From 758a69515b2987feb6d5ea8f1bcf2ee56c11ac06 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Fri, 18 Mar 2005 14:01:39 +0000 Subject: [PATCH] Implement summary information loading and saving. --- dlls/msi/msipriv.h | 6 - dlls/msi/suminfo.c | 765 +++++++++++++++++++++++++++++++++++---------- include/msi.h | 14 - include/msiquery.h | 15 + 4 files changed, 612 insertions(+), 188 deletions(-) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index cbb71e1b37f..2065bd176ef 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -171,12 +171,6 @@ typedef struct tagMSIVIEWOPS } MSIVIEWOPS; -typedef struct tagMSISUMMARYINFO -{ - MSIOBJECTHDR hdr; - IPropertyStorage *propstg; -} MSISUMMARYINFO; - struct tagMSIVIEW { MSIOBJECTHDR hdr; diff --git a/dlls/msi/suminfo.c b/dlls/msi/suminfo.c index 6f39d5cf8a7..423c8286b98 100644 --- a/dlls/msi/suminfo.c +++ b/dlls/msi/suminfo.c @@ -1,7 +1,7 @@ /* * Implementation of the Microsoft Installer (msi.dll) * - * Copyright 2002 Mike McCormack for CodeWeavers + * Copyright 2002, 2005 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 @@ -31,61 +31,395 @@ #include "wine/debug.h" #include "msi.h" #include "msiquery.h" +#include "msidefs.h" #include "msipriv.h" #include "objidl.h" WINE_DEFAULT_DEBUG_CHANNEL(msi); +#define MSI_MAX_PROPS 19 + +#include "pshpack1.h" + +typedef struct { + WORD wByteOrder; + WORD wFormat; + DWORD dwOSVer; + CLSID clsID; + DWORD reserved; +} PROPERTYSETHEADER; + +typedef struct { + FMTID fmtid; + DWORD dwOffset; +} FORMATIDOFFSET; + +typedef struct { + DWORD cbSection; + DWORD cProperties; +} PROPERTYSECTIONHEADER; + +typedef struct { + DWORD propid; + DWORD dwOffset; +} PROPERTYIDOFFSET; + +typedef struct { + DWORD type; + union { + INT i4; + SHORT i2; + FILETIME ft; + struct { + DWORD len; + BYTE str[1]; + } str; + } u; +} PROPERTY_DATA; + +#include "poppack.h" + +typedef struct { + BOOL unicode; + union { + LPSTR a; + LPWSTR w; + } str; +} awstring; + +typedef struct tagMSISUMMARYINFO +{ + MSIOBJECTHDR hdr; + MSIDATABASE *db; + DWORD update_count; + PROPVARIANT property[MSI_MAX_PROPS]; +} MSISUMMARYINFO; + 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 ); + MSISUMMARYINFO *si = (MSISUMMARYINFO *) arg; + msiobj_release( &si->db->hdr ); } -UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, - LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo) +static UINT get_type( UINT uiProperty ) { - LPWSTR szwDatabase = NULL; - UINT ret; - - TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase), - uiUpdateCount, phSummaryInfo); - - if( szDatabase ) + switch( uiProperty ) { - 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 ); + case PID_CODEPAGE: + return VT_I2; + + case PID_SUBJECT: + case PID_AUTHOR: + case PID_KEYWORDS: + case PID_COMMENTS: + case PID_TEMPLATE: + case PID_LASTAUTHOR: + case PID_REVNUMBER: + case PID_APPNAME: + case PID_TITLE: + return VT_LPSTR; + + case PID_LASTPRINTED: + case PID_CREATE_DTM: + case PID_LASTSAVE_DTM: + return VT_FILETIME; + + case PID_WORDCOUNT: + case PID_CHARCOUNT: + case PID_SECURITY: + case PID_PAGECOUNT: + return VT_I4; + } + return VT_EMPTY; +} + +static UINT get_property_count( PROPVARIANT *property ) +{ + UINT i, n = 0; + + if( !property ) + return n; + for( i=0; itype ) + { + ERR("wrong type\n"); + break; + } + + /* check we don't run off the end of the data */ + size = sz - idofs[i].dwOffset - sizeof(DWORD); + if( sizeof(DWORD) > size || + ( type == VT_FILETIME && sizeof(FILETIME) > size ) || + ( type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) ) + { + ERR("not enough data\n"); + break; + } + + property = &prop[ idofs[i].propid ]; + property->vt = type; + + if( type == VT_LPSTR ) + { + LPSTR str = HeapAlloc( GetProcessHeap(), 0, propdata->u.str.len ); + memcpy( str, propdata->u.str.str, propdata->u.str.len ); + str[ propdata->u.str.len - 1 ] = 0; + property->u.pszVal = str; + } + else if( type == VT_FILETIME ) + property->u.filetime = propdata->u.ft; + else if( type == VT_I2 ) + property->u.iVal = propdata->u.i2; + else if( type == VT_I4 ) + property->u.lVal = propdata->u.i4; + } +} + +static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm ) +{ + UINT ret = ERROR_FUNCTION_FAILED; + PROPERTYSETHEADER set_hdr; + FORMATIDOFFSET format_hdr; + PROPERTYSECTIONHEADER section_hdr; + PROPERTYIDOFFSET idofs[MSI_MAX_PROPS]; + LPBYTE data = NULL; + LARGE_INTEGER ofs; + ULONG count, sz; + HRESULT r; + + TRACE("%p %p\n", si, stm); + + /* read the header */ + sz = sizeof set_hdr; + r = IStream_Read( stm, &set_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + if( set_hdr.wByteOrder != 0xfffe ) + { + ERR("property set not big-endian %04X\n", set_hdr.wByteOrder); + return ret; } - ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, phSummaryInfo); + sz = sizeof format_hdr; + r = IStream_Read( stm, &format_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; - HeapFree( GetProcessHeap(), 0, szwDatabase ); + /* check the format id is correct */ + if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) ) + return ret; + /* seek to the location of the section */ + ofs.QuadPart = format_hdr.dwOffset; + r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL ); + if( FAILED(r) ) + return ret; + + /* read the section itself */ + sz = sizeof section_hdr; + r = IStream_Read( stm, §ion_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + if( section_hdr.cProperties > MSI_MAX_PROPS ) + { + ERR("too many properties %ld\n", section_hdr.cProperties); + return ret; + } + + /* read the offsets */ + sz = sizeof idofs[0] * section_hdr.cProperties; + r = IStream_Read( stm, idofs, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* read all the data in one go */ + sz = section_hdr.cbSection; + data = HeapAlloc( GetProcessHeap(), 0, sz ); + if( !data ) + return ret; + r = IStream_Read( stm, data, sz, &count ); + if( SUCCEEDED(r) && count == sz ) + { + read_properties_from_data( si->property, idofs, + section_hdr.cProperties, data, sz ); + } + + HeapFree( GetProcessHeap(), 0, data ); return ret; } -UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, - LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo) +static DWORD write_dword( LPBYTE data, DWORD ofs, DWORD val ) { + if( data ) + { + data[ofs++] = val&0xff; + data[ofs++] = (val>>8)&0xff; + data[ofs++] = (val>>16)&0xff; + data[ofs++] = (val>>24)&0xff; + } + return 4; +} + +static DWORD write_filetime( LPBYTE data, DWORD ofs, LPFILETIME ft ) +{ + write_dword( data, ofs, ft->dwLowDateTime ); + write_dword( data, ofs + 4, ft->dwHighDateTime ); + return 8; +} + +static DWORD write_string( LPBYTE data, DWORD ofs, LPCSTR str ) +{ + DWORD len = lstrlenA( str ) + 1; + write_dword( data, ofs, len ); + if( data ) + lstrcpyA( &data[ofs + 4], str ); + return (7 + len) & ~3; +} + +static UINT write_property_to_data( PROPVARIANT *prop, LPBYTE data ) +{ + DWORD sz = 0; + + if( prop->vt == VT_EMPTY ) + return sz; + + /* add the type */ + sz += write_dword( data, sz, prop->vt ); + switch( prop->vt ) + { + case VT_I2: + sz += write_dword( data, sz, prop->u.iVal ); + break; + case VT_I4: + sz += write_dword( data, sz, prop->u.lVal ); + break; + case VT_FILETIME: + sz += write_filetime( data, sz, &prop->u.filetime ); + break; + case VT_LPSTR: + sz += write_string( data, sz, prop->u.pszVal ); + break; + } + return sz; +} + +static UINT save_summary_info( MSISUMMARYINFO * si, IStream *stm ) +{ + UINT ret = ERROR_FUNCTION_FAILED; + PROPERTYSETHEADER set_hdr; + FORMATIDOFFSET format_hdr; + PROPERTYSECTIONHEADER section_hdr; + PROPERTYIDOFFSET idofs[MSI_MAX_PROPS]; + LPBYTE data = NULL; + ULONG count, sz; HRESULT r; - MSIHANDLE handle; - MSISUMMARYINFO *suminfo; - MSIDATABASE *db; + int i, n; + + /* write the header */ + sz = sizeof set_hdr; + memset( &set_hdr, 0, sz ); + set_hdr.wByteOrder = 0xfffe; + set_hdr.wFormat = 0; + set_hdr.dwOSVer = 0x00020005; /* build 5, platform id 2 */ + /* set_hdr.clsID is {00000000-0000-0000-0000-000000000000} */ + set_hdr.reserved = 1; + r = IStream_Write( stm, &set_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* write the format header */ + sz = sizeof format_hdr; + memcpy( &format_hdr.fmtid, &FMTID_SummaryInformation, sizeof (FMTID) ); + format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr; + r = IStream_Write( stm, &format_hdr, sz, &count ); + if( FAILED(r) || count != sz ) + return ret; + + /* add up how much space the data will take and calculate the offsets */ + section_hdr.cbSection = sizeof section_hdr; + section_hdr.cbSection += (get_property_count( si->property ) * sizeof idofs[0]); + section_hdr.cProperties = 0; + n = 0; + for( i = 0; i < MSI_MAX_PROPS; i++ ) + { + sz = write_property_to_data( &si->property[i], NULL ); + if( !sz ) + continue; + idofs[ section_hdr.cProperties ].propid = i; + idofs[ section_hdr.cProperties ].dwOffset = section_hdr.cbSection; + section_hdr.cProperties++; + section_hdr.cbSection += sz; + } + + data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, section_hdr.cbSection ); + + sz = 0; + memcpy( &data[sz], §ion_hdr, sizeof section_hdr ); + sz += sizeof section_hdr; + + memcpy( &data[sz], idofs, section_hdr.cProperties * sizeof idofs[0] ); + sz += section_hdr.cProperties * sizeof idofs[0]; + + /* write out the data */ + for( i = 0; i < MSI_MAX_PROPS; i++ ) + sz += write_property_to_data( &si->property[i], &data[sz] ); + + r = IStream_Write( stm, data, sz, &count ); + HeapFree( GetProcessHeap(), 0, data ); + if( FAILED(r) || count != sz ) + return ret; + + return ERROR_SUCCESS; +} + +UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase, + LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle ) +{ UINT ret = ERROR_SUCCESS; - IPropertySetStorage *psstg = NULL; - IPropertyStorage *ps = NULL; + IStream *stm = NULL; + MSISUMMARYINFO *si; + MSIHANDLE handle; + MSIDATABASE *db; DWORD grfMode; + HRESULT r; TRACE("%ld %s %d %p\n", hDatabase, debugstr_w(szDatabase), - uiUpdateCount, phSummaryInfo); + uiUpdateCount, pHandle); - if( !phSummaryInfo ) + if( !pHandle ) return ERROR_INVALID_PARAMETER; if( szDatabase ) @@ -103,207 +437,302 @@ UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE hDatabase, return ERROR_INVALID_PARAMETER; } - r = IStorage_QueryInterface( db->storage, - &IID_IPropertySetStorage, (LPVOID)&psstg); - if( FAILED( r ) ) - { - ERR("IStorage -> IPropertySetStorage failed\n"); - ret = ERROR_FUNCTION_FAILED; - goto end; - } - - 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, + si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo ); - if( !suminfo ) + if( !si ) { ret = ERROR_FUNCTION_FAILED; goto end; } - IPropertyStorage_AddRef(ps); - suminfo->propstg = ps; - handle = alloc_msihandle( &suminfo->hdr ); + msiobj_addref( &db->hdr ); + si->db = db; + memset( &si->property, 0, sizeof si->property ); + si->update_count = uiUpdateCount; + + /* read the stream... if we fail, we'll start with an empty property set */ + grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE; + r = IStorage_OpenStream( si->db->storage, szSumInfo, 0, grfMode, 0, &stm ); + if( SUCCEEDED(r) ) + { + load_summary_info( si, stm ); + IStream_Release( stm ); + } + + handle = alloc_msihandle( &si->hdr ); if( handle ) - *phSummaryInfo = handle; + *pHandle = handle; else ret = ERROR_FUNCTION_FAILED; - msiobj_release( &suminfo->hdr ); + msiobj_release( &si->hdr ); end: - if( ps ) - IPropertyStorage_Release(ps); - if( psstg ) - IPropertySetStorage_Release(psstg); if( db ) msiobj_release(&db->hdr); return ret; } +UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, + LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle) +{ + LPWSTR szwDatabase = NULL; + UINT ret; + + TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase), + uiUpdateCount, pHandle); + + if( szDatabase ) + { + szwDatabase = strdupAtoW( szDatabase ); + if( !szwDatabase ) + return ERROR_FUNCTION_FAILED; + } + + ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, pHandle); + + HeapFree( GetProcessHeap(), 0, szwDatabase ); + + return ret; +} + UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount) { - MSISUMMARYINFO *suminfo; + MSISUMMARYINFO *si; - FIXME("%ld %p\n",hSummaryInfo, pCount); + TRACE("%ld %p\n",hSummaryInfo, pCount); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) + si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) return ERROR_INVALID_HANDLE; - msiobj_release( &suminfo->hdr ); - return ERROR_CALL_NOT_IMPLEMENTED; + if( pCount ) + *pCount = get_property_count( si->property ); + msiobj_release( &si->hdr ); + + return ERROR_SUCCESS; +} + +static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, + INT *piValue, FILETIME *pftValue, awstring *str, DWORD *pcchValueBuf) +{ + MSISUMMARYINFO *si; + PROPVARIANT *prop; + UINT type; + + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, str, pcchValueBuf); + + type = get_type( uiProperty ); + if( puiDataType ) + *puiDataType = type; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + + prop = &si->property[uiProperty]; + if( prop->vt != type ) + goto end; + + switch( type ) + { + case VT_I2: + if( piValue ) + *piValue = prop->u.iVal; + break; + case VT_I4: + if( piValue ) + *piValue = prop->u.lVal; + break; + case VT_LPSTR: + if( pcchValueBuf ) + { + DWORD len = 0; + + if( str->unicode ) + { + len = MultiByteToWideChar( CP_ACP, 0, prop->u.pszVal, -1, + str->str.w, *pcchValueBuf ); + } + else + { + len = lstrlenA( prop->u.pszVal ); + if( str->str.a ) + lstrcpynA(str->str.a, prop->u.pszVal, *pcchValueBuf ); + } + *pcchValueBuf = len; + } + break; + case VT_FILETIME: + if( pftValue ) + memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) ); + break; + case VT_EMPTY: + break; + default: + FIXME("Unknown property variant type\n"); + break; + } +end: + msiobj_release( &si->hdr ); + return ERROR_SUCCESS; } UINT WINAPI MsiSummaryInfoGetPropertyA( - MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue, + MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, INT *piValue, FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf) { - MSISUMMARYINFO *suminfo; - HRESULT r; - PROPSPEC spec; - PROPVARIANT var; - UINT rc = ERROR_SUCCESS; + awstring str; - TRACE("%ld %d %p %p %p %p %p\n", - hSummaryInfo, uiProperty, puiDataType, piValue, - pftValue, szValueBuf, pcchValueBuf); + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, szValueBuf, pcchValueBuf ); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) - return ERROR_INVALID_HANDLE; + str.unicode = FALSE; + str.str.a = szValueBuf; - spec.ulKind = PRSPEC_PROPID; - spec.u.propid = uiProperty; - - r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); - if( FAILED(r) ) - { - rc = ERROR_FUNCTION_FAILED; - goto end; - } - - 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; - } - -end: - msiobj_release( &suminfo->hdr ); - return rc; + return get_prop( handle, uiProperty, puiDataType, piValue, + pftValue, &str, pcchValueBuf ); } UINT WINAPI MsiSummaryInfoGetPropertyW( - MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue, + MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, INT *piValue, FILETIME *pftValue, LPWSTR szValueBuf, DWORD *pcchValueBuf) { - MSISUMMARYINFO *suminfo; - HRESULT r; - PROPSPEC spec; - PROPVARIANT var; - UINT rc = ERROR_SUCCESS; + awstring str; - TRACE("%ld %d %p %p %p %p %p\n", - hSummaryInfo, uiProperty, puiDataType, piValue, - pftValue, szValueBuf, pcchValueBuf); + TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType, + piValue, pftValue, szValueBuf, pcchValueBuf ); - suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO ); - if( !suminfo ) + str.unicode = TRUE; + str.str.w = szValueBuf; + + return get_prop( handle, uiProperty, puiDataType, piValue, + pftValue, &str, pcchValueBuf ); +} + +static UINT set_prop( MSIHANDLE handle, UINT uiProperty, UINT uiDataType, + INT iValue, FILETIME* pftValue, awstring *str ) +{ + MSISUMMARYINFO *si; + PROPVARIANT *prop; + UINT type, len, ret = ERROR_SUCCESS; + + TRACE("%ld %u %u %i %p %p\n", handle, uiProperty, uiDataType, + iValue, pftValue, str ); + + type = get_type( uiProperty ); + if( type == VT_EMPTY || type != uiDataType ) + return ERROR_DATATYPE_MISMATCH; + + if( uiDataType == VT_LPSTR && !str->str.w ) + return ERROR_INVALID_PARAMETER; + + if( uiDataType == VT_FILETIME && !pftValue ) + return ERROR_INVALID_PARAMETER; + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) return ERROR_INVALID_HANDLE; - spec.ulKind = PRSPEC_PROPID; - spec.u.propid = uiProperty; + prop = &si->property[uiProperty]; - r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var); - if( FAILED(r) ) + if( prop->vt == VT_EMPTY ) { - rc = ERROR_FUNCTION_FAILED; - goto end; + if( !si->update_count ) + { + ret = ERROR_FUNCTION_FAILED; + goto end; + } + si->update_count--; + prop->vt = type; } + else if( prop->vt != type ) + goto end; - if( puiDataType ) - *puiDataType = var.vt; - - switch( var.vt ) + switch( type ) { case VT_I4: - if( piValue ) - *piValue = var.u.lVal; + prop->u.lVal = iValue; break; - case VT_LPSTR: - if( pcchValueBuf && szValueBuf ) - { - MultiByteToWideChar(CP_ACP, 0, var.u.pszVal, -1, szValueBuf, - *pcchValueBuf ); - *pcchValueBuf = lstrlenA( var.u.pszVal ); - } + case VT_I2: + prop->u.iVal = iValue; break; case VT_FILETIME: - if( pftValue ) - memcpy(pftValue, &var.u.filetime, sizeof (FILETIME) ); + memcpy( &prop->u.filetime, pftValue, sizeof prop->u.filetime ); break; - case VT_EMPTY: - break; - default: - FIXME("Unknown property variant type\n"); + case VT_LPSTR: + HeapFree( GetProcessHeap(), 0, prop->u.pszVal ); + if( str->unicode ) + { + len = WideCharToMultiByte( CP_ACP, 0, str->str.w, -1, + NULL, 0, NULL, NULL ); + prop->u.pszVal = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( CP_ACP, 0, str->str.w, -1, + prop->u.pszVal, len, NULL, NULL ); + } + else + { + len = lstrlenA( str->str.a ) + 1; + prop->u.pszVal = HeapAlloc( GetProcessHeap(), 0, len ); + lstrcpyA( prop->u.pszVal, str->str.a ); + } break; } end: - msiobj_release( &suminfo->hdr ); - return rc; + msiobj_release( &si->hdr ); + return ret; } -UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE hSummaryInfo, UINT uiProperty, - UINT uiDataType, INT iValue, - FILETIME* pftValue, LPSTR szValue ) +UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE handle, UINT uiProperty, + UINT uiDataType, INT iValue, FILETIME* pftValue, LPWSTR szValue ) { - FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, - uiDataType, iValue, pftValue, debugstr_a(szValue) ); - return ERROR_CALL_NOT_IMPLEMENTED; + awstring str; + + TRACE("%ld %u %u %i %p %s\n", handle, uiProperty, uiDataType, + iValue, pftValue, debugstr_w(szValue) ); + + str.unicode = TRUE; + str.str.w = szValue; + return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); } -UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE hSummaryInfo, UINT uiProperty, - UINT uiDataType, INT iValue, - FILETIME* pftValue, LPWSTR szValue ) +UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE handle, UINT uiProperty, + UINT uiDataType, INT iValue, FILETIME* pftValue, LPSTR szValue ) { - FIXME("%ld %u %u %i %p %s\n", hSummaryInfo, uiProperty, - uiDataType, iValue, pftValue, debugstr_w(szValue) ); - return ERROR_CALL_NOT_IMPLEMENTED; + awstring str; + + TRACE("%ld %u %u %i %p %s\n", handle, uiProperty, uiDataType, + iValue, pftValue, debugstr_a(szValue) ); + + str.unicode = FALSE; + str.str.a = szValue; + return set_prop( handle, uiProperty, uiDataType, iValue, pftValue, &str ); } -UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE hSummaryInfo ) +UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle ) { - FIXME("%ld\n", hSummaryInfo ); - return ERROR_CALL_NOT_IMPLEMENTED; + IStream *stm = NULL; + MSISUMMARYINFO *si; + DWORD grfMode; + HRESULT r; + UINT ret = ERROR_FUNCTION_FAILED; + + TRACE("%ld\n", handle ); + + si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO ); + if( !si ) + return ERROR_INVALID_HANDLE; + + grfMode = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE; + r = IStorage_CreateStream( si->db->storage, szSumInfo, grfMode, 0, 0, &stm ); + if( SUCCEEDED(r) ) + { + ret = save_summary_info( si, stm ); + IStream_Release( stm ); + } + msiobj_release( &si->hdr ); + + return ret; } diff --git a/include/msi.h b/include/msi.h index 9ae0f6c2a2d..9554a0e7b38 100644 --- a/include/msi.h +++ b/include/msi.h @@ -201,20 +201,6 @@ UINT WINAPI MsiOpenProductA(LPCSTR, MSIHANDLE*); UINT WINAPI MsiOpenProductW(LPCWSTR, MSIHANDLE*); #define MsiOpenProduct WINELIB_NAME_AW(MsiOpenProduct) -UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE, LPCSTR, UINT, MSIHANDLE *); -UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE, LPCWSTR, UINT, MSIHANDLE *); -#define MsiGetSummaryInformation WINELIB_NAME_AW(MsiGetSummaryInformation) - -UINT WINAPI MsiSummaryInfoGetPropertyA(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPSTR,DWORD*); -UINT WINAPI MsiSummaryInfoGetPropertyW(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPWSTR,DWORD*); -#define MsiSummaryInfoGetProperty WINELIB_NAME_AW(MsiSummaryInfoGetProperty) - -UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE); - -UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE, UINT, UINT, INT, FILETIME*, LPSTR); -UINT WINAPI MsiSummaryInfoSetPropertyW(MSIHANDLE, UINT, UINT, INT, FILETIME*, LPWSTR); -#define MsiSummaryInfoSetProperty WINELIB_NAME_AW(MsiSummaryInfoSetProperty) - UINT WINAPI MsiProvideComponentFromDescriptorA(LPCSTR,LPSTR,DWORD*,DWORD*); UINT WINAPI MsiProvideComponentFromDescriptorW(LPCWSTR,LPWSTR,DWORD*,DWORD*); #define MsiProvideComponentFromDescriptor WINELIB_NAME_AW(MsiProvideComponentFromDescriptor) diff --git a/include/msiquery.h b/include/msiquery.h index ed194ddc11b..af313e96093 100644 --- a/include/msiquery.h +++ b/include/msiquery.h @@ -181,6 +181,21 @@ UINT WINAPI MsiPreviewBillboardA(MSIHANDLE, LPCSTR, LPCSTR); UINT WINAPI MsiPreviewBillboardW(MSIHANDLE, LPCWSTR, LPCWSTR); #define MsiPreviewBillboard WINELIB_NAME_AW(MsiPreviewBillboard) +UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE, LPCSTR, UINT, MSIHANDLE *); +UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE, LPCWSTR, UINT, MSIHANDLE *); +#define MsiGetSummaryInformation WINELIB_NAME_AW(MsiGetSummaryInformation) + +UINT WINAPI MsiSummaryInfoGetPropertyA(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPSTR,DWORD*); +UINT WINAPI MsiSummaryInfoGetPropertyW(MSIHANDLE,UINT,UINT*,INT*,FILETIME*,LPWSTR,DWORD*); +#define MsiSummaryInfoGetProperty WINELIB_NAME_AW(MsiSummaryInfoGetProperty) + +UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE, UINT, UINT, INT, FILETIME*, LPSTR); +UINT WINAPI MsiSummaryInfoSetPropertyW(MSIHANDLE, UINT, UINT, INT, FILETIME*, LPWSTR); +#define MsiSummaryInfoSetProperty WINELIB_NAME_AW(MsiSummaryInfoSetProperty) + +UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE); +UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE,UINT*); + UINT WINAPI MsiEnableUIPreview(MSIHANDLE, MSIHANDLE*); BOOL WINAPI MsiGetMode(MSIHANDLE, MSIRUNMODE);