Commit 2308d49b authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

ole32: Implement CoRegisterPSClsid.

parent fb6bd241
......@@ -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(&registered_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(&registered_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(&registered_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, &registered_psclsid->entry);
LeaveCriticalSection(&apt->cs);
return S_OK;
}
/***********************************************************************
......
......@@ -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) */
......
......@@ -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()
......
......@@ -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();
}
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