[PATCH v3] ole32: Properly implement OleRegGetUserType()
Nikolay Sivov
nsivov at codeweavers.com
Wed Dec 30 14:48:38 CST 2015
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
v3: fixed test failures
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;
--
2.6.4
More information about the wine-patches
mailing list