From 006801366e1b9e9f647ae46ccf3e899e8872a796 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 1 Apr 2015 12:32:18 +0200 Subject: [PATCH] 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 edd08f74ac3..a9a157bba20 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 dff00df3c76..96fb48a5577 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 (!(patch = find_filepatch( package, disk_id, file ))) return FALSE; - if (!(p = get_next_filepatch(package, file)) || !p->File->Component->Enabled) - 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; } } + } - if (!patch->IsApplied && !(patch->Attributes & msidbPatchAttributesNonVital)) + 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) { - ERR("Failed to apply patch to file: %s\n", debugstr_w(file->File)); + 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 (!ret && !(patch->Attributes & msidbPatchAttributesNonVital)) + { + 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 b58dc322b08..fe4f6d6702d 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 fcbf6632fec..1053053cdfe 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 ) {