msi: Compare file versions as numbers instead of strings.
This commit is contained in:
parent
341daad861
commit
15f5b9dca3
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue