Commit 00c8117a authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

combase: Omit thread ID from the stub manager ipid for MTA objects.

It is possible for a thread that creates an MTA to call CoUninitialize() and not destroy the MTA if another thread has entered the MTA in the meantime. If the original thread then creates an STA, subsequent attempts to find the MTA with 'apartment_findfromtid' will get the original thread's STA. To avoid this, don't set a TID value in the stub manager IPID value to indicate that the stub resides in the MTA. Signed-off-by: 's avatarConnor McAdams <cmcadams@codeweavers.com>
parent 55db1dbb
...@@ -46,7 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); ...@@ -46,7 +46,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
/* generates an ipid in the following format (similar to native version): /* generates an ipid in the following format (similar to native version):
* Data1 = apartment-local ipid counter * Data1 = apartment-local ipid counter
* Data2 = apartment creator thread ID * Data2 = apartment creator thread ID, or 0 for an MTA.
* Data3 = process ID * Data3 = process ID
* Data4 = random value * Data4 = random value
*/ */
...@@ -62,7 +62,7 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid) ...@@ -62,7 +62,7 @@ static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
} }
ipid->Data1 = InterlockedIncrement(&m->apt->ipidc); ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
ipid->Data2 = (USHORT)m->apt->tid; ipid->Data2 = !m->apt->multi_threaded ? (USHORT)m->apt->tid : 0;
ipid->Data3 = (USHORT)GetCurrentProcessId(); ipid->Data3 = (USHORT)GetCurrentProcessId();
return S_OK; return S_OK;
} }
...@@ -499,6 +499,8 @@ static HRESULT ipid_to_ifstub(const IPID *ipid, struct apartment **stub_apt, ...@@ -499,6 +499,8 @@ static HRESULT ipid_to_ifstub(const IPID *ipid, struct apartment **stub_apt,
/* FIXME: hack for IRemUnknown */ /* FIXME: hack for IRemUnknown */
if (ipid->Data2 == 0xffff) if (ipid->Data2 == 0xffff)
*stub_apt = apartment_findfromoxid(*(const OXID *)ipid->Data4); *stub_apt = apartment_findfromoxid(*(const OXID *)ipid->Data4);
else if (!ipid->Data2)
*stub_apt = apartment_get_mta();
else else
*stub_apt = apartment_findfromtid(ipid->Data2); *stub_apt = apartment_findfromtid(ipid->Data2);
if (!*stub_apt) if (!*stub_apt)
......
...@@ -4489,6 +4489,63 @@ static void test_channel_hook(void) ...@@ -4489,6 +4489,63 @@ static void test_channel_hook(void)
ok_ole_success(hr, CoRegisterMessageFilter); ok_ole_success(hr, CoRegisterMessageFilter);
} }
static DWORD CALLBACK second_mta_thread_proc(void *param)
{
struct implicit_mta_marshal_data *data = param;
HRESULT hr;
/* Second thread now keeps MTA created on first thread alive. */
CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = CoMarshalInterface(data->stream, &IID_IClassFactory,
(IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok_ole_success(hr, CoMarshalInterface);
SetEvent(data->start);
ok(!WaitForSingleObject(data->stop, 1000), "wait failed\n");
CoUninitialize();
return 0;
}
static void test_mta_creation_thread_change_apartment(void)
{
struct implicit_mta_marshal_data data;
IClassFactory *cf;
IUnknown *proxy;
HANDLE thread;
HRESULT hr;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
hr = CreateStreamOnHGlobal(NULL, TRUE, &data.stream);
ok_ole_success(hr, CreateStreamOnHGlobal);
data.start = CreateEventA(NULL, FALSE, FALSE, NULL);
data.stop = CreateEventA(NULL, FALSE, FALSE, NULL);
thread = CreateThread(NULL, 0, second_mta_thread_proc, &data, 0, NULL);
ok(!WaitForSingleObject(data.start, 1000), "wait failed\n");
CoUninitialize();
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
IStream_Seek(data.stream, ullZero, STREAM_SEEK_SET, NULL);
hr = CoUnmarshalInterface(data.stream, &IID_IClassFactory, (void **)&cf);
ok_ole_success(hr, CoUnmarshalInterface);
hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
ok_ole_success(hr, IClassFactory_CreateInstance);
IUnknown_Release(proxy);
IStream_Release(data.stream);
SetEvent(data.stop);
ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
CloseHandle(thread);
CoUninitialize();
}
START_TEST(marshal) START_TEST(marshal)
{ {
HMODULE hOle32 = GetModuleHandleA("ole32"); HMODULE hOle32 = GetModuleHandleA("ole32");
...@@ -4511,6 +4568,7 @@ START_TEST(marshal) ...@@ -4511,6 +4568,7 @@ START_TEST(marshal)
test_cocreateinstance_proxy(); test_cocreateinstance_proxy();
test_implicit_mta(); test_implicit_mta();
test_mta_creation_thread_change_apartment();
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
......
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