[v2] shell32: fix two bugs in IQueryAssocations
Theodore Dubois
tblodt at icloud.com
Sat Feb 6 16:09:57 CST 2016
Basically, returns the correct value for
ASSOCSTR_FRIENDLYDOCNAME and ASSOCSTR_DEFAULTICON
when passed a ProgID instead of a file extension.
Also adds some tests to make sure it works.
Signed-off-by: Theodore Dubois <tblodt at icloud.com>
---
dlls/shell32/assoc.c | 115 +++++++++++++++++++++++----------------------
dlls/shell32/tests/assoc.c | 12 ++++-
2 files changed, 70 insertions(+), 57 deletions(-)
diff --git a/dlls/shell32/assoc.c b/dlls/shell32/assoc.c
index 90d00a8..49af3c3 100644
--- a/dlls/shell32/assoc.c
+++ b/dlls/shell32/assoc.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
+#include <assert.h>
#define COBJMACROS
#include "windef.h"
@@ -88,6 +89,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
*
@@ -200,6 +203,9 @@ static HRESULT WINAPI IQueryAssociations_fnInit(
This->hkeySource = This->hkeyProgID = NULL;
if (pszAssoc != NULL)
{
+ WCHAR *progId;
+ HRESULT hr;
+
ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,
pszAssoc,
0,
@@ -207,17 +213,48 @@ 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 hr;
+ }
+ else /* if (*pszAssoc == '{') */
+ {
+ assert(*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 HRESULT_FROM_WIN32(ret);
+ hr = ASSOC_GetValue(progIdKey, NULL, (void**)&progId, NULL);
+ if (FAILED(hr))
+ return hr;
+ RegCloseKey(progIdKey);
+ }
+
+ /* open the actual progid key, the one with the shell subkey */
+ ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,
+ progId,
+ 0,
+ KEY_READ,
+ &This->hkeyProgID);
+ if (ret != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(ret);
return S_OK;
}
else if (hkeyProgid != NULL)
@@ -507,33 +544,12 @@ 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);
+ hr = ASSOC_GetValue(This->hkeyProgID, NULL, (void**)&docName, 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;
- }
- else
- hr = HRESULT_FROM_WIN32(ret);
- HeapFree(GetProcessHeap(), 0, pszFileType);
+ hr = ASSOC_ReturnString(flags, pszOut, pcchOut, docName, strlenW(docName) + 1);
return hr;
}
@@ -623,41 +639,28 @@ 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;
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
hr = HRESULT_FROM_WIN32(ret);
- HeapFree(GetProcessHeap(), 0, pszFileType);
return hr;
}
case ASSOCSTR_SHELLEXTENSION:
diff --git a/dlls/shell32/tests/assoc.c b/dlls/shell32/tests/assoc.c
index 8aa2535..8e42446 100644
--- a/dlls/shell32/tests/assoc.c
+++ b/dlls/shell32/tests/assoc.c
@@ -91,12 +91,18 @@ struct assoc_getstring_test
};
static const WCHAR httpW[] = {'h','t','t','p',0};
+static const WCHAR dot_urlW[] = {'.','u','r','l',0};
+static const WCHAR InternetShortcutW[] = {'I','n','t','e','r','n','e','t','S','h','o','r','t','c','u','t',0};
static const WCHAR badW[] = {'b','a','d','b','a','d',0};
static struct assoc_getstring_test getstring_tests[] =
{
{ httpW, 0, ASSOCSTR_EXECUTABLE, 2, 0x8007007a /* E_NOT_SUFFICIENT_BUFFER */, S_OK },
{ httpW, ASSOCF_NOTRUNCATE, ASSOCSTR_EXECUTABLE, 2, E_POINTER },
+ { InternetShortcutW, 0, ASSOCSTR_DEFAULTICON, 0, S_OK, 0x80070002 /* HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) */},
+ { InternetShortcutW, 0, ASSOCSTR_FRIENDLYDOCNAME, 0, S_OK, 0x80070002 /* HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) */},
+ { dot_urlW, 0, ASSOCSTR_DEFAULTICON, 0, S_OK, 0x80070002 },
+ { dot_urlW, 0, ASSOCSTR_FRIENDLYDOCNAME, 0, S_OK, 0x80070002 },
{ NULL }
};
@@ -128,6 +134,8 @@ static void test_IQueryAssociations_GetString(void)
ok(hr == S_OK, "%d: Init failed, 0x%x\n", i, hr);
len = ptr->len;
+ if (ptr->len == 0)
+ len = MAX_PATH;
buffW[0] = ptr->flags & ASSOCF_NOTRUNCATE ? 0x1 : 0;
hr = IQueryAssociations_GetString(assoc, ptr->flags, ptr->str, NULL, buffW, &len);
if (hr != ptr->hr)
@@ -135,7 +143,9 @@ static void test_IQueryAssociations_GetString(void)
else
{
ok(hr == ptr->hr, "%d: GetString failed, 0x%08x\n", i, hr);
- ok(len > ptr->len, "%d: got needed length %d\n", i, len);
+ /* len = 0 means we're not testing that */
+ if (ptr->len != 0)
+ ok(len >= ptr->len, "%d: got needed length %d\n", i, len);
}
/* even with ASSOCF_NOTRUNCATE it's null terminated */
--
2.5.4 (Apple Git-61)
More information about the wine-patches
mailing list