From 2308d49bcba08d12582c99e2f43aebc1e0568df8 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Thu, 20 Jul 2006 19:30:21 +0100 Subject: [PATCH] ole32: Implement CoRegisterPSClsid. --- dlls/ole32/compobj.c | 105 +++++++++++++++++++++++- dlls/ole32/compobj_private.h | 1 + dlls/ole32/ole32.spec | 2 +- dlls/ole32/tests/compobj.c | 152 +++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 4 deletions(-) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index c89d8ce2eee..22f93448d33 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -94,6 +94,13 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION csApartment = { &critsect_debug, -1, 0, 0, 0, 0 }; +struct registered_psclsid +{ + struct list entry; + IID iid; + CLSID clsid; +}; + /* * This lock count counts the number of times CoInitialize is called. It is * decreased every time CoUninitialize is called. When it hits 0, the COM @@ -220,6 +227,7 @@ static APARTMENT *apartment_construct(DWORD model) list_init(&apt->proxies); list_init(&apt->stubmgrs); + list_init(&apt->psclsids); apt->ipidc = 0; apt->refs = 1; apt->remunk_exported = FALSE; @@ -343,6 +351,15 @@ DWORD apartment_release(struct apartment *apt) stub_manager_int_release(stubmgr); } + LIST_FOR_EACH_SAFE(cursor, cursor2, &apt->psclsids) + { + struct registered_psclsid *registered_psclsid = + LIST_ENTRY(cursor, struct registered_psclsid, entry); + + HeapFree(GetProcessHeap(), 0, registered_psclsid); + list_remove(®istered_psclsid->entry); + } + /* if this assert fires, then another thread took a reference to a * stub manager without taking a reference to the containing * apartment, which it must do. */ @@ -1147,11 +1164,12 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid) * * BUGS * - * We only search the registry, not ids registered with - * CoRegisterPSClsid. - * Also, native returns S_OK for interfaces with a key in HKCR\Interface, but + * Native returns S_OK for interfaces with a key in HKCR\Interface, but * without a ProxyStubClsid32 key and leaves garbage in pclsid. This should be * considered a bug in native unless an application depends on this (unlikely). + * + * SEE ALSO + * CoRegisterPSClsid. */ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) { @@ -1161,9 +1179,29 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) WCHAR value[CHARS_IN_GUID]; LONG len; HKEY hkey; + APARTMENT *apt = COM_CurrentApt(); + struct registered_psclsid *registered_psclsid; TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid); + if (!apt) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + + EnterCriticalSection(&apt->cs); + + LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry) + if (IsEqualIID(®istered_psclsid->iid, riid)) + { + *pclsid = registered_psclsid->clsid; + LeaveCriticalSection(&apt->cs); + return S_OK; + } + + LeaveCriticalSection(&apt->cs); + /* Interface\\{string form of riid}\\ProxyStubClsid32 */ strcpyW(path, wszInterface); StringFromGUID2(riid, path + ARRAYSIZE(wszInterface) - 1, CHARS_IN_GUID); @@ -1196,6 +1234,67 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) return S_OK; } +/***************************************************************************** + * CoRegisterPSClsid [OLE32.@] + * + * Register a proxy/stub CLSID for the given interface in the current process + * only. + * + * PARAMS + * riid [I] Interface whose proxy/stub CLSID is to be registered. + * rclsid [I] CLSID of the proxy/stub. + * + * RETURNS + * Success: S_OK + * Failure: E_OUTOFMEMORY + * + * NOTES + * + * This function does not add anything to the registry and the effects are + * limited to the lifetime of the current process. + * + * SEE ALSO + * CoGetPSClsid. + */ +HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid) +{ + APARTMENT *apt = COM_CurrentApt(); + struct registered_psclsid *registered_psclsid; + + TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid)); + + if (!apt) + { + ERR("apartment not initialised\n"); + return CO_E_NOTINITIALIZED; + } + + EnterCriticalSection(&apt->cs); + + LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry) + if (IsEqualIID(®istered_psclsid->iid, riid)) + { + registered_psclsid->clsid = *rclsid; + LeaveCriticalSection(&apt->cs); + return S_OK; + } + + registered_psclsid = HeapAlloc(GetProcessHeap(), 0, sizeof(struct registered_psclsid)); + if (!registered_psclsid) + { + LeaveCriticalSection(&apt->cs); + return E_OUTOFMEMORY; + } + + registered_psclsid->iid = *riid; + registered_psclsid->clsid = *rclsid; + list_add_head(&apt->psclsids, ®istered_psclsid->entry); + + LeaveCriticalSection(&apt->cs); + + return S_OK; +} + /*********************************************************************** diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 97519cf5d60..643eb145f05 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -152,6 +152,7 @@ struct apartment struct list stubmgrs; /* stub managers for exported objects (CS cs) */ BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */ LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */ + struct list psclsids; /* list of registered PS CLSIDs (CS cs) */ /* FIXME: OID's should be given out by RPCSS */ OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 56058bbe5cd..87605ca8ff6 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -56,7 +56,7 @@ @ stdcall CoRegisterClassObject(ptr ptr long long ptr) @ stdcall CoRegisterMallocSpy (ptr) @ stdcall CoRegisterMessageFilter(ptr ptr) -@ stub CoRegisterPSClsid #@ stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED +@ stdcall CoRegisterPSClsid(ptr ptr) @ stub CoRegisterSurrogate @ stdcall CoReleaseMarshalData(ptr) @ stdcall CoReleaseServerProcess() diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 19a6faa2498..bcce10abe01 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -48,6 +48,15 @@ static const WCHAR wszCLSID_CDeviceMoniker[] = '}',0 }; +static const IID IID_IWineTest = +{ + 0x5201163f, + 0x8164, + 0x4fd0, + {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} +}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ + + static void test_ProgIDFromCLSID(void) { LPWSTR progid; @@ -253,6 +262,148 @@ static void test_CoRegisterMessageFilter(void) CoUninitialize(); } +static HRESULT WINAPI Test_IUnknown_QueryInterface( + LPUNKNOWN iface, + REFIID riid, + LPVOID *ppvObj) +{ + if (ppvObj == NULL) return E_POINTER; + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IWineTest)) + { + *ppvObj = (LPVOID)iface; + IUnknown_AddRef(iface); + return S_OK; + } + + *ppvObj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface) +{ + return 2; /* non-heap-based object */ +} + +static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface) +{ + return 1; /* non-heap-based object */ +} + +static const IUnknownVtbl TestUnknown_Vtbl = +{ + Test_IUnknown_QueryInterface, + Test_IUnknown_AddRef, + Test_IUnknown_Release, +}; + +static IUnknown Test_Unknown = { &TestUnknown_Vtbl }; + +static HRESULT WINAPI PSFactoryBuffer_QueryInterface( + IPSFactoryBuffer * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject) +{ + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IPSFactoryBuffer)) + { + *ppvObject = This; + IPSFactoryBuffer_AddRef(This); + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI PSFactoryBuffer_AddRef( + IPSFactoryBuffer * This) +{ + return 2; +} + +static ULONG WINAPI PSFactoryBuffer_Release( + IPSFactoryBuffer * This) +{ + return 1; +} + +static HRESULT WINAPI PSFactoryBuffer_CreateProxy( + IPSFactoryBuffer * This, + /* [in] */ IUnknown *pUnkOuter, + /* [in] */ REFIID riid, + /* [out] */ IRpcProxyBuffer **ppProxy, + /* [out] */ void **ppv) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI PSFactoryBuffer_CreateStub( + IPSFactoryBuffer * This, + /* [in] */ REFIID riid, + /* [unique][in] */ IUnknown *pUnkServer, + /* [out] */ IRpcStubBuffer **ppStub) +{ + return E_NOTIMPL; +} + +static IPSFactoryBufferVtbl PSFactoryBufferVtbl = +{ + PSFactoryBuffer_QueryInterface, + PSFactoryBuffer_AddRef, + PSFactoryBuffer_Release, + PSFactoryBuffer_CreateProxy, + PSFactoryBuffer_CreateStub +}; + +static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl }; + +static const CLSID CLSID_WineTestPSFactoryBuffer = +{ + 0x52011640, + 0x8164, + 0x4fd0, + {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} +}; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */ + +static void test_CoRegisterPSClsid(void) +{ + HRESULT hr; + DWORD dwRegistrationKey; + IStream *stream; + CLSID clsid; + + hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); + ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returened CO_E_NOTINITIALIZED instead of 0x%08lx\n", hr); + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer, + CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &dwRegistrationKey); + ok_ole_success(hr, "CoRegisterClassObject"); + + hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); + ok_ole_success(hr, "CoRegisterPSClsid"); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok_ole_success(hr, "CreateStreamOnHGlobal"); + + hr = CoMarshalInterface(stream, &IID_IWineTest, (IUnknown *)&Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); + ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08lx\n", hr); + IStream_Release(stream); + + hr = CoRevokeClassObject(dwRegistrationKey); + ok_ole_success(hr, "CoRevokeClassObject"); + + CoUninitialize(); + + pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + hr = CoGetPSClsid(&IID_IWineTest, &clsid); + ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08lx\n", hr); + + CoUninitialize(); +} + START_TEST(compobj) { HMODULE hOle32 = GetModuleHandle("ole32"); @@ -269,4 +420,5 @@ START_TEST(compobj) test_ole_menu(); test_CoGetClassObject(); test_CoRegisterMessageFilter(); + test_CoRegisterPSClsid(); }