Hans Leidekker : msi: Support multiple patches per package.

Alexandre Julliard julliard at winehq.org
Thu Apr 29 14:45:06 CDT 2010


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Thu Apr 29 09:39:22 2010 +0200

msi: Support multiple patches per package.

---

 dlls/msi/action.c  |  111 +++++++++++++++++++++++++++++++++-------------------
 dlls/msi/msipriv.h |    3 +-
 dlls/msi/package.c |   12 ++++--
 3 files changed, 81 insertions(+), 45 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 96dbc3d..5ca786d 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -492,44 +492,31 @@ done:
     return r;
 }
 
-static UINT msi_parse_patch_summary( MSIPACKAGE *package, MSIDATABASE *patch_db )
+static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
 {
-    MSISUMMARYINFO *si;
+    MSIPATCHINFO *pi;
     UINT r = ERROR_SUCCESS;
 
-    si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
-    if (!si)
-        return ERROR_FUNCTION_FAILED;
-
-    if (msi_check_patch_applicable( package, si ) != ERROR_SUCCESS)
-    {
-        TRACE("Patch not applicable\n");
-        msiobj_release( &si->hdr );
-        return ERROR_SUCCESS;
-    }
-
-    package->patch = msi_alloc(sizeof(MSIPATCHINFO));
-    if (!package->patch)
-    {
-        msiobj_release( &si->hdr );
+    pi = msi_alloc( sizeof(MSIPATCHINFO) );
+    if (!pi)
         return ERROR_OUTOFMEMORY;
-    }
 
-    package->patch->patchcode = msi_suminfo_dup_string(si, PID_REVNUMBER);
-    if (!package->patch->patchcode)
+    pi->patchcode = msi_suminfo_dup_string( si, PID_REVNUMBER );
+    if (!pi->patchcode)
     {
-        msiobj_release( &si->hdr );
+        msi_free( pi );
         return ERROR_OUTOFMEMORY;
     }
 
-    package->patch->transforms = msi_suminfo_dup_string(si, PID_LASTAUTHOR);
-    if (!package->patch->transforms)
+    pi->transforms = msi_suminfo_dup_string( si, PID_LASTAUTHOR );
+    if (!pi->transforms)
     {
-        msiobj_release( &si->hdr );
+        msi_free( pi->patchcode );
+        msi_free( pi );
         return ERROR_OUTOFMEMORY;
     }
 
-    msiobj_release( &si->hdr );
+    *patch = pi;
     return r;
 }
 
@@ -537,6 +524,8 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
 {
     MSIDATABASE *patch_db = NULL;
     LPWSTR *substorage;
+    MSISUMMARYINFO *si;
+    MSIPATCHINFO *patch;
     UINT i, r;
 
     TRACE("%p %s\n", package, debugstr_w( file ) );
@@ -548,10 +537,32 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
         return r;
     }
 
-    msi_parse_patch_summary( package, patch_db );
+    si = MSI_GetSummaryInformationW( patch_db->storage, 0 );
+    if (!si)
+    {
+        msiobj_release( &patch_db->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+
+    r = msi_check_patch_applicable( package, si );
+    if (r != ERROR_SUCCESS)
+    {
+        TRACE("patch not applicable\n");
+        msiobj_release( &si->hdr );
+        msiobj_release( &patch_db->hdr );
+        return ERROR_SUCCESS;
+    }
+
+    r = msi_parse_patch_summary( si, &patch );
+    if ( r != ERROR_SUCCESS )
+    {
+        msiobj_release( &si->hdr );
+        msiobj_release( &patch_db->hdr );
+        return r;
+    }
 
     /* apply substorage transforms */
-    substorage = msi_split_string( package->patch->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] );
 
@@ -564,6 +575,9 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
      */
     append_storage_to_db( package->db, patch_db->storage );
 
+    list_add_tail( &package->patches, &patch->entry );
+
+    msiobj_release( &si->hdr );
     msiobj_release( &patch_db->hdr );
 
     return ERROR_SUCCESS;
@@ -3753,34 +3767,51 @@ static BOOL msi_check_unpublish(MSIPACKAGE *package)
     return TRUE;
 }
 
-static UINT msi_publish_patch(MSIPACKAGE *package, HKEY prodkey, HKEY hudkey)
+static UINT msi_publish_patches( MSIPACKAGE *package, HKEY prodkey, HKEY hudkey )
 {
     WCHAR patch_squashed[GUID_SIZE];
     HKEY patches;
     LONG res;
+    MSIPATCHINFO *patch;
     UINT r = ERROR_FUNCTION_FAILED;
+    WCHAR *p, *all_patches = NULL;
+    DWORD len = 0;
 
-    res = RegCreateKeyExW(prodkey, szPatches, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
-                          &patches, NULL);
+    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);
+    LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
+    {
+        squash_guid( patch->patchcode, patch_squashed );
+        len += strlenW( patch_squashed ) + 1;
+    }
 
-    res = RegSetValueExW(patches, szPatches, 0, REG_MULTI_SZ,
-                         (const BYTE *)patch_squashed,
-                         (lstrlenW(patch_squashed) + 1) * sizeof(WCHAR));
-    if (res != ERROR_SUCCESS)
+    p = all_patches = msi_alloc( (len + 1) * sizeof(WCHAR) );
+    if (!all_patches)
         goto done;
 
-    res = RegSetValueExW(patches, patch_squashed, 0, REG_SZ,
-                         (const BYTE *)package->patch->transforms,
-                         (lstrlenW(package->patch->transforms) + 1) * sizeof(WCHAR));
+    LIST_FOR_EACH_ENTRY( patch, &package->patches, MSIPATCHINFO, entry )
+    {
+        squash_guid( patch->patchcode, p );
+        p += strlenW( p ) + 1;
+
+        res = RegSetValueExW( patches, patch_squashed, 0, REG_SZ,
+                              (const BYTE *)patch->transforms,
+                              (strlenW(patch->transforms) + 1) * sizeof(WCHAR) );
+        if (res != ERROR_SUCCESS)
+            goto done;
+    }
+
+    all_patches[len] = 0;
+    res = RegSetValueExW( patches, szPatches, 0, REG_MULTI_SZ,
+                          (const BYTE *)all_patches, (len + 1) * sizeof(WCHAR) );
     if (res == ERROR_SUCCESS)
         r = ERROR_SUCCESS;
 
 done:
     RegCloseKey(patches);
+    msi_free( all_patches );
     return r;
 }
 
@@ -3814,9 +3845,9 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package)
     if (rc != ERROR_SUCCESS)
         goto end;
 
-    if (package->patch)
+    if (!list_empty(&package->patches))
     {
-        rc = msi_publish_patch(package, hukey, hudkey);
+        rc = msi_publish_patches(package, hukey, hudkey);
         if (rc != ERROR_SUCCESS)
             goto end;
     }
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 06a4367..c339ea9 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -148,6 +148,7 @@ typedef struct tagMSIMEDIAINFO
 
 typedef struct tagMSIPATCHINFO
 {
+    struct list entry;
     LPWSTR patchcode;
     LPWSTR transforms;
 } MSIPATCHINFO;
@@ -302,7 +303,7 @@ typedef struct tagMSIPACKAGE
 {
     MSIOBJECTHDR hdr;
     MSIDATABASE *db;
-    MSIPATCHINFO *patch;
+    struct list patches;
     struct list components;
     struct list features;
     struct list files;
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 0c06088..45b4dc9 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -264,11 +264,14 @@ static void free_package_structures( MSIPACKAGE *package )
         msi_free( package->script );
     }
 
-    if (package->patch)
+    LIST_FOR_EACH_SAFE( item, cursor, &package->patches )
     {
-        msi_free( package->patch->patchcode );
-        msi_free( package->patch->transforms );
-        msi_free( package->patch );
+        MSIPATCHINFO *patch = LIST_ENTRY( item, MSIPATCHINFO, entry );
+
+        list_remove( &patch->entry );
+        msi_free( patch->patchcode );
+        msi_free( patch->transforms );
+        msi_free( patch );
     }
 
     msi_free( package->BaseURL );
@@ -987,6 +990,7 @@ static MSIPACKAGE *msi_alloc_package( void )
         list_init( &package->RunningActions );
         list_init( &package->sourcelist_info );
         list_init( &package->sourcelist_media );
+        list_init( &package->patches );
     }
 
     return package;




More information about the wine-cvs mailing list