msi: Add support for 64-bit registry components.
This commit is contained in:
parent
9fa443dcd9
commit
f0ea60049c
|
@ -2554,12 +2554,13 @@ static const WCHAR *get_root_key( MSIPACKAGE *package, INT root, HKEY *root_key
|
||||||
return ret;
|
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 WCHAR prefixW[] = {'S','O','F','T','W','A','R','E','\\'};
|
||||||
static const UINT len = sizeof(prefixW) / sizeof(prefixW[0]);
|
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 ))
|
root == HKEY_LOCAL_MACHINE && !strncmpiW( path, prefixW, len ))
|
||||||
{
|
{
|
||||||
UINT size;
|
UINT size;
|
||||||
|
@ -2574,7 +2575,6 @@ static WCHAR *get_keypath( MSIPACKAGE *package, HKEY root, const WCHAR *path )
|
||||||
strcatW( path_32node, path + len );
|
strcatW( path_32node, path + len );
|
||||||
return path_32node;
|
return path_32node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return strdupW( path );
|
return strdupW( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2634,9 +2634,9 @@ static UINT ITERATE_WriteRegistryValues(MSIRECORD *row, LPVOID param)
|
||||||
strcpyW(uikey,szRoot);
|
strcpyW(uikey,szRoot);
|
||||||
strcatW(uikey,deformated);
|
strcatW(uikey,deformated);
|
||||||
|
|
||||||
keypath = get_keypath( package, root_key, deformated );
|
keypath = get_keypath( comp, root_key, deformated );
|
||||||
msi_free( 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));
|
ERR("Could not create key %s\n", debugstr_w(keypath));
|
||||||
msi_free(uikey);
|
msi_free(uikey);
|
||||||
|
@ -2722,7 +2722,7 @@ static void delete_reg_value( HKEY root, const WCHAR *keypath, const WCHAR *valu
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
DWORD num_subkeys, num_values;
|
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 )))
|
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)
|
if (!res && !num_subkeys && !num_values)
|
||||||
{
|
{
|
||||||
TRACE("removing empty key %s\n", debugstr_w(keypath));
|
TRACE("removing empty key %s\n", debugstr_w(keypath));
|
||||||
RegDeleteKeyW( root, keypath );
|
RegDeleteKeyExW( root, keypath, KEY_WOW64_64KEY, 0 );
|
||||||
}
|
}
|
||||||
return;
|
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 )
|
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);
|
if (res) TRACE("failed to delete key %s (%d)\n", debugstr_w(keypath), res);
|
||||||
|
RegCloseKey( hkey );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ITERATE_RemoveRegistryValuesOnUninstall( MSIRECORD *row, LPVOID param )
|
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 );
|
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 );
|
msi_free( deformated_key );
|
||||||
if (delete_key) delete_reg_key( hkey_root, keypath );
|
if (delete_key) delete_reg_key( hkey_root, keypath );
|
||||||
else delete_reg_value( hkey_root, keypath, deformated_name );
|
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 );
|
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 );
|
msi_free( deformated_key );
|
||||||
if (delete_key) delete_reg_key( hkey_root, keypath );
|
if (delete_key) delete_reg_key( hkey_root, keypath );
|
||||||
else delete_reg_value( hkey_root, keypath, deformated_name );
|
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:
|
case DLL_PROCESS_ATTACH:
|
||||||
msi_hInstance = hinstDLL;
|
msi_hInstance = hinstDLL;
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
|
IsWow64Process( GetCurrentProcess(), &is_wow64 );
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
msi_dialog_unregister_class();
|
msi_dialog_unregister_class();
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
static const BOOL is_64bit = sizeof(void *) > sizeof(int);
|
static const BOOL is_64bit = sizeof(void *) > sizeof(int);
|
||||||
|
BOOL is_wow64;
|
||||||
|
|
||||||
#define MSI_DATASIZEMASK 0x00ff
|
#define MSI_DATASIZEMASK 0x00ff
|
||||||
#define MSITYPE_VALID 0x0100
|
#define MSITYPE_VALID 0x0100
|
||||||
|
|
|
@ -1339,7 +1339,6 @@ static UINT msi_parse_summary( MSISUMMARYINFO *si, MSIPACKAGE *package )
|
||||||
|
|
||||||
static UINT validate_package( MSIPACKAGE *package )
|
static UINT validate_package( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
BOOL is_wow64;
|
|
||||||
UINT i;
|
UINT i;
|
||||||
|
|
||||||
if (package->platform == PLATFORM_INTEL64)
|
if (package->platform == PLATFORM_INTEL64)
|
||||||
|
@ -1348,7 +1347,6 @@ static UINT validate_package( MSIPACKAGE *package )
|
||||||
if (package->platform == PLATFORM_ARM)
|
if (package->platform == PLATFORM_ARM)
|
||||||
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
return ERROR_INSTALL_PLATFORM_UNSUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
IsWow64Process( GetCurrentProcess(), &is_wow64 );
|
|
||||||
if (package->platform == PLATFORM_X64)
|
if (package->platform == PLATFORM_X64)
|
||||||
{
|
{
|
||||||
if (!is_64bit && !is_wow64)
|
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"
|
"PublishProduct\t\t1200\n"
|
||||||
"InstallFinalize\t\t1300\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
|
typedef struct _msi_table
|
||||||
{
|
{
|
||||||
const CHAR *filename;
|
const CHAR *filename;
|
||||||
|
@ -1928,6 +1975,18 @@ static const msi_table uc_tables[] =
|
||||||
ADD_TABLE(uc_property)
|
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 */
|
/* cabinet definitions */
|
||||||
|
|
||||||
/* make the max size large so there is only one cab file */
|
/* make the max size large so there is only one cab file */
|
||||||
|
@ -6618,6 +6677,86 @@ static void test_MsiSetFeatureAttributes(void)
|
||||||
DeleteFileA( msifile );
|
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)
|
START_TEST(install)
|
||||||
{
|
{
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
@ -6709,6 +6848,7 @@ START_TEST(install)
|
||||||
test_upgrade_code();
|
test_upgrade_code();
|
||||||
test_MsiGetFeatureInfo();
|
test_MsiGetFeatureInfo();
|
||||||
test_MsiSetFeatureAttributes();
|
test_MsiSetFeatureAttributes();
|
||||||
|
test_mixed_package();
|
||||||
|
|
||||||
DeleteFileA(log_file);
|
DeleteFileA(log_file);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue