msi 4: Use the correct registry key when detecting a published product

James Hawkins truiken at gmail.com
Tue Jun 26 21:01:03 CDT 2007


Hi,

Causes a todo_wine in the automation tests because PublishProduct is
still publishing to the wrong location (will be fixed in a later
patch).  If this is a problem, let me know.

Changelog:
* Use the correct registry key when detecting a published product.

 dlls/msi/msi.c              |   14 ++++++++--
 dlls/msi/msipriv.h          |    1 +
 dlls/msi/registry.c         |   59 +++++++++++++++++++++++++++++++++++++++++++
 dlls/msi/tests/automation.c |    5 +++-
 dlls/msi/tests/msi.c        |   26 ++++++++++++++++---
 5 files changed, 97 insertions(+), 8 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 7240ea4..fce1bc5 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -763,10 +763,13 @@ INSTALLSTATE WINAPI MsiQueryProductState
 {
     UINT rc;
     INSTALLSTATE state = INSTALLSTATE_UNKNOWN;
-    HKEY hkey = 0;
+    HKEY hkey = 0, props = 0;
     DWORD sz;
 
     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
     };
@@ -783,12 +786,16 @@ INSTALLSTATE WINAPI MsiQueryProductState
     state = INSTALLSTATE_ADVERTISED;
     RegCloseKey(hkey);
 
-    rc = MSIREG_OpenUninstallKey(szProduct,&hkey,FALSE);
+    rc = MSIREG_OpenUserDataProductKey(szProduct,&hkey,FALSE);
+    if (rc != ERROR_SUCCESS)
+        goto end;
+
+    rc = RegOpenKeyW(hkey, szInstallProperties, &props);
     if (rc != ERROR_SUCCESS)
         goto end;
 
     sz = sizeof(state);
-    rc = RegQueryValueExW(hkey,szWindowsInstaller,NULL,NULL,(LPVOID)&state, &sz);
+    rc = RegQueryValueExW(props,szWindowsInstaller,NULL,NULL,(LPVOID)&state, &sz);
     if (rc != ERROR_SUCCESS)
         goto end;
 
@@ -804,6 +811,7 @@ INSTALLSTATE WINAPI MsiQueryProductState
         break;
     }
 end:
+    RegCloseKey(props);
     RegCloseKey(hkey);
     return state;
 }
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index fc28f05..455db78 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -682,6 +682,7 @@ extern UINT MSIREG_OpenComponents(HKEY* 
 extern UINT MSIREG_OpenUserComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
 extern UINT MSIREG_OpenComponentsKey(LPCWSTR szComponent, HKEY* key, BOOL create);
 extern UINT MSIREG_OpenProductsKey(LPCWSTR szProduct, HKEY* key, BOOL create);
+extern UINT MSIREG_OpenUserDataProductKey(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 14a4754..21e0804 100644
--- a/dlls/msi/registry.c
+++ b/dlls/msi/registry.c
@@ -36,6 +36,7 @@ #include "wincrypt.h"
 #include "wine/unicode.h"
 #include "winver.h"
 #include "winuser.h"
+#include "sddl.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msi);
 
@@ -140,6 +141,15 @@ static const WCHAR szInstaller_UserUpgra
 'U','p','g','r','a','d','e','C','o','d','e','s','\\',
 '%','s',0};
 
+static const WCHAR szUserDataProd_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','\\','P','r','o','d','u','c','t','s','\\','%','s',0};
+
 
 #define SQUISH_GUID_SIZE 33
 
@@ -501,6 +511,55 @@ UINT MSIREG_OpenUserComponentsKey(LPCWST
     return rc;
 }
 
+static UINT get_user_sid(LPWSTR *usersid)
+{
+    HANDLE token;
+    BYTE buf[1024];
+    DWORD size;
+    PTOKEN_USER user;
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
+        return ERROR_FUNCTION_FAILED;
+
+    size = sizeof(buf);
+    if (!GetTokenInformation(token, TokenUser, (void *)buf, size, &size))
+        return ERROR_FUNCTION_FAILED;
+
+    user = (PTOKEN_USER)buf;
+    if (!ConvertSidToStringSidW(user->User.Sid, usersid))
+        return ERROR_FUNCTION_FAILED;
+
+    return ERROR_SUCCESS;
+}
+
+UINT MSIREG_OpenUserDataProductKey(LPCWSTR szProduct, HKEY *key, BOOL create)
+{
+    UINT rc;
+    WCHAR squished_pc[GUID_SIZE];
+    WCHAR keypath[0x200];
+    LPWSTR usersid;
+
+    TRACE("%s\n", debugstr_w(szProduct));
+    squash_guid(szProduct, squished_pc);
+    TRACE("squished (%s)\n", debugstr_w(squished_pc));
+
+    rc = get_user_sid(&usersid);
+    if (rc != ERROR_SUCCESS || !usersid)
+    {
+        ERR("Failed to retrieve user SID: %d\n", rc);
+        return rc;
+    }
+
+    sprintfW(keypath, szUserDataProd_fmt, usersid, squished_pc);
+
+    if (create)
+        rc = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+    else
+        rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+
+    return rc;
+}
+
 UINT MSIREG_OpenProducts(HKEY* key)
 {
     return RegCreateKeyW(HKEY_LOCAL_MACHINE,szInstaller_Products,key);
diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c
index 7308671..84c3627 100644
--- a/dlls/msi/tests/automation.c
+++ b/dlls/msi/tests/automation.c
@@ -2110,7 +2110,10 @@ static void test_Installer_InstallProduc
     /* Installer::ProductState for our product code, which has been installed */
     hr = Installer_ProductState(szProductCode, &iValue);
     ok(hr == S_OK, "Installer_ProductState failed, hresult 0x%08x\n", hr);
-    ok(iValue == INSTALLSTATE_DEFAULT, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_DEFAULT);
+    todo_wine
+    {
+        ok(iValue == INSTALLSTATE_DEFAULT, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_DEFAULT);
+    }
 
     /* Installer::ProductInfo for our product code */
 
diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c
index 9afa576..4e42fea 100644
--- a/dlls/msi/tests/msi.c
+++ b/dlls/msi/tests/msi.c
@@ -379,6 +379,27 @@ static void test_MsiQueryProductState(vo
     state = MsiQueryProductStateA(prodcode);
     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
 
+    lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
+    lstrcatA(keypath, prodcode);
+
+    res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &localkey);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+
+    /* local uninstall key exists */
+    state = MsiQueryProductStateA(prodcode);
+    ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
+
+    data = 1;
+    res = RegSetValueExA(localkey, "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_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
+
+    RegDeleteValueA(localkey, "WindowsInstaller");
+    RegDeleteKeyA(localkey, "");
+
     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
     lstrcatA(keypath, usersid);
     lstrcatA(keypath, "\\Products\\");
@@ -404,10 +425,7 @@ static void test_MsiQueryProductState(vo
 
     /* WindowsInstaller value exists */
     state = MsiQueryProductStateA(prodcode);
-    todo_wine
-    {
-        ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
-    }
+    ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
 
     RegDeleteKeyA(userkey, "");
 
-- 
1.4.1


More information about the wine-patches mailing list