diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 01201228f15..75926e9fb77 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -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 */ diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 7e5ddbb64ca..de3fcc8865e 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -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 */ diff --git a/dlls/ole32/tests/.cvsignore b/dlls/ole32/tests/.cvsignore index 3d7f0d76644..fbde286de7f 100644 --- a/dlls/ole32/tests/.cvsignore +++ b/dlls/ole32/tests/.cvsignore @@ -1,4 +1,5 @@ Makefile +compobj.ok marshal.ok moniker.ok propvariant.ok diff --git a/dlls/ole32/tests/Makefile.in b/dlls/ole32/tests/Makefile.in index a7bf0683e1e..a0049e9e695 100644 --- a/dlls/ole32/tests/Makefile.in +++ b/dlls/ole32/tests/Makefile.in @@ -7,6 +7,7 @@ IMPORTS = oleaut32 ole32 user32 kernel32 EXTRALIBS = -luuid CTESTS = \ + compobj.c \ marshal.c \ moniker.c \ propvariant.c \ diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c new file mode 100644 index 00000000000..a7759523959 --- /dev/null +++ b/dlls/ole32/tests/compobj.c @@ -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 + +#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(); +}