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