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