[1/5] msi: Add support for 64-bit registry components.

Hans Leidekker hans at codeweavers.com
Tue Jun 5 06:42:59 CDT 2012


---
 dlls/msi/action.c        |   30 +++++++---
 dlls/msi/msi_main.c      |    1 +
 dlls/msi/msipriv.h       |    1 +
 dlls/msi/package.c       |    2 -
 dlls/msi/tests/install.c |  140 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 162 insertions(+), 12 deletions(-)

diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index ec00886..17e8696 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -2554,12 +2554,13 @@ static const WCHAR *get_root_key( MSIPACKAGE *package, INT root, HKEY *root_key
     return ret;
 }
 
-static WCHAR *get_keypath( MSIPACKAGE *package, HKEY root, const WCHAR *path )
+static WCHAR *get_keypath( MSICOMPONENT *comp, HKEY root, const WCHAR *path )
 {
     static const WCHAR prefixW[] = {'S','O','F','T','W','A','R','E','\\'};
     static const UINT len = sizeof(prefixW) / sizeof(prefixW[0]);
 
-    if (is_64bit && package->platform == PLATFORM_INTEL &&
+    if ((is_64bit || is_wow64) &&
+        !(comp->Attributes & msidbComponentAttributes64bit) &&
         root == HKEY_LOCAL_MACHINE && !strncmpiW( path, prefixW, len ))
     {
         UINT size;
@@ -2574,7 +2575,6 @@ static WCHAR *get_keypath( MSIPACKAGE *package, HKEY root, const WCHAR *path )
         strcatW( path_32node, path + len );
         return path_32node;
     }
-
     return strdupW( path );
 }
 
@@ -2634,9 +2634,9 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
     strcpyW(uikey,szRoot);
     strcatW(uikey,deformated);
 
-    keypath = get_keypath( package, root_key, deformated );
+    keypath = get_keypath( comp, root_key, deformated );
     msi_free( deformated );
-    if (RegCreateKeyW( root_key, keypath, &hkey ))
+    if (RegCreateKeyExW( root_key, keypath, 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, NULL, &hkey, NULL ))
     {
         ERR("Could not create key %s\n", debugstr_w(keypath));
         msi_free(uikey);
@@ -2722,7 +2722,7 @@ static void delete_reg_value( HKEY root, const WCHAR *keypath, const WCHAR *valu
     HKEY hkey;
     DWORD num_subkeys, num_values;
 
-    if (!(res = RegOpenKeyW( root, keypath, &hkey )))
+    if (!(res = RegOpenKeyExW( root, keypath, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey )))
     {
         if ((res = RegDeleteValueW( hkey, value )))
         {
@@ -2734,7 +2734,7 @@ static void delete_reg_value( HKEY root, const WCHAR *keypath, const WCHAR *valu
         if (!res && !num_subkeys && !num_values)
         {
             TRACE("removing empty key %s\n", debugstr_w(keypath));
-            RegDeleteKeyW( root, keypath );
+            RegDeleteKeyExW( root, keypath, KEY_WOW64_64KEY, 0 );
         }
         return;
     }
@@ -2743,8 +2743,18 @@ static void delete_reg_value( HKEY root, const WCHAR *keypath, const WCHAR *valu
 
 static void delete_reg_key( HKEY root, const WCHAR *keypath )
 {
-    LONG res = RegDeleteTreeW( root, keypath );
+    HKEY hkey;
+    LONG res = RegOpenKeyExW( root, keypath, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey );
+    if (res)
+    {
+        TRACE("failed to open key %s (%d)\n", debugstr_w(keypath), res);
+        return;
+    }
+    res = RegDeleteTreeW( hkey, NULL );
+    if (res) TRACE("failed to delete subtree of %s (%d)\n", debugstr_w(keypath), res);
+    res = RegDeleteKeyExW( root, keypath, KEY_WOW64_64KEY, 0 );
     if (res) TRACE("failed to delete key %s (%d)\n", debugstr_w(keypath), res);
+    RegCloseKey( hkey );
 }
 
 static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID param )
@@ -2800,7 +2810,7 @@ static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID para
 
     deformat_string( package, name, &deformated_name );
 
-    keypath = get_keypath( package, hkey_root, deformated_key );
+    keypath = get_keypath( comp, hkey_root, deformated_key );
     msi_free( deformated_key );
     if (delete_key) delete_reg_key( hkey_root, keypath );
     else delete_reg_value( hkey_root, keypath, deformated_name );
@@ -2865,7 +2875,7 @@ static UINT ITERATE_RemoveRegistryValuesOnInstall( MSIRECORD *row, LPVOID param
 
     deformat_string( package, name, &deformated_name );
 
-    keypath = get_keypath( package, hkey_root, deformated_key );
+    keypath = get_keypath( comp, hkey_root, deformated_key );
     msi_free( deformated_key );
     if (delete_key) delete_reg_key( hkey_root, keypath );
     else delete_reg_value( hkey_root, keypath, deformated_name );
diff --git a/dlls/msi/msi_main.c b/dlls/msi/msi_main.c
index 669d93b..de0534a 100644
--- a/dlls/msi/msi_main.c
+++ b/dlls/msi/msi_main.c
@@ -73,6 +73,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     case DLL_PROCESS_ATTACH:
         msi_hInstance = hinstDLL;
         DisableThreadLibraryCalls(hinstDLL);
+        IsWow64Process( GetCurrentProcess(), &is_wow64 );
         break;
     case DLL_PROCESS_DETACH:
         msi_dialog_unregister_class();
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 605ee8d..a0657f4 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -39,6 +39,7 @@
 #include "wine/debug.h"
 
 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
+BOOL is_wow64;
 
 #define MSI_DATASIZEMASK 0x00ff
 #define MSITYPE_VALID    0x0100
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index b1668d3..7c8b1b4 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1339,7 +1339,6 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
 
 static UINT validate_package( MSIPACKAGE *package )
 {
-    BOOL is_wow64;
     UINT i;
 
     if (package->platform == PLATFORM_INTEL64)
@@ -1348,7 +1347,6 @@ static UINT validate_package( MSIPACKAGE *package )
     if (package->platform == PLATFORM_ARM)
         return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
 #endif
-    IsWow64Process( GetCurrentProcess(), &is_wow64 );
     if (package->platform == PLATFORM_X64)
     {
         if (!is_64bit && !is_wow64)
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index 8e4e4b7..ad3ea66 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -1237,6 +1237,53 @@ static const CHAR uc_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
                                               "PublishProduct\t\t1200\n"
                                               "InstallFinalize\t\t1300\n";
 
+static const char mixed_feature_dat[] =
+    "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
+    "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
+    "Feature\tFeature\n"
+    "feature1\t\t\t\t1\t2\tMSITESTDIR\t0\n"
+    "feature2\t\t\t\t1\t2\tMSITESTDIR\t0\n";
+
+static const char mixed_feature_comp_dat[] =
+    "Feature_\tComponent_\n"
+    "s38\ts72\n"
+    "FeatureComponents\tFeature_\tComponent_\n"
+    "feature1\tcomp1\n"
+    "feature2\tcomp2\n";
+
+static const char mixed_component_dat[] =
+    "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
+    "s72\tS38\ts72\ti2\tS255\tS72\n"
+    "Component\tComponent\n"
+    "comp1\t{DE9F0EF4-0ED3-495A-8105-060C0EA457B8}\tTARGETDIR\t4\t\tregdata1\n"
+    "comp2\t{4912DBE7-FC3A-4F91-BB5C-88F5C15C19A5}\tTARGETDIR\t260\t\tregdata2\n";
+
+static const char mixed_registry_dat[] =
+    "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
+    "s72\ti2\tl255\tL255\tL0\ts72\n"
+    "Registry\tRegistry\n"
+    "regdata1\t2\tSOFTWARE\\Wine\\msitest\ttest1\t\tcomp1\n"
+    "regdata2\t2\tSOFTWARE\\Wine\\msitest\ttest2\t\tcomp2\n";
+
+static const char mixed_install_exec_seq_dat[] =
+    "Action\tCondition\tSequence\n"
+    "s72\tS255\tI2\n"
+    "InstallExecuteSequence\tAction\n"
+    "LaunchConditions\t\t100\n"
+    "CostInitialize\t\t200\n"
+    "FileCost\t\t300\n"
+    "CostFinalize\t\t400\n"
+    "InstallValidate\t\t500\n"
+    "InstallInitialize\t\t600\n"
+    "ProcessComponents\t\t700\n"
+    "UnpublishFeatures\t\t800\n"
+    "RemoveRegistryValues\t\t900\n"
+    "WriteRegistryValues\t\t1000\n"
+    "RegisterProduct\t\t1100\n"
+    "PublishFeatures\t\t1200\n"
+    "PublishProduct\t\t1300\n"
+    "InstallFinalize\t\t1400\n";
+
 typedef struct _msi_table
 {
     const CHAR *filename;
@@ -1928,6 +1975,18 @@ static const msi_table uc_tables[] =
     ADD_TABLE(uc_property)
 };
 
+static const msi_table mixed_tables[] =
+{
+    ADD_TABLE(directory),
+    ADD_TABLE(mixed_component),
+    ADD_TABLE(mixed_feature),
+    ADD_TABLE(mixed_feature_comp),
+    ADD_TABLE(mixed_install_exec_seq),
+    ADD_TABLE(mixed_registry),
+    ADD_TABLE(media),
+    ADD_TABLE(property)
+};
+
 /* cabinet definitions */
 
 /* make the max size large so there is only one cab file */
@@ -6618,6 +6677,86 @@ static void test_MsiSetFeatureAttributes(void)
     DeleteFileA( msifile );
 }
 
+static void test_mixed_package(void)
+{
+    UINT r;
+    LONG res;
+    HKEY hkey;
+
+    if (is_process_limited())
+    {
+        skip("process is limited\n");
+        return;
+    }
+    if (!is_wow64 && !is_64bit)
+    {
+        skip("this test must be run on 64-bit\n");
+        return;
+    }
+    MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+    create_database_template(msifile, mixed_tables, sizeof(mixed_tables)/sizeof(msi_table), 200, "x64;1033");
+
+    r = MsiInstallProductA(msifile, NULL);
+    if (r == ERROR_INSTALL_PACKAGE_REJECTED)
+    {
+        skip("Not enough rights to perform tests\n");
+        goto error;
+    }
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
+    ok(!res, "can't open 32-bit component key\n");
+    res = RegQueryValueExA(hkey, "test1", NULL, NULL, NULL, NULL);
+    ok(!res, "value test1 not found\n");
+    RegCloseKey(hkey);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey);
+    ok(!res, "can't open 64-bit component key\n");
+    res = RegQueryValueExA(hkey, "test2", NULL, NULL, NULL, NULL);
+    ok(!res, "value test2 not found\n");
+    RegCloseKey(hkey);
+
+    r = MsiInstallProductA(msifile, "REMOVE=ALL");
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
+    ok(res == ERROR_FILE_NOT_FOUND, "32-bit component key not removed\n");
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey);
+    ok(res == ERROR_FILE_NOT_FOUND, "64-bit component key not removed\n");
+
+    DeleteFileA( msifile );
+    create_database_template(msifile, mixed_tables, sizeof(mixed_tables)/sizeof(msi_table), 200, "Intel;1033");
+
+    r = MsiInstallProductA(msifile, NULL);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
+    ok(!res, "can't open 32-bit component key\n");
+    res = RegQueryValueExA(hkey, "test1", NULL, NULL, NULL, NULL);
+    ok(!res, "value test1 not found\n");
+    RegCloseKey(hkey);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey);
+    ok(!res, "can't open 64-bit component key\n");
+    res = RegQueryValueExA(hkey, "test2", NULL, NULL, NULL, NULL);
+    ok(!res, "value test2 not found\n");
+    RegCloseKey(hkey);
+
+    r = MsiInstallProductA(msifile, "REMOVE=ALL");
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hkey);
+    ok(res == ERROR_FILE_NOT_FOUND, "32-bit component key not removed\n");
+
+    res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine\\msitest", 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hkey);
+    ok(res == ERROR_FILE_NOT_FOUND, "64-bit component key not removed\n");
+
+error:
+    DeleteFileA( msifile );
+    return;
+}
+
 START_TEST(install)
 {
     DWORD len;
@@ -6709,6 +6848,7 @@ START_TEST(install)
     test_upgrade_code();
     test_MsiGetFeatureInfo();
     test_MsiSetFeatureAttributes();
+    test_mixed_package();
 
     DeleteFileA(log_file);
 
-- 
1.7.5.4







More information about the wine-patches mailing list