diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 1aaf4d9..b2e1345 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1821,10 +1821,11 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) if (!squash_guid( szProduct, squishProduct )) return INSTALLSTATE_INVALIDARG; - /* check that it's installed at all */ - rc = MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE); - if (rc != ERROR_SUCCESS) + if (MSIREG_OpenManagedFeaturesKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS && + MSIREG_OpenUserFeaturesKey(szProduct, &hkey, FALSE) != ERROR_SUCCESS) + { return INSTALLSTATE_UNKNOWN; + } parent_feature = msi_reg_get_val_str( hkey, szFeature ); RegCloseKey(hkey); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 18a029f..fe880c6 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -788,6 +788,7 @@ extern UINT MSIREG_OpenLocalSystemComponentKey(LPCWSTR szComponent, HKEY *key, B 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_OpenManagedFeaturesKey(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); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index beb98a8..a12a825 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -220,6 +220,16 @@ static const WCHAR szInstaller_LocalManagedProd_fmt[] = { 'I','n','s','t','a','l','l','e','r','\\', 'P','r','o','d','u','c','t','s','\\','%','s',0}; +static const WCHAR szInstaller_LocalManagedFeat_fmt[] = { +'S','o','f','t','w','a','r','e','\\', +'M','i','c','r','o','s','o','f','t','\\', +'W','i','n','d','o','w','s','\\', +'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', +'I','n','s','t','a','l','l','e','r','\\', +'M','a','n','a','g','e','d','\\','%','s','\\', +'I','n','s','t','a','l','l','e','r','\\', +'F','e','a','t','u','r','e','s','\\','%','s',0}; + static const WCHAR szInstaller_ClassesUpgrade_fmt[] = { 'I','n','s','t','a','l','l','e','r','\\', 'U','p','g','r','a','d','e','C','o','d','e','s','\\', @@ -1128,6 +1138,36 @@ UINT MSIREG_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL cr return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); } +UINT MSIREG_OpenManagedFeaturesKey(LPCWSTR szProductCode, HKEY *key, BOOL create) +{ + WCHAR squished_pc[GUID_SIZE]; + WCHAR keypath[0x200]; + LPWSTR usersid; + UINT r; + + TRACE("%s\n", debugstr_w(szProductCode)); + + if (!squash_guid(szProductCode, squished_pc)) + return ERROR_FUNCTION_FAILED; + + TRACE("squished (%s)\n", debugstr_w(squished_pc)); + + r = get_user_sid(&usersid); + if (r != ERROR_SUCCESS || !usersid) + { + ERR("Failed to retrieve user SID: %d\n", r); + return r; + } + + sprintfW(keypath, szInstaller_LocalManagedFeat_fmt, usersid, squished_pc); + LocalFree(usersid); + + if (create) + return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); +} + UINT MSIREG_OpenClassesUpgradeCodesKey(LPCWSTR szUpgradeCode, HKEY* key, BOOL create) { WCHAR squished_pc[GUID_SIZE]; diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index 1945b44..f094c2d 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -842,10 +842,7 @@ static void test_MsiQueryFeatureState(void) /* feature value exists */ state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); lstrcatA(keypath, usersid); @@ -858,46 +855,31 @@ static void test_MsiQueryFeatureState(void) /* userdata features key exists */ state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaa", 20); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state); - } + ok(state == INSTALLSTATE_BADCONFIG, "Expected INSTALLSTATE_BADCONFIG, got %d\n", state); res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaa", 21); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)"aaaaaaaaaaaaaaaaaaaaa", 22); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); res = RegSetValueExA(localkey, "feature", 0, REG_SZ, (const BYTE *)comp_base85, 21); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); lstrcatA(keypath, usersid); @@ -908,28 +890,19 @@ static void test_MsiQueryFeatureState(void) ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); - } + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"", 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"apple", 1); ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); state = MsiQueryFeatureStateA(prodcode, "feature"); - todo_wine - { - ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); - } + ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state); RegDeleteValueA(compkey, prod_squashed); RegDeleteKeyA(compkey, ""); -- 1.5.4.3