On 07.02.2016 1:09, Theodore Dubois wrote:
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@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>
Why do you need this?
This->hkeyProgID = This->hkeySource;
I know it's not something you introduced, but it's dirty and should be fixed, because it leads to double free on a same handle.
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)
} else if (hkeyProgid != NULL)return HRESULT_FROM_WIN32(ret); return S_OK;
@@ -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;
Basically you remove everything, and tests don't show that you should do that. For example looking at Win7 registry I see HKCR.exe with default value of "exefile", then default value for HKCR\exefile is Application (and also there is a FriendlyTypeName key that's most likely localized). Current code will return "Application" and that seems like a better candidate for a friendly name.
A convincing test should create a custom extension key, and test all possible combinations of empty default values, missing keys with default value name etc.
@@ -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;
Same.