mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 10:41:12 +00:00
- Change some of the registry helper functions to use the unicode
versions of the CLSID & registry functions. - Reindent CoGetClassObject and output an error message if the class isn't registered. - Add tests for the touched functions.
This commit is contained in:
parent
843cd506c5
commit
f419880d64
5 changed files with 169 additions and 90 deletions
|
@ -76,6 +76,8 @@ typedef LPCSTR LPCOLESTR16;
|
|||
|
||||
HINSTANCE OLE32_hInstance = 0; /* FIXME: make static ... */
|
||||
|
||||
#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
/****************************************************************************
|
||||
* This section defines variables internal to the COM module.
|
||||
*
|
||||
|
@ -981,6 +983,16 @@ 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)
|
||||
{
|
||||
static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
|
||||
WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) - 1];
|
||||
strcpyW(path, wszCLSIDSlash);
|
||||
StringFromGUID2(clsid, path + strlenW(wszCLSIDSlash), CHARS_IN_GUID);
|
||||
return RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, access, key);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ProgIDFromCLSID [OLE32.@]
|
||||
*
|
||||
|
@ -997,43 +1009,42 @@ INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
|
|||
*/
|
||||
HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *lplpszProgID)
|
||||
{
|
||||
char strCLSID[50], *buf, *buf2;
|
||||
DWORD buf2len;
|
||||
HKEY xhkey;
|
||||
LPMALLOC mllc;
|
||||
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
|
||||
HKEY hkey = NULL;
|
||||
HKEY hkey_clsid;
|
||||
HRESULT ret = S_OK;
|
||||
|
||||
WINE_StringFromCLSID(clsid, strCLSID);
|
||||
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, strlen(strCLSID)+14);
|
||||
sprintf(buf,"CLSID\\%s\\ProgID", strCLSID);
|
||||
if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
|
||||
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(clsid, KEY_READ, &hkey_clsid))
|
||||
ret = REGDB_E_CLASSNOTREG;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
if (ret == S_OK)
|
||||
{
|
||||
buf2 = HeapAlloc(GetProcessHeap(), 0, 255);
|
||||
buf2len = 255;
|
||||
if (RegQueryValueA(xhkey, NULL, buf2, &buf2len))
|
||||
if (RegOpenKeyExW(hkey_clsid, wszProgID, 0, KEY_READ, &hkey))
|
||||
ret = REGDB_E_CLASSNOTREG;
|
||||
RegCloseKey(hkey_clsid);
|
||||
}
|
||||
|
||||
if (ret == S_OK)
|
||||
{
|
||||
DWORD progidlen = 0;
|
||||
|
||||
if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
|
||||
ret = REGDB_E_CLASSNOTREG;
|
||||
|
||||
if (ret == S_OK)
|
||||
{
|
||||
if (CoGetMalloc(0,&mllc))
|
||||
ret = E_OUTOFMEMORY;
|
||||
else
|
||||
*lplpszProgID = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
|
||||
if (*lplpszProgID)
|
||||
{
|
||||
DWORD len = MultiByteToWideChar( CP_ACP, 0, buf2, -1, NULL, 0 );
|
||||
*lplpszProgID = IMalloc_Alloc(mllc, len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_ACP, 0, buf2, -1, *lplpszProgID, len );
|
||||
if (RegQueryValueW(hkey, NULL, *lplpszProgID, &progidlen))
|
||||
ret = REGDB_E_CLASSNOTREG;
|
||||
}
|
||||
else
|
||||
ret = E_OUTOFMEMORY;
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, buf2);
|
||||
RegCloseKey(xhkey);
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1089,7 +1100,7 @@ HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid)
|
|||
HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid)
|
||||
{
|
||||
static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
|
||||
char buf2[80];
|
||||
WCHAR buf2[CHARS_IN_GUID];
|
||||
DWORD buf2len = sizeof(buf2);
|
||||
HKEY xhkey;
|
||||
|
||||
|
@ -1103,13 +1114,13 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid)
|
|||
}
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
|
||||
if (RegQueryValueA(xhkey,NULL,buf2,&buf2len))
|
||||
if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
|
||||
{
|
||||
RegCloseKey(xhkey);
|
||||
return CO_E_CLASSSTRING;
|
||||
}
|
||||
RegCloseKey(xhkey);
|
||||
return __CLSIDFromStringA(buf2,riid);
|
||||
return CLSIDFromString(buf2,riid);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1151,46 +1162,41 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid)
|
|||
*/
|
||||
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
|
||||
{
|
||||
char *buf, buf2[40];
|
||||
DWORD buf2len;
|
||||
HKEY xhkey;
|
||||
static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0};
|
||||
static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
|
||||
WCHAR path[ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAYSIZE(wszPSC)];
|
||||
WCHAR value[CHARS_IN_GUID];
|
||||
DWORD len;
|
||||
HKEY hkey;
|
||||
|
||||
TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
|
||||
|
||||
/* Get the input iid as a string */
|
||||
WINE_StringFromCLSID(riid, buf2);
|
||||
/* Allocate memory for the registry key we will construct.
|
||||
(length of iid string plus constant length of static text */
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, strlen(buf2)+27);
|
||||
if (buf == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
/* Construct the registry key we want */
|
||||
sprintf(buf,"Interface\\%s\\ProxyStubClsid32", buf2);
|
||||
/* Interface\\{string form of riid}\\ProxyStubClsid32 */
|
||||
strcpyW(path, wszInterface);
|
||||
StringFromGUID2(riid, path + ARRAYSIZE(wszInterface) - 1, CHARS_IN_GUID);
|
||||
strcpyW(path + ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1, wszPSC);
|
||||
|
||||
/* Open the key.. */
|
||||
if (RegOpenKeyA(HKEY_CLASSES_ROOT, buf, &xhkey))
|
||||
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &hkey))
|
||||
{
|
||||
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
return REGDB_E_IIDNOTREG;
|
||||
}
|
||||
HeapFree(GetProcessHeap(),0,buf);
|
||||
|
||||
/* ... Once we have the key, query the registry to get the
|
||||
value of CLSID as a string, and convert it into a
|
||||
proper CLSID structure to be passed back to the app */
|
||||
buf2len = sizeof(buf2);
|
||||
if ( (RegQueryValueA(xhkey,NULL,buf2,&buf2len)) )
|
||||
len = sizeof(value);
|
||||
if (ERROR_SUCCESS != RegQueryValueW(hkey, NULL, value, &len))
|
||||
{
|
||||
RegCloseKey(xhkey);
|
||||
RegCloseKey(hkey);
|
||||
return REGDB_E_IIDNOTREG;
|
||||
}
|
||||
RegCloseKey(xhkey);
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/* We have the CLSid we want back from the registry as a string, so
|
||||
lets convert it into a CLSID structure */
|
||||
if ( (__CLSIDFromStringA(buf2,pclsid)) != NOERROR)
|
||||
if (CLSIDFromString(value, pclsid) != NOERROR)
|
||||
return REGDB_E_IIDNOTREG;
|
||||
|
||||
TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
|
||||
|
@ -1528,25 +1534,24 @@ end:
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* compobj_RegReadPath [internal]
|
||||
* COM_RegReadPath [internal]
|
||||
*
|
||||
* Reads a registry value and expands it when necessary
|
||||
*/
|
||||
static HRESULT
|
||||
compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen)
|
||||
HRESULT COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen)
|
||||
{
|
||||
HRESULT hres;
|
||||
HKEY key;
|
||||
DWORD keytype;
|
||||
char src[MAX_PATH];
|
||||
DWORD dwLength = dstlen;
|
||||
WCHAR src[MAX_PATH];
|
||||
DWORD dwLength = dstlen * sizeof(WCHAR);
|
||||
|
||||
if((hres = RegOpenKeyExA(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) {
|
||||
if( (hres = RegQueryValueExA(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) {
|
||||
if((hres = RegOpenKeyExW(hkeyroot, keyname, 0, KEY_READ, &key)) == ERROR_SUCCESS) {
|
||||
if( (hres = RegQueryValueExW(key, NULL, NULL, &keytype, (LPBYTE)src, &dwLength)) == ERROR_SUCCESS ) {
|
||||
if (keytype == REG_EXPAND_SZ) {
|
||||
if (dstlen <= ExpandEnvironmentStringsA(src, dst, dstlen)) hres = ERROR_MORE_DATA;
|
||||
if (dstlen <= ExpandEnvironmentStringsW(src, dst, dstlen)) hres = ERROR_MORE_DATA;
|
||||
} else {
|
||||
lstrcpynA(dst, src, dstlen);
|
||||
lstrcpynW(dst, src, dstlen);
|
||||
}
|
||||
}
|
||||
RegCloseKey (key);
|
||||
|
@ -1565,16 +1570,10 @@ compobj_RegReadPath(char * keyname, char * valuename, char * dst, DWORD dstlen)
|
|||
*/
|
||||
HRESULT WINAPI CoGetClassObject(
|
||||
REFCLSID rclsid, DWORD dwClsContext, COSERVERINFO *pServerInfo,
|
||||
REFIID iid, LPVOID *ppv
|
||||
) {
|
||||
REFIID iid, LPVOID *ppv)
|
||||
{
|
||||
LPUNKNOWN regClassObject;
|
||||
HRESULT hres = E_UNEXPECTED;
|
||||
char xclsid[80];
|
||||
HINSTANCE hLibrary;
|
||||
typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
|
||||
DllGetClassObjectFunc DllGetClassObject;
|
||||
|
||||
WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
|
||||
|
||||
TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n", debugstr_guid(rclsid), debugstr_guid(iid));
|
||||
|
||||
|
@ -1589,9 +1588,7 @@ HRESULT WINAPI CoGetClassObject(
|
|||
*/
|
||||
if (S_OK == COM_GetRegisteredClassObject(rclsid, dwClsContext, ®ClassObject))
|
||||
{
|
||||
/*
|
||||
* Get the required interface from the retrieved pointer.
|
||||
*/
|
||||
/* Get the required interface from the retrieved pointer. */
|
||||
hres = IUnknown_QueryInterface(regClassObject, iid, ppv);
|
||||
|
||||
/*
|
||||
|
@ -1605,32 +1602,49 @@ HRESULT WINAPI CoGetClassObject(
|
|||
}
|
||||
|
||||
/* first try: in-process */
|
||||
if ((CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER) & dwClsContext) {
|
||||
char keyname[MAX_PATH];
|
||||
char dllpath[MAX_PATH+1];
|
||||
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;
|
||||
|
||||
sprintf(keyname,"CLSID\\%s\\InprocServer32",xclsid);
|
||||
|
||||
if ( compobj_RegReadPath(keyname, NULL, dllpath, sizeof(dllpath)) != ERROR_SUCCESS) {
|
||||
/* failure: CLSID is not found in registry */
|
||||
WARN("class %s not registered inproc\n", xclsid);
|
||||
if (ERROR_SUCCESS != COM_OpenKeyForCLSID(rclsid, KEY_READ, &hkey))
|
||||
{
|
||||
ERR("class %s not registered\n", debugstr_guid(rclsid));
|
||||
hres = REGDB_E_CLASSNOTREG;
|
||||
} else {
|
||||
if ((hLibrary = LoadLibraryExA(dllpath, 0, LOAD_WITH_ALTERED_SEARCH_PATH)) == 0) {
|
||||
/* failure: DLL could not be loaded */
|
||||
ERR("couldn't load InprocServer32 dll %s\n", 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", dllpath);
|
||||
FreeLibrary( hLibrary );
|
||||
hres = CO_E_DLLNOTFOUND;
|
||||
} else {
|
||||
/* OK: get the ClassObject */
|
||||
COMPOBJ_DLLList_Add( hLibrary );
|
||||
return DllGetClassObject(rclsid, iid, ppv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 ((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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Next try out of process */
|
||||
|
|
|
@ -163,6 +163,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 MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
||||
|
||||
/* Stub Manager */
|
||||
|
@ -256,4 +257,6 @@ static inline APARTMENT* COM_CurrentApt(void)
|
|||
|
||||
extern HINSTANCE OLE32_hInstance; /* FIXME: make static */
|
||||
|
||||
#define CHARS_IN_GUID 39 /* including NULL */
|
||||
|
||||
#endif /* __WINE_OLE_COMPOBJ_H */
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
Makefile
|
||||
compobj.ok
|
||||
marshal.ok
|
||||
moniker.ok
|
||||
propvariant.ok
|
||||
|
|
|
@ -7,6 +7,7 @@ IMPORTS = oleaut32 ole32 user32 kernel32
|
|||
EXTRALIBS = -luuid
|
||||
|
||||
CTESTS = \
|
||||
compobj.c \
|
||||
marshal.c \
|
||||
moniker.c \
|
||||
propvariant.c \
|
||||
|
|
60
dlls/ole32/tests/compobj.c
Normal file
60
dlls/ole32/tests/compobj.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Component Object Tests
|
||||
*
|
||||
* Copyright 2005 Robert Shearman
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "objbase.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08lx\n", hr)
|
||||
|
||||
static const CLSID CLSID_CDeviceMoniker = { 0x4315d437, 0x5b8c, 0x11d0, { 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86 } };
|
||||
static const WCHAR devicedotone[] = {'d','e','v','i','c','e','.','1',0};
|
||||
|
||||
static void test_ProgIDFromCLSID(void)
|
||||
{
|
||||
LPWSTR progid;
|
||||
HRESULT hr = ProgIDFromCLSID(&CLSID_CDeviceMoniker, &progid);
|
||||
ok(hr == S_OK, "ProgIDFromCLSID failed with error 0x%08lx\n", hr);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
ok(!lstrcmpiW(progid, devicedotone), "Didn't get expected prog ID\n");
|
||||
CoTaskMemFree(progid);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_CLSIDFromProgID(void)
|
||||
{
|
||||
CLSID clsid;
|
||||
HRESULT hr = CLSIDFromProgID(devicedotone, &clsid);
|
||||
ok(hr == S_OK, "CLSIDFromProgID failed with error 0x%08lx\n", hr);
|
||||
ok(IsEqualCLSID(&clsid, &CLSID_CDeviceMoniker), "clsid wasn't equal to CLSID_CDeviceMoniker\n");
|
||||
}
|
||||
|
||||
START_TEST(compobj)
|
||||
{
|
||||
test_ProgIDFromCLSID();
|
||||
test_CLSIDFromProgID();
|
||||
}
|
Loading…
Reference in a new issue