[1/3] msi: Make a second pass to determine which files to install in the InstallFiles action.
Hans Leidekker
hans at codeweavers.com
Tue Mar 8 03:08:16 CST 2011
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.
---
dlls/msi/action.c | 52 +++++++--------------------------
dlls/msi/files.c | 81 ++++++++++++++++++++++++++++++++++++++++++++-------
dlls/msi/msipriv.h | 4 ++-
3 files changed, 84 insertions(+), 53 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 86aa33f..a003f5e 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -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 */
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index df765e5..e88a0c6 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -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;
- }
}
}
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 7c25ec9..9ddcaeb 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -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 );
--
1.7.1
More information about the wine-patches
mailing list