msi: Simplify MsiQueryComponentState, with more tests

James Hawkins truiken at gmail.com
Wed Aug 8 20:42:30 CDT 2007


Hi,

Changelog:
* Simplify MsiQueryComponentState, with more tests.

 dlls/msi/msi.c           |  116 +++++++++++++++++++++++++++++++++-------------
 dlls/msi/msipriv.h       |    2 +
 dlls/msi/registry.c      |   64 +++++++++++++++++++++++++
 dlls/msi/tests/install.c |   15 ++----
 dlls/msi/tests/msi.c     |   82 ++++++++++++++++++++++++++++++++-
 5 files changed, 236 insertions(+), 43 deletions(-)

-- 
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index 1b01a4d..61d4e45 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -760,21 +760,88 @@ UINT WINAPI MsiQueryComponentStateA(LPCS
     return r;
 }
 
-UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
-                                    LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
-                                    LPCWSTR szComponent, INSTALLSTATE *pdwState)
+static BOOL msi_comp_find_prod_key(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
 {
-    WCHAR squished_pc[GUID_SIZE];
+    UINT r;
+    HKEY hkey;
+
+    if (context == MSIINSTALLCONTEXT_MACHINE)
+        r = MSIREG_OpenLocalClassesProductKey(prodcode, &hkey, FALSE);
+    else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
+        r = MSIREG_OpenUserProductsKey(prodcode, &hkey, FALSE);
+    else
+        r = MSIREG_OpenLocalManagedProductKey(prodcode, &hkey, FALSE);
+
+    RegCloseKey(hkey);
+    return (r == ERROR_SUCCESS);
+}
+
+static BOOL msi_comp_find_package(LPCWSTR prodcode, MSIINSTALLCONTEXT context)
+{
+    LPCWSTR package;
     HKEY hkey;
-    LONG res;
     DWORD sz;
+    LONG res;
     UINT r;
 
     static const WCHAR local_package[] = {'L','o','c','a','l','P','a','c','k','a','g','e',0};
     static const WCHAR managed_local_package[] = {
-            'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
+        'M','a','n','a','g','e','d','L','o','c','a','l','P','a','c','k','a','g','e',0
     };
 
+    if (context == MSIINSTALLCONTEXT_MACHINE)
+        r = MSIREG_OpenLocalSystemProductKey(prodcode, &hkey, FALSE);
+    else
+        r = MSIREG_OpenInstallPropertiesKey(prodcode, &hkey, FALSE);
+
+    if (r != ERROR_SUCCESS)
+        return FALSE;
+
+    if (context == MSIINSTALLCONTEXT_USERMANAGED)
+        package = managed_local_package;
+    else
+        package = local_package;
+
+    sz = 0;
+    res = RegQueryValueExW(hkey, package, NULL, NULL, NULL, &sz);
+    RegCloseKey(hkey);
+
+    return (res == ERROR_SUCCESS);
+}
+
+static BOOL msi_comp_find_prodcode(LPCWSTR prodcode, LPWSTR squished_pc,
+                                   MSIINSTALLCONTEXT context,
+                                   LPCWSTR comp, DWORD *sz)
+{
+    HKEY hkey;
+    LONG res;
+    UINT r;
+
+    if (context == MSIINSTALLCONTEXT_MACHINE)
+        r = MSIREG_OpenLocalSystemComponentKey(comp, &hkey, FALSE);
+    else
+        r = MSIREG_OpenUserDataComponentKey(comp, &hkey, FALSE);
+
+    if (r != ERROR_SUCCESS)
+        return FALSE;
+
+    *sz = 0;
+    res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, NULL, sz);
+    if (res != ERROR_SUCCESS)
+        return FALSE;
+
+    RegCloseKey(hkey);
+    return TRUE;
+}
+
+UINT WINAPI MsiQueryComponentStateW(LPCWSTR szProductCode,
+                                    LPCWSTR szUserSid, MSIINSTALLCONTEXT dwContext,
+                                    LPCWSTR szComponent, INSTALLSTATE *pdwState)
+{
+    WCHAR squished_pc[GUID_SIZE];
+    BOOL found;
+    DWORD sz;
+
     TRACE("(%s, %s, %d, %s, %p)\n", debugstr_w(szProductCode),
           debugstr_w(szUserSid), dwContext, debugstr_w(szComponent), pdwState);
 
@@ -787,41 +854,24 @@ UINT WINAPI MsiQueryComponentStateW(LPCW
     if (!squash_guid(szProductCode, squished_pc))
         return ERROR_INVALID_PARAMETER;
 
-    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
-        r = MSIREG_OpenLocalSystemProductKey(szProductCode, &hkey, FALSE);
-    else
-        r = MSIREG_OpenInstallPropertiesKey(szProductCode, &hkey, FALSE);
-
-    if (r != ERROR_SUCCESS)
-        return ERROR_UNKNOWN_PRODUCT;
+    found = msi_comp_find_prod_key(szProductCode, dwContext);
 
-    sz = 0;
-    if (dwContext != MSIINSTALLCONTEXT_USERMANAGED)
-        res = RegQueryValueExW(hkey, local_package, NULL, NULL, NULL, &sz);
-    else
-        res = RegQueryValueExW(hkey, managed_local_package, NULL, NULL, NULL, &sz);
+    if (!msi_comp_find_package(szProductCode, dwContext))
+    {
+        if (found)
+        {
+            *pdwState = INSTALLSTATE_UNKNOWN;
+            return ERROR_UNKNOWN_COMPONENT;
+        }
 
-    if (res != ERROR_SUCCESS)
         return ERROR_UNKNOWN_PRODUCT;
+    }
 
-    RegCloseKey(hkey);
     *pdwState = INSTALLSTATE_UNKNOWN;
 
-    if (dwContext == MSIINSTALLCONTEXT_MACHINE)
-        r = MSIREG_OpenLocalSystemComponentKey(szComponent, &hkey, FALSE);
-    else
-        r = MSIREG_OpenUserDataComponentKey(szComponent, &hkey, FALSE);
-
-    if (r != ERROR_SUCCESS)
-        return ERROR_UNKNOWN_COMPONENT;
-
-    sz = 0;
-    res = RegQueryValueExW(hkey, squished_pc, NULL, NULL, NULL, &sz);
-    if (res != ERROR_SUCCESS)
+    if (!msi_comp_find_prodcode(szProductCode, squished_pc, dwContext, szComponent, &sz))
         return ERROR_UNKNOWN_COMPONENT;
 
-    RegCloseKey(hkey);
-
     if (sz == 0)
         *pdwState = INSTALLSTATE_NOTUSED;
     else
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 799e90a..a5bb7b6 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -749,6 +749,8 @@ extern UINT MSIREG_DeleteUserProductKey(
 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_OpenLocalManagedProductKey(LPCWSTR szProductCode, HKEY *key, BOOL create);
 
 extern LPWSTR msi_reg_get_val_str( HKEY hkey, LPCWSTR name );
 extern BOOL msi_reg_get_val_dword( HKEY hkey, LPCWSTR name, DWORD *val);
diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c
index 67eae4b..fd00786 100644
--- a/dlls/msi/registry.c
+++ b/dlls/msi/registry.c
@@ -215,6 +215,21 @@ static const WCHAR szInstaller_LocalSyst
 'S','-','1','-','5','-','1','8','\\',
 'C','o','m','p','o','n','e','n','t','s','\\','%','s',0};
 
+static const WCHAR szInstaller_LocalClassesProd_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','\\',
+'P','r','o','d','u','c','t','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','\\',
+'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','\\',
+'P','r','o','d','u','c','t','s','\\','%','s',0};
 
 #define SQUISH_GUID_SIZE 33
 
@@ -929,6 +944,55 @@ UINT MSIREG_OpenLocalSystemComponentKey(
     return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
 }
 
+UINT MSIREG_OpenLocalClassesProductKey(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_LocalClassesProd_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];
+    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_LocalManagedProd_fmt, usersid, squished_pc);
+    msi_free(usersid);
+
+    if (create)
+        return RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+
+    return RegOpenKeyW(HKEY_LOCAL_MACHINE, keypath, key);
+}
 
 /*************************************************************************
  *  MsiDecomposeDescriptorW   [MSI.@]
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index be54cdb..0e99d34 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -1783,10 +1783,7 @@ static void test_publish(void)
 
     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
-    todo_wine
-    {
-        ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
-    }
+    ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
 
     /* try to uninstall after PublishProduct */
@@ -1826,10 +1823,7 @@ static void test_publish(void)
 
     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
-    todo_wine
-    {
-        ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
-    }
+    ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
 
     /* try it again */
@@ -1852,7 +1846,10 @@ static void test_publish(void)
 
     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
-    ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
+    todo_wine
+    {
+        ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
+    }
     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
 
     /* uninstall has a problem with this */
diff --git a/dlls/msi/tests/msi.c b/dlls/msi/tests/msi.c
index f654aab..867eb42 100644
--- a/dlls/msi/tests/msi.c
+++ b/dlls/msi/tests/msi.c
@@ -698,6 +698,25 @@ static void test_MsiQueryComponentState(
     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
     ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
 
+    state = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
+    ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
+    ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
+
+    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 = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
+    ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
+    ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+
+    RegDeleteKeyA(prodkey, "");
+    RegCloseKey(prodkey);
+
     /* create local system product key */
     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\");
     lstrcatA(keypath, prod_squashed);
@@ -706,10 +725,16 @@ static void test_MsiQueryComponentState(
     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
 
+    /* local system product key exists */
+    state = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
+    ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
+    ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
+
     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
 
-    /* local system product key exists */
+    /* LocalPackage value exists */
     state = 0xdeadbeef;
     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_MACHINE, component, &state);
     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
@@ -758,6 +783,20 @@ static void test_MsiQueryComponentState(
     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
     ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
 
+    lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
+    lstrcatA(keypath, prod_squashed);
+
+    res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+
+    state = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
+    ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
+    ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+
+    RegDeleteKeyA(prodkey, "");
+    RegCloseKey(prodkey);
+
     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
     lstrcatA(keypath, usersid);
     lstrcatA(keypath, "\\Products\\");
@@ -770,6 +809,8 @@ static void test_MsiQueryComponentState(
     res = RegSetValueExA(prodkey, "LocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
 
+    RegCloseKey(prodkey);
+
     state = 0xdeadbeef;
     r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, component, &state);
     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
@@ -813,6 +854,45 @@ static void test_MsiQueryComponentState(
     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
     ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
 
+    lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
+    lstrcatA(keypath, prod_squashed);
+
+    res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+
+    state = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
+    ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
+    ok(state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
+
+    RegDeleteKeyA(prodkey, "");
+    RegCloseKey(prodkey);
+
+    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 = 0xdeadbeef;
+    r = MsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERMANAGED, component, &state);
+    ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
+    ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+
+    RegDeleteKeyA(prodkey, "");
+    RegCloseKey(prodkey);
+
+    lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
+    lstrcatA(keypath, usersid);
+    lstrcatA(keypath, "\\Products\\");
+    lstrcatA(keypath, prod_squashed);
+    lstrcatA(keypath, "\\InstallProperties");
+
+    res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &prodkey);
+    ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
+
     res = RegSetValueExA(prodkey, "ManagedLocalPackage", 0, REG_SZ, (const BYTE *)"msitest.msi", 11);
     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
 
-- 
1.4.1


More information about the wine-patches mailing list