ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

suminfo.c
Go to the documentation of this file.
00001 /*
00002  * Implementation of the Microsoft Installer (msi.dll)
00003  *
00004  * Copyright 2002, 2005 Mike McCormack for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <stdarg.h>
00022 
00023 #define COBJMACROS
00024 #define NONAMELESSUNION
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winreg.h"
00029 #include "winnls.h"
00030 #include "shlwapi.h"
00031 #include "wine/debug.h"
00032 #include "wine/unicode.h"
00033 #include "msi.h"
00034 #include "msiquery.h"
00035 #include "msidefs.h"
00036 #include "msipriv.h"
00037 #include "objidl.h"
00038 #include "propvarutil.h"
00039 #include "msiserver.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(msi);
00042 
00043 #include "pshpack1.h"
00044 
00045 typedef struct { 
00046     WORD wByteOrder;
00047     WORD wFormat;
00048     DWORD dwOSVer;
00049     CLSID clsID;
00050     DWORD reserved;
00051 } PROPERTYSETHEADER;
00052 
00053 typedef struct { 
00054     FMTID fmtid;
00055     DWORD dwOffset;
00056 } FORMATIDOFFSET;
00057 
00058 typedef struct { 
00059     DWORD cbSection;
00060     DWORD cProperties;
00061 } PROPERTYSECTIONHEADER; 
00062  
00063 typedef struct { 
00064     DWORD propid;
00065     DWORD dwOffset;
00066 } PROPERTYIDOFFSET; 
00067 
00068 typedef struct {
00069     DWORD type;
00070     union {
00071         INT i4;
00072         SHORT i2;
00073         FILETIME ft;
00074         struct {
00075             DWORD len;
00076             BYTE str[1];
00077         } str;
00078     } u;
00079 } PROPERTY_DATA;
00080  
00081 #include "poppack.h"
00082 
00083 static HRESULT (WINAPI *pPropVariantChangeType)
00084     (PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc,
00085      PROPVAR_CHANGE_FLAGS flags, VARTYPE vt);
00086 
00087 #define SECT_HDR_SIZE (sizeof(PROPERTYSECTIONHEADER))
00088 
00089 static void free_prop( PROPVARIANT *prop )
00090 {
00091     if (prop->vt == VT_LPSTR )
00092         msi_free( prop->u.pszVal );
00093     prop->vt = VT_EMPTY;
00094 }
00095 
00096 static void MSI_CloseSummaryInfo( MSIOBJECTHDR *arg )
00097 {
00098     MSISUMMARYINFO *si = (MSISUMMARYINFO *) arg;
00099     DWORD i;
00100 
00101     for( i = 0; i < MSI_MAX_PROPS; i++ )
00102         free_prop( &si->property[i] );
00103     IStorage_Release( si->storage );
00104 }
00105 
00106 static UINT get_type( UINT uiProperty )
00107 {
00108     switch( uiProperty )
00109     {
00110     case PID_CODEPAGE:
00111          return VT_I2;
00112 
00113     case PID_SUBJECT:
00114     case PID_AUTHOR:
00115     case PID_KEYWORDS:
00116     case PID_COMMENTS:
00117     case PID_TEMPLATE:
00118     case PID_LASTAUTHOR:
00119     case PID_REVNUMBER:
00120     case PID_APPNAME:
00121     case PID_TITLE:
00122          return VT_LPSTR;
00123 
00124     case PID_LASTPRINTED:
00125     case PID_CREATE_DTM:
00126     case PID_LASTSAVE_DTM:
00127          return VT_FILETIME;
00128 
00129     case PID_WORDCOUNT:
00130     case PID_CHARCOUNT:
00131     case PID_SECURITY:
00132     case PID_PAGECOUNT:
00133          return VT_I4;
00134     }
00135     return VT_EMPTY;
00136 }
00137 
00138 static UINT get_property_count( const PROPVARIANT *property )
00139 {
00140     UINT i, n = 0;
00141 
00142     if( !property )
00143         return n;
00144     for( i = 0; i < MSI_MAX_PROPS; i++ )
00145         if( property[i].vt != VT_EMPTY )
00146             n++;
00147     return n;
00148 }
00149 
00150 static UINT propvar_changetype(PROPVARIANT *changed, PROPVARIANT *property, VARTYPE vt)
00151 {
00152     HRESULT hr;
00153     HMODULE propsys = LoadLibraryA("propsys.dll");
00154     pPropVariantChangeType = (void *)GetProcAddress(propsys, "PropVariantChangeType");
00155 
00156     if (!pPropVariantChangeType)
00157     {
00158         ERR("PropVariantChangeType function missing!\n");
00159         return ERROR_FUNCTION_FAILED;
00160     }
00161 
00162     hr = pPropVariantChangeType(changed, property, 0, vt);
00163     return (hr == S_OK) ? ERROR_SUCCESS : ERROR_FUNCTION_FAILED;
00164 }
00165 
00166 /* FIXME: doesn't deal with endian conversion */
00167 static void read_properties_from_data( PROPVARIANT *prop, LPBYTE data, DWORD sz )
00168 {
00169     UINT type;
00170     DWORD i, size;
00171     PROPERTY_DATA *propdata;
00172     PROPVARIANT property, *ptr;
00173     PROPVARIANT changed;
00174     PROPERTYIDOFFSET *idofs;
00175     PROPERTYSECTIONHEADER *section_hdr;
00176 
00177     section_hdr = (PROPERTYSECTIONHEADER*) &data[0];
00178     idofs = (PROPERTYIDOFFSET*) &data[SECT_HDR_SIZE];
00179 
00180     /* now set all the properties */
00181     for( i = 0; i < section_hdr->cProperties; i++ )
00182     {
00183         if( idofs[i].propid >= MSI_MAX_PROPS )
00184         {
00185             ERR("Unknown property ID %d\n", idofs[i].propid );
00186             break;
00187         }
00188 
00189         type = get_type( idofs[i].propid );
00190         if( type == VT_EMPTY )
00191         {
00192             ERR("propid %d has unknown type\n", idofs[i].propid);
00193             break;
00194         }
00195 
00196         propdata = (PROPERTY_DATA*) &data[ idofs[i].dwOffset ];
00197 
00198         /* check we don't run off the end of the data */
00199         size = sz - idofs[i].dwOffset - sizeof(DWORD);
00200         if( sizeof(DWORD) > size ||
00201             ( propdata->type == VT_FILETIME && sizeof(FILETIME) > size ) ||
00202             ( propdata->type == VT_LPSTR && (propdata->u.str.len + sizeof(DWORD)) > size ) )
00203         {
00204             ERR("not enough data\n");
00205             break;
00206         }
00207 
00208         property.vt = propdata->type;
00209         if( propdata->type == VT_LPSTR )
00210         {
00211             LPSTR str = msi_alloc( propdata->u.str.len );
00212             memcpy( str, propdata->u.str.str, propdata->u.str.len );
00213             str[ propdata->u.str.len - 1 ] = 0;
00214             property.u.pszVal = str;
00215         }
00216         else if( propdata->type == VT_FILETIME )
00217             property.u.filetime = propdata->u.ft;
00218         else if( propdata->type == VT_I2 )
00219             property.u.iVal = propdata->u.i2;
00220         else if( propdata->type == VT_I4 )
00221             property.u.lVal = propdata->u.i4;
00222 
00223         /* check the type is the same as we expect */
00224         if( type != propdata->type )
00225         {
00226             propvar_changetype(&changed, &property, type);
00227             ptr = &changed;
00228         }
00229         else
00230             ptr = &property;
00231 
00232         prop[ idofs[i].propid ] = *ptr;
00233     }
00234 }
00235 
00236 static UINT load_summary_info( MSISUMMARYINFO *si, IStream *stm )
00237 {
00238     UINT ret = ERROR_FUNCTION_FAILED;
00239     PROPERTYSETHEADER set_hdr;
00240     FORMATIDOFFSET format_hdr;
00241     PROPERTYSECTIONHEADER section_hdr;
00242     LPBYTE data = NULL;
00243     LARGE_INTEGER ofs;
00244     ULONG count, sz;
00245     HRESULT r;
00246 
00247     TRACE("%p %p\n", si, stm);
00248 
00249     /* read the header */
00250     sz = sizeof set_hdr;
00251     r = IStream_Read( stm, &set_hdr, sz, &count );
00252     if( FAILED(r) || count != sz )
00253         return ret;
00254 
00255     if( set_hdr.wByteOrder != 0xfffe )
00256     {
00257         ERR("property set not big-endian %04X\n", set_hdr.wByteOrder);
00258         return ret;
00259     }
00260 
00261     sz = sizeof format_hdr;
00262     r = IStream_Read( stm, &format_hdr, sz, &count );
00263     if( FAILED(r) || count != sz )
00264         return ret;
00265 
00266     /* check the format id is correct */
00267     if( !IsEqualGUID( &FMTID_SummaryInformation, &format_hdr.fmtid ) )
00268         return ret;
00269 
00270     /* seek to the location of the section */
00271     ofs.QuadPart = format_hdr.dwOffset;
00272     r = IStream_Seek( stm, ofs, STREAM_SEEK_SET, NULL );
00273     if( FAILED(r) )
00274         return ret;
00275 
00276     /* read the section itself */
00277     sz = SECT_HDR_SIZE;
00278     r = IStream_Read( stm, &section_hdr, sz, &count );
00279     if( FAILED(r) || count != sz )
00280         return ret;
00281 
00282     if( section_hdr.cProperties > MSI_MAX_PROPS )
00283     {
00284         ERR("too many properties %d\n", section_hdr.cProperties);
00285         return ret;
00286     }
00287 
00288     data = msi_alloc( section_hdr.cbSection);
00289     if( !data )
00290         return ret;
00291 
00292     memcpy( data, &section_hdr, SECT_HDR_SIZE );
00293 
00294     /* read all the data in one go */
00295     sz = section_hdr.cbSection - SECT_HDR_SIZE;
00296     r = IStream_Read( stm, &data[ SECT_HDR_SIZE ], sz, &count );
00297     if( SUCCEEDED(r) && count == sz )
00298         read_properties_from_data( si->property, data, sz + SECT_HDR_SIZE );
00299     else
00300         ERR("failed to read properties %d %d\n", count, sz);
00301 
00302     msi_free( data );
00303     return ret;
00304 }
00305 
00306 static DWORD write_dword( LPBYTE data, DWORD ofs, DWORD val )
00307 {
00308     if( data )
00309     {
00310         data[ofs++] = val&0xff;
00311         data[ofs++] = (val>>8)&0xff;
00312         data[ofs++] = (val>>16)&0xff;
00313         data[ofs++] = (val>>24)&0xff;
00314     }
00315     return 4;
00316 }
00317 
00318 static DWORD write_filetime( LPBYTE data, DWORD ofs, const FILETIME *ft )
00319 {
00320     write_dword( data, ofs, ft->dwLowDateTime );
00321     write_dword( data, ofs + 4, ft->dwHighDateTime );
00322     return 8;
00323 }
00324 
00325 static DWORD write_string( LPBYTE data, DWORD ofs, LPCSTR str )
00326 {
00327     DWORD len = lstrlenA( str ) + 1;
00328     write_dword( data, ofs, len );
00329     if( data )
00330         memcpy( &data[ofs + 4], str, len );
00331     return (7 + len) & ~3;
00332 }
00333 
00334 static UINT write_property_to_data( const PROPVARIANT *prop, LPBYTE data )
00335 {
00336     DWORD sz = 0;
00337 
00338     if( prop->vt == VT_EMPTY )
00339         return sz;
00340 
00341     /* add the type */
00342     sz += write_dword( data, sz, prop->vt );
00343     switch( prop->vt )
00344     {
00345     case VT_I2:
00346         sz += write_dword( data, sz, prop->u.iVal );
00347         break;
00348     case VT_I4:
00349         sz += write_dword( data, sz, prop->u.lVal );
00350         break;
00351     case VT_FILETIME:
00352         sz += write_filetime( data, sz, &prop->u.filetime );
00353         break;
00354     case VT_LPSTR:
00355         sz += write_string( data, sz, prop->u.pszVal );
00356         break;
00357     }
00358     return sz;
00359 }
00360 
00361 static UINT save_summary_info( const MSISUMMARYINFO * si, IStream *stm )
00362 {
00363     UINT ret = ERROR_FUNCTION_FAILED;
00364     PROPERTYSETHEADER set_hdr;
00365     FORMATIDOFFSET format_hdr;
00366     PROPERTYSECTIONHEADER section_hdr;
00367     PROPERTYIDOFFSET idofs[MSI_MAX_PROPS];
00368     LPBYTE data = NULL;
00369     ULONG count, sz;
00370     HRESULT r;
00371     int i;
00372 
00373     /* write the header */
00374     sz = sizeof set_hdr;
00375     memset( &set_hdr, 0, sz );
00376     set_hdr.wByteOrder = 0xfffe;
00377     set_hdr.wFormat = 0;
00378     set_hdr.dwOSVer = 0x00020005; /* build 5, platform id 2 */
00379     /* set_hdr.clsID is {00000000-0000-0000-0000-000000000000} */
00380     set_hdr.reserved = 1;
00381     r = IStream_Write( stm, &set_hdr, sz, &count );
00382     if( FAILED(r) || count != sz )
00383         return ret;
00384 
00385     /* write the format header */
00386     sz = sizeof format_hdr;
00387     format_hdr.fmtid = FMTID_SummaryInformation;
00388     format_hdr.dwOffset = sizeof format_hdr + sizeof set_hdr;
00389     r = IStream_Write( stm, &format_hdr, sz, &count );
00390     if( FAILED(r) || count != sz )
00391         return ret;
00392 
00393     /* add up how much space the data will take and calculate the offsets */
00394     section_hdr.cbSection = sizeof section_hdr;
00395     section_hdr.cbSection += (get_property_count( si->property ) * sizeof idofs[0]);
00396     section_hdr.cProperties = 0;
00397     for( i = 0; i < MSI_MAX_PROPS; i++ )
00398     {
00399         sz = write_property_to_data( &si->property[i], NULL );
00400         if( !sz )
00401             continue;
00402         idofs[ section_hdr.cProperties ].propid = i;
00403         idofs[ section_hdr.cProperties ].dwOffset = section_hdr.cbSection;
00404         section_hdr.cProperties++;
00405         section_hdr.cbSection += sz;
00406     }
00407 
00408     data = msi_alloc_zero( section_hdr.cbSection );
00409 
00410     sz = 0;
00411     memcpy( &data[sz], &section_hdr, sizeof section_hdr );
00412     sz += sizeof section_hdr;
00413 
00414     memcpy( &data[sz], idofs, section_hdr.cProperties * sizeof idofs[0] );
00415     sz += section_hdr.cProperties * sizeof idofs[0];
00416 
00417     /* write out the data */
00418     for( i = 0; i < MSI_MAX_PROPS; i++ )
00419         sz += write_property_to_data( &si->property[i], &data[sz] );
00420 
00421     r = IStream_Write( stm, data, sz, &count );
00422     msi_free( data );
00423     if( FAILED(r) || count != sz )
00424         return ret;
00425 
00426     return ERROR_SUCCESS;
00427 }
00428 
00429 MSISUMMARYINFO *MSI_GetSummaryInformationW( IStorage *stg, UINT uiUpdateCount )
00430 {
00431     IStream *stm = NULL;
00432     MSISUMMARYINFO *si;
00433     DWORD grfMode;
00434     HRESULT r;
00435 
00436     TRACE("%p %d\n", stg, uiUpdateCount );
00437 
00438     si = alloc_msiobject( MSIHANDLETYPE_SUMMARYINFO, 
00439                   sizeof (MSISUMMARYINFO), MSI_CloseSummaryInfo );
00440     if( !si )
00441         return si;
00442 
00443     si->update_count = uiUpdateCount;
00444     IStorage_AddRef( stg );
00445     si->storage = stg;
00446 
00447     /* read the stream... if we fail, we'll start with an empty property set */
00448     grfMode = STGM_READ | STGM_SHARE_EXCLUSIVE;
00449     r = IStorage_OpenStream( si->storage, szSumInfo, 0, grfMode, 0, &stm );
00450     if( SUCCEEDED(r) )
00451     {
00452         load_summary_info( si, stm );
00453         IStream_Release( stm );
00454     }
00455 
00456     return si;
00457 }
00458 
00459 UINT WINAPI MsiGetSummaryInformationW( MSIHANDLE hDatabase, 
00460               LPCWSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle )
00461 {
00462     MSISUMMARYINFO *si;
00463     MSIDATABASE *db;
00464     UINT ret = ERROR_FUNCTION_FAILED;
00465 
00466     TRACE("%d %s %d %p\n", hDatabase, debugstr_w(szDatabase),
00467            uiUpdateCount, pHandle);
00468 
00469     if( !pHandle )
00470         return ERROR_INVALID_PARAMETER;
00471 
00472     if( szDatabase && szDatabase[0] )
00473     {
00474         LPCWSTR persist = uiUpdateCount ? MSIDBOPEN_TRANSACT : MSIDBOPEN_READONLY;
00475 
00476         ret = MSI_OpenDatabaseW( szDatabase, persist, &db );
00477         if( ret != ERROR_SUCCESS )
00478             return ret;
00479     }
00480     else
00481     {
00482         db = msihandle2msiinfo( hDatabase, MSIHANDLETYPE_DATABASE );
00483         if( !db )
00484         {
00485             HRESULT hr;
00486             IWineMsiRemoteDatabase *remote_database;
00487 
00488             remote_database = (IWineMsiRemoteDatabase *)msi_get_remote( hDatabase );
00489             if ( !remote_database )
00490                 return ERROR_INVALID_HANDLE;
00491 
00492             hr = IWineMsiRemoteDatabase_GetSummaryInformation( remote_database,
00493                                                                uiUpdateCount, pHandle );
00494             IWineMsiRemoteDatabase_Release( remote_database );
00495 
00496             if (FAILED(hr))
00497             {
00498                 if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
00499                     return HRESULT_CODE(hr);
00500 
00501                 return ERROR_FUNCTION_FAILED;
00502             }
00503 
00504             return ERROR_SUCCESS;
00505         }
00506     }
00507 
00508     si = MSI_GetSummaryInformationW( db->storage, uiUpdateCount );
00509     if (si)
00510     {
00511         *pHandle = alloc_msihandle( &si->hdr );
00512         if( *pHandle )
00513             ret = ERROR_SUCCESS;
00514         else
00515             ret = ERROR_NOT_ENOUGH_MEMORY;
00516         msiobj_release( &si->hdr );
00517     }
00518 
00519     msiobj_release( &db->hdr );
00520     return ret;
00521 }
00522 
00523 UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, 
00524               LPCSTR szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
00525 {
00526     LPWSTR szwDatabase = NULL;
00527     UINT ret;
00528 
00529     TRACE("%d %s %d %p\n", hDatabase, debugstr_a(szDatabase),
00530           uiUpdateCount, pHandle);
00531 
00532     if( szDatabase )
00533     {
00534         szwDatabase = strdupAtoW( szDatabase );
00535         if( !szwDatabase )
00536             return ERROR_FUNCTION_FAILED;
00537     }
00538 
00539     ret = MsiGetSummaryInformationW(hDatabase, szwDatabase, uiUpdateCount, pHandle);
00540 
00541     msi_free( szwDatabase );
00542 
00543     return ret;
00544 }
00545 
00546 UINT WINAPI MsiSummaryInfoGetPropertyCount(MSIHANDLE hSummaryInfo, PUINT pCount)
00547 {
00548     MSISUMMARYINFO *si;
00549 
00550     TRACE("%d %p\n", hSummaryInfo, pCount);
00551 
00552     si = msihandle2msiinfo( hSummaryInfo, MSIHANDLETYPE_SUMMARYINFO );
00553     if( !si )
00554         return ERROR_INVALID_HANDLE;
00555 
00556     if( pCount )
00557         *pCount = get_property_count( si->property );
00558     msiobj_release( &si->hdr );
00559 
00560     return ERROR_SUCCESS;
00561 }
00562 
00563 static UINT get_prop( MSIHANDLE handle, UINT uiProperty, UINT *puiDataType,
00564           INT *piValue, FILETIME *pftValue, awstring *str, DWORD *pcchValueBuf)
00565 {
00566     MSISUMMARYINFO *si;
00567     PROPVARIANT *prop;
00568     UINT ret = ERROR_SUCCESS;
00569 
00570     TRACE("%d %d %p %p %p %p %p\n", handle, uiProperty, puiDataType,
00571           piValue, pftValue, str, pcchValueBuf);
00572 
00573     if ( uiProperty >= MSI_MAX_PROPS )
00574     {
00575         if (puiDataType) *puiDataType = VT_EMPTY;
00576         return ERROR_UNKNOWN_PROPERTY;
00577     }
00578 
00579     si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
00580     if( !si )
00581         return ERROR_INVALID_HANDLE;
00582 
00583     prop = &si->property[uiProperty];
00584 
00585     if( puiDataType )
00586         *puiDataType = prop->vt;
00587 
00588     switch( prop->vt )
00589     {
00590     case VT_I2:
00591         if( piValue )
00592             *piValue = prop->u.iVal;
00593         break;
00594     case VT_I4:
00595         if( piValue )
00596             *piValue = prop->u.lVal;
00597         break;
00598     case VT_LPSTR:
00599         if( pcchValueBuf )
00600         {
00601             DWORD len = 0;
00602 
00603             if( str->unicode )
00604             {
00605                 len = MultiByteToWideChar( CP_ACP, 0, prop->u.pszVal, -1, NULL, 0 ) - 1;
00606                 MultiByteToWideChar( CP_ACP, 0, prop->u.pszVal, -1, str->str.w, *pcchValueBuf );
00607             }
00608             else
00609             {
00610                 len = lstrlenA( prop->u.pszVal );
00611                 if( str->str.a )
00612                     lstrcpynA(str->str.a, prop->u.pszVal, *pcchValueBuf );
00613             }
00614             if (len >= *pcchValueBuf)
00615                 ret = ERROR_MORE_DATA;
00616             *pcchValueBuf = len;
00617         }
00618         break;
00619     case VT_FILETIME:
00620         if( pftValue )
00621             *pftValue = prop->u.filetime;
00622         break;
00623     case VT_EMPTY:
00624         break;
00625     default:
00626         FIXME("Unknown property variant type\n");
00627         break;
00628     }
00629     msiobj_release( &si->hdr );
00630     return ret;
00631 }
00632 
00633 LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty )
00634 {
00635     PROPVARIANT *prop;
00636 
00637     if ( uiProperty >= MSI_MAX_PROPS )
00638         return NULL;
00639     prop = &si->property[uiProperty];
00640     if( prop->vt != VT_LPSTR )
00641         return NULL;
00642     return strdupAtoW( prop->u.pszVal );
00643 }
00644 
00645 INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty )
00646 {
00647     PROPVARIANT *prop;
00648 
00649     if ( uiProperty >= MSI_MAX_PROPS )
00650         return -1;
00651     prop = &si->property[uiProperty];
00652     if( prop->vt != VT_I4 )
00653         return -1;
00654     return prop->u.lVal;
00655 }
00656 
00657 LPWSTR msi_get_suminfo_product( IStorage *stg )
00658 {
00659     MSISUMMARYINFO *si;
00660     LPWSTR prod;
00661 
00662     si = MSI_GetSummaryInformationW( stg, 0 );
00663     if (!si)
00664     {
00665         ERR("no summary information!\n");
00666         return NULL;
00667     }
00668     prod = msi_suminfo_dup_string( si, PID_REVNUMBER );
00669     msiobj_release( &si->hdr );
00670     return prod;
00671 }
00672 
00673 UINT WINAPI MsiSummaryInfoGetPropertyA(
00674       MSIHANDLE handle, UINT uiProperty, PUINT puiDataType, LPINT piValue,
00675       FILETIME *pftValue, LPSTR szValueBuf, LPDWORD pcchValueBuf)
00676 {
00677     awstring str;
00678 
00679     TRACE("%d %d %p %p %p %p %p\n", handle, uiProperty, puiDataType,
00680           piValue, pftValue, szValueBuf, pcchValueBuf );
00681 
00682     str.unicode = FALSE;
00683     str.str.a = szValueBuf;
00684 
00685     return get_prop( handle, uiProperty, puiDataType, piValue,
00686                      pftValue, &str, pcchValueBuf );
00687 }
00688 
00689 UINT WINAPI MsiSummaryInfoGetPropertyW(
00690       MSIHANDLE handle, UINT uiProperty, PUINT puiDataType, LPINT piValue,
00691       FILETIME *pftValue, LPWSTR szValueBuf, LPDWORD pcchValueBuf)
00692 {
00693     awstring str;
00694 
00695     TRACE("%d %d %p %p %p %p %p\n", handle, uiProperty, puiDataType,
00696           piValue, pftValue, szValueBuf, pcchValueBuf );
00697 
00698     str.unicode = TRUE;
00699     str.str.w = szValueBuf;
00700 
00701     return get_prop( handle, uiProperty, puiDataType, piValue,
00702                      pftValue, &str, pcchValueBuf );
00703 }
00704 
00705 static UINT set_prop( MSISUMMARYINFO *si, UINT uiProperty, UINT type,
00706                INT iValue, FILETIME* pftValue, awcstring *str )
00707 {
00708     PROPVARIANT *prop;
00709     UINT len;
00710 
00711     TRACE("%p %u %u %i %p %p\n", si, uiProperty, type, iValue,
00712           pftValue, str );
00713 
00714     prop = &si->property[uiProperty];
00715 
00716     if( prop->vt == VT_EMPTY )
00717     {
00718         if( !si->update_count )
00719             return ERROR_FUNCTION_FAILED;
00720 
00721         si->update_count--;
00722     }
00723     else if( prop->vt != type )
00724         return ERROR_SUCCESS;
00725 
00726     free_prop( prop );
00727     prop->vt = type;
00728     switch( type )
00729     {
00730     case VT_I4:
00731         prop->u.lVal = iValue;
00732         break;
00733     case VT_I2:
00734         prop->u.iVal = iValue;
00735         break;
00736     case VT_FILETIME:
00737         prop->u.filetime = *pftValue;
00738         break;
00739     case VT_LPSTR:
00740         if( str->unicode )
00741         {
00742             len = WideCharToMultiByte( CP_ACP, 0, str->str.w, -1,
00743                                        NULL, 0, NULL, NULL );
00744             prop->u.pszVal = msi_alloc( len );
00745             WideCharToMultiByte( CP_ACP, 0, str->str.w, -1,
00746                                  prop->u.pszVal, len, NULL, NULL );
00747         }
00748         else
00749         {
00750             len = lstrlenA( str->str.a ) + 1;
00751             prop->u.pszVal = msi_alloc( len );
00752             lstrcpyA( prop->u.pszVal, str->str.a );
00753         }
00754         break;
00755     }
00756 
00757     return ERROR_SUCCESS;
00758 }
00759 
00760 UINT WINAPI MsiSummaryInfoSetPropertyW( MSIHANDLE handle, UINT uiProperty,
00761                UINT uiDataType, INT iValue, FILETIME* pftValue, LPCWSTR szValue )
00762 {
00763     awcstring str;
00764     MSISUMMARYINFO *si;
00765     UINT type, ret;
00766 
00767     TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType,
00768           iValue, pftValue, debugstr_w(szValue) );
00769 
00770     type = get_type( uiProperty );
00771     if( type == VT_EMPTY || type != uiDataType )
00772         return ERROR_DATATYPE_MISMATCH;
00773 
00774     if( uiDataType == VT_LPSTR && !szValue )
00775         return ERROR_INVALID_PARAMETER;
00776 
00777     if( uiDataType == VT_FILETIME && !pftValue )
00778         return ERROR_INVALID_PARAMETER;
00779 
00780     si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
00781     if( !si )
00782         return ERROR_INVALID_HANDLE;
00783 
00784     str.unicode = TRUE;
00785     str.str.w = szValue;
00786     ret = set_prop( si, uiProperty, type, iValue, pftValue, &str );
00787 
00788     msiobj_release( &si->hdr );
00789     return ret;
00790 }
00791 
00792 UINT WINAPI MsiSummaryInfoSetPropertyA( MSIHANDLE handle, UINT uiProperty,
00793                UINT uiDataType, INT iValue, FILETIME* pftValue, LPCSTR szValue )
00794 {
00795     awcstring str;
00796     MSISUMMARYINFO *si;
00797     UINT type, ret;
00798 
00799     TRACE("%d %u %u %i %p %s\n", handle, uiProperty, uiDataType,
00800           iValue, pftValue, debugstr_a(szValue) );
00801 
00802     type = get_type( uiProperty );
00803     if( type == VT_EMPTY || type != uiDataType )
00804         return ERROR_DATATYPE_MISMATCH;
00805 
00806     if( uiDataType == VT_LPSTR && !szValue )
00807         return ERROR_INVALID_PARAMETER;
00808 
00809     if( uiDataType == VT_FILETIME && !pftValue )
00810         return ERROR_INVALID_PARAMETER;
00811 
00812     si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
00813     if( !si )
00814         return ERROR_INVALID_HANDLE;
00815 
00816     str.unicode = FALSE;
00817     str.str.a = szValue;
00818     ret = set_prop( si, uiProperty, uiDataType, iValue, pftValue, &str );
00819 
00820     msiobj_release( &si->hdr );
00821     return ret;
00822 }
00823 
00824 static UINT suminfo_persist( MSISUMMARYINFO *si )
00825 {
00826     UINT ret = ERROR_FUNCTION_FAILED;
00827     IStream *stm = NULL;
00828     DWORD grfMode;
00829     HRESULT r;
00830 
00831     grfMode = STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
00832     r = IStorage_CreateStream( si->storage, szSumInfo, grfMode, 0, 0, &stm );
00833     if( SUCCEEDED(r) )
00834     {
00835         ret = save_summary_info( si, stm );
00836         IStream_Release( stm );
00837     }
00838     return ret;
00839 }
00840 
00841 static void parse_filetime( LPCWSTR str, FILETIME *ft )
00842 {
00843     SYSTEMTIME lt, utc;
00844     const WCHAR *p = str;
00845     WCHAR *end;
00846 
00847     memset( &lt, 0, sizeof(lt) );
00848 
00849     /* YYYY/MM/DD hh:mm:ss */
00850 
00851     while (isspaceW( *p )) p++;
00852 
00853     lt.wYear = strtolW( p, &end, 10 );
00854     if (*end != '/') return;
00855     p = end + 1;
00856 
00857     lt.wMonth = strtolW( p, &end, 10 );
00858     if (*end != '/') return;
00859     p = end + 1;
00860 
00861     lt.wDay = strtolW( p, &end, 10 );
00862     if (*end != ' ') return;
00863     p = end + 1;
00864 
00865     while (isspaceW( *p )) p++;
00866 
00867     lt.wHour = strtolW( p, &end, 10 );
00868     if (*end != ':') return;
00869     p = end + 1;
00870 
00871     lt.wMinute = strtolW( p, &end, 10 );
00872     if (*end != ':') return;
00873     p = end + 1;
00874 
00875     lt.wSecond = strtolW( p, &end, 10 );
00876 
00877     TzSpecificLocalTimeToSystemTime( NULL, &lt, &utc );
00878     SystemTimeToFileTime( &utc, ft );
00879 }
00880 
00881 static UINT parse_prop( LPCWSTR prop, LPCWSTR value, UINT *pid, INT *int_value,
00882                         FILETIME *ft_value, awcstring *str_value )
00883 {
00884     *pid = atoiW( prop );
00885     switch (*pid)
00886     {
00887     case PID_CODEPAGE:
00888     case PID_WORDCOUNT:
00889     case PID_CHARCOUNT:
00890     case PID_SECURITY:
00891     case PID_PAGECOUNT:
00892         *int_value = atoiW( value );
00893         break;
00894 
00895     case PID_LASTPRINTED:
00896     case PID_CREATE_DTM:
00897     case PID_LASTSAVE_DTM:
00898         parse_filetime( value, ft_value );
00899         break;
00900 
00901     case PID_SUBJECT:
00902     case PID_AUTHOR:
00903     case PID_KEYWORDS:
00904     case PID_COMMENTS:
00905     case PID_TEMPLATE:
00906     case PID_LASTAUTHOR:
00907     case PID_REVNUMBER:
00908     case PID_APPNAME:
00909     case PID_TITLE:
00910         str_value->str.w = value;
00911         str_value->unicode = TRUE;
00912         break;
00913 
00914     default:
00915         WARN("unhandled prop id %u\n", *pid);
00916         return ERROR_FUNCTION_FAILED;
00917     }
00918 
00919     return ERROR_SUCCESS;
00920 }
00921 
00922 UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns )
00923 {
00924     UINT r = ERROR_FUNCTION_FAILED;
00925     DWORD i, j;
00926     MSISUMMARYINFO *si;
00927 
00928     si = MSI_GetSummaryInformationW( db->storage, num_records * (num_columns / 2) );
00929     if (!si)
00930     {
00931         ERR("no summary information!\n");
00932         return ERROR_FUNCTION_FAILED;
00933     }
00934 
00935     for (i = 0; i < num_records; i++)
00936     {
00937         for (j = 0; j < num_columns; j += 2)
00938         {
00939             UINT pid;
00940             INT int_value = 0;
00941             FILETIME ft_value;
00942             awcstring str_value;
00943 
00944             r = parse_prop( records[i][j], records[i][j + 1], &pid, &int_value, &ft_value, &str_value );
00945             if (r != ERROR_SUCCESS)
00946                 goto end;
00947 
00948             r = set_prop( si, pid, get_type(pid), int_value, &ft_value, &str_value );
00949             if (r != ERROR_SUCCESS)
00950                 goto end;
00951         }
00952     }
00953 
00954 end:
00955     if (r == ERROR_SUCCESS)
00956         r = suminfo_persist( si );
00957 
00958     msiobj_release( &si->hdr );
00959     return r;
00960 }
00961 
00962 UINT WINAPI MsiSummaryInfoPersist( MSIHANDLE handle )
00963 {
00964     MSISUMMARYINFO *si;
00965     UINT ret;
00966 
00967     TRACE("%d\n", handle );
00968 
00969     si = msihandle2msiinfo( handle, MSIHANDLETYPE_SUMMARYINFO );
00970     if( !si )
00971         return ERROR_INVALID_HANDLE;
00972 
00973     ret = suminfo_persist( si );
00974 
00975     msiobj_release( &si->hdr );
00976     return ret;
00977 }
00978 
00979 UINT WINAPI MsiCreateTransformSummaryInfoA( MSIHANDLE db, MSIHANDLE db_ref, LPCSTR transform, int error, int validation )
00980 {
00981     UINT r;
00982     WCHAR *transformW = NULL;
00983 
00984     TRACE("%u, %u, %s, %d, %d\n", db, db_ref, debugstr_a(transform), error, validation);
00985 
00986     if (transform && !(transformW = strdupAtoW( transform )))
00987         return ERROR_OUTOFMEMORY;
00988 
00989     r = MsiCreateTransformSummaryInfoW( db, db_ref, transformW, error, validation );
00990     msi_free( transformW );
00991     return r;
00992 }
00993 
00994 UINT WINAPI MsiCreateTransformSummaryInfoW( MSIHANDLE db, MSIHANDLE db_ref, LPCWSTR transform, int error, int validation )
00995 {
00996     FIXME("%u, %u, %s, %d, %d\n", db, db_ref, debugstr_w(transform), error, validation);
00997     return ERROR_FUNCTION_FAILED;
00998 }

Generated on Sat May 26 2012 04:23:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.