[7/8] msi: Delay creating local installer and patch packages until the product is registered.

Hans Leidekker hans at codeweavers.com
Thu Jun 30 05:15:37 CDT 2011


---
 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 4671f3e..9070b76 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 9b5a894..2c45a7a 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 e2fb03e..5a264df 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 1cbb221..5d6523d 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 00281a8..a31802e 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;
+}
-- 
1.7.4.1







More information about the wine-patches mailing list