Hans Leidekker : msi: Apply registered patches in MsiOpenPackage.
Module: wine Branch: master Commit: 82d7b04c2cbf5fe1a7f8072d9c66d0abc38252c3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=82d7b04c2cbf5fe1a7f8072d9c... Author: Hans Leidekker <hans(a)codeweavers.com> Date: Wed May 5 14:37:55 2010 +0200 msi: Apply registered patches in MsiOpenPackage. --- dlls/msi/action.c | 53 ++++++++++++++++++------------ dlls/msi/msipriv.h | 4 ++ dlls/msi/package.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++- dlls/msi/tests/patch.c | 8 ++-- 4 files changed, 120 insertions(+), 27 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 35030e2..6ed1417 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -492,7 +492,7 @@ done: return r; } -static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) +UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) { MSIPATCHINFO *pi; UINT r = ERROR_SUCCESS; @@ -520,15 +520,40 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ) return r; } +UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ) +{ + UINT i, r = ERROR_SUCCESS; + WCHAR **substorage; + + /* apply substorage transforms */ + substorage = msi_split_string( patch->transforms, ';' ); + for (i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++) + r = msi_apply_substorage_transform( package, patch_db, substorage[i] ); + + msi_free( substorage ); + if (r != ERROR_SUCCESS) + return r; + + msi_set_media_source_prop( package ); + + /* + * There might be a CAB file in the patch package, + * so append it to the list of storages to search for streams. + */ + append_storage_to_db( package->db, patch_db->storage ); + + list_add_tail( &package->patches, &patch->entry ); + return ERROR_SUCCESS; +} + static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) { static const WCHAR dotmsp[] = {'.','m','s','p',0}; MSIDATABASE *patch_db = NULL; WCHAR localfile[MAX_PATH]; - LPWSTR *substorage; MSISUMMARYINFO *si; MSIPATCHINFO *patch = NULL; - UINT i, r = ERROR_SUCCESS; + UINT r = ERROR_SUCCESS; TRACE("%p %s\n", package, debugstr_w( file ) ); @@ -573,23 +598,9 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file ) } patch->localfile = strdupW( localfile ); - /* apply substorage transforms */ - substorage = msi_split_string( patch->transforms, ';' ); - for ( i = 0; substorage && substorage[i] && r == ERROR_SUCCESS; i++ ) - r = msi_apply_substorage_transform( package, patch_db, substorage[i] ); - - msi_free( substorage ); - if (r != ERROR_SUCCESS) - goto done; - msi_set_media_source_prop( package ); - - /* - * There might be a CAB file in the patch package, - * so append it to the list of storages to search for streams. - */ - append_storage_to_db( package->db, patch_db->storage ); - - list_add_tail( &package->patches, &patch->entry ); + r = msi_apply_patch_db( package, patch_db, patch ); + if ( r != ERROR_SUCCESS ) + WARN("patch failed to apply %u\n", r); done: msiobj_release( &si->hdr ); @@ -729,7 +740,7 @@ static BOOL needs_ui_sequence(MSIPACKAGE *package) return (level & INSTALLUILEVEL_MASK) >= INSTALLUILEVEL_REDUCED; } -static UINT msi_set_context(MSIPACKAGE *package) +UINT msi_set_context(MSIPACKAGE *package) { int num; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 354aca5..a8737a2 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -685,7 +685,10 @@ extern UINT MSI_DatabaseApplyTransformW( MSIDATABASE *db, LPCWSTR szTransformFile, int iErrorCond ); extern void append_storage_to_db( MSIDATABASE *db, IStorage *stg ); +/* patch functions */ extern UINT msi_check_patch_applicable( MSIPACKAGE *package, MSISUMMARYINFO *si ); +extern UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch ); +extern UINT msi_apply_patch_db( MSIPACKAGE *package, MSIDATABASE *patch_db, MSIPATCHINFO *patch ); /* action internals */ extern UINT MSI_InstallPackage( MSIPACKAGE *, LPCWSTR, LPCWSTR ); @@ -758,6 +761,7 @@ extern UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename ); extern UINT msi_package_add_info(MSIPACKAGE *, DWORD, DWORD, LPCWSTR, LPWSTR); extern UINT msi_package_add_media_disk(MSIPACKAGE *, DWORD, DWORD, DWORD, LPWSTR, LPWSTR); extern UINT msi_clone_properties(MSIPACKAGE *); +extern UINT msi_set_context(MSIPACKAGE *); extern UINT MSI_GetFeatureCost(MSIPACKAGE *, MSIFEATURE *, MSICOSTTREE, INSTALLSTATE, LPINT); /* for deformating */ diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 2ffd66e..e53de53 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -1048,6 +1048,8 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) msi_clone_properties( package ); package->ProductCode = msi_dup_property( package->db, szProductCode ); + package->script = msi_alloc_zero( sizeof(MSISCRIPT) ); + set_installed_prop( package ); set_installer_properties( package ); @@ -1167,6 +1169,60 @@ 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; + } + + 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; +} + UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) { static const WCHAR OriginalDatabase[] = @@ -1180,6 +1236,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) UINT r; WCHAR temppath[MAX_PATH], localfile[MAX_PATH], cachefile[MAX_PATH]; LPCWSTR file = szPackage; + DWORD index = 0; TRACE("%s %p\n", debugstr_w(szPackage), pPackage); @@ -1293,9 +1350,30 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) msi_set_property( package->db, OriginalDatabase, fullpath ); } - package->script = msi_alloc_zero( sizeof(MSISCRIPT) ); - *pPackage = package; + msi_set_context( package ); + + while (1) + { + WCHAR patch_code[GUID_SIZE]; + r = MsiEnumPatchesExW( package->ProductCode, NULL, package->Context, + MSIPATCHSTATE_APPLIED, index, patch_code, NULL, NULL, NULL, NULL ); + if (r != ERROR_SUCCESS) + break; + + TRACE("found registered patch %s\n", debugstr_w(patch_code)); + r = apply_registered_patch( package, patch_code ); + if (r != ERROR_SUCCESS) + { + ERR("registered patch failed to apply %u\n", r); + MSI_FreePackage( (MSIOBJECTHDR *)package ); + return r; + } + + index++; + } + + *pPackage = package; return ERROR_SUCCESS; } diff --git a/dlls/msi/tests/patch.c b/dlls/msi/tests/patch.c index e386925..2c7459d 100644 --- a/dlls/msi/tests/patch.c +++ b/dlls/msi/tests/patch.c @@ -731,7 +731,7 @@ static void test_simple_patch( void ) ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); r = MsiViewFetch( hview, &hrec ); - todo_wine ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); + ok( r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r ); MsiCloseHandle( hrec ); MsiViewClose( hview ); @@ -942,13 +942,13 @@ static void test_system_tables( void ) ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "MsiPatchHeaders" ); - todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); + ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "Patch" ); - todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); + ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); r = find_entry( hdb, "_Tables", "PatchPackage" ); - todo_wine ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); + ok( r == ERROR_SUCCESS, "failed to find entry %u\n", r ); MsiCloseHandle( hdb ); MsiCloseHandle( hproduct );
participants (1)
-
Alexandre Julliard