/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
 * Copyright 2002 Mike McCormack for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <stdarg.h>

#define COBJMACROS
#define NONAMELESSUNION

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winnls.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "msipriv.h"
#include "objidl.h"

WINE_DEFAULT_DEBUG_CHANNEL(msi);

static const WCHAR szSumInfo[] = { 5 ,'S','u','m','m','a','r','y',
                       'I','n','f','o','r','m','a','t','i','o','n',0 };

static void MSI_CloseSummaryInfo( MSIOBJECTHDR *arg )
{
    MSISUMMARYINFO *suminfo = (MSISUMMARYINFO *) arg;
    IPropertyStorage_Release( suminfo->propstg );
}

UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, 
              LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo)
{
    LPWSTR szwDatabase = NULL;
    UINT ret;

    TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase), 
          uiUpdateCount, phSummaryInfo);

    if( szDatabase )
    {
        UINT len = MultiByteToWideChar( CP_ACP, 0, szDatabase, -1, NULL, 0 );
        szwDatabase = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
        if( !szwDatabase )
            return ERROR_FUNCTION_FAILED;
        MultiByteToWideChar( CP_ACP, 0, szDatabase, -1, szwDatabase, len );
    }

    ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, phSummaryInfo);

    HeapFree( GetProcessHeap(), 0, szwDatabase );

    return ret;
}

UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, 
              LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo)
{
    HRESULT r;
    MSIHANDLE handle;
    MSISUMMARYINFO *suminfo;
    MSIDATABASE *db;
    UINT ret = ERROR_SUCCESS;
    IPropertySetStorage *psstg = NULL;
    IPropertyStorage *ps = NULL;
    DWORD grfMode;

    TRACE("%ld %s %d %p\n", hDatabase, debugstr_w(szDatabase),
           uiUpdateCount, phSummaryInfo);

    if( !phSummaryInfo )
        return ERROR_INVALID_PARAMETER;

    if( szDatabase )
    {
        UINT res;

        res = MSI_OpenDatabaseW(szDatabase, NULL, &db);
        if( res != ERROR_SUCCESS )
            return res;
    }
    else
    {
        db = msihandle2msiinfo(hDatabase, MSIHANDLETYPE_DATABASE);
        if( !db )
            return ERROR_INVALID_PARAMETER;
    }

    r = IStorage_QueryInterface( db->storage, 
             &IID_IPropertySetStorage, (LPVOID)&psstg);
    if( FAILED( r ) )
    {
        ERR("IStorage -> IPropertySetStorage failed\n");
        if (db)
            msiobj_release(&db->hdr);
        return ERROR_FUNCTION_FAILED;
    }
    ERR("storage = %p propertysetstorage = %p\n", db->storage, psstg);

    grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE;
    r = IPropertySetStorage_Open( psstg, &FMTID_SummaryInformation, grfMode, &ps );
    if( FAILED( r ) )
    {
        ERR("failed to get IPropertyStorage r=%08lx\n",r);
        ret = ERROR_FUNCTION_FAILED;
        goto end;
    }

    suminfo = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, 
                  sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
    if( !suminfo )
    {
        ret = ERROR_FUNCTION_FAILED;
        goto end;
    }

    IPropertyStorage_AddRef(ps);
    suminfo->propstg = ps;
    handle = alloc_msihandle( &suminfo->hdr );
    if( handle )
    *phSummaryInfo = handle;
    else
        ret = ERROR_FUNCTION_FAILED;
    msiobj_release( &suminfo->hdr );

end:
    if( ps )
        IPropertyStorage_Release(ps);
    if( psstg )
        IPropertySetStorage_Release(psstg);
    if (db)
        msiobj_release(&db->hdr);

    return ret;
}

UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
{
    MSISUMMARYINFO *suminfo;

    FIXME("%ld %p\n",hSummaryInfo, pCount);

    suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
    if( !suminfo )
        return ERROR_INVALID_HANDLE;

    return ERROR_CALL_NOT_IMPLEMENTED;
}

UINT WINAPI MsiSummaryInfoGetPropertyA(
      MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue,
      FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf)
{
    MSISUMMARYINFO *suminfo;
    HRESULT r;
    PROPSPEC spec;
    PROPVARIANT var;

    TRACE("%ld %d %p %p %p %p %p\n",
        hSummaryInfo, uiProperty, puiDataType, piValue,
        pftValue, szValueBuf, pcchValueBuf);

    suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
    if( !suminfo )
        return ERROR_INVALID_HANDLE;

    spec.ulKind = PRSPEC_PROPID;
    spec.u.propid = uiProperty;

    r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var);
    if( FAILED(r) )
        return ERROR_FUNCTION_FAILED;

    if( puiDataType )
        *puiDataType = var.vt;

    switch( var.vt )
    {
    case VT_I4:
        if( piValue )
            *piValue = var.u.lVal;
        break;
    case VT_LPSTR:
        if( pcchValueBuf && szValueBuf )
        {
            lstrcpynA(szValueBuf, var.u.pszVal, *pcchValueBuf );
            *pcchValueBuf = lstrlenA( var.u.pszVal );
        }
        break;
    case VT_FILETIME:
        if( pftValue )
            memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) );
        break;
    case VT_EMPTY:
        break;
    default:
        FIXME("Unknown property variant type\n");
        break;
    }

    return ERROR_SUCCESS;
}

UINT WINAPI MsiSummaryInfoGetPropertyW(
      MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue,
      FILETIME *pftValue, LPWSTR szValueBuf, DWORD *pcchValueBuf)
{
    MSISUMMARYINFO *suminfo;
    HRESULT r;
    PROPSPEC spec;
    PROPVARIANT var;

    TRACE("%ld %d %p %p %p %p %p\n",
        hSummaryInfo, uiProperty, puiDataType, piValue,
        pftValue, szValueBuf, pcchValueBuf);

    suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
    if( !suminfo )
        return ERROR_INVALID_HANDLE;

    spec.ulKind = PRSPEC_PROPID;
    spec.u.propid = uiProperty;

    r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var);
    if( FAILED(r) )
        return ERROR_FUNCTION_FAILED;

    if( puiDataType )
        *puiDataType = var.vt;

    switch( var.vt )
    {
    case VT_I4:
        if( piValue )
            *piValue = var.u.lVal;
        break;
    case VT_LPSTR:
        if( pcchValueBuf && szValueBuf )
        {
            MultiByteToWideChar(CP_ACP, 0,  var.u.pszVal, -1, szValueBuf, 
                                *pcchValueBuf );
            *pcchValueBuf = lstrlenA( var.u.pszVal );
        }
        break;
    case VT_FILETIME:
        if( pftValue )
            memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) );
        break;
    case VT_EMPTY:
        break;
    default:
        FIXME("Unknown property variant type\n");
        break;
    }

    return ERROR_SUCCESS;
}

UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty,
                                       UINT uiDataType, INT iValue, 
                                       FILETIME* pftValue, LPSTR szValue)
{
    return ERROR_CALL_NOT_IMPLEMENTED;
}

UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE hSummaryInfo, UINT uiProperty,
                                       UINT uiDataType, INT iValue, 
                                       FILETIME* pftValue, LPWSTR szValue)
{
    return ERROR_CALL_NOT_IMPLEMENTED;
}

UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE hSummaryInfo)
{
    return ERROR_CALL_NOT_IMPLEMENTED;
}
