Module: wine Branch: master Commit: 8fe18a16f7f5e0326d2fe6ab32ef2aad947b343d URL: http://source.winehq.org/git/wine.git/?a=commit;h=8fe18a16f7f5e0326d2fe6ab32...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Wed Dec 30 23:48:38 2015 +0300
ole32: Properly implement OleRegGetUserType().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ole32/ole2.c | 84 ++++++++++++++++++----------------- dlls/ole32/tests/compobj.c | 106 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 41 deletions(-)
diff --git a/dlls/ole32/ole2.c b/dlls/ole32/ole2.c index e7e6510..7929d3d 100644 --- a/dlls/ole32/ole2.c +++ b/dlls/ole32/ole2.c @@ -661,69 +661,73 @@ HRESULT WINAPI RevokeDragDrop(HWND hwnd)
/*********************************************************************** * OleRegGetUserType (OLE32.@) - * - * This implementation of OleRegGetUserType ignores the dwFormOfType - * parameter and always returns the full name of the object. This is - * not too bad since this is the case for many objects because of the - * way they are registered. - */ -HRESULT WINAPI OleRegGetUserType( - REFCLSID clsid, - DWORD dwFormOfType, - LPOLESTR* pszUserType) -{ - DWORD dwKeyType; - DWORD cbData; - HKEY clsidKey; + */ +HRESULT WINAPI OleRegGetUserType(REFCLSID clsid, DWORD form, LPOLESTR *usertype) +{ + static const WCHAR auxusertypeW[] = {'A','u','x','U','s','e','r','T','y','p','e','\','%','d',0}; + DWORD valuetype, valuelen; + WCHAR auxkeynameW[16]; + HKEY usertypekey; HRESULT hres; LONG ret;
- TRACE("(%s, %d, %p)\n", debugstr_guid(clsid), dwFormOfType, pszUserType); + TRACE("(%s, %u, %p)\n", debugstr_guid(clsid), form, usertype);
- if (!pszUserType) + if (!usertype) return E_INVALIDARG;
- *pszUserType = NULL; + *usertype = NULL;
- hres = COM_OpenKeyForCLSID(clsid, NULL, KEY_READ, &clsidKey); + /* Return immediately if it's not registered. */ + hres = COM_OpenKeyForCLSID(clsid, NULL, KEY_READ, &usertypekey); if (FAILED(hres)) return hres;
- /* - * Retrieve the size of the name string. - */ - cbData = 0; + valuelen = 0;
- if (RegQueryValueExW(clsidKey, emptyW, NULL, &dwKeyType, NULL, &cbData)) + /* Try additional types if requested. If they don't exist fall back to USERCLASSTYPE_FULL. */ + if (form != USERCLASSTYPE_FULL) { - RegCloseKey(clsidKey); - return REGDB_E_READREGDB; + HKEY auxkey; + + sprintfW(auxkeynameW, auxusertypeW, form); + if (COM_OpenKeyForCLSID(clsid, auxkeynameW, KEY_READ, &auxkey) == S_OK) + { + if (!RegQueryValueExW(auxkey, emptyW, NULL, &valuetype, NULL, &valuelen) && valuelen) + { + RegCloseKey(usertypekey); + usertypekey = auxkey; + } + else + RegCloseKey(auxkey); + } }
- /* - * Allocate a buffer for the registry value. - */ - *pszUserType = CoTaskMemAlloc(cbData); + valuelen = 0; + if (RegQueryValueExW(usertypekey, emptyW, NULL, &valuetype, NULL, &valuelen)) + { + RegCloseKey(usertypekey); + return REGDB_E_READREGDB; + }
- if (*pszUserType==NULL) + *usertype = CoTaskMemAlloc(valuelen); + if (!*usertype) { - RegCloseKey(clsidKey); + RegCloseKey(usertypekey); return E_OUTOFMEMORY; }
- ret = RegQueryValueExW(clsidKey, + ret = RegQueryValueExW(usertypekey, emptyW, NULL, - &dwKeyType, - (LPBYTE) *pszUserType, - &cbData); - - RegCloseKey(clsidKey); - + &valuetype, + (LPBYTE)*usertype, + &valuelen); + RegCloseKey(usertypekey); if (ret != ERROR_SUCCESS) { - CoTaskMemFree(*pszUserType); - *pszUserType = NULL; + CoTaskMemFree(*usertype); + *usertype = NULL; return REGDB_E_READREGDB; }
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 792d7dc..5fe9876 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -2229,11 +2229,29 @@ static void test_OleRegGetUserType(void) { static const WCHAR stdfont_usertypeW[] = {'S','t','a','n','d','a','r','d',' ','F','o','n','t',0}; static const WCHAR stdfont2_usertypeW[] = {'C','L','S','I','D','_','S','t','d','F','o','n','t',0}; + static const WCHAR clsidkeyW[] = {'C','L','S','I','D',0}; + static const WCHAR defvalueW[] = {'D','e','f','a','u','l','t',' ','N','a','m','e',0}; + static const WCHAR auxvalue0W[] = {'A','u','x',' ','N','a','m','e',' ','0',0}; + static const WCHAR auxvalue2W[] = {'A','u','x',' ','N','a','m','e',' ','2',0}; + static const WCHAR auxvalue3W[] = {'A','u','x',' ','N','a','m','e',' ','3',0}; + static const WCHAR auxvalue4W[] = {'A','u','x',' ','N','a','m','e',' ','4',0}; + + static const char auxvalues[][16] = { + "Aux Name 0", + "Aux Name 1", + "Aux Name 2", + "Aux Name 3", + "Aux Name 4" + }; + + HKEY clsidhkey, hkey, auxhkey, classkey; + DWORD form, ret, disposition; + WCHAR clsidW[39]; ULONG_PTR cookie; HANDLE handle; HRESULT hr; WCHAR *str; - DWORD form; + int i;
for (form = 0; form <= USERCLASSTYPE_APPNAME+1; form++) { hr = OleRegGetUserType(&CLSID_Testclass, form, NULL); @@ -2273,7 +2291,93 @@ static void test_OleRegGetUserType(void) pDeactivateActCtx(0, cookie); pReleaseActCtx(handle); } + + /* test using registered CLSID */ + StringFromGUID2(&CLSID_non_existent, clsidW, sizeof(clsidW)/sizeof(clsidW[0])); + + ret = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsidkeyW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &clsidhkey, &disposition); + if (ret == ERROR_ACCESS_DENIED) + { + skip("Failed to create test key, skipping some of OleRegGetUserType() tests.\n"); + return; + } + + ok(!ret, "failed to create a key %d, error %d\n", ret, GetLastError()); + + ret = RegCreateKeyExW(clsidhkey, clsidW, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &classkey, NULL); + ok(!ret, "failed to create a key %d, error %d\n", ret, GetLastError()); + + ret = RegSetValueExW(classkey, NULL, 0, REG_SZ, (const BYTE*)defvalueW, sizeof(defvalueW)); + ok(!ret, "got %d, error %d\n", ret, GetLastError()); + + ret = RegCreateKeyExA(classkey, "AuxUserType", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &auxhkey, NULL); + ok(!ret, "got %d, error %d\n", ret, GetLastError()); + + /* populate AuxUserType */ + for (i = 0; i <= 4; i++) { + char name[16]; + + sprintf(name, "AuxUserType\%d", i); + ret = RegCreateKeyExA(classkey, name, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); + ok(!ret, "got %d, error %d\n", ret, GetLastError()); + + ret = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE*)auxvalues[i], strlen(auxvalues[i])); + ok(!ret, "got %d, error %d\n", ret, GetLastError()); + RegCloseKey(hkey); + } + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, 0, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, auxvalue0W), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_FULL, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_SHORT, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, auxvalue2W), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, auxvalue3W), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+1, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, auxvalue4W), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + str = NULL; + hr = OleRegGetUserType(&CLSID_non_existent, USERCLASSTYPE_APPNAME+2, &str); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(!lstrcmpW(str, defvalueW), "got %s\n", wine_dbgstr_w(str)); + CoTaskMemFree(str); + + /* registry cleanup */ + for (i = 0; i <= 4; i++) + { + char name[2]; + sprintf(name, "%d", i); + RegDeleteKeyA(auxhkey, name); + } + RegCloseKey(auxhkey); + RegDeleteKeyA(classkey, "AuxUserType"); + RegCloseKey(classkey); + RegDeleteKeyW(clsidhkey, clsidW); + RegCloseKey(clsidhkey); + if (disposition == REG_CREATED_NEW_KEY) + RegDeleteKeyA(HKEY_CLASSES_ROOT, "CLSID"); } + static void test_CoCreateGuid(void) { HRESULT hr;