Module: wine Branch: master Commit: 4160722b07c4cdd98a46cbe93b7c059c395b8864 URL: http://source.winehq.org/git/wine.git/?a=commit;h=4160722b07c4cdd98a46cbe93b...
Author: James Hawkins truiken@gmail.com Date: Sun Nov 25 18:01:19 2007 -0600
msi: Check the destination file's hash and skip that file if the hash matches.
---
dlls/msi/action.c | 37 +++++++++++++++++++++++++++++++++++++ dlls/msi/files.c | 22 ++++++++++++++++++++++ dlls/msi/msipriv.h | 1 + dlls/msi/tests/install.c | 5 +---- 4 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 3066308..89f7bd7 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -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 ); diff --git a/dlls/msi/files.c b/dlls/msi/files.c index c50e420..6662e4a 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -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)) { diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 4c7565b..d541260 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -424,6 +424,7 @@ typedef struct tagMSIFILE LPWSTR SourcePath; LPWSTR TargetPath; BOOL IsCompressed; + MSIFILEHASHINFO hash; } MSIFILE;
typedef struct tagMSITEMPFILE diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 34fc126..fd8184b 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -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(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");