Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensuminfo.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, §ion_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, §ion_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], §ion_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( <, 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, <, &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
1.7.6.1
|