[1/4] msi: Compare file versions as numbers instead of strings.
Hans Leidekker
hans at codeweavers.com
Fri Jun 11 08:19:15 CDT 2010
Fix for http://bugs.winehq.org/show_bug.cgi?id=19319
---
dlls/msi/action.c | 55 +++++++++++++++++++++++++++----------------------
dlls/msi/appsearch.c | 6 ++--
dlls/msi/files.c | 35 ++++++++++--------------------
dlls/msi/msipriv.h | 5 ++++
4 files changed, 50 insertions(+), 51 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 48948fb..7ae8286 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -1964,16 +1964,12 @@ static UINT ITERATE_CostFinalizeConditions(MSIRECORD *row, LPVOID param)
return ERROR_SUCCESS;
}
-static LPWSTR get_disk_file_version( LPCWSTR filename )
+VS_FIXEDFILEINFO *msi_get_disk_file_version( LPCWSTR filename )
{
- static const WCHAR name_fmt[] =
- {'%','u','.','%','u','.','%','u','.','%','u',0};
static const WCHAR name[] = {'\\',0};
- VS_FIXEDFILEINFO *lpVer;
- WCHAR filever[0x100];
+ VS_FIXEDFILEINFO *ret;
LPVOID version;
- DWORD versize;
- DWORD handle;
+ DWORD versize, handle;
UINT sz;
TRACE("%s\n", debugstr_w(filename));
@@ -1983,23 +1979,32 @@ static LPWSTR get_disk_file_version( LPCWSTR filename )
return NULL;
version = msi_alloc( versize );
+ if (!version)
+ return NULL;
+
GetFileVersionInfoW( filename, 0, versize, version );
- if (!VerQueryValueW( version, name, (LPVOID*)&lpVer, &sz ))
+ if (!VerQueryValueW( version, name, (LPVOID *)&ret, &sz ))
{
msi_free( version );
return NULL;
}
- sprintfW( filever, name_fmt,
- HIWORD(lpVer->dwFileVersionMS),
- LOWORD(lpVer->dwFileVersionMS),
- HIWORD(lpVer->dwFileVersionLS),
- LOWORD(lpVer->dwFileVersionLS));
-
msi_free( version );
+ return ret;
+}
- return strdupW( filever );
+int msi_compare_file_versions( VS_FIXEDFILEINFO *fi, const WCHAR *version )
+{
+ DWORD ms, ls;
+
+ msi_parse_version_string( version, &ms, &ls );
+
+ if (fi->dwFileVersionMS > ms) return 1;
+ else if (fi->dwFileVersionMS < ms) return -1;
+ else if (fi->dwFileVersionLS > ls) return 1;
+ else if (fi->dwFileVersionLS < ls) return -1;
+ return 0;
}
static DWORD get_disk_file_size( LPCWSTR filename )
@@ -2033,7 +2038,7 @@ static BOOL hash_matches( MSIFILE *file )
static UINT set_file_install_states( MSIPACKAGE *package )
{
- LPWSTR file_version;
+ VS_FIXEDFILEINFO *file_version;
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
@@ -2050,18 +2055,14 @@ static UINT set_file_install_states( MSIPACKAGE *package )
/* calculate target */
p = resolve_folder(package, comp->Directory, FALSE, FALSE, TRUE, NULL);
-
msi_free(file->TargetPath);
- TRACE("file %s is named %s\n",
- debugstr_w(file->File), debugstr_w(file->FileName));
+ TRACE("file %s is named %s\n", debugstr_w(file->File), debugstr_w(file->FileName));
file->TargetPath = build_directory_name(2, p, file->FileName);
-
msi_free(p);
- TRACE("file %s resolves to %s\n",
- debugstr_w(file->File), debugstr_w(file->TargetPath));
+ TRACE("file %s resolves to %s\n", debugstr_w(file->File), debugstr_w(file->TargetPath));
if (GetFileAttributesW(file->TargetPath) == INVALID_FILE_ATTRIBUTES)
{
@@ -2069,11 +2070,15 @@ static UINT set_file_install_states( MSIPACKAGE *package )
comp->Cost += file->FileSize;
continue;
}
- if (file->Version && (file_version = get_disk_file_version( file->TargetPath )))
+ if (file->Version && (file_version = msi_get_disk_file_version( file->TargetPath )))
{
- TRACE("new %s old %s\n", debugstr_w(file->Version), debugstr_w(file_version));
+ 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 (strcmpiW(file_version, file->Version) < 0)
+ if (msi_compare_file_versions( file_version, file->Version ) < 0)
{
file->state = msifs_overwrite;
comp->Cost += file->FileSize;
diff --git a/dlls/msi/appsearch.c b/dlls/msi/appsearch.c
index 336bfca..34130b6 100644
--- a/dlls/msi/appsearch.c
+++ b/dlls/msi/appsearch.c
@@ -50,7 +50,7 @@ typedef struct tagMSISIGNATURE
LPWSTR Languages;
}MSISIGNATURE;
-static void ACTION_VerStrToInteger(LPCWSTR verStr, PDWORD ms, PDWORD ls)
+void msi_parse_version_string(LPCWSTR verStr, PDWORD ms, PDWORD ls)
{
const WCHAR *ptr;
int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
@@ -109,13 +109,13 @@ static UINT ACTION_AppSearchGetSignature(MSIPACKAGE *package, MSISIGNATURE *sig,
minVersion = msi_dup_record_field(row,3);
if (minVersion)
{
- ACTION_VerStrToInteger(minVersion, &sig->MinVersionMS, &sig->MinVersionLS);
+ msi_parse_version_string( minVersion, &sig->MinVersionMS, &sig->MinVersionLS );
msi_free( minVersion );
}
maxVersion = msi_dup_record_field(row,4);
if (maxVersion)
{
- ACTION_VerStrToInteger(maxVersion, &sig->MaxVersionMS, &sig->MaxVersionLS);
+ msi_parse_version_string( maxVersion, &sig->MaxVersionMS, &sig->MaxVersionLS );
msi_free( maxVersion );
}
sig->MinSize = MSI_RecordGetInteger(row,5);
diff --git a/dlls/msi/files.c b/dlls/msi/files.c
index f21cd28..79d7814 100644
--- a/dlls/msi/files.c
+++ b/dlls/msi/files.c
@@ -60,24 +60,6 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
ui_progress( package, 2, f->FileSize, 0, 0 );
}
-/* compares the version of a file read from the filesystem and
- * the version specified in the File table
- */
-static int msi_compare_file_version(MSIFILE *file)
-{
- WCHAR version[MAX_PATH];
- DWORD size;
- UINT r;
-
- size = MAX_PATH;
- version[0] = '\0';
- r = MsiGetFileVersionW(file->TargetPath, version, &size, NULL, NULL);
- if (r != ERROR_SUCCESS)
- return 0;
-
- return lstrcmpW(version, file->Version);
-}
-
static void schedule_install_files(MSIPACKAGE *package)
{
MSIFILE *file;
@@ -981,6 +963,7 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
{
MSIRECORD *uirow;
LPWSTR dir, p;
+ VS_FIXEDFILEINFO *ver;
if ( file->state == msifs_installed )
ERR("removing installed file %s\n", debugstr_w(file->TargetPath));
@@ -989,11 +972,17 @@ UINT ACTION_RemoveFiles( MSIPACKAGE *package )
file->Component->Installed == INSTALLSTATE_SOURCE )
continue;
- /* don't remove a file if the old file
- * is strictly newer than the version to be installed
- */
- if ( msi_compare_file_version( file ) < 0 )
- continue;
+ if (file->Version)
+ {
+ ver = msi_get_disk_file_version( file->TargetPath );
+ if (ver && msi_compare_file_versions( ver, file->Version ) > 0)
+ {
+ TRACE("newer version detected, not removing file\n");
+ msi_free( ver );
+ continue;
+ }
+ msi_free( ver );
+ }
TRACE("removing %s\n", debugstr_w(file->File) );
if (!DeleteFileW( file->TargetPath ))
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 819d8bc..9f029f3 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -32,6 +32,7 @@
#include "objbase.h"
#include "objidl.h"
#include "winnls.h"
+#include "winver.h"
#include "wine/list.h"
#include "wine/debug.h"
@@ -811,6 +812,10 @@ extern LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name );
extern BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val);
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 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.0.4
More information about the wine-patches
mailing list