Commit a56bc8f9 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ole32: Store proxy/stub CLSIDs per process, not per apartment.

parent 2100e140
...@@ -172,6 +172,17 @@ struct registered_psclsid ...@@ -172,6 +172,17 @@ struct registered_psclsid
CLSID clsid; CLSID clsid;
}; };
static struct list registered_psclsid_list = LIST_INIT(registered_psclsid_list);
static CRITICAL_SECTION cs_registered_psclsid_list;
static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
{
0, 0, &cs_registered_psclsid_list,
{ &psclsid_cs_debug.ProcessLocksList, &psclsid_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
};
static CRITICAL_SECTION cs_registered_psclsid_list = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
/* /*
* This is a marshallable object exposing registered local servers. * This is a marshallable object exposing registered local servers.
* IServiceProvider is used only because it happens meet requirements * IServiceProvider is used only because it happens meet requirements
...@@ -622,7 +633,6 @@ static APARTMENT *apartment_construct(DWORD model) ...@@ -622,7 +633,6 @@ static APARTMENT *apartment_construct(DWORD model)
list_init(&apt->proxies); list_init(&apt->proxies);
list_init(&apt->stubmgrs); list_init(&apt->stubmgrs);
list_init(&apt->psclsids);
list_init(&apt->loaded_dlls); list_init(&apt->loaded_dlls);
apt->ipidc = 0; apt->ipidc = 0;
apt->refs = 1; apt->refs = 1;
...@@ -733,6 +743,21 @@ static void COM_RevokeAllClasses(const struct apartment *apt) ...@@ -733,6 +743,21 @@ static void COM_RevokeAllClasses(const struct apartment *apt)
LeaveCriticalSection( &csRegisteredClassList ); LeaveCriticalSection( &csRegisteredClassList );
} }
static void revoke_registered_psclsids(void)
{
struct registered_psclsid *psclsid, *psclsid2;
EnterCriticalSection( &cs_registered_psclsid_list );
LIST_FOR_EACH_ENTRY_SAFE(psclsid, psclsid2, &registered_psclsid_list, struct registered_psclsid, entry)
{
list_remove(&psclsid->entry);
HeapFree(GetProcessHeap(), 0, psclsid);
}
LeaveCriticalSection( &cs_registered_psclsid_list );
}
/****************************************************************************** /******************************************************************************
* Implementation of the manual reset event object. (CLSID_ManualResetEvent) * Implementation of the manual reset event object. (CLSID_ManualResetEvent)
*/ */
...@@ -1173,15 +1198,6 @@ DWORD apartment_release(struct apartment *apt) ...@@ -1173,15 +1198,6 @@ DWORD apartment_release(struct apartment *apt)
stub_manager_int_release(stubmgr); 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);
list_remove(&registered_psclsid->entry);
HeapFree(GetProcessHeap(), 0, registered_psclsid);
}
/* if this assert fires, then another thread took a reference to a /* if this assert fires, then another thread took a reference to a
* stub manager without taking a reference to the containing * stub manager without taking a reference to the containing
* apartment, which it must do. */ * apartment, which it must do. */
...@@ -1988,6 +2004,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void) ...@@ -1988,6 +2004,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
{ {
TRACE("() - Releasing the COM libraries\n"); TRACE("() - Releasing the COM libraries\n");
revoke_registered_psclsids();
RunningObjectTableImpl_UnInitialize(); RunningObjectTableImpl_UnInitialize();
} }
else if (lCOMRefCnt<1) { else if (lCOMRefCnt<1) {
...@@ -2580,17 +2597,17 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) ...@@ -2580,17 +2597,17 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
if (!pclsid) if (!pclsid)
return E_INVALIDARG; return E_INVALIDARG;
EnterCriticalSection(&apt->cs); EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry) LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid)) if (IsEqualIID(&registered_psclsid->iid, riid))
{ {
*pclsid = registered_psclsid->clsid; *pclsid = registered_psclsid->clsid;
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK; return S_OK;
} }
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&cs_registered_psclsid_list);
data.cbSize = sizeof(data); data.cbSize = sizeof(data);
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION, if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
...@@ -2635,6 +2652,9 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid) ...@@ -2635,6 +2652,9 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
* *
* NOTES * NOTES
* *
* Unlike CoRegisterClassObject(), CLSIDs registered with CoRegisterPSClsid()
* will be returned from other apartments in the same process.
*
* This function does not add anything to the registry and the effects are * This function does not add anything to the registry and the effects are
* limited to the lifetime of the current process. * limited to the lifetime of the current process.
* *
...@@ -2654,28 +2674,28 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid) ...@@ -2654,28 +2674,28 @@ HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
return CO_E_NOTINITIALIZED; return CO_E_NOTINITIALIZED;
} }
EnterCriticalSection(&apt->cs); EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry) LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid)) if (IsEqualIID(&registered_psclsid->iid, riid))
{ {
registered_psclsid->clsid = *rclsid; registered_psclsid->clsid = *rclsid;
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK; return S_OK;
} }
registered_psclsid = HeapAlloc(GetProcessHeap(), 0, sizeof(struct registered_psclsid)); registered_psclsid = HeapAlloc(GetProcessHeap(), 0, sizeof(struct registered_psclsid));
if (!registered_psclsid) if (!registered_psclsid)
{ {
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&cs_registered_psclsid_list);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
registered_psclsid->iid = *riid; registered_psclsid->iid = *riid;
registered_psclsid->clsid = *rclsid; registered_psclsid->clsid = *rclsid;
list_add_head(&apt->psclsids, &registered_psclsid->entry); list_add_head(&registered_psclsid_list, &registered_psclsid->entry);
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK; return S_OK;
} }
......
...@@ -137,7 +137,6 @@ struct apartment ...@@ -137,7 +137,6 @@ struct apartment
struct list stubmgrs; /* stub managers for exported objects (CS cs) */ 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) */ 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) */ LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */
struct list psclsids; /* list of registered PS CLSIDs (CS cs) */
struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */ struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */
DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */ DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */
HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */ HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */
......
...@@ -1158,12 +1158,35 @@ static const CLSID CLSID_WineTestPSFactoryBuffer = ...@@ -1158,12 +1158,35 @@ static const CLSID CLSID_WineTestPSFactoryBuffer =
{0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
}; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */ }; /* 52011640-8164-4fd0-a1a2-5d5a3654d3bd */
static DWORD CALLBACK register_ps_clsid_thread(void *context)
{
HRESULT hr;
CLSID clsid = {0};
pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
hr = CoGetPSClsid(&IID_IWineTest, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
/* test registering a PSClsid in an apartment which is then destroyed */
hr = CoRegisterPSClsid(&IID_TestPS, &clsid);
ok_ole_success(hr, "CoRegisterPSClsid");
CoUninitialize();
return hr;
}
static void test_CoRegisterPSClsid(void) static void test_CoRegisterPSClsid(void)
{ {
HRESULT hr; HRESULT hr;
DWORD dwRegistrationKey; DWORD dwRegistrationKey;
IStream *stream; IStream *stream;
CLSID clsid; CLSID clsid;
HANDLE thread;
DWORD tid;
hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr); ok(hr == CO_E_NOTINITIALIZED, "CoRegisterPSClsid should have returned CO_E_NOTINITIALIZED instead of 0x%08x\n", hr);
...@@ -1177,6 +1200,21 @@ static void test_CoRegisterPSClsid(void) ...@@ -1177,6 +1200,21 @@ static void test_CoRegisterPSClsid(void)
hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer); hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
ok_ole_success(hr, "CoRegisterPSClsid"); ok_ole_success(hr, "CoRegisterPSClsid");
hr = CoGetPSClsid(&IID_IWineTest, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
CloseHandle(thread);
hr = CoGetPSClsid(&IID_TestPS, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
ok_ole_success(hr, "CreateStreamOnHGlobal"); ok_ole_success(hr, "CreateStreamOnHGlobal");
...@@ -1196,11 +1234,11 @@ static void test_CoRegisterPSClsid(void) ...@@ -1196,11 +1234,11 @@ static void test_CoRegisterPSClsid(void)
SET_EXPECT(CreateStub); SET_EXPECT(CreateStub);
hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr); ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
CHECK_CALLED(CreateStub); CHECK_CALLED(CreateStub);
hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok(hr == S_OK, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr); ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
IStream_Release(stream); IStream_Release(stream);
IPSFactoryBuffer_Release(ps_factory_buffer); IPSFactoryBuffer_Release(ps_factory_buffer);
...@@ -1216,6 +1254,31 @@ static void test_CoRegisterPSClsid(void) ...@@ -1216,6 +1254,31 @@ static void test_CoRegisterPSClsid(void)
hr = CoGetPSClsid(&IID_IWineTest, &clsid); hr = CoGetPSClsid(&IID_IWineTest, &clsid);
ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr); ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
hr = CoGetPSClsid(&IID_TestPS, &clsid);
ok(hr == REGDB_E_IIDNOTREG, "CoGetPSClsid should have returned REGDB_E_IIDNOTREG instead of 0x%08x\n", hr);
CoUninitialize();
pCoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = CoRegisterPSClsid(&IID_IWineTest, &CLSID_WineTestPSFactoryBuffer);
ok_ole_success(hr, "CoRegisterPSClsid");
hr = CoGetPSClsid(&IID_IWineTest, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
thread = CreateThread(NULL, 0, register_ps_clsid_thread, NULL, 0, &tid);
ok(thread != NULL, "CreateThread failed with error %d\n", GetLastError());
ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
CloseHandle(thread);
hr = CoGetPSClsid(&IID_TestPS, &clsid);
ok_ole_success(hr, "CoGetPSClsid");
ok(IsEqualGUID(&clsid, &CLSID_WineTestPSFactoryBuffer), "expected %s, got %s\n",
wine_dbgstr_guid(&CLSID_WineTestPSFactoryBuffer), wine_dbgstr_guid(&clsid));
CoUninitialize(); CoUninitialize();
} }
......
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