From: Piotr Caban Subject: [PATCH 1/2] msi: Report error when cached installer has different version Message-Id: Date: Thu, 21 Jun 2018 21:48:50 +0200 Signed-off-by: Piotr Caban --- dlls/msi/package.c | 114 +++++++++++++++++++++++++---------------------- dlls/msi/tests/package.c | 6 +-- 2 files changed, 63 insertions(+), 57 deletions(-) diff --git a/dlls/msi/package.c b/dlls/msi/package.c index c423bbf69c..46fbebaf42 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -1310,17 +1310,19 @@ static UINT validate_package( MSIPACKAGE *package ) return ERROR_INSTALL_LANGUAGE_UNSUPPORTED; } -static WCHAR *get_product_code( MSIDATABASE *db ) +static WCHAR *get_property( MSIDATABASE *db, const WCHAR *prop ) { - static const WCHAR query[] = { + static const WCHAR select_query[] = { 'S','E','L','E','C','T',' ','`','V','a','l','u','e','`',' ', 'F','R','O','M',' ','`','P','r','o','p','e','r','t','y','`',' ', 'W','H','E','R','E',' ','`','P','r','o','p','e','r','t','y','`','=', - '\'','P','r','o','d','u','c','t','C','o','d','e','\'',0}; + '\'','%','s','\'',0}; + WCHAR query[MAX_PATH]; MSIQUERY *view; MSIRECORD *rec; WCHAR *ret = NULL; + sprintfW(query, select_query, prop); if (MSI_DatabaseOpenViewW( db, query, &view ) != ERROR_SUCCESS) { return NULL; @@ -1341,48 +1343,39 @@ static WCHAR *get_product_code( MSIDATABASE *db ) return ret; } -static UINT get_registered_local_package( const WCHAR *product, const WCHAR *package, WCHAR *localfile ) +static WCHAR *get_product_code( MSIDATABASE *db ) +{ + return get_property( db, szProductCode ); +} + +static WCHAR *get_product_version( MSIDATABASE *db ) +{ + return get_property( db, szProductVersion ); +} + +static UINT get_registered_local_package( const WCHAR *product, WCHAR *localfile ) { MSIINSTALLCONTEXT context; - HKEY product_key, props_key; - WCHAR *registered_package = NULL, unsquashed[GUID_SIZE]; + WCHAR *filename; + HKEY props_key; UINT r; r = msi_locate_product( product, &context ); if (r != ERROR_SUCCESS) return r; - r = MSIREG_OpenProductKey( product, NULL, context, &product_key, FALSE ); - if (r != ERROR_SUCCESS) - return r; - r = MSIREG_OpenInstallProps( product, context, NULL, &props_key, FALSE ); if (r != ERROR_SUCCESS) - { - RegCloseKey( product_key ); return r; - } - r = ERROR_FUNCTION_FAILED; - registered_package = msi_reg_get_val_str( product_key, INSTALLPROPERTY_PACKAGECODEW ); - if (!registered_package) - goto done; - unsquash_guid( registered_package, unsquashed ); - if (!strcmpiW( package, unsquashed )) - { - WCHAR *filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); - if (!filename) - goto done; - - strcpyW( localfile, filename ); - msi_free( filename ); - r = ERROR_SUCCESS; - } -done: - msi_free( registered_package ); + filename = msi_reg_get_val_str( props_key, INSTALLPROPERTY_LOCALPACKAGEW ); RegCloseKey( props_key ); - RegCloseKey( product_key ); - return r; + if (!filename) + return ERROR_FUNCTION_FAILED; + + strcpyW( localfile, filename ); + msi_free( filename ); + return ERROR_SUCCESS; } WCHAR *msi_get_package_code( MSIDATABASE *db ) @@ -1406,33 +1399,15 @@ WCHAR *msi_get_package_code( MSIDATABASE *db ) return ret; } -static UINT get_local_package( const WCHAR *filename, WCHAR *localfile ) +static UINT get_local_package( MSIDATABASE *db, WCHAR *localfile ) { - WCHAR *product_code, *package_code; - MSIDATABASE *db; + WCHAR *product_code; UINT r; - if ((r = MSI_OpenDatabaseW( filename, MSIDBOPEN_READONLY, &db )) != ERROR_SUCCESS) - { - if (GetFileAttributesW( filename ) == INVALID_FILE_ATTRIBUTES) - return ERROR_FILE_NOT_FOUND; - return r; - } if (!(product_code = get_product_code( db ))) - { - msiobj_release( &db->hdr ); return ERROR_INSTALL_PACKAGE_INVALID; - } - if (!(package_code = msi_get_package_code( db ))) - { - msi_free( product_code ); - msiobj_release( &db->hdr ); - return ERROR_INSTALL_PACKAGE_INVALID; - } - r = get_registered_local_package( product_code, package_code, localfile ); - msi_free( package_code ); + r = get_registered_local_package( product_code, localfile ); msi_free( product_code ); - msiobj_release( &db->hdr ); return r; } @@ -1497,6 +1472,8 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) } else { + WCHAR *product_version = NULL; + if ( UrlIsW( szPackage, URLIS_URL ) ) { r = msi_download_file( szPackage, cachefile ); @@ -1505,26 +1482,55 @@ UINT MSI_OpenPackageW(LPCWSTR szPackage, MSIPACKAGE **pPackage) file = cachefile; } - r = get_local_package( file, localfile ); + r = MSI_OpenDatabaseW( file, MSIDBOPEN_READONLY, &db ); + if (r != ERROR_SUCCESS) + { + if (GetFileAttributesW( file ) == INVALID_FILE_ATTRIBUTES) + return ERROR_FILE_NOT_FOUND; + return r; + } + r = get_local_package( db, localfile ); if (r != ERROR_SUCCESS || GetFileAttributesW( localfile ) == INVALID_FILE_ATTRIBUTES) { r = msi_create_empty_local_file( localfile, dotmsi ); if (r != ERROR_SUCCESS) + { + msiobj_release( &db->hdr ); return r; + } if (!CopyFileW( file, localfile, FALSE )) { r = GetLastError(); WARN("unable to copy package %s to %s (%u)\n", debugstr_w(file), debugstr_w(localfile), r); DeleteFileW( localfile ); + msiobj_release( &db->hdr ); return r; } delete_on_close = TRUE; } + else + product_version = get_product_version( db ); + msiobj_release( &db->hdr ); TRACE("opening package %s\n", debugstr_w( localfile )); r = MSI_OpenDatabaseW( localfile, MSIDBOPEN_TRANSACT, &db ); if (r != ERROR_SUCCESS) return r; + + if (product_version) + { + WCHAR *cache_version = get_product_version( db ); + if (!product_version != !cache_version || + (product_version && strcmpW(product_version, cache_version))) + { + msiobj_release( &db->hdr ); + msi_free(product_version); + msi_free(cache_version); + return ERROR_PRODUCT_VERSION; + } + msi_free(product_version); + msi_free(cache_version); + } } package = MSI_CreatePackage( db ); msiobj_release( &db->hdr ); diff --git a/dlls/msi/tests/package.c b/dlls/msi/tests/package.c index 52a4bfd2f7..b1c7a76783 100644 --- a/dlls/msi/tests/package.c +++ b/dlls/msi/tests/package.c @@ -3838,17 +3838,17 @@ static void test_states(void) MsiCloseHandle(hdb); r = MsiInstallProductA(msifile2, ""); - todo_wine ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r); + ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r); r = MsiInstallProductA(msifile2, "REINSTALLMODE=v"); - ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); size = MAX_PATH; r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); - ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value); + todo_wine ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value); MsiCloseHandle(hprod); /* major upgrade test */