MSI: implement summary information loading and saving
Mike McCormack
mike at codeweavers.com
Fri Mar 18 04:31:49 CST 2005
ChangeLog:
* implement summary information loading and saving
-------------- next part --------------
Index: include/msi.h
===================================================================
RCS file: /home/wine/wine/include/msi.h,v
retrieving revision 1.21
diff -u -p -r1.21 msi.h
--- include/msi.h 10 Feb 2005 18:57:42 -0000 1.21
+++ include/msi.h 18 Mar 2005 10:30:52 -0000
@@ -201,20 +201,6 @@ UINT WINAPI MsiOpenProductA(LPCSTR, MSIH
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)
Index: include/msiquery.h
===================================================================
RCS file: /home/wine/wine/include/msiquery.h,v
retrieving revision 1.10
diff -u -p -r1.10 msiquery.h
--- include/msiquery.h 28 Jan 2005 11:28:00 -0000 1.10
+++ include/msiquery.h 18 Mar 2005 10:30:52 -0000
@@ -181,6 +181,21 @@ UINT WINAPI MsiPreviewBillboardA(MSIHAND
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);
Index: dlls/msi/msipriv.h
===================================================================
RCS file: /home/wine/wine/dlls/msi/msipriv.h,v
retrieving revision 1.50
diff -u -p -r1.50 msipriv.h
--- dlls/msi/msipriv.h 16 Mar 2005 11:31:35 -0000 1.50
+++ dlls/msi/msipriv.h 18 Mar 2005 10:30:53 -0000
@@ -171,12 +171,6 @@ typedef struct tagMSIVIEWOPS
} MSIVIEWOPS;
-typedef struct tagMSISUMMARYINFO
-{
- MSIOBJECTHDR hdr;
- IPropertyStorage *propstg;
-} MSISUMMARYINFO;
-
struct tagMSIVIEW
{
MSIOBJECTHDR hdr;
Index: dlls/msi/suminfo.c
===================================================================
RCS file: /home/wine/wine/dlls/msi/suminfo.c,v
retrieving revision 1.14
diff -u -p -r1.14 suminfo.c
--- dlls/msi/suminfo.c 10 Mar 2005 11:15:40 -0000 1.14
+++ dlls/msi/suminfo.c 18 Mar 2005 10:30:53 -0000
@@ -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;
+ switch( uiProperty )
+ {
+ 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;
+}
- TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase),
- uiUpdateCount, phSummaryInfo);
+static UINT get_property_count( PROPVARIANT *property )
+{
+ UINT i, n = 0;
- if( szDatabase )
+ if( !property )
+ return n;
+ for( i=0; i<MSI_MAX_PROPS; i++ )
+ if( property[i].vt != VT_EMPTY )
+ n++;
+ return n;
+}
+
+/* FIXME: doesn't deal with endian conversion */
+static void read_properties_from_data( PROPVARIANT *prop,
+ PROPERTYIDOFFSET *idofs, DWORD count, LPBYTE data, DWORD sz )
+{
+ UINT type;
+ DWORD i;
+ int size;
+ PROPERTY_DATA *propdata;
+ PROPVARIANT *property;
+
+ /* now set all the properties */
+ for( i = 0; i < count; i++ )
{
- 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 );
+ type = get_type( idofs[i].propid );
+ if( type == VT_EMPTY )
+ {
+ ERR("propid %ld has unknown type\n", idofs[i].propid);
+ break;
+ }
+
+ propdata = (PROPERTY_DATA*) &data[idofs[i].dwOffset];
+
+ /* check the type is the same as we expect */
+ if( type != propdata->type )
+ {
+ 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;
+
+ /* 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;
- HeapFree( GetProcessHeap(), 0, szwDatabase );
+ /* 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;
+ 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;
+ IStream *stm = NULL;
+ MSISUMMARYINFO *si;
MSIHANDLE handle;
- MSISUMMARYINFO *suminfo;
MSIDATABASE *db;
- UINT ret = ERROR_SUCCESS;
- IPropertySetStorage *psstg = NULL;
- IPropertyStorage *ps = NULL;
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,113 +437,136 @@ UINT WINAPI MsiGetSummaryInformationW(MS
return ERROR_INVALID_PARAMETER;
}
- r = IStorage_QueryInterface( db->storage,
- &IID_IPropertySetStorage, (LPVOID)&psstg);
- if( FAILED( r ) )
+ si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO,
+ sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
+ if( !si )
{
- 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;
- }
+ msiobj_addref( &db->hdr );
+ si->db = db;
+ memset( &si->property, 0, sizeof si->property );
+ si->update_count = uiUpdateCount;
- suminfo = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO,
- sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
- if( !suminfo )
+ /* 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) )
{
- ret = ERROR_FUNCTION_FAILED;
- goto end;
+ load_summary_info( si, stm );
+ IStream_Release( stm );
}
- IPropertyStorage_AddRef(ps);
- suminfo->propstg = ps;
- handle = alloc_msihandle( &suminfo->hdr );
+ 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 MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
+UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase,
+ LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
{
- MSISUMMARYINFO *suminfo;
+ LPWSTR szwDatabase = NULL;
+ UINT ret;
- FIXME("%ld %p\n",hSummaryInfo, pCount);
+ TRACE("%ld %s %d %p\n", hDatabase, debugstr_a(szDatabase),
+ uiUpdateCount, pHandle);
- suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
- if( !suminfo )
- return ERROR_INVALID_HANDLE;
+ if( szDatabase )
+ {
+ szwDatabase = strdupAtoW( szDatabase );
+ if( !szwDatabase )
+ return ERROR_FUNCTION_FAILED;
+ }
+
+ ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, pHandle);
+
+ HeapFree( GetProcessHeap(), 0, szwDatabase );
- msiobj_release( &suminfo->hdr );
- return ERROR_CALL_NOT_IMPLEMENTED;
+ return ret;
}
-UINT WINAPI MsiSummaryInfoGetPropertyA(
- MSIHANDLE hSummaryInfo, UINT uiProperty, UINT *puiDataType, INT *piValue,
- FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf)
+UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, UINT *pCount)
{
- MSISUMMARYINFO *suminfo;
- HRESULT r;
- PROPSPEC spec;
- PROPVARIANT var;
- UINT rc = ERROR_SUCCESS;
-
- TRACE("%ld %d %p %p %p %p %p\n",
- hSummaryInfo, uiProperty, puiDataType, piValue,
- pftValue, szValueBuf, pcchValueBuf);
+ MSISUMMARYINFO *si;
- suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
- if( !suminfo )
+ TRACE("%ld %p\n",hSummaryInfo, pCount);
+
+ si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
+ if( !si )
return ERROR_INVALID_HANDLE;
- spec.ulKind = PRSPEC_PROPID;
- spec.u.propid = uiProperty;
+ if( pCount )
+ *pCount = get_property_count( si->property );
+ msiobj_release( &si->hdr );
- r = IPropertyStorage_ReadMultiple( suminfo->propstg, 1, &spec, &var);
- if( FAILED(r) )
- {
- rc = ERROR_FUNCTION_FAILED;
- goto end;
- }
+ 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 = var.vt;
+ *puiDataType = type;
+
+ si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
+ if( !si )
+ return ERROR_INVALID_HANDLE;
+
+ prop = &si->property[uiProperty];
+ if( prop->vt != type )
+ goto end;
- switch( var.vt )
+ switch( type )
{
+ case VT_I2:
+ if( piValue )
+ *piValue = prop->u.iVal;
+ break;
case VT_I4:
if( piValue )
- *piValue = var.u.lVal;
+ *piValue = prop->u.lVal;
break;
case VT_LPSTR:
- if( pcchValueBuf && szValueBuf )
+ if( pcchValueBuf )
{
- lstrcpynA(szValueBuf, var.u.pszVal, *pcchValueBuf );
- *pcchValueBuf = lstrlenA( var.u.pszVal );
+ 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, &var.u.filetime, sizeof (FILETIME) );
+ memcpy(pftValue, &prop->u.filetime, sizeof (FILETIME) );
break;
case VT_EMPTY:
break;
@@ -217,93 +574,165 @@ UINT WINAPI MsiSummaryInfoGetPropertyA(
FIXME("Unknown property variant type\n");
break;
}
-
end:
- msiobj_release( &suminfo->hdr );
- return rc;
+ msiobj_release( &si->hdr );
+ return ERROR_SUCCESS;
+}
+
+UINT WINAPI MsiSummaryInfoGetPropertyA(
+ MSIHANDLE handle, UINT uiProperty, UINT *puiDataType, INT *piValue,
+ FILETIME *pftValue, LPSTR szValueBuf, DWORD *pcchValueBuf)
+{
+ awstring str;
+
+ TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType,
+ piValue, pftValue, szValueBuf, pcchValueBuf );
+
+ str.unicode = FALSE;
+ str.str.a = szValueBuf;
+
+ 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;
-
- TRACE("%ld %d %p %p %p %p %p\n",
- hSummaryInfo, uiProperty, puiDataType, piValue,
- pftValue, szValueBuf, pcchValueBuf);
+ awstring str;
+
+ TRACE("%ld %d %p %p %p %p %p\n", handle, uiProperty, puiDataType,
+ piValue, pftValue, szValueBuf, pcchValueBuf );
+
+ 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;
- suminfo = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
- if( !suminfo )
+ 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;
}
More information about the wine-patches
mailing list