mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-15 03:24:47 +00:00
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: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
55db1dbb32
commit
00c8117a72
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
/* 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)
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue