Commit f7b65cc7 authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

- Extend COM_OpenKeyForCLSID to open a subkey and return an HRESULT.

- Fix up the callers and reorganize CoGetClassObject to split out the inproc code into another function.
parent 8c4ead4d
......@@ -978,14 +978,36 @@ INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
}
/* open HKCR\\CLSID\\{string form of clsid} key */
DWORD COM_OpenKeyForCLSID(REFCLSID clsid, REGSAM access, HKEY *key)
/* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */
HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey)
{
static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) - 1];
LONG res;
HKEY key;
strcpyW(path, wszCLSIDSlash);
StringFromGUID2(clsid, path + strlenW(wszCLSIDSlash), CHARS_IN_GUID);
return RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, access, key);
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, keyname ? KEY_READ : access, &key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_CLASSNOTREG;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
if (!keyname)
{
*subkey = key;
return S_OK;
}
res = RegOpenKeyExW(key, keyname, 0, access, subkey);
RegCloseKey(key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_KEYMISSING;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
return S_OK;
}
/******************************************************************************
......@@ -1004,25 +1026,15 @@ DWORD COM_OpenKeyForCLSID(REFCLSID clsid, REGSAM access, HKEY *key)
*/
HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID)
{
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
HKEY hkey = NULL;
HKEY hkey_clsid;
HRESULT ret = S_OK;
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(clsid, KEY_READ, &hkey_clsid))
ret = REGDB_E_CLASSNOTREG;
if (ret == S_OK)
{
if (RegOpenKeyExW(hkey_clsid, wszProgID, 0, KEY_READ, &hkey))
ret = REGDB_E_CLASSNOTREG;
RegCloseKey(hkey_clsid);
}
if (ret == S_OK)
{
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
HKEY hkey;
HRESULT ret;
LONG progidlen = 0;
ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey);
if (FAILED(ret))
return ret;
if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
ret = REGDB_E_CLASSNOTREG;
......@@ -1037,10 +1049,9 @@ HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID)
else
ret = E_OUTOFMEMORY;
}
}
RegCloseKey(hkey);
return ret;
RegCloseKey(hkey);
return ret;
}
/******************************************************************************
......@@ -1526,6 +1537,40 @@ HRESULT COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuen
return hres;
}
static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID riid, void **ppv)
{
HINSTANCE hLibrary;
typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
DllGetClassObjectFunc DllGetClassObject;
WCHAR dllpath[MAX_PATH+1];
if (COM_RegReadPath(hkeydll, NULL, NULL, dllpath, ARRAYSIZE(dllpath)) != ERROR_SUCCESS)
{
/* failure: CLSID is not found in registry */
WARN("class %s not registered inproc\n", debugstr_guid(rclsid));
return REGDB_E_CLASSNOTREG;
}
if ((hLibrary = LoadLibraryExW(dllpath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0)
{
/* failure: DLL could not be loaded */
ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(dllpath));
return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
}
if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
{
/* failure: the dll did not export DllGetClassObject */
ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(dllpath));
FreeLibrary( hLibrary );
return CO_E_DLLNOTFOUND;
}
/* OK: get the ClassObject */
COMPOBJ_DLLList_Add( hLibrary );
return DllGetClassObject(rclsid, riid, ppv);
}
/***********************************************************************
* CoGetClassObject [OLE32.@]
*
......@@ -1571,46 +1616,27 @@ HRESULT WINAPI CoGetClassObject(
if ((CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER) & dwClsContext)
{
static const WCHAR wszInprocServer32[] = {'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
HINSTANCE hLibrary;
typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
DllGetClassObjectFunc DllGetClassObject;
WCHAR dllpath[MAX_PATH+1];
HKEY hkey;
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(rclsid, KEY_READ, &hkey))
hres = COM_OpenKeyForCLSID(rclsid, wszInprocServer32, KEY_READ, &hkey);
if (FAILED(hres))
{
ERR("class %s not registered\n", debugstr_guid(rclsid));
hres = REGDB_E_CLASSNOTREG;
if (hres == REGDB_E_CLASSNOTREG)
ERR("class %s not registered\n", debugstr_guid(rclsid));
else
WARN("class %s not registered inproc\n", debugstr_guid(rclsid));
}
if (COM_RegReadPath(hkey, wszInprocServer32, NULL, dllpath, ARRAYSIZE(dllpath)) != ERROR_SUCCESS)
{
/* failure: CLSID is not found in registry */
WARN("class %s not registered inproc\n", debugstr_guid(rclsid));
hres = REGDB_E_CLASSNOTREG;
}
else
if (SUCCEEDED(hres))
{
if ((hLibrary = LoadLibraryExW(dllpath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0)
{
/* failure: DLL could not be loaded */
ERR("couldn't load InprocServer32 dll %s\n", debugstr_w(dllpath));
hres = E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
}
else if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
{
/* failure: the dll did not export DllGetClassObject */
ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(dllpath));
FreeLibrary( hLibrary );
hres = CO_E_DLLNOTFOUND;
}
else
{
/* OK: get the ClassObject */
COMPOBJ_DLLList_Add( hLibrary );
return DllGetClassObject(rclsid, iid, ppv);
}
hres = get_inproc_class_object(hkey, rclsid, iid, ppv);
RegCloseKey(hkey);
}
/* return if we got a class, otherwise fall through to one of the
* other types */
if (SUCCEEDED(hres))
return hres;
}
/* Next try out of process */
......@@ -2144,16 +2170,12 @@ HRESULT WINAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
LONG len;
HRESULT res = S_OK;
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(clsidOld, KEY_READ, &hkey))
{
res = REGDB_E_CLASSNOTREG;
res = COM_OpenKeyForCLSID(clsidOld, wszAutoConvertTo, KEY_READ, &hkey);
if (FAILED(res))
goto done;
}
len = sizeof(buf);
/* we can just query for the default value of AutoConvertTo key like that,
without opening the AutoConvertTo key and querying for NULL (default) */
if (RegQueryValueW(hkey, wszAutoConvertTo, buf, &len))
if (RegQueryValueW(hkey, NULL, buf, &len))
{
res = REGDB_E_KEYMISSING;
goto done;
......@@ -2191,11 +2213,9 @@ HRESULT WINAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
LONG auto_treat_as_size = sizeof(auto_treat_as);
CLSID id;
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(clsidOld, KEY_READ | KEY_WRITE, &hkey))
{
res = REGDB_E_CLASSNOTREG;
goto done;
}
res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
if (FAILED(res))
goto done;
if (!memcmp( clsidOld, clsidNew, sizeof(*clsidOld) ))
{
if (!RegQueryValueW(hkey, wszAutoTreatAs, auto_treat_as, &auto_treat_as_size) &&
......@@ -2252,12 +2272,10 @@ HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew)
FIXME("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew);
memcpy(clsidNew,clsidOld,sizeof(CLSID)); /* copy over old value */
if (COM_OpenKeyForCLSID(clsidOld, KEY_READ, &hkey))
{
res = REGDB_E_CLASSNOTREG;
goto done;
}
if (RegQueryValueW(hkey, wszTreatAs, szClsidNew, &len))
res = COM_OpenKeyForCLSID(clsidOld, wszTreatAs, KEY_READ, &hkey);
if (FAILED(res))
goto done;
if (RegQueryValueW(hkey, NULL, szClsidNew, &len))
{
res = S_FALSE;
goto done;
......
......@@ -171,7 +171,7 @@ extern void* StdGlobalInterfaceTableInstance;
extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr);
HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id);
DWORD COM_OpenKeyForCLSID(REFCLSID clsid, REGSAM access, HKEY *key);
HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *key);
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
/* Stub Manager */
......
......@@ -353,34 +353,33 @@ HRESULT WINAPI ProgIDFromCLSID16(
LPOLESTR16 *lplpszProgID/* [out] associated Prog ID */
) {
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
HKEY xhkey;
HKEY hkey;
HRESULT ret = S_OK;
HRESULT ret;
LONG len;
char *buffer;
if (COM_OpenKeyForCLSID(clsid, KEY_READ, &hkey))
ret = REGDB_E_CLASSNOTREG;
ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey);
if (FAILED(ret))
return ret;
if ((ret == S_OK) &&
RegOpenKeyW(hkey, wszProgID, &xhkey))
ret = REGDB_E_CLASSNOTREG;
if (RegQueryValueA(hkey, NULL, NULL, &len))
ret = REGDB_E_READREGDB;
if (ret == S_OK)
{
LONG buf2len;
char *buf2 = HeapAlloc(GetProcessHeap(), 0, 255);
buf2len = 255;
if (RegQueryValueA(xhkey, NULL, buf2, &buf2len))
ret = REGDB_E_CLASSNOTREG;
buffer = HeapAlloc(GetProcessHeap(), 0, len);
if (RegQueryValueA(hkey, NULL, buffer, &len))
ret = REGDB_E_READREGDB;
if (ret == S_OK)
{
ret = _xmalloc16(buf2len+1, (SEGPTR*)lplpszProgID);
ret = _xmalloc16(len, (SEGPTR*)lplpszProgID);
if (ret == S_OK)
strcpy(MapSL((SEGPTR)*lplpszProgID),buf2);
strcpy(MapSL((SEGPTR)*lplpszProgID),buffer);
}
HeapFree(GetProcessHeap(), 0, buf2);
HeapFree(GetProcessHeap(), 0, buffer);
}
RegCloseKey(xhkey);
RegCloseKey(hkey);
return ret;
}
......
......@@ -882,37 +882,23 @@ static HRESULT EnumOLEVERB_Construct(HKEY hkeyVerb, ULONG index, IEnumOLEVERB **
HRESULT WINAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB* ppenum)
{
LONG res;
HKEY hkeyClass;
HKEY hkeyVerb;
DWORD dwSubKeys;
static const WCHAR wszVerb[] = {'V','e','r','b',0};
TRACE("(%s, %p)\n", debugstr_guid(clsid), ppenum);
res = COM_OpenKeyForCLSID(clsid, KEY_READ, &hkeyClass);
if (res == ERROR_FILE_NOT_FOUND)
res = COM_OpenKeyForCLSID(clsid, wszVerb, KEY_READ, &hkeyVerb);
if (FAILED(res))
{
ERR("CLSID %s not registered\n", debugstr_guid(clsid));
return REGDB_E_CLASSNOTREG;
}
else if (res != ERROR_SUCCESS)
{
ERR("failed to open key for CLSID %s with error %ld\n",
debugstr_guid(clsid), res);
return REGDB_E_READREGDB;
}
res = RegOpenKeyExW(hkeyClass, wszVerb, 0, KEY_READ, &hkeyVerb);
RegCloseKey(hkeyClass);
if (res == ERROR_FILE_NOT_FOUND)
{
ERR("no Verbs key for class %s\n", debugstr_guid(clsid));
return REGDB_E_KEYMISSING;
}
else if (res != ERROR_SUCCESS)
{
ERR("failed to open Verbs key for CLSID %s with error %ld\n",
debugstr_guid(clsid), res);
return REGDB_E_READREGDB;
if (res == REGDB_E_CLASSNOTREG)
ERR("CLSID %s not registered\n", debugstr_guid(clsid));
else if (res == REGDB_E_KEYMISSING)
ERR("no Verbs key for class %s\n", debugstr_guid(clsid));
else
ERR("failed to open Verbs key for CLSID %s with error %ld\n",
debugstr_guid(clsid), res);
return res;
}
res = RegQueryInfoKeyW(hkeyVerb, NULL, NULL, NULL, &dwSubKeys, NULL,
......@@ -2561,11 +2547,9 @@ HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
if (COM_OpenKeyForCLSID(clsidOld, KEY_READ | KEY_WRITE, &hkey))
{
res = REGDB_E_CLASSNOTREG;
goto done;
}
res = COM_OpenKeyForCLSID(clsidOld, NULL, KEY_READ | KEY_WRITE, &hkey);
if (FAILED(res))
goto done;
StringFromGUID2(clsidNew, szClsidNew, CHARS_IN_GUID);
if (RegSetValueW(hkey, wszAutoConvertTo, REG_SZ, szClsidNew, (strlenW(szClsidNew)+1) * sizeof(WCHAR)))
{
......
......@@ -621,7 +621,6 @@ static HRESULT create_server(REFCLSID rclsid)
{
static const WCHAR wszLocalServer32[] = { 'L','o','c','a','l','S','e','r','v','e','r','3','2',0 };
static const WCHAR embedding[] = { ' ', '-','E','m','b','e','d','d','i','n','g',0 };
HKEY hkeyclsid;
HKEY key;
HRESULT hres;
WCHAR command[MAX_PATH+sizeof(embedding)/sizeof(WCHAR)];
......@@ -629,18 +628,10 @@ static HRESULT create_server(REFCLSID rclsid)
STARTUPINFOW sinfo;
PROCESS_INFORMATION pinfo;
hres = HRESULT_FROM_WIN32(COM_OpenKeyForCLSID(rclsid, KEY_READ, &hkeyclsid));
if (hres != S_OK) {
hres = COM_OpenKeyForCLSID(rclsid, wszLocalServer32, KEY_READ, &key);
if (FAILED(hres)) {
ERR("class %s not registered\n", debugstr_guid(rclsid));
return REGDB_E_READREGDB;
}
hres = RegOpenKeyExW(hkeyclsid, wszLocalServer32, 0, KEY_READ, &key);
RegCloseKey(hkeyclsid);
if (hres != ERROR_SUCCESS) {
WARN("class %s not registered as LocalServer32\n", debugstr_guid(rclsid));
return REGDB_E_READREGDB; /* Probably */
return hres;
}
hres = RegQueryValueExW(key, NULL, NULL, NULL, (LPBYTE)command, &size);
......@@ -713,7 +704,7 @@ static DWORD start_local_service(LPCWSTR name, DWORD num, LPWSTR *params)
*/
static HRESULT create_local_service(REFCLSID rclsid)
{
HRESULT hres = REGDB_E_READREGDB;
HRESULT hres;
WCHAR buf[CHARS_IN_GUID], keyname[50];
static const WCHAR szAppId[] = { 'A','p','p','I','d',0 };
static const WCHAR szAppIdKey[] = { 'A','p','p','I','d','\\',0 };
......@@ -726,11 +717,11 @@ static HRESULT create_local_service(REFCLSID rclsid)
TRACE("Attempting to start Local service for %s\n", debugstr_guid(rclsid));
/* read the AppID value under the class's key */
r = COM_OpenKeyForCLSID(rclsid, KEY_READ, &hkey);
if (r!=ERROR_SUCCESS)
hres = COM_OpenKeyForCLSID(rclsid, szAppId, KEY_READ, &hkey);
if (FAILED(hres))
return hres;
sz = sizeof buf;
r = RegQueryValueExW(hkey, szAppId, NULL, &type, (LPBYTE)buf, &sz);
r = RegQueryValueExW(hkey, NULL, NULL, &type, (LPBYTE)buf, &sz);
RegCloseKey(hkey);
if (r!=ERROR_SUCCESS || type!=REG_SZ)
return hres;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment