diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 2029c1110a4..ff931248742 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -3372,7 +3372,7 @@ static UINT ACTION_PublishProduct(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) goto end; - rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode,&props,TRUE); + rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE); if (rc != ERROR_SUCCESS) goto end; @@ -3905,7 +3905,7 @@ static UINT msi_make_package_local( MSIPACKAGE *package, HKEY hkey ) msi_reg_set_val_str( hkey, INSTALLPROPERTY_LOCALPACKAGEW, packagefile ); - r = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE); + r = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE); if (r != ERROR_SUCCESS) return r; @@ -3995,7 +3995,7 @@ static UINT ACTION_RegisterProduct(MSIPACKAGE *package) if (rc != ERROR_SUCCESS) return rc; - rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &props, TRUE); + rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &props, TRUE); if (rc != ERROR_SUCCESS) return rc; @@ -4295,7 +4295,7 @@ static UINT ACTION_RegisterUser(MSIPACKAGE *package) if (!productid) return ERROR_SUCCESS; - rc = MSIREG_OpenInstallPropertiesKey(package->ProductCode, &hkey, TRUE); + rc = MSIREG_OpenCurrentUserInstallProps(package->ProductCode, &hkey, TRUE); if (rc != ERROR_SUCCESS) goto end; diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c index 32a41732eb7..adc4b6862d0 100644 --- a/dlls/msi/msi.c +++ b/dlls/msi/msi.c @@ -630,7 +630,7 @@ static UINT WINAPI MSI_GetProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, if (classes) MSIREG_OpenLocalSystemProductKey(szProduct, &userdata, FALSE); else - MSIREG_OpenInstallPropertiesKey(szProduct, &userdata, FALSE); + MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE); if (!lstrcmpW(szAttribute, INSTALLPROPERTY_HELPLINKW) || !lstrcmpW(szAttribute, INSTALLPROPERTY_HELPTELEPHONEW) || @@ -939,7 +939,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, if (dwContext == MSIINSTALLCONTEXT_USERUNMANAGED) { package = INSTALLPROPERTY_LOCALPACKAGEW; - MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE); + MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE); if (!props && !prod) goto done; @@ -947,7 +947,7 @@ UINT WINAPI MsiGetProductInfoExW(LPCWSTR szProductCode, LPCWSTR szUserSid, else if (dwContext == MSIINSTALLCONTEXT_USERMANAGED) { package = managed_local_package; - MSIREG_OpenInstallPropertiesKey(szProductCode, &props, FALSE); + MSIREG_OpenCurrentUserInstallProps(szProductCode, &props, FALSE); if (!props && !managed) goto done; @@ -1197,7 +1197,7 @@ static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context) if (context == MSIINSTALLCONTEXT_MACHINE) r = MSIREG_OpenLocalSystemProductKey(prodcode, &hkey, FALSE); else - r = MSIREG_OpenInstallPropertiesKey(prodcode, &hkey, FALSE); + r = MSIREG_OpenCurrentUserInstallProps(prodcode, &hkey, FALSE); if (r != ERROR_SUCCESS) return FALSE; @@ -1303,57 +1303,67 @@ INSTALLSTATE WINAPI MsiQueryProductStateA(LPCSTR szProduct) INSTALLSTATE WINAPI MsiQueryProductStateW(LPCWSTR szProduct) { - UINT rc; - INSTALLSTATE state = INSTALLSTATE_UNKNOWN; - HKEY hkey = 0, props = 0; - DWORD sz; - BOOL userkey_exists = FALSE; + INSTALLSTATE state = INSTALLSTATE_ADVERTISED; + HKEY prodkey = 0, userdata = 0; + BOOL user = TRUE; + DWORD val; + UINT r; - static const int GUID_LEN = 38; - static const WCHAR szInstallProperties[] = { - 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0 - }; static const WCHAR szWindowsInstaller[] = { - 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0 - }; + 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r',0}; TRACE("%s\n", debugstr_w(szProduct)); - if (!szProduct || !*szProduct || lstrlenW(szProduct) != GUID_LEN) + if (!szProduct || !*szProduct) return INSTALLSTATE_INVALIDARG; - rc = MSIREG_OpenUserProductsKey(szProduct,&hkey,FALSE); - if (rc == ERROR_SUCCESS) + if (lstrlenW(szProduct) != GUID_SIZE - 1) + return INSTALLSTATE_INVALIDARG; + + r = MSIREG_OpenLocalManagedProductKey(szProduct, &prodkey, FALSE); + if (r != ERROR_SUCCESS) { - userkey_exists = TRUE; - state = INSTALLSTATE_ADVERTISED; - RegCloseKey(hkey); + r = MSIREG_OpenUserProductsKey(szProduct, &prodkey, FALSE); + if (r != ERROR_SUCCESS) + { + r = MSIREG_OpenLocalClassesProductKey(szProduct, &prodkey, FALSE); + if (r == ERROR_SUCCESS) + user = FALSE; + } } - rc = MSIREG_OpenUserDataProductKey(szProduct,&hkey,FALSE); - if (rc != ERROR_SUCCESS) - goto end; + if (user) + { + r = MSIREG_OpenCurrentUserInstallProps(szProduct, &userdata, FALSE); + if (r != ERROR_SUCCESS) + goto done; + } + else + { + r = MSIREG_OpenLocalSystemInstallProps(szProduct, &userdata, FALSE); + if (r != ERROR_SUCCESS) + goto done; + } - rc = RegOpenKeyW(hkey, szInstallProperties, &props); - if (rc != ERROR_SUCCESS) - goto end; + if (!msi_reg_get_val_dword(userdata, szWindowsInstaller, &val)) + goto done; - sz = sizeof(state); - rc = RegQueryValueExW(props,szWindowsInstaller,NULL,NULL,(LPVOID)&state, &sz); - if (rc != ERROR_SUCCESS) - goto end; - - if (state) + if (val) state = INSTALLSTATE_DEFAULT; else state = INSTALLSTATE_UNKNOWN; - if (state == INSTALLSTATE_DEFAULT && !userkey_exists) - state = INSTALLSTATE_ABSENT; +done: + if (!prodkey) + { + state = INSTALLSTATE_UNKNOWN; -end: - RegCloseKey(props); - RegCloseKey(hkey); + if (userdata) + state = INSTALLSTATE_ABSENT; + } + + RegCloseKey(prodkey); + RegCloseKey(userdata); return state; } diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 43fa9231871..58877ba08a2 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -758,7 +758,8 @@ extern UINT MSIREG_OpenUserDataComponentKey(LPCWSTR szComponent, HKEY *key, BOOL 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); -extern UINT MSIREG_OpenInstallPropertiesKey(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct, HKEY* key, BOOL create); +extern UINT MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserFeaturesKey(LPCWSTR szProduct, HKEY* key, BOOL create); extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create); extern UINT MSIREG_OpenUpgradeCodesKey(LPCWSTR szProduct, HKEY* key, BOOL create); diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c index 1d41e6505cf..74f84f7141d 100644 --- a/dlls/msi/registry.c +++ b/dlls/msi/registry.c @@ -753,18 +753,34 @@ UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create) return rc; } -UINT MSIREG_OpenInstallPropertiesKey(LPCWSTR szProduct, HKEY *key, BOOL create) +static UINT MSIREG_OpenInstallProps(LPCWSTR szProduct, LPCWSTR szUserSID, + HKEY *key, BOOL create) { UINT rc; WCHAR squished_pc[GUID_SIZE]; WCHAR keypath[0x200]; - LPWSTR usersid; 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, szInstallProperties_fmt, szUserSID, squished_pc); + + if (create) + rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); + else + rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); + + return rc; +} + +UINT MSIREG_OpenCurrentUserInstallProps(LPCWSTR szProduct, HKEY *key, + BOOL create) +{ + UINT rc; + LPWSTR usersid; + rc = get_user_sid(&usersid); if (rc != ERROR_SUCCESS || !usersid) { @@ -772,17 +788,20 @@ UINT MSIREG_OpenInstallPropertiesKey(LPCWSTR szProduct, HKEY *key, BOOL create) return rc; } - sprintfW(keypath, szInstallProperties_fmt, usersid, squished_pc); - - if (create) - rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key); - else - rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key); + rc = MSIREG_OpenInstallProps(szProduct, usersid, key, create); LocalFree(usersid); return rc; } +UINT MSIREG_OpenLocalSystemInstallProps(LPCWSTR szProduct, HKEY *key, + BOOL create) +{ + static const WCHAR localsid[] = {'S','-','1','-','5','-','1','8',0}; + + return MSIREG_OpenInstallProps(szProduct, localsid, key, create); +} + UINT MSIREG_DeleteUserDataProductKey(LPCWSTR szProduct) { UINT rc; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 5ac3852416b..7b1d92e8ffe 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -2552,7 +2552,10 @@ static void test_publish_registeruser(void) ok(pf_exists("msitest"), "File not installed\n"); state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}"); - ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + todo_wine + { + ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); + } state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c index bb45d8da8fe..b704d2b13b8 100644 --- a/dlls/msi/tests/msi.c +++ b/dlls/msi/tests/msi.c @@ -414,6 +414,7 @@ static void test_MsiQueryProductState(void) INSTALLSTATE state; LONG res; HKEY userkey, localkey, props; + HKEY prodkey; DWORD data; create_test_guid(prodcode, prod_squashed); @@ -443,7 +444,8 @@ static void test_MsiQueryProductState(void) state = MsiQueryProductStateA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93"); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); - /* created guid cannot possibly be an installed product code */ + /* MSIINSTALLCONTEXT_USERUNMANAGED */ + state = MsiQueryProductStateA(prodcode); ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state); @@ -519,13 +521,109 @@ static void test_MsiQueryProductState(void) state = MsiQueryProductStateA(prodcode); ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state); - LocalFree(usersid); RegDeleteValueA(props, "WindowsInstaller"); RegDeleteKeyA(props, ""); - RegDeleteKeyA(localkey, ""); - RegCloseKey(userkey); - RegCloseKey(localkey); RegCloseKey(props); + RegDeleteKeyA(localkey, ""); + RegCloseKey(localkey); + RegDeleteKeyA(userkey, ""); + RegCloseKey(userkey); + + /* MSIINSTALLCONTEXT_USERMANAGED */ + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, + "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, usersid); + lstrcatA(keypath, "\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, + "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegCreateKeyA(localkey, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, + "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + data = 1; + res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD)); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* WindowsInstaller value exists */ + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); + + RegDeleteValueA(props, "WindowsInstaller"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(localkey, ""); + RegCloseKey(localkey); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + /* MSIINSTALLCONTEXT_MACHINE */ + + lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\"); + lstrcatA(keypath, "S-1-5-18\\Products\\"); + lstrcatA(keypath, prod_squashed); + + res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, + "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + res = RegCreateKeyA(localkey, "InstallProperties", &props); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_ADVERTISED, + "Expected INSTALLSTATE_ADVERTISED, got %d\n", state); + + data = 1; + res = RegSetValueExA(props, "WindowsInstaller", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD)); + ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res); + + /* WindowsInstaller value exists */ + state = MsiQueryProductStateA(prodcode); + ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state); + + RegDeleteValueA(props, "WindowsInstaller"); + RegDeleteKeyA(props, ""); + RegCloseKey(props); + RegDeleteKeyA(localkey, ""); + RegCloseKey(localkey); + RegDeleteKeyA(prodkey, ""); + RegCloseKey(prodkey); + + LocalFree(usersid); } static const char table_enc85[] =