Hans Leidekker : msi: Apply registered patches in MsiOpenPackage.

Alexandre Julliard julliard at winehq.org
Wed May 5 11:08:37 CDT 2010


Module: wine
Branch: master
Commit: 82d7b04c2cbf5fe1a7f8072d9c66d0abc38252c3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=82d7b04c2cbf5fe1a7f8072d9c66d0abc38252c3

Author: Hans Leidekker <hans at 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 );




More information about the wine-cvs mailing list