Theodore Dubois : shell32: Fix return value for ASSOCSTR_FRIENDLYDOCNAME and ASSOCSTR_DEFAULTICON when passed a ProgID.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 21 11:21:11 CDT 2016


Module: wine
Branch: master
Commit: 04a339e770e790440042392a2411944bd6b733c6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=04a339e770e790440042392a2411944bd6b733c6

Author: Theodore Dubois <tblodt at icloud.com>
Date:   Wed Mar 16 13:19:50 2016 -0700

shell32: Fix return value for ASSOCSTR_FRIENDLYDOCNAME and ASSOCSTR_DEFAULTICON when passed a ProgID.

Signed-off-by: Theodore Dubois <tblodt at icloud.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/shell32/assoc.c | 133 ++++++++++++++++++++++++++++-----------------------
 1 file changed, 72 insertions(+), 61 deletions(-)

diff --git a/dlls/shell32/assoc.c b/dlls/shell32/assoc.c
index 90d00a8..a3d21b9 100644
--- a/dlls/shell32/assoc.c
+++ b/dlls/shell32/assoc.c
@@ -88,6 +88,8 @@ static inline struct enumassochandlers *impl_from_IEnumAssocHandlers(IEnumAssocH
   return CONTAINING_RECORD(iface, struct enumassochandlers, IEnumAssocHandlers_iface);
 }
 
+static HRESULT ASSOC_GetValue(HKEY hkey, const WCHAR *name, void **data, DWORD *data_size);
+
 /**************************************************************************
  *  IQueryAssociations_QueryInterface
  *
@@ -196,10 +198,16 @@ static HRESULT WINAPI IQueryAssociations_fnInit(
 	FIXME("unsupported flags: %x\n", cfFlags);
 
     RegCloseKey(This->hkeySource);
-    RegCloseKey(This->hkeyProgID);
+    if (This->hkeySource != This->hkeyProgID)
+        RegCloseKey(This->hkeyProgID);
     This->hkeySource = This->hkeyProgID = NULL;
+
+    /* If the process of initializing hkeyProgID fails, just return S_OK. That's what Windows does. */
     if (pszAssoc != NULL)
     {
+        WCHAR *progId;
+        HRESULT hr;
+
         ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,
                             pszAssoc,
                             0,
@@ -207,22 +215,51 @@ static HRESULT WINAPI IQueryAssociations_fnInit(
                             &This->hkeySource);
         if (ret)
             return S_OK;
-        /* if this is not a prog id */
-        if ((*pszAssoc == '.') || (*pszAssoc == '{'))
+        /* if this is a progid */
+        if (*pszAssoc != '.' && *pszAssoc != '{')
         {
-            RegOpenKeyExW(This->hkeySource,
-                          szProgID,
-                          0,
-                          KEY_READ,
-                          &This->hkeyProgID);
-        }
-        else
             This->hkeyProgID = This->hkeySource;
+            return S_OK;
+        }
+
+        /* if it's not a progid, it's a file extension or clsid */
+        if (*pszAssoc == '.')
+        {
+            /* for a file extension, the progid is the default value */
+            hr = ASSOC_GetValue(This->hkeySource, NULL, (void**)&progId, NULL);
+            if (FAILED(hr))
+                return S_OK;
+        }
+        else /* if (*pszAssoc == '{') */
+        {
+            HKEY progIdKey;
+            /* for a clsid, the progid is the default value of the ProgID subkey */
+            ret = RegOpenKeyExW(This->hkeySource,
+                                szProgID,
+                                0,
+                                KEY_READ,
+                                &progIdKey);
+            if (ret != ERROR_SUCCESS)
+                return S_OK;
+            hr = ASSOC_GetValue(progIdKey, NULL, (void**)&progId, NULL);
+            if (FAILED(hr))
+                return S_OK;
+            RegCloseKey(progIdKey);
+        }
+
+        /* open the actual progid key, the one with the shell subkey */
+        ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,
+                            progId,
+                            0,
+                            KEY_READ,
+                            &This->hkeyProgID);
+        HeapFree(GetProcessHeap(), 0, progId);
+
         return S_OK;
     }
     else if (hkeyProgid != NULL)
     {
-        This->hkeyProgID = hkeyProgid;
+        This->hkeySource = This->hkeyProgID = hkeyProgid;
         return S_OK;
     }
     else
@@ -507,33 +544,15 @@ static HRESULT WINAPI IQueryAssociations_fnGetString(
 
     case ASSOCSTR_FRIENDLYDOCNAME:
     {
-      WCHAR *pszFileType;
-      DWORD ret;
-      DWORD size;
+      WCHAR *docName;
 
-      hr = ASSOC_GetValue(This->hkeySource, NULL, (void**)&pszFileType, NULL);
-      if (FAILED(hr))
-        return hr;
-      size = 0;
-      ret = RegGetValueW(HKEY_CLASSES_ROOT, pszFileType, NULL, RRF_RT_REG_SZ, NULL, NULL, &size);
-      if (ret == ERROR_SUCCESS)
-      {
-        WCHAR *docName = HeapAlloc(GetProcessHeap(), 0, size);
-        if (docName)
-        {
-          ret = RegGetValueW(HKEY_CLASSES_ROOT, pszFileType, NULL, RRF_RT_REG_SZ, NULL, docName, &size);
-          if (ret == ERROR_SUCCESS)
-            hr = ASSOC_ReturnString(flags, pszOut, pcchOut, docName, strlenW(docName) + 1);
-          else
-            hr = HRESULT_FROM_WIN32(ret);
-          HeapFree(GetProcessHeap(), 0, docName);
-        }
-        else
-          hr = E_OUTOFMEMORY;
+      hr = ASSOC_GetValue(This->hkeyProgID, NULL, (void**)&docName, NULL);
+      if (FAILED(hr)) {
+          /* hKeyProgID is NULL or there is no default value, so fail */
+          return HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
       }
-      else
-        hr = HRESULT_FROM_WIN32(ret);
-      HeapFree(GetProcessHeap(), 0, pszFileType);
+      hr = ASSOC_ReturnString(flags, pszOut, pcchOut, docName, strlenW(docName) + 1);
+      HeapFree(GetProcessHeap(), 0, docName);
       return hr;
     }
 
@@ -623,41 +642,33 @@ get_friendly_name_fail:
     case ASSOCSTR_DEFAULTICON:
     {
       static const WCHAR DefaultIconW[] = {'D','e','f','a','u','l','t','I','c','o','n',0};
-      WCHAR *pszFileType;
+      static const WCHAR documentIcon[] = {'s','h','e','l','l','3','2','.','d','l','l',',','0',0};
       DWORD ret;
       DWORD size;
-      HKEY hkeyFile;
 
-      hr = ASSOC_GetValue(This->hkeySource, NULL, (void**)&pszFileType, NULL);
-      if (FAILED(hr))
-        return hr;
-      ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, pszFileType, 0, KEY_READ, &hkeyFile);
+      size = 0;
+      ret = RegGetValueW(This->hkeyProgID, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, NULL, &size);
       if (ret == ERROR_SUCCESS)
       {
-        size = 0;
-        ret = RegGetValueW(hkeyFile, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, NULL, &size);
-        if (ret == ERROR_SUCCESS)
+        WCHAR *icon = HeapAlloc(GetProcessHeap(), 0, size);
+        if (icon)
         {
-          WCHAR *icon = HeapAlloc(GetProcessHeap(), 0, size);
-          if (icon)
-          {
-            ret = RegGetValueW(hkeyFile, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, icon, &size);
-            if (ret == ERROR_SUCCESS)
-              hr = ASSOC_ReturnString(flags, pszOut, pcchOut, icon, strlenW(icon) + 1);
-            else
-              hr = HRESULT_FROM_WIN32(ret);
-            HeapFree(GetProcessHeap(), 0, icon);
-          }
+          ret = RegGetValueW(This->hkeyProgID, DefaultIconW, NULL, RRF_RT_REG_SZ, NULL, icon, &size);
+          if (ret == ERROR_SUCCESS)
+            hr = ASSOC_ReturnString(flags, pszOut, pcchOut, icon, strlenW(icon) + 1);
           else
-            hr = E_OUTOFMEMORY;
+            hr = HRESULT_FROM_WIN32(ret);
+          HeapFree(GetProcessHeap(), 0, icon);
         }
         else
-          hr = HRESULT_FROM_WIN32(ret);
-        RegCloseKey(hkeyFile);
+          hr = E_OUTOFMEMORY;
+      } else {
+          /* there is no DefaultIcon subkey or hkeyProgID is NULL, so return the default document icon */
+          if (This->hkeyProgID == NULL)
+              hr = ASSOC_ReturnString(flags, pszOut, pcchOut, documentIcon, strlenW(documentIcon) + 1);
+          else
+              return HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
       }
-      else
-        hr = HRESULT_FROM_WIN32(ret);
-      HeapFree(GetProcessHeap(), 0, pszFileType);
       return hr;
     }
     case ASSOCSTR_SHELLEXTENSION:




More information about the wine-cvs mailing list