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

This commit is contained in:
Hans Leidekker 2015-04-01 12:32:18 +02:00 committed by Alexandre Julliard
parent 0762dd68f8
commit 006801366e
4 changed files with 61 additions and 44 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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

View File

@ -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 )
{