Commit f0ea6004 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

msi: Add support for 64-bit registry components.

parent 9fa443dc
......@@ -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 );
......
......@@ -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();
......
......@@ -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
......
......@@ -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)
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment