Hans Leidekker : msi: Don' t apply file patches in the cabinet extraction callback.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Apr 1 10:40:59 CDT 2015


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Apr  1 12:32:18 2015 +0200

msi: Don't apply file patches in the cabinet extraction callback.

---

 dlls/msi/action.c  |  1 -
 dlls/msi/files.c   | 92 +++++++++++++++++++++++++++++-------------------------
 dlls/msi/msipriv.h |  3 +-
 dlls/msi/package.c |  9 ++++++
 4 files changed, 61 insertions(+), 44 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index edd08f7..a9a157b 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1377,7 +1377,6 @@ static UINT load_patch(MSIRECORD *row, LPVOID param)
     patch->Sequence = MSI_RecordGetInteger( row, 2 );
     patch->PatchSize = MSI_RecordGetInteger( row, 3 );
     patch->Attributes = MSI_RecordGetInteger( row, 4 );
-    patch->IsApplied = FALSE;
 
     /* FIXME:
      * Header field - for patch validation.
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index dff00df..96fb48a 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -436,13 +436,14 @@ done:
     return rc;
 }
 
-static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key )
+static MSIFILEPATCH *find_filepatch( MSIPACKAGE *package, UINT disk_id, const WCHAR *key )
 {
     MSIFILEPATCH *patch;
 
     LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
     {
-        if (!patch->IsApplied && !strcmpW( key, patch->File->File )) return patch;
+        if (!patch->extracted && patch->disk_id == disk_id && !strcmpW( key, patch->File->File ))
+            return patch;
     }
     return NULL;
 }
@@ -450,45 +451,25 @@ static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key )
 static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
                           LPWSTR *path, DWORD *attrs, PVOID user)
 {
-    static MSIFILEPATCH *p = NULL;
-    static WCHAR patch_path[MAX_PATH] = {0};
-    static WCHAR temp_folder[MAX_PATH] = {0};
+    static MSIFILEPATCH *patch;
+    static WCHAR tmpfile[MAX_PATH], tmpdir[MAX_PATH];
+    UINT_PTR disk_id = (UINT_PTR)user;
+
+    if (!tmpdir[0]) GetTempPathW( MAX_PATH, tmpdir );
 
     if (action == MSICABEXTRACT_BEGINEXTRACT)
     {
-        if (temp_folder[0] == '\0')
-            GetTempPathW(MAX_PATH, temp_folder);
-
-        if (!(p = get_next_filepatch(package, file)) || !p->File->Component->Enabled)
-            return FALSE;
+        if (!(patch = find_filepatch( package, disk_id, file ))) return FALSE;
 
-        GetTempFileNameW(temp_folder, NULL, 0, patch_path);
-
-        *path = strdupW(patch_path);
-        *attrs = p->File->Attributes;
+        GetTempFileNameW( tmpdir, NULL, 0, tmpfile );
+        *path = strdupW( tmpfile );
+        *attrs = patch->File->Attributes;
     }
     else if (action == MSICABEXTRACT_FILEEXTRACTED)
     {
-        WCHAR patched_file[MAX_PATH];
-        BOOL br;
-
-        GetTempFileNameW(temp_folder, NULL, 0, patched_file);
-
-        br = ApplyPatchToFileW(patch_path, p->File->TargetPath, patched_file, 0);
-        if (br)
-        {
-            /* FIXME: baseline cache */
-
-            DeleteFileW( p->File->TargetPath );
-            MoveFileW( patched_file, p->File->TargetPath );
-
-            p->IsApplied = TRUE;
-        }
-        else
-            ERR("Failed patch %s: %d.\n", debugstr_w(p->File->TargetPath), GetLastError());
-
-        DeleteFileW(patch_path);
-        p = NULL;
+        patch->path = strdupW( tmpfile );
+        patch->extracted = TRUE;
+        patch = NULL;
     }
 
     return TRUE;
@@ -504,6 +485,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
 
     mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
 
+    TRACE("extracting files\n");
+
     LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
     {
         MSIFILE *file = patch->File;
@@ -519,7 +502,7 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
         comp->Action = msi_get_component_action( package, comp );
         if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue;
 
-        if (!patch->IsApplied)
+        if (!patch->extracted)
         {
             MSICABDATA data;
 
@@ -529,23 +512,48 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
                 ERR("Failed to ready media for %s\n", debugstr_w(file->File));
                 goto done;
             }
-
-            data.mi = mi;
+            data.mi      = mi;
             data.package = package;
-            data.cb = patchfiles_cb;
-            data.user = (PVOID)(UINT_PTR)mi->disk_id;
+            data.cb      = patchfiles_cb;
+            data.user    = (PVOID)(UINT_PTR)mi->disk_id;
 
-            if (!msi_cabextract(package, mi, &data))
+            if (!msi_cabextract( package, mi, &data ))
             {
                 ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
                 rc = ERROR_INSTALL_FAILURE;
                 goto done;
             }
         }
+    }
+
+    TRACE("applying patches\n");
+
+    LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
+    {
+        WCHAR tmpdir[MAX_PATH], tmpfile[MAX_PATH];
+        BOOL ret;
+
+        if (!patch->path) continue;
+
+        GetTempPathW( MAX_PATH, tmpdir );
+        GetTempFileNameW( tmpdir, NULL, 0, tmpfile );
+
+        ret = ApplyPatchToFileW( patch->path, patch->File->TargetPath, tmpfile, 0 );
+        if (ret)
+        {
+            DeleteFileW( patch->File->TargetPath );
+            MoveFileW( tmpfile, patch->File->TargetPath );
+        }
+        else
+            WARN("failed to patch %s: %08x\n", debugstr_w(patch->File->TargetPath), GetLastError());
+
+        DeleteFileW( patch->path );
+        DeleteFileW( tmpfile );
+        RemoveDirectoryW( tmpdir );
 
-        if (!patch->IsApplied && !(patch->Attributes & msidbPatchAttributesNonVital))
+        if (!ret && !(patch->Attributes & msidbPatchAttributesNonVital))
         {
-            ERR("Failed to apply patch to file: %s\n", debugstr_w(file->File));
+            ERR("Failed to apply patch to file: %s\n", debugstr_w(patch->File->File));
             rc = ERROR_INSTALL_FAILURE;
             goto done;
         }
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index b58dc32..fe4f6d6 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -593,8 +593,9 @@ typedef struct tagMSIFILEPATCH
     INT Sequence;
     INT PatchSize;
     INT Attributes;
-    BOOL IsApplied;
+    BOOL extracted;
     UINT disk_id;
+    WCHAR *path;
 } MSIFILEPATCH;
 
 typedef struct tagMSIAPPID
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index fcbf663..1053053 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -200,6 +200,15 @@ static void free_package_structures( MSIPACKAGE *package )
         msi_free( file );
     }
 
+    LIST_FOR_EACH_SAFE( item, cursor, &package->filepatches )
+    {
+        MSIFILEPATCH *patch = LIST_ENTRY( item, MSIFILEPATCH, entry );
+
+        list_remove( &patch->entry );
+        msi_free( patch->path );
+        msi_free( patch );
+    }
+
     /* clean up extension, progid, class and verb structures */
     LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
     {




More information about the wine-cvs mailing list