diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 5168cf94ee6..0b236560b99 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -1909,7 +1909,7 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param) return ERROR_SUCCESS; } -static LPWSTR msi_get_disk_file_version( LPCWSTR filename ) +static LPWSTR get_disk_file_version( LPCWSTR filename ) { static const WCHAR name_fmt[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; @@ -1947,7 +1947,36 @@ static LPWSTR msi_get_disk_file_version( LPCWSTR filename ) return strdupW( filever ); } -static UINT msi_check_file_install_states( MSIPACKAGE *package ) +static DWORD get_disk_file_size( LPCWSTR filename ) +{ + HANDLE file; + DWORD size; + + TRACE("%s\n", debugstr_w(filename)); + + file = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); + if (file == INVALID_HANDLE_VALUE) + return INVALID_FILE_SIZE; + + size = GetFileSize( file, NULL ); + CloseHandle( file ); + return size; +} + +static BOOL hash_matches( MSIFILE *file ) +{ + UINT r; + MSIFILEHASHINFO hash; + + hash.dwFileHashInfoSize = sizeof(MSIFILEHASHINFO); + r = MsiGetFileHashW( file->TargetPath, 0, &hash ); + if (r != ERROR_SUCCESS) + return FALSE; + + return !memcmp( &hash, &file->hash, sizeof(MSIFILEHASHINFO) ); +} + +static UINT set_file_install_states( MSIPACKAGE *package ) { LPWSTR file_version; MSIFILE *file; @@ -1955,6 +1984,7 @@ static UINT msi_check_file_install_states( MSIPACKAGE *package ) LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry ) { MSICOMPONENT* comp = file->Component; + DWORD file_size; LPWSTR p; if (!comp) @@ -1978,41 +2008,43 @@ static UINT msi_check_file_install_states( MSIPACKAGE *package ) TRACE("file %s resolves to %s\n", debugstr_w(file->File), debugstr_w(file->TargetPath)); - /* don't check files of components that aren't installed */ - if (comp->Installed == INSTALLSTATE_UNKNOWN || - comp->Installed == INSTALLSTATE_ABSENT) - { - file->state = msifs_missing; /* assume files are missing */ - continue; - } - if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES) { file->state = msifs_missing; comp->Cost += file->FileSize; continue; } - - if (file->Version && - (file_version = msi_get_disk_file_version( file->TargetPath ))) + if (file->Version && (file_version = get_disk_file_version( file->TargetPath ))) { - TRACE("new %s old %s\n", debugstr_w(file->Version), - debugstr_w(file_version)); - /* FIXME: seems like a bad way to compare version numbers */ - if (lstrcmpiW(file_version, file->Version)<0) + TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(file_version)); + + if (strcmpiW(file_version, file->Version) < 0) { file->state = msifs_overwrite; comp->Cost += file->FileSize; } else + { + TRACE("Destination file version equal or greater, not overwriting\n"); file->state = msifs_present; + } msi_free( file_version ); + continue; } - else + if ((file_size = get_disk_file_size( file->TargetPath )) != file->FileSize) { file->state = msifs_overwrite; - comp->Cost += file->FileSize; + comp->Cost += file->FileSize - file_size; + continue; } + if (file->hash.dwFileHashInfoSize && hash_matches( file )) + { + TRACE("File hashes match, not overwriting\n"); + file->state = msifs_present; + continue; + } + file->state = msifs_overwrite; + comp->Cost += file->FileSize - file_size; } return ERROR_SUCCESS; @@ -2057,8 +2089,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package) ACTION_GetComponentInstallStates(package); ACTION_GetFeatureInstallStates(package); - TRACE("File calculations\n"); - msi_check_file_install_states( package ); + TRACE("Calculating file install states\n"); + set_file_install_states( package ); if (!process_overrides( package, msi_get_property_int( package->db, szlevel, 1 ) )) { diff --git a/dlls/msi/files.c b/dlls/msi/files.c index 14366f42709..44457736166 100644 --- a/dlls/msi/files.c +++ b/dlls/msi/files.c @@ -175,22 +175,6 @@ static UINT copy_install_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR source) 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)); -} - static BOOL installfiles_cb(MSIPACKAGE *package, LPCWSTR file, DWORD action, LPWSTR *path, DWORD *attrs, PVOID user) { @@ -258,19 +242,6 @@ 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 (MsiGetFileVersionW(file->TargetPath, NULL, NULL, NULL, NULL) == ERROR_SUCCESS && - msi_compare_file_version(file) >= 0) - { - TRACE("Destination file version greater, not overwriting\n"); - continue; - } - if (file->Sequence > mi->last_sequence || mi->is_continuous || (file->IsCompressed && !mi->is_extracted)) {