Module: wine Branch: master Commit: 4f6230d5c46c3e2287e56c426889bb6220b36289 URL: http://source.winehq.org/git/wine.git/?a=commit;h=4f6230d5c46c3e2287e56c4268...
Author: Nikolay Sivov nsivov@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; }