Piotr Caban : msi: Report error when cached installer has different version.

Alexandre Julliard julliard at winehq.org
Fri Jun 22 18:32:37 CDT 2018


Module: wine
Branch: master
Commit: 0657d966ffb9afdcd7cf8bd0c2ac7289a8bfbe5e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=0657d966ffb9afdcd7cf8bd0c2ac7289a8bfbe5e

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Jun 21 21:48:50 2018 +0200

msi: Report error when cached installer has different version.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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 c423bbf..46fbeba 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 52a4bfd..b1c7a76 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 */




More information about the wine-cvs mailing list