msi: Check the destination file's hash and skip that file if the hash matches.

This commit is contained in:
James Hawkins 2007-11-25 18:01:19 -06:00 committed by Alexandre Julliard
parent 6a6a218548
commit 4160722b07
4 changed files with 61 additions and 4 deletions

View File

@ -1394,6 +1394,41 @@ static LPWSTR folder_split_path(LPWSTR p, WCHAR ch)
return p+1;
}
static UINT load_file_hash(MSIPACKAGE *package, MSIFILE *file)
{
static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
'`','M','s','i','F','i','l','e','H','a','s','h','`',' ',
'W','H','E','R','E',' ','`','F','i','l','e','_','`',' ','=',' ','\'','%','s','\'',0};
MSIQUERY *view = NULL;
MSIRECORD *row;
UINT r;
TRACE("%s\n", debugstr_w(file->File));
r = MSI_OpenQuery(package->db, &view, query, file->File);
if (r != ERROR_SUCCESS)
goto done;
r = MSI_ViewExecute(view, NULL);
if (r != ERROR_SUCCESS)
goto done;
r = MSI_ViewFetch(view, &row);
if (r != ERROR_SUCCESS)
goto done;
file->hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
file->hash.dwData[0] = MSI_RecordGetInteger(row, 3);
file->hash.dwData[1] = MSI_RecordGetInteger(row, 4);
file->hash.dwData[2] = MSI_RecordGetInteger(row, 5);
file->hash.dwData[3] = MSI_RecordGetInteger(row, 6);
done:
if (view) msiobj_release(&view->hdr);
return r;
}
static UINT load_file(MSIRECORD *row, LPVOID param)
{
MSIPACKAGE* package = (MSIPACKAGE*)param;
@ -1444,6 +1479,8 @@ static UINT load_file(MSIRECORD *row, LPVOID param)
file->IsCompressed = package->WordCount & MSIWORDCOUNT_COMPRESSED;
}
load_file_hash(package, file);
TRACE("File Loaded (%s)\n",debugstr_w(file->File));
list_add_tail( &package->files, &file->entry );

View File

@ -733,6 +733,22 @@ static UINT copy_install_file(MSIFILE *file)
return gle;
}
static BOOL check_dest_hash_matches(MSIFILE *file)
{
MSIFILEHASHINFO hash;
UINT r;
if (!file->hash.dwFileHashInfoSize)
return FALSE;
hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO);
r = MsiGetFileHashW(file->TargetPath, 0, &hash);
if (r != ERROR_SUCCESS)
return FALSE;
return !memcmp(&hash, &file->hash, sizeof(MSIFILEHASHINFO));
}
/*
* ACTION_InstallFiles()
*
@ -776,6 +792,12 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
if (file->state != msifs_missing && !mi->is_continuous && file->state != msifs_overwrite)
continue;
if (check_dest_hash_matches(file))
{
TRACE("File hashes match, not overwriting\n");
continue;
}
if (file->Sequence > mi->last_sequence || mi->is_continuous ||
(file->IsCompressed && !mi->is_extracted))
{

View File

@ -424,6 +424,7 @@ typedef struct tagMSIFILE
LPWSTR SourcePath;
LPWSTR TargetPath;
BOOL IsCompressed;
MSIFILEHASHINFO hash;
} MSIFILE;
typedef struct tagMSITEMPFILE

View File

@ -3540,10 +3540,7 @@ static void test_missingcab(void)
create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
r = MsiInstallProductA(msifile, NULL);
todo_wine
{
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
}
ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");