diff --git a/dlls/msi/action.c b/dlls/msi/action.c index fdb2aff91af..481c5476311 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -490,18 +490,29 @@ static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db if (!si) return ERROR_FUNCTION_FAILED; - msi_check_patch_applicable( package, si ); + if (msi_check_patch_applicable( package, si ) != ERROR_SUCCESS) + { + TRACE("Patch not applicable\n"); + return ERROR_SUCCESS; + } + + package->patch = msi_alloc(sizeof(MSIPATCHINFO)); + if (!package->patch) + return ERROR_OUTOFMEMORY; + + package->patch->patchcode = msi_suminfo_dup_string(si, PID_REVNUMBER); + if (!package->patch->patchcode) + return ERROR_OUTOFMEMORY; /* enumerate the substorage */ str = msi_suminfo_dup_string( si, PID_LASTAUTHOR ); + package->patch->transforms = str; + substorage = msi_split_string( str, ';' ); for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ ) r = msi_apply_substorage_transform( package, patch_db, substorage[i] ); + msi_free( substorage ); - msi_free( str ); - - /* FIXME: parse the sources in PID_REVNUMBER and do something with them... */ - msiobj_release( &si->hdr ); return r; @@ -3568,6 +3579,39 @@ static BOOL msi_check_unpublish(MSIPACKAGE *package) return TRUE; } +static UINT msi_publish_patch(MSIPACKAGE *package, HKEY prodkey, HKEY hudkey) +{ + WCHAR patch_squashed[GUID_SIZE]; + HKEY patches; + LONG res; + UINT r = ERROR_FUNCTION_FAILED; + + static const WCHAR szPatches[] = {'P','a','t','c','h','e','s',0}; + + res = RegCreateKeyExW(prodkey, szPatches, 0, NULL, 0, KEY_ALL_ACCESS, NULL, + &patches, NULL); + if (res != ERROR_SUCCESS) + return ERROR_FUNCTION_FAILED; + + squash_guid(package->patch->patchcode, patch_squashed); + + res = RegSetValueExW(patches, szPatches, 0, REG_MULTI_SZ, + (const BYTE *)patch_squashed, + (lstrlenW(patch_squashed) + 1) * sizeof(WCHAR)); + if (res != ERROR_SUCCESS) + goto done; + + res = RegSetValueExW(patches, patch_squashed, 0, REG_SZ, + (const BYTE *)package->patch->transforms, + (lstrlenW(package->patch->transforms) + 1) * sizeof(WCHAR)); + if (res == ERROR_SUCCESS) + r = ERROR_SUCCESS; + +done: + RegCloseKey(patches); + return r; +} + /* * 99% of the work done here is only done for * advertised installs. However this is where the @@ -3598,6 +3642,13 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) goto end; + if (package->patch) + { + rc = msi_publish_patch(package, hukey, hudkey); + if (rc != ERROR_SUCCESS) + goto end; + } + rc = msi_publish_product_properties(package, hukey); if (rc != ERROR_SUCCESS) goto end; diff --git a/dlls/msi/helpers.c b/dlls/msi/helpers.c index 5c9dfd017ec..ea36b3d5f9c 100644 --- a/dlls/msi/helpers.c +++ b/dlls/msi/helpers.c @@ -661,6 +661,13 @@ void ACTION_free_package_structures( MSIPACKAGE* package) msi_free(package->script); } + if (package->patch) + { + msi_free(package->patch->patchcode); + msi_free(package->patch->transforms); + msi_free(package->patch); + } + msi_free(package->BaseURL); msi_free(package->PackagePath); msi_free(package->ProductCode); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index fe9dbb07667..7c788d40426 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -144,6 +144,12 @@ typedef struct tagMSIMEDIAINFO WCHAR source[MAX_PATH]; } MSIMEDIAINFO; +typedef struct tagMSIPATCHINFO +{ + LPWSTR patchcode; + LPWSTR transforms; +} MSIPATCHINFO; + typedef struct _column_info { LPCWSTR table; @@ -294,6 +300,7 @@ typedef struct tagMSIPACKAGE { MSIOBJECTHDR hdr; MSIDATABASE *db; + MSIPATCHINFO *patch; struct list components; struct list features; struct list files; diff --git a/dlls/msi/package.c b/dlls/msi/package.c index f6ef1993e2b..018389a140c 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -731,6 +731,7 @@ static MSIPACKAGE *msi_alloc_package( void ) list_init( &package->sourcelist_info ); list_init( &package->sourcelist_media ); + package->patch = NULL; package->ActionFormat = NULL; package->LastAction = NULL; package->dialog = NULL;