Commit 15f5b9dc authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Compare file versions as numbers instead of strings.

parent 341daad8
......@@ -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;
......
......@@ -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);
......
......@@ -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 ))
......
......@@ -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 );
......
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