Nikolay Sivov : shell32: Fix search for a command string to cover more cases ( like protocol associations).

Alexandre Julliard julliard at winehq.org
Mon Sep 9 16:08:08 CDT 2013


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Sep  9 09:26:40 2013 +0400

shell32: Fix search for a command string to cover more cases (like protocol associations).

---

 dlls/shell32/assoc.c |  113 ++++++++++++++++++++++++++-----------------------
 1 files changed, 60 insertions(+), 53 deletions(-)

diff --git a/dlls/shell32/assoc.c b/dlls/shell32/assoc.c
index ad23c7d..65f4644 100644
--- a/dlls/shell32/assoc.c
+++ b/dlls/shell32/assoc.c
@@ -240,79 +240,86 @@ static HRESULT ASSOC_GetValue(HKEY hkey, const WCHAR *name, void **data, DWORD *
   return S_OK;
 }
 
-static HRESULT ASSOC_GetCommand(IQueryAssociationsImpl *This,
-                                LPCWSTR pszExtra, WCHAR **ppszCommand)
+static HRESULT ASSOC_GetCommand(IQueryAssociationsImpl *This, const WCHAR *extra, WCHAR **command)
 {
   HKEY hkeyCommand;
-  HKEY hkeyFile;
   HKEY hkeyShell;
   HKEY hkeyVerb;
   HRESULT hr;
   LONG ret;
-  WCHAR * pszExtraFromReg = NULL;
-  WCHAR * pszFileType;
+  WCHAR *extra_from_reg = NULL;
+  WCHAR *filetype;
   static const WCHAR commandW[] = { 'c','o','m','m','a','n','d',0 };
   static const WCHAR shellW[] = { 's','h','e','l','l',0 };
 
-  hr = ASSOC_GetValue(This->hkeySource, NULL, (void**)&pszFileType, NULL);
-  if (FAILED(hr))
-    return hr;
-  ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, pszFileType, 0, KEY_READ, &hkeyFile);
-  HeapFree(GetProcessHeap(), 0, pszFileType);
-  if (ret != ERROR_SUCCESS)
-    return HRESULT_FROM_WIN32(ret);
+  /* When looking for file extension it's possible to have a default value
+     that points to another key that contains 'shell/<verb>/command' subtree. */
+  hr = ASSOC_GetValue(This->hkeySource, NULL, (void**)&filetype, NULL);
+  if (hr == S_OK)
+  {
+      HKEY hkeyFile;
 
-  ret = RegOpenKeyExW(hkeyFile, shellW, 0, KEY_READ, &hkeyShell);
-  RegCloseKey(hkeyFile);
-  if (ret != ERROR_SUCCESS)
-    return HRESULT_FROM_WIN32(ret);
+      ret = RegOpenKeyExW(HKEY_CLASSES_ROOT, filetype, 0, KEY_READ, &hkeyFile);
+      HeapFree(GetProcessHeap(), 0, filetype);
+      if (ret) return HRESULT_FROM_WIN32(ret);
 
-  if (!pszExtra)
+      ret = RegOpenKeyExW(hkeyFile, shellW, 0, KEY_READ, &hkeyShell);
+      RegCloseKey(hkeyFile);
+      if (ret) return HRESULT_FROM_WIN32(ret);
+  }
+  else
   {
-    hr = ASSOC_GetValue(hkeyShell, NULL, (void**)&pszExtraFromReg, NULL);
-    /* if no default action */
-    if (hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
-    {
-      DWORD rlen;
-      ret = RegQueryInfoKeyW(hkeyShell, 0, 0, 0, 0, &rlen, 0, 0, 0, 0, 0, 0);
-      if (ret != ERROR_SUCCESS)
-      {
-        RegCloseKey(hkeyShell);
-        return HRESULT_FROM_WIN32(ret);
-      }
-      rlen++;
-      pszExtraFromReg = HeapAlloc(GetProcessHeap(), 0, rlen * sizeof(WCHAR));
-      if (!pszExtraFromReg)
-      {
-        RegCloseKey(hkeyShell);
-        return E_OUTOFMEMORY;
-      }
-      ret = RegEnumKeyExW(hkeyShell, 0, pszExtraFromReg, &rlen, 0, NULL, NULL, NULL);
-      if (ret != ERROR_SUCCESS)
+      ret = RegOpenKeyExW(This->hkeySource, shellW, 0, KEY_READ, &hkeyShell);
+      if (ret) return HRESULT_FROM_WIN32(ret);
+  }
+
+  if (!extra)
+  {
+      /* check for default verb */
+      hr = ASSOC_GetValue(hkeyShell, NULL, (void**)&extra_from_reg, NULL);
+      if (FAILED(hr))
       {
-        RegCloseKey(hkeyShell);
-        return HRESULT_FROM_WIN32(ret);
+          /* no default verb, try first subkey */
+          DWORD max_subkey_len;
+
+          ret = RegQueryInfoKeyW(hkeyShell, NULL, NULL, NULL, NULL, &max_subkey_len, NULL, NULL, NULL, NULL, NULL, NULL);
+          if (ret)
+          {
+              RegCloseKey(hkeyShell);
+              return HRESULT_FROM_WIN32(ret);
+          }
+
+          max_subkey_len++;
+          extra_from_reg = HeapAlloc(GetProcessHeap(), 0, max_subkey_len * sizeof(WCHAR));
+          if (!extra_from_reg)
+          {
+              RegCloseKey(hkeyShell);
+              return E_OUTOFMEMORY;
+          }
+
+          ret = RegEnumKeyExW(hkeyShell, 0, extra_from_reg, &max_subkey_len, NULL, NULL, NULL, NULL);
+          if (ret)
+          {
+              HeapFree(GetProcessHeap(), 0, extra_from_reg);
+              RegCloseKey(hkeyShell);
+              return HRESULT_FROM_WIN32(ret);
+          }
       }
-    }
-    else if (FAILED(hr))
-    {
-      RegCloseKey(hkeyShell);
-      return hr;
-    }
+      extra = extra_from_reg;
   }
 
-  ret = RegOpenKeyExW(hkeyShell, pszExtra ? pszExtra : pszExtraFromReg, 0,
-                      KEY_READ, &hkeyVerb);
-  HeapFree(GetProcessHeap(), 0, pszExtraFromReg);
+  /* open verb subkey */
+  ret = RegOpenKeyExW(hkeyShell, extra, 0, KEY_READ, &hkeyVerb);
+  HeapFree(GetProcessHeap(), 0, extra_from_reg);
   RegCloseKey(hkeyShell);
-  if (ret != ERROR_SUCCESS)
-    return HRESULT_FROM_WIN32(ret);
+  if (ret) return HRESULT_FROM_WIN32(ret);
 
+  /* open command subkey */
   ret = RegOpenKeyExW(hkeyVerb, commandW, 0, KEY_READ, &hkeyCommand);
   RegCloseKey(hkeyVerb);
-  if (ret != ERROR_SUCCESS)
-    return HRESULT_FROM_WIN32(ret);
-  hr = ASSOC_GetValue(hkeyCommand, NULL, (void**)ppszCommand, NULL);
+  if (ret) return HRESULT_FROM_WIN32(ret);
+
+  hr = ASSOC_GetValue(hkeyCommand, NULL, (void**)command, NULL);
   RegCloseKey(hkeyCommand);
   return hr;
 }




More information about the wine-cvs mailing list