Commit 00680136 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

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

parent 0762dd68
...@@ -1377,7 +1377,6 @@ static UINT load_patch(MSIRECORD *row, LPVOID param) ...@@ -1377,7 +1377,6 @@ static UINT load_patch(MSIRECORD *row, LPVOID param)
patch->Sequence = MSI_RecordGetInteger( row, 2 ); patch->Sequence = MSI_RecordGetInteger( row, 2 );
patch->PatchSize = MSI_RecordGetInteger( row, 3 ); patch->PatchSize = MSI_RecordGetInteger( row, 3 );
patch->Attributes = MSI_RecordGetInteger( row, 4 ); patch->Attributes = MSI_RecordGetInteger( row, 4 );
patch->IsApplied = FALSE;
/* FIXME: /* FIXME:
* Header field - for patch validation. * Header field - for patch validation.
......
...@@ -436,13 +436,14 @@ done: ...@@ -436,13 +436,14 @@ done:
return rc; 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; MSIFILEPATCH *patch;
LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) 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; return NULL;
} }
...@@ -450,45 +451,25 @@ static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key ) ...@@ -450,45 +451,25 @@ static MSIFILEPATCH *get_next_filepatch( MSIPACKAGE *package, const WCHAR *key )
static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, static BOOL patchfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action,
LPWSTR *path, DWORD *attrs, PVOID user) LPWSTR *path, DWORD *attrs, PVOID user)
{ {
static MSIFILEPATCH *p = NULL; static MSIFILEPATCH *patch;
static WCHAR patch_path[MAX_PATH] = {0}; static WCHAR tmpfile[MAX_PATH], tmpdir[MAX_PATH];
static WCHAR temp_folder[MAX_PATH] = {0}; UINT_PTR disk_id = (UINT_PTR)user;
if (!tmpdir[0]) GetTempPathW( MAX_PATH, tmpdir );
if (action == MSICABEXTRACT_BEGINEXTRACT) if (action == MSICABEXTRACT_BEGINEXTRACT)
{ {
if (temp_folder[0] == '\0') if (!(patch = find_filepatch( package, disk_id, file ))) return FALSE;
GetTempPathW(MAX_PATH, temp_folder);
if (!(p = get_next_filepatch(package, file)) || !p->File->Component->Enabled)
return FALSE;
GetTempFileNameW(temp_folder, NULL, 0, patch_path); GetTempFileNameW( tmpdir, NULL, 0, tmpfile );
*path = strdupW( tmpfile );
*path = strdupW(patch_path); *attrs = patch->File->Attributes;
*attrs = p->File->Attributes;
} }
else if (action == MSICABEXTRACT_FILEEXTRACTED) else if (action == MSICABEXTRACT_FILEEXTRACTED)
{ {
WCHAR patched_file[MAX_PATH]; patch->path = strdupW( tmpfile );
BOOL br; patch->extracted = TRUE;
patch = NULL;
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;
} }
return TRUE; return TRUE;
...@@ -504,6 +485,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package ) ...@@ -504,6 +485,8 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) ); mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
TRACE("extracting files\n");
LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry ) LIST_FOR_EACH_ENTRY( patch, &package->filepatches, MSIFILEPATCH, entry )
{ {
MSIFILE *file = patch->File; MSIFILE *file = patch->File;
...@@ -519,7 +502,7 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package ) ...@@ -519,7 +502,7 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
comp->Action = msi_get_component_action( package, comp ); comp->Action = msi_get_component_action( package, comp );
if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue; if (!comp->Enabled || comp->Action != INSTALLSTATE_LOCAL) continue;
if (!patch->IsApplied) if (!patch->extracted)
{ {
MSICABDATA data; MSICABDATA data;
...@@ -529,23 +512,48 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package ) ...@@ -529,23 +512,48 @@ UINT ACTION_PatchFiles( MSIPACKAGE *package )
ERR("Failed to ready media for %s\n", debugstr_w(file->File)); ERR("Failed to ready media for %s\n", debugstr_w(file->File));
goto done; goto done;
} }
data.mi = mi;
data.mi = mi;
data.package = package; data.package = package;
data.cb = patchfiles_cb; data.cb = patchfiles_cb;
data.user = (PVOID)(UINT_PTR)mi->disk_id; 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)); ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
rc = ERROR_INSTALL_FAILURE; rc = ERROR_INSTALL_FAILURE;
goto done; 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; rc = ERROR_INSTALL_FAILURE;
goto done; goto done;
} }
......
...@@ -593,8 +593,9 @@ typedef struct tagMSIFILEPATCH ...@@ -593,8 +593,9 @@ typedef struct tagMSIFILEPATCH
INT Sequence; INT Sequence;
INT PatchSize; INT PatchSize;
INT Attributes; INT Attributes;
BOOL IsApplied; BOOL extracted;
UINT disk_id; UINT disk_id;
WCHAR *path;
} MSIFILEPATCH; } MSIFILEPATCH;
typedef struct tagMSIAPPID typedef struct tagMSIAPPID
......
...@@ -200,6 +200,15 @@ static void free_package_structures( MSIPACKAGE *package ) ...@@ -200,6 +200,15 @@ static void free_package_structures( MSIPACKAGE *package )
msi_free( file ); 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 */ /* clean up extension, progid, class and verb structures */
LIST_FOR_EACH_SAFE( item, cursor, &package->classes ) LIST_FOR_EACH_SAFE( item, cursor, &package->classes )
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment