diff --git a/dlls/msi/action.c b/dlls/msi/action.c index d3aeb38d1d2..c42c4f90f91 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -3733,19 +3733,35 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) { MSIFEATURE *feature; UINT rc; - HKEY hukey=0; - HKEY userdata=0; + HKEY hkey; + HKEY userdata; if (!msi_check_publish(package)) return ERROR_SUCCESS; - rc = MSIREG_OpenUserFeaturesKey(package->ProductCode,&hukey,TRUE); - if (rc != ERROR_SUCCESS) - goto end; + if (package->Context == MSIINSTALLCONTEXT_MACHINE) + { + rc = MSIREG_OpenLocalClassesFeaturesKey(package->ProductCode, + &hkey, TRUE); + if (rc != ERROR_SUCCESS) + goto end; - rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, &userdata, TRUE); - if (rc != ERROR_SUCCESS) - goto end; + rc = MSIREG_OpenLocalUserDataFeaturesKey(package->ProductCode, + &userdata, TRUE); + if (rc != ERROR_SUCCESS) + goto end; + } + else + { + rc = MSIREG_OpenUserFeaturesKey(package->ProductCode, &hkey, TRUE); + if (rc != ERROR_SUCCESS) + goto end; + + rc = MSIREG_OpenUserDataFeaturesKey(package->ProductCode, + &userdata, TRUE); + if (rc != ERROR_SUCCESS) + goto end; + } /* here the guids are base 85 encoded */ LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry ) @@ -3806,7 +3822,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) { static const WCHAR emptyW[] = {0}; size += sizeof(WCHAR); - RegSetValueExW(hukey,feature->Feature,0,REG_SZ, + RegSetValueExW(hkey,feature->Feature,0,REG_SZ, (LPBYTE)(feature->Feature_Parent ? feature->Feature_Parent : emptyW),size); } else @@ -3817,7 +3833,7 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) data[1] = 0; if (feature->Feature_Parent) strcpyW( &data[1], feature->Feature_Parent ); - RegSetValueExW(hukey,feature->Feature,0,REG_SZ, + RegSetValueExW(hkey,feature->Feature,0,REG_SZ, (LPBYTE)data,size); msi_free(data); } @@ -3831,7 +3847,8 @@ static UINT ACTION_PublishFeatures(MSIPACKAGE *package) } end: - RegCloseKey(hukey); + RegCloseKey(hkey); + RegCloseKey(userdata); return rc; } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 098206543e1..b045710ef8a 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -785,7 +785,9 @@ extern UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct); extern UINT MSIREG_OpenLocalSystemProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); +extern UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create); extern UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create); +extern UINT MSIREG_OpenLocalUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create); extern UINT MSIREG_DeleteUserFeaturesKey(LPCWSTR szProduct); extern UINT MSIREG_DeleteLocalUserDataComponentKey(LPCWSTR szComponent); extern UINT MSIREG_DeleteUserDataComponentKey(LPCWSTR szComponent); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index 6135b470024..7b586a8740b 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -204,6 +204,12 @@ static const WCHAR szInstaller_LocalClassesProd_fmt[] = { 'I','n','s','t','a','l','l','e','r','\\', 'P','r','o','d','u','c','t','s','\\','%','s',0}; +static const WCHAR szInstaller_LocalClassesFeat_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'C','l','a','s','s','e','s','\\', +'I','n','s','t','a','l','l','e','r','\\', +'F','e','a','t','u','r','e','s','\\','%','s',0}; + static const WCHAR szInstaller_LocalManagedProd_fmt[] = { 'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\', @@ -647,6 +653,24 @@ UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create) return rc; } +UINT MSIREG_OpenLocalUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProduct)); + if (!squash_guid(szProduct, squished_pc)) + return ERROR_FUNCTION_FAILED; + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szUserDataFeatures_fmt, localsid, squished_pc); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) { UINT rc; @@ -1016,6 +1040,26 @@ UINT MSIREG_OpenLocalClassesProductKey(LPCWSTR szProductCode, HKEY *key, BOOL cr return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_OpenLocalClassesFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + sprintfW(keypath, szInstaller_LocalClassesFeat_fmt, squished_pc); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create) { WCHAR squished_pc[GUID_SIZE]; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 9a952d3888c..bc3757168d6 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -2500,6 +2500,8 @@ static void test_publish_publishfeatures(void) "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features"; static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion" "\\Installer\\Features"; + static const CHAR classfeat[] = "Software\\Classes\\Installer\\Features" + "\\84A88FD7F6998CE40A22FB59F6B9C2BB"; get_user_sid(&usersid); if (!usersid) @@ -2524,6 +2526,9 @@ static void test_publish_publishfeatures(void) res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey); ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); @@ -2547,6 +2552,41 @@ static void test_publish_publishfeatures(void) RegDeleteKeyA(hkey, ""); RegCloseKey(hkey); + /* PublishFeatures, machine */ + r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1 ALLUSERS=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey); + ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res); + + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_REG_STR(hkey, "feature", ""); + CHECK_REG_STR(hkey, "montecristo", ""); + + RegDeleteValueA(hkey, "feature"); + RegDeleteValueA(hkey, "montecristo"); + RegDeleteKeyA(hkey, ""); + RegCloseKey(hkey); + + sprintf(keypath, udpath, "S-1-5-18"); + res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE"); + CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE"); + + RegDeleteValueA(hkey, "feature"); + RegDeleteValueA(hkey, "montecristo"); + RegDeleteKeyA(hkey, ""); + RegCloseKey(hkey); + DeleteFile(msifile); DeleteFile("msitest\\maximus"); RemoveDirectory("msitest");