From 7d677fc3271367c4c9f8dfab012eb5ad5020368b Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Thu, 30 Jun 2011 12:15:37 +0200 Subject: [PATCH] msi: Delay creating local installer and patch packages until the product is registered. --- dlls/msi/action.c | 44 ++++++++++++++++---- dlls/msi/database.c | 5 --- dlls/msi/msipriv.h | 4 +- dlls/msi/package.c | 97 +++++++-------------------------------------- dlls/msi/patch.c | 71 ++++++++++++++++++++++++++++----- 5 files changed, 113 insertions(+), 108 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 4671f3e1402..9070b7630fd 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -4088,13 +4088,18 @@ static UINT msi_publish_patches( MSIPACKAGE *package ) if (r != ERROR_SUCCESS) goto done; - res = RegSetValueExW( patch_key, szLocalPackage, 0, REG_SZ, - (const BYTE *)patch->localfile, - (strlenW(patch->localfile) + 1) * sizeof(WCHAR) ); + res = RegSetValueExW( patch_key, szLocalPackage, 0, REG_SZ, (const BYTE *)patch->localfile, + (strlenW( patch->localfile ) + 1) * sizeof(WCHAR) ); RegCloseKey( patch_key ); if (res != ERROR_SUCCESS) goto done; + if (patch->filename && !CopyFileW( patch->filename, patch->localfile, FALSE )) + { + res = GetLastError(); + ERR("Unable to copy patch package %d\n", res); + goto done; + } res = RegCreateKeyExW( product_patches_key, patch_squashed, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &patch_key, NULL ); if (res != ERROR_SUCCESS) goto done; @@ -4898,14 +4903,22 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) return rc; - rc = MSIREG_OpenInstallProps(package->ProductCode, package->Context, - NULL, &props, TRUE); + rc = MSIREG_OpenInstallProps(package->ProductCode, package->Context, NULL, &props, TRUE); if (rc != ERROR_SUCCESS) goto done; - msi_reg_set_val_str( props, INSTALLPROPERTY_LOCALPACKAGEW, package->db->localfile ); - msi_free( package->db->localfile ); - package->db->localfile = NULL; + if (!msi_get_property_int( package->db, szInstalled, 0 )) + { + msi_reg_set_val_str( props, INSTALLPROPERTY_LOCALPACKAGEW, package->localfile ); + if (!CopyFileW( package->PackagePath, package->localfile, FALSE )) + { + rc = GetLastError(); + ERR("Unable to copy package %u\n", rc); + goto done; + } + } + msi_free( package->localfile ); + package->localfile = NULL; rc = msi_publish_install_properties(package, hkey); if (rc != ERROR_SUCCESS) @@ -4986,8 +4999,14 @@ static UINT msi_unpublish_product( MSIPACKAGE *package, const WCHAR *remove ) LIST_FOR_EACH_ENTRY(patch, &package->patches, MSIPATCHINFO, entry) { MSIREG_DeleteUserDataPatchKey(patch->patchcode, package->Context); + /* FIXME: remove local patch package if this is the last product */ } + TRACE("removing local package %s\n", debugstr_w(package->localfile)); + DeleteFileW( package->localfile ); + msi_free( package->localfile ); + package->localfile = NULL; + return ERROR_SUCCESS; } @@ -7435,6 +7454,15 @@ UINT MSI_InstallPackage( MSIPACKAGE *package, LPCWSTR szPackagePath, msi_adjust_privilege_properties( package ); msi_set_context( package ); + if (msi_get_property_int( package->db, szInstalled, 0 )) + { + HKEY hkey; + DeleteFileW( package->localfile ); + msi_free( package->localfile ); + MSIREG_OpenInstallProps( package->ProductCode, package->Context, NULL, &hkey, FALSE ); + package->localfile = msi_reg_get_val_str( hkey, INSTALLPROPERTY_LOCALPACKAGEW ); + RegCloseKey( hkey ); + } if (msi_get_property_int( package->db, szDisableRollback, 0 )) { TRACE("disabling rollback\n"); diff --git a/dlls/msi/database.c b/dlls/msi/database.c index 9b5a89455ad..2c45a7afd62 100644 --- a/dlls/msi/database.c +++ b/dlls/msi/database.c @@ -257,11 +257,6 @@ static VOID MSI_CloseDatabase( MSIOBJECTHDR *arg ) DeleteFileW( db->deletefile ); msi_free( db->deletefile ); } - if (db->localfile) - { - DeleteFileW( db->localfile ); - msi_free( db->localfile ); - } } static HRESULT db_initialize( IStorage *stg, const GUID *clsid ) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index e2fb03e99f0..5a264dff3ef 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -86,7 +86,6 @@ typedef struct tagMSIDATABASE UINT bytes_per_strref; LPWSTR path; LPWSTR deletefile; - LPWSTR localfile; LPCWSTR mode; UINT media_transform_offset; UINT media_transform_disk_id; @@ -172,6 +171,7 @@ typedef struct tagMSIPATCHINFO struct list entry; LPWSTR patchcode; LPWSTR transforms; + LPWSTR filename; LPWSTR localfile; MSIPATCHSTATE state; } MSIPATCHINFO; @@ -383,6 +383,7 @@ typedef struct tagMSIPACKAGE LPWSTR BaseURL; LPWSTR PackagePath; LPWSTR ProductCode; + LPWSTR localfile; UINT CurrentInstallState; msi_dialog *dialog; @@ -770,6 +771,7 @@ extern UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si extern UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) DECLSPEC_HIDDEN; extern UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ) DECLSPEC_HIDDEN; extern UINT msi_apply_patches( MSIPACKAGE *package ) DECLSPEC_HIDDEN; +extern UINT msi_apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code ) DECLSPEC_HIDDEN; /* action internals */ extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR ) DECLSPEC_HIDDEN; diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 1cbb221b2dc..5d6523d906c 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -157,8 +157,6 @@ static void free_package_structures( MSIPACKAGE *package ) INT i; struct list *item, *cursor; - TRACE("Freeing package action data\n"); - LIST_FOR_EACH_SAFE( item, cursor, &package->features ) { MSIFEATURE *feature = LIST_ENTRY( item, MSIFEATURE, entry ); @@ -303,6 +301,7 @@ static void free_package_structures( MSIPACKAGE *package ) msi_free( patch->patchcode ); msi_free( patch->transforms ); msi_free( patch->localfile ); + msi_free( patch->filename ); msi_free( patch ); } @@ -358,6 +357,12 @@ static void MSI_FreePackage( MSIOBJECTHDR *arg) for (i = 0; i < CLR_VERSION_MAX; i++) if (package->cache_net[i]) IAssemblyCache_Release( package->cache_net[i] ); if (package->cache_sxs) IAssemblyCache_Release( package->cache_sxs ); + + if (package->localfile) + { + DeleteFileW( package->localfile ); + msi_free( package->localfile ); + } } static UINT create_temp_property_table(MSIPACKAGE *package) @@ -1291,67 +1296,6 @@ UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix ) return ERROR_SUCCESS; } -static UINT apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code ) -{ - UINT r; - DWORD len; - WCHAR patch_file[MAX_PATH]; - MSIDATABASE *patch_db; - MSIPATCHINFO *patch_info; - MSISUMMARYINFO *si; - - len = sizeof(patch_file) / sizeof(WCHAR); - r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context, - INSTALLPROPERTY_LOCALPACKAGEW, patch_file, &len ); - if (r != ERROR_SUCCESS) - { - ERR("failed to get patch filename %u\n", r); - return r; - } - - r = MSI_OpenDatabaseW( patch_file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db ); - if (r != ERROR_SUCCESS) - { - ERR("failed to open patch database %s\n", debugstr_w( patch_file )); - return r; - } - - si = MSI_GetSummaryInformationW( patch_db->storage, 0 ); - if (!si) - { - msiobj_release( &patch_db->hdr ); - return ERROR_FUNCTION_FAILED; - } - - r = msi_parse_patch_summary( si, &patch_info ); - msiobj_release( &si->hdr ); - if (r != ERROR_SUCCESS) - { - ERR("failed to parse patch summary %u\n", r); - msiobj_release( &patch_db->hdr ); - return r; - } - - patch_info->localfile = strdupW( patch_file ); - if (!patch_info->localfile) - { - msiobj_release( &patch_db->hdr ); - return ERROR_OUTOFMEMORY; - } - - r = msi_apply_patch_db( package, patch_db, patch_info ); - msiobj_release( &patch_db->hdr ); - if (r != ERROR_SUCCESS) - { - ERR("failed to apply patch %u\n", r); - msi_free( patch_info->patchcode ); - msi_free( patch_info->transforms ); - msi_free( patch_info->localfile ); - msi_free( patch_info ); - } - return r; -} - static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package ) { WCHAR *template, *p, *q; @@ -1531,20 +1475,6 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) file = temppath; } - - r = msi_get_local_package_name( localfile, dotmsi ); - if (r != ERROR_SUCCESS) - return r; - - TRACE("Copying to local package %s\n", debugstr_w(localfile)); - - if (!CopyFileW( file, localfile, FALSE )) - { - ERR("Unable to copy package (%s -> %s) (error %u)\n", - debugstr_w(file), debugstr_w(localfile), GetLastError()); - return GetLastError(); - } - TRACE("Opening relocated package %s\n", debugstr_w( file )); /* transforms that add binary streams require that we open the database @@ -1562,10 +1492,12 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) return r; } - - db->localfile = strdupW( localfile ); } + r = msi_get_local_package_name( localfile, dotmsi ); + if (r != ERROR_SUCCESS) + return r; + package = MSI_CreatePackage( db, base_url ); msi_free( base_url ); msiobj_release( &db->hdr ); @@ -1576,9 +1508,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) return ERROR_INSTALL_PACKAGE_INVALID; } - - if( file != szPackage ) - msi_track_tempfile( package, file ); + if (file != szPackage) msi_track_tempfile( package, file ); + package->localfile = strdupW( localfile ); si = MSI_GetSummaryInformationW( db->storage, 0 ); if (!si) @@ -1629,7 +1560,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) TRACE("found registered patch %s\n", debugstr_w(patch_code)); - r = apply_registered_patch( package, patch_code ); + r = msi_apply_registered_patch( package, patch_code ); if (r != ERROR_SUCCESS) { ERR("registered patch failed to apply %u\n", r); diff --git a/dlls/msi/patch.c b/dlls/msi/patch.c index 00281a8d198..a31802ef751 100644 --- a/dlls/msi/patch.c +++ b/dlls/msi/patch.c @@ -630,16 +630,9 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, const WCHAR *file ) if ( r != ERROR_SUCCESS ) goto done; - TRACE("copying to local package %s\n", debugstr_w(localfile)); - - if (!CopyFileW( file, localfile, FALSE )) - { - ERR("Unable to copy package (%s -> %s) (error %u)\n", - debugstr_w(file), debugstr_w(localfile), GetLastError()); - r = GetLastError(); - goto done; - } - patch->localfile = strdupW( localfile ); + r = ERROR_OUTOFMEMORY; + if (!(patch->filename = strdupW( file ))) goto done; + if (!(patch->localfile = strdupW( localfile ))) goto done; r = msi_apply_patch_db( package, patch_db, patch ); if (r != ERROR_SUCCESS) WARN("patch failed to apply %u\n", r); @@ -649,9 +642,9 @@ done: msiobj_release( &patch_db->hdr ); if (patch && r != ERROR_SUCCESS) { - if (patch->localfile) DeleteFileW( patch->localfile ); msi_free( patch->patchcode ); msi_free( patch->transforms ); + msi_free( patch->filename ); msi_free( patch->localfile ); msi_free( patch ); } @@ -717,3 +710,59 @@ UINT msi_apply_transforms( MSIPACKAGE *package ) msi_free( xform_list ); return r; } + +UINT msi_apply_registered_patch( MSIPACKAGE *package, LPCWSTR patch_code ) +{ + UINT r; + DWORD len; + WCHAR patch_file[MAX_PATH]; + MSIDATABASE *patch_db; + MSIPATCHINFO *patch_info; + MSISUMMARYINFO *si; + + len = sizeof(patch_file) / sizeof(WCHAR); + r = MsiGetPatchInfoExW( patch_code, package->ProductCode, NULL, package->Context, + INSTALLPROPERTY_LOCALPACKAGEW, patch_file, &len ); + if (r != ERROR_SUCCESS) + { + ERR("failed to get patch filename %u\n", r); + return r; + } + r = MSI_OpenDatabaseW( patch_file, MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE, &patch_db ); + if (r != ERROR_SUCCESS) + { + ERR("failed to open patch database %s\n", debugstr_w( patch_file )); + return r; + } + si = MSI_GetSummaryInformationW( patch_db->storage, 0 ); + if (!si) + { + msiobj_release( &patch_db->hdr ); + return ERROR_FUNCTION_FAILED; + } + r = msi_parse_patch_summary( si, &patch_info ); + msiobj_release( &si->hdr ); + if (r != ERROR_SUCCESS) + { + ERR("failed to parse patch summary %u\n", r); + msiobj_release( &patch_db->hdr ); + return r; + } + patch_info->localfile = strdupW( patch_file ); + if (!patch_info->localfile) + { + msiobj_release( &patch_db->hdr ); + return ERROR_OUTOFMEMORY; + } + r = msi_apply_patch_db( package, patch_db, patch_info ); + msiobj_release( &patch_db->hdr ); + if (r != ERROR_SUCCESS) + { + ERR("failed to apply patch %u\n", r); + msi_free( patch_info->patchcode ); + msi_free( patch_info->transforms ); + msi_free( patch_info->localfile ); + msi_free( patch_info ); + } + return r; +}