Hans Leidekker : msi: Make a local copy of patch packages.

Alexandre Julliard julliard at winehq.org
Tue May 4 13:06:36 CDT 2010


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue May  4 09:06:42 2010 +0200

msi: Make a local copy of patch packages.

---

 dlls/msi/action.c  |   44 ++++++++++++++++++++++++++++++++++----------
 dlls/msi/msipriv.h |    2 ++
 dlls/msi/package.c |   13 ++++++++-----
 3 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 5ca786d..e744973 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -497,7 +497,7 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
     MSIPATCHINFO *pi;
     UINT r = ERROR_SUCCESS;
 
-    pi = msi_alloc( sizeof(MSIPATCHINFO) );
+    pi = msi_alloc_zero( sizeof(MSIPATCHINFO) );
     if (!pi)
         return ERROR_OUTOFMEMORY;
 
@@ -522,11 +522,13 @@ static UINT msi_parse_patch_summary( MSISUMMARYINFO *si, MSIPATCHINFO **patch )
 
 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;
-    UINT i, r;
+    MSIPATCHINFO *patch = NULL;
+    UINT i, r = ERROR_SUCCESS;
 
     TRACE("%p %s\n", package, debugstr_w( file ) );
 
@@ -548,18 +550,28 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
     if (r != ERROR_SUCCESS)
     {
         TRACE("patch not applicable\n");
-        msiobj_release( &si->hdr );
-        msiobj_release( &patch_db->hdr );
-        return ERROR_SUCCESS;
+        r = ERROR_SUCCESS;
+        goto done;
     }
 
     r = msi_parse_patch_summary( si, &patch );
     if ( r != ERROR_SUCCESS )
+        goto done;
+
+    r = msi_get_local_package_name( localfile, dotmsp );
+    if ( r != ERROR_SUCCESS )
+        goto done;
+
+    TRACE("copying to local package %s\n", debugstr_w(localfile));
+
+    if (!CopyFileW( file, localfile, FALSE ))
     {
-        msiobj_release( &si->hdr );
-        msiobj_release( &patch_db->hdr );
-        return r;
+        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 );
 
     /* apply substorage transforms */
     substorage = msi_split_string( patch->transforms, ';' );
@@ -567,6 +579,8 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
         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 );
 
     /*
@@ -577,10 +591,20 @@ static UINT msi_apply_patch_package( MSIPACKAGE *package, LPCWSTR file )
 
     list_add_tail( &package->patches, &patch->entry );
 
+done:
     msiobj_release( &si->hdr );
     msiobj_release( &patch_db->hdr );
+    if (patch && r != ERROR_SUCCESS)
+    {
+        if (patch->localfile)
+            DeleteFileW( patch->localfile );
 
-    return ERROR_SUCCESS;
+        msi_free( patch->patchcode );
+        msi_free( patch->transforms );
+        msi_free( patch->localfile );
+        msi_free( patch );
+    }
+    return r;
 }
 
 /* get the PATCH property, and apply all the patches it specifies */
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index c339ea9..a8594a8 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -151,6 +151,7 @@ typedef struct tagMSIPATCHINFO
     struct list entry;
     LPWSTR patchcode;
     LPWSTR transforms;
+    LPWSTR localfile;
 } MSIPATCHINFO;
 
 typedef struct _column_info
@@ -996,6 +997,7 @@ extern WCHAR* generate_error_string(MSIPACKAGE *, UINT, DWORD, ... );
 extern UINT msi_create_component_directories( MSIPACKAGE *package );
 extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
                         MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
+extern UINT msi_get_local_package_name(LPWSTR path, LPCWSTR suffix);
 
 /* media */
 
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 45b4dc9..2ffd66e 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -271,6 +271,7 @@ static void free_package_structures( MSIPACKAGE *package )
         list_remove( &patch->entry );
         msi_free( patch->patchcode );
         msi_free( patch->transforms );
+        msi_free( patch->localfile );
         msi_free( patch );
     }
 
@@ -1133,12 +1134,12 @@ UINT msi_download_file( LPCWSTR szUrl, LPWSTR filename )
     return ERROR_SUCCESS;
 }
 
-static UINT msi_get_local_package_name( LPWSTR path )
+UINT msi_get_local_package_name( LPWSTR path, LPCWSTR suffix )
 {
     static const WCHAR szInstaller[] = {
         '\\','I','n','s','t','a','l','l','e','r','\\',0};
-    static const WCHAR fmt[] = { '%','x','.','m','s','i',0};
-    DWORD time, len, i;
+    static const WCHAR fmt[] = {'%','x',0};
+    DWORD time, len, i, offset;
     HANDLE handle;
 
     time = GetTickCount();
@@ -1149,7 +1150,8 @@ static UINT msi_get_local_package_name( LPWSTR path )
     len = strlenW(path);
     for (i = 0; i < 0x10000; i++)
     {
-        snprintfW( &path[len], MAX_PATH - len, fmt, (time + i)&0xffff );
+        offset = snprintfW( path + len, MAX_PATH - len, fmt, (time + i) & 0xffff );
+        memcpy( path + len + offset, suffix, (strlenW( suffix ) + 1) * sizeof(WCHAR) );
         handle = CreateFileW( path, GENERIC_WRITE, 0, NULL,
                               CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
         if (handle != INVALID_HANDLE_VALUE)
@@ -1170,6 +1172,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
     static const WCHAR OriginalDatabase[] =
         {'O','r','i','g','i','n','a','l','D','a','t','a','b','a','s','e',0};
     static const WCHAR Database[] = {'D','A','T','A','B','A','S','E',0};
+    static const WCHAR dotmsi[] = {'.','m','s','i',0};
     MSIDATABASE *db = NULL;
     MSIPACKAGE *package;
     MSIHANDLE handle;
@@ -1228,7 +1231,7 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage)
             file = temppath;
         }
 
-        r = msi_get_local_package_name( localfile );
+        r = msi_get_local_package_name( localfile, dotmsi );
         if (r != ERROR_SUCCESS)
             return r;
 




More information about the wine-cvs mailing list