[1/3] msi: Enumerate products from all contexts.

Hans Leidekker hans at codeweavers.com
Fri Mar 27 07:40:16 CDT 2009


Fix for office 2007 proofing tools installer.

 -Hans

diff --git a/dlls/msi/registry.c b/dlls/msi/registry.c
index 3205079..3ba34d1 100644
--- a/dlls/msi/registry.c
+++ b/dlls/msi/registry.c
@@ -103,6 +103,12 @@ static const WCHAR szUninstall_fmt[] = {
 'U','n','i','n','s','t','a','l','l','\\',
 '%','s',0 };
 
+static const WCHAR szUserProduct[] = {
+'S','o','f','t','w','a','r','e','\\',
+'M','i','c','r','o','s','o','f','t','\\',
+'I','n','s','t','a','l','l','e','r','\\',
+'P','r','o','d','u','c','t','s',0};
+
 static const WCHAR szUserProduct_fmt[] = {
 'S','o','f','t','w','a','r','e','\\',
 'M','i','c','r','o','s','o','f','t','\\',
@@ -187,6 +193,12 @@ static const WCHAR szInstallProperties_fmt[] = {
 '%','s','\\','P','r','o','d','u','c','t','s','\\','%','s','\\',
 'I','n','s','t','a','l','l','P','r','o','p','e','r','t','i','e','s',0};
 
+static const WCHAR szInstaller_LocalClassesProd[] = {
+'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',0};
+
 static const WCHAR szInstaller_LocalClassesProd_fmt[] = {
 'S','o','f','t','w','a','r','e','\\',
 'C','l','a','s','s','e','s','\\',
@@ -199,6 +211,16 @@ static const WCHAR szInstaller_LocalClassesFeat_fmt[] = {
 'I','n','s','t','a','l','l','e','r','\\',
 'F','e','a','t','u','r','e','s','\\','%','s',0};
 
+static const WCHAR szInstaller_LocalManaged_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',0};
+
 static const WCHAR szInstaller_LocalManagedProd_fmt[] = {
 'S','o','f','t','w','a','r','e','\\',
 'M','i','c','r','o','s','o','f','t','\\',
@@ -1198,25 +1220,108 @@ UINT WINAPI MsiEnumProductsA(DWORD index, LPSTR lpguid)
 
 UINT WINAPI MsiEnumProductsW(DWORD index, LPWSTR lpguid)
 {
-    HKEY hkeyProducts = 0;
-    DWORD r;
+    UINT r;
     WCHAR szKeyName[SQUISH_GUID_SIZE];
+    HKEY key;
+    DWORD machine_count, managed_count, unmanaged_count;
+    WCHAR keypath[MAX_PATH];
+    LPWSTR usersid = NULL;
+
+    static DWORD last_index;
 
     TRACE("%d %p\n", index, lpguid);
 
     if (NULL == lpguid)
         return ERROR_INVALID_PARAMETER;
 
-    r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_Products, &hkeyProducts);
+    if (index && index - last_index != 1)
+        return ERROR_INVALID_PARAMETER;
+
+    r = RegCreateKeyW(HKEY_LOCAL_MACHINE, szInstaller_LocalClassesProd, &key);
     if( r != ERROR_SUCCESS )
         return ERROR_NO_MORE_ITEMS;
 
-    r = RegEnumKeyW(hkeyProducts, index, szKeyName, SQUISH_GUID_SIZE);
-    if( r == ERROR_SUCCESS )
-        unsquash_guid(szKeyName, lpguid);
-    RegCloseKey(hkeyProducts);
+    r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &machine_count, NULL, NULL,
+                         NULL, NULL, NULL, NULL, NULL);
+    if( r != ERROR_SUCCESS )
+    {
+        RegCloseKey(key);
+        return ERROR_NO_MORE_ITEMS;
+    }
 
-    return r;
+    if (machine_count && index <= machine_count)
+    {
+        r = RegEnumKeyW(key, index, szKeyName, SQUISH_GUID_SIZE);
+        if( r == ERROR_SUCCESS )
+        {
+            unsquash_guid(szKeyName, lpguid);
+            last_index = index;
+            RegCloseKey(key);
+            return ERROR_SUCCESS;
+        }
+    }
+    RegCloseKey(key);
+
+    r = get_user_sid(&usersid);
+    if (r != ERROR_SUCCESS || !usersid)
+    {
+        ERR("Failed to retrieve user SID: %d\n", r);
+        return r;
+    }
+    sprintfW(keypath, szInstaller_LocalManaged_fmt, usersid);
+    LocalFree(usersid);
+
+    r = RegCreateKeyW(HKEY_LOCAL_MACHINE, keypath, &key);
+    if( r != ERROR_SUCCESS )
+        return ERROR_NO_MORE_ITEMS;
+
+    r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &managed_count, NULL, NULL,
+                         NULL, NULL, NULL, NULL, NULL);
+    if( r != ERROR_SUCCESS )
+    {
+        RegCloseKey(key);
+        return ERROR_NO_MORE_ITEMS;
+    }
+
+    if (managed_count && index <= machine_count + managed_count)
+    {
+        r = RegEnumKeyW(key, index - machine_count, szKeyName, SQUISH_GUID_SIZE);
+        if( r == ERROR_SUCCESS )
+        {
+            unsquash_guid(szKeyName, lpguid);
+            last_index = index;
+            RegCloseKey(key);
+            return ERROR_SUCCESS;
+        }
+    }
+    RegCloseKey(key);
+
+    r = RegCreateKeyW(HKEY_CURRENT_USER, szUserProduct, &key);
+    if( r != ERROR_SUCCESS )
+        return ERROR_NO_MORE_ITEMS;
+
+    r = RegQueryInfoKeyW(key, NULL, NULL, NULL, &unmanaged_count, NULL, NULL,
+                         NULL, NULL, NULL, NULL, NULL);
+    if( r != ERROR_SUCCESS )
+    {
+        RegCloseKey(key);
+        return ERROR_NO_MORE_ITEMS;
+    }
+
+    if (unmanaged_count && index <= machine_count + managed_count + unmanaged_count)
+    {
+        r = RegEnumKeyW(key, index - machine_count - managed_count, szKeyName, SQUISH_GUID_SIZE);
+        if( r == ERROR_SUCCESS )
+        {
+            unsquash_guid(szKeyName, lpguid);
+            last_index = index;
+            RegCloseKey(key);
+            return ERROR_SUCCESS;
+        }
+    }
+    RegCloseKey(key);
+
+    return ERROR_NO_MORE_ITEMS;
 }
 
 UINT WINAPI MsiEnumFeaturesA(LPCSTR szProduct, DWORD index, 
diff --git a/dlls/msi/tests/automation.c b/dlls/msi/tests/automation.c
index ca40f09..f9ab254 100644
--- a/dlls/msi/tests/automation.c
+++ b/dlls/msi/tests/automation.c
@@ -2022,7 +2022,7 @@ static void test_Installer_Products(BOOL bProductInstalled)
             }
         }
 
-        if (bProductInstalled) todo_wine
+        if (bProductInstalled)
         {
             ok(bProductInstalled == bProductFound, "Product expected to %s installed but product code was %s\n",
                bProductInstalled ? "be" : "not be",



More information about the wine-patches mailing list