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

Signed-off-by: Theodore Dubois <tblodt@icloud.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Theodore Dubois 2016-03-16 13:19:50 -07:00 committed by Alexandre Julliard
parent 446ee50b90
commit 04a339e770
1 changed files with 72 additions and 61 deletions

View File

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