Commit 4a6c63e2 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Make a second pass to determine which files to install in the InstallFiles action.

This is needed because the target path can still change after CostFinalize is executed. This happens in the .NET 1.1 Service Pack 1 installer where a custom action calls SetTargetPath.
parent afcfb510
......@@ -2178,7 +2178,7 @@ int msi_compare_file_versions( VS_FIXEDFILEINFO *fi, const WCHAR *version )
return 0;
}
static int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
{
DWORD ms1, ms2;
......@@ -2190,7 +2190,7 @@ static int msi_compare_font_versions( const WCHAR *ver1, const WCHAR *ver2 )
return 0;
}
static DWORD get_disk_file_size( LPCWSTR filename )
DWORD msi_get_disk_file_size( LPCWSTR filename )
{
HANDLE file;
DWORD size;
......@@ -2206,7 +2206,7 @@ static DWORD get_disk_file_size( LPCWSTR filename )
return size;
}
static BOOL hash_matches( MSIFILE *file )
BOOL msi_file_hash_matches( MSIFILE *file )
{
UINT r;
MSIFILEHASHINFO hash;
......@@ -2256,7 +2256,7 @@ static void set_target_path( MSIPACKAGE *package, MSIFILE *file )
TRACE("resolves to %s\n", debugstr_w(file->TargetPath));
}
static UINT set_file_install_states( MSIPACKAGE *package )
static UINT calculate_file_cost( MSIPACKAGE *package )
{
VS_FIXEDFILEINFO *file_version;
WCHAR *font_version;
......@@ -2277,67 +2277,37 @@ static UINT set_file_install_states( MSIPACKAGE *package )
if ((comp->assembly && !comp->assembly->installed) ||
GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
{
file->state = msifs_missing;
comp->Cost += file->FileSize;
continue;
}
file_size = msi_get_disk_file_size( file->TargetPath );
if (file->Version)
{
if ((file_version = msi_get_disk_file_version( file->TargetPath )))
{
TRACE("new %s old %u.%u.%u.%u\n", debugstr_w(file->Version),
HIWORD(file_version->dwFileVersionMS),
LOWORD(file_version->dwFileVersionMS),
HIWORD(file_version->dwFileVersionLS),
LOWORD(file_version->dwFileVersionLS));
if (msi_compare_file_versions( 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;
comp->Cost += file->FileSize - file_size;
}
msi_free( file_version );
continue;
}
else if ((font_version = font_version_from_file( file->TargetPath )))
{
TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(font_version));
if (msi_compare_font_versions( font_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;
comp->Cost += file->FileSize - file_size;
}
msi_free( font_version );
continue;
}
}
if ((file_size = get_disk_file_size( file->TargetPath )) != file->FileSize)
if (file_size != file->FileSize)
{
file->state = msifs_overwrite;
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;
}
......@@ -2404,8 +2374,8 @@ static UINT ACTION_CostFinalize(MSIPACKAGE *package)
}
}
TRACE("Calculating file install states\n");
set_file_install_states( package );
TRACE("Calculating file cost\n");
calculate_file_cost( package );
msi_set_property( package->db, szCosting, szOne );
/* set default run level if not set */
......
......@@ -60,6 +60,73 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
ui_progress( package, 2, f->FileSize, 0, 0 );
}
static msi_file_state calculate_install_state( MSIFILE *file )
{
MSICOMPONENT *comp = file->Component;
VS_FIXEDFILEINFO *file_version;
WCHAR *font_version;
msi_file_state state;
DWORD file_size;
if (comp->ActionRequest != INSTALLSTATE_LOCAL || !comp->Enabled ||
(comp->assembly && comp->assembly->installed))
{
TRACE("file %s is not scheduled for install\n", debugstr_w(file->File));
return msifs_skipped;
}
if ((comp->assembly && !comp->assembly->installed) ||
GetFileAttributesW( file->TargetPath ) == INVALID_FILE_ATTRIBUTES)
{
TRACE("file %s is missing\n", debugstr_w(file->File));
return msifs_missing;
}
if (file->Version)
{
if ((file_version = msi_get_disk_file_version( file->TargetPath )))
{
TRACE("new %s old %u.%u.%u.%u\n", debugstr_w(file->Version),
HIWORD(file_version->dwFileVersionMS),
LOWORD(file_version->dwFileVersionMS),
HIWORD(file_version->dwFileVersionLS),
LOWORD(file_version->dwFileVersionLS));
if (msi_compare_file_versions( file_version, file->Version ) < 0)
state = msifs_overwrite;
else
{
TRACE("destination file version equal or greater, not overwriting\n");
state = msifs_present;
}
msi_free( file_version );
return state;
}
else if ((font_version = font_version_from_file( file->TargetPath )))
{
TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(font_version));
if (msi_compare_font_versions( font_version, file->Version ) < 0)
state = msifs_overwrite;
else
{
TRACE("destination file version equal or greater, not overwriting\n");
state = msifs_present;
}
msi_free( font_version );
return state;
}
}
if ((file_size = msi_get_disk_file_size( file->TargetPath )) != file->FileSize)
{
return msifs_overwrite;
}
if (file->hash.dwFileHashInfoSize && msi_file_hash_matches( file ))
{
TRACE("file hashes match, not overwriting\n");
return msifs_present;
}
return msifs_overwrite;
}
static void schedule_install_files(MSIPACKAGE *package)
{
MSIFILE *file;
......@@ -68,22 +135,14 @@ static void schedule_install_files(MSIPACKAGE *package)
{
MSICOMPONENT *comp = file->Component;
if (comp->ActionRequest != INSTALLSTATE_LOCAL || !comp->Enabled ||
(comp->assembly && comp->assembly->installed))
file->state = calculate_install_state( file );
if (file->state == msifs_overwrite && (comp->Attributes & msidbComponentAttributesNeverOverwrite))
{
TRACE("File %s is not scheduled for install\n", debugstr_w(file->File));
TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
file->state = msifs_skipped;
continue;
}
comp->Action = INSTALLSTATE_LOCAL;
ui_progress( package, 2, file->FileSize, 0, 0 );
if (file->state == msifs_overwrite &&
(comp->Attributes & msidbComponentAttributesNeverOverwrite))
{
TRACE("not overwriting %s\n", debugstr_w(file->TargetPath));
file->state = msifs_skipped;
}
}
}
......
......@@ -856,7 +856,9 @@ extern DWORD msi_version_str_to_dword(LPCWSTR p);
extern void msi_parse_version_string(LPCWSTR, PDWORD, PDWORD);
extern VS_FIXEDFILEINFO *msi_get_disk_file_version(LPCWSTR);
extern int msi_compare_file_versions(VS_FIXEDFILEINFO *, const WCHAR *);
extern int msi_compare_font_versions(const WCHAR *, const WCHAR *);
extern DWORD msi_get_disk_file_size(LPCWSTR);
extern BOOL msi_file_hash_matches(MSIFILE *);
extern LONG msi_reg_set_val_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
extern LONG msi_reg_set_val_multi_str( HKEY hkey, LPCWSTR name, LPCWSTR value );
......
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