diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index b3525953e3d783b760ff2d237d3dcbf7e19ccfed..b669c37225cd6073cbed4c5586e38623c5bca3a4 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -1229,7 +1229,7 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) { WCHAR squishProduct[33], comp[GUID_SIZE]; GUID guid; - LPWSTR components, p, parent_feature; + LPWSTR components, p, parent_feature, path; UINT rc; HKEY hkey; INSTALLSTATE r; @@ -1284,17 +1284,18 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR szProduct, LPCWSTR szFeature) } StringFromGUID2(&guid, comp, GUID_SIZE); - r = MsiGetComponentPathW(szProduct, comp, NULL, 0); - TRACE("component %s state %d\n", debugstr_guid(&guid), r); - switch (r) + rc = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE); + if (rc != ERROR_SUCCESS) { - case INSTALLSTATE_NOTUSED: - case INSTALLSTATE_LOCAL: - case INSTALLSTATE_SOURCE: - break; - default: - missing = TRUE; + msi_free(components); + return INSTALLSTATE_ADVERTISED; } + + path = msi_reg_get_val_str(hkey, squishProduct); + if (!path) + missing = TRUE; + + msi_free(path); } TRACE("%s %s -> %d\n", debugstr_w(szProduct), debugstr_w(szFeature), r); diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 33ca02757bf66e49fdcac879a1110976f29d6496..bb85e9ab1685dab3815f1cbb9f9523b131df1979 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -707,6 +707,7 @@ extern UINT MSIREG_OpenUserDataFeaturesKey(LPCWSTR szProduct, HKEY *key, BOOL cr extern UINT MSIREG_OpenComponents(HKEY* key); extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); +extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create); extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenPatchesKey(LPCWSTR szPatch, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY* key, BOOL create); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index 22a2498bdb91a3b823684f8fca6fff06c6edd492..b9c0af4ceaa005390af05779b02cd65978b8a332 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -103,6 +103,15 @@ static const WCHAR szUser_Components_fmt[] = { 'C','o','m','p','o','n','e','n','t','s','\\', '%','s',0}; +static const WCHAR szUserDataComp_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','\\', +'U','s','e','r','D','a','t','a','\\', +'%','s','\\','C','o','m','p','o','n','e','n','t','s','\\','%','s',0}; + static const WCHAR szUninstall_fmt[] = { 'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\', @@ -631,6 +640,35 @@ UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create) return rc; } +UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL create) +{ + UINT rc; + WCHAR comp[GUID_SIZE]; + WCHAR keypath[0x200]; + LPWSTR usersid; + + TRACE("%s\n", debugstr_w(szComponent)); + squash_guid(szComponent, comp); + TRACE("squished (%s)\n", debugstr_w(comp)); + + rc = get_user_sid(&usersid); + if (rc != ERROR_SUCCESS || !usersid) + { + ERR("Failed to retrieve user SID: %d\n", rc); + return rc; + } + + sprintfW(keypath, szUserDataComp_fmt, usersid, comp); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + msi_free(usersid); + return rc; +} + UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) { UINT rc; diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index 78145719ea1e5c0df63f0e1b33ed1eb60934d62a..38126d46dd9415310037325df1c33c19bb6619be 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -626,19 +626,13 @@ 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_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); RegDeleteValueA(compkey, "");