[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