Marshall function call to another thread
Short tutorial on how to make cross apartment (cross thread) COM call without interfaces, proxies, stubs and tlbs.
Each apartment (thread) has its own accesible context object. It can be obtained
via
CoGetObjectContext
API function:
CComPtr<IContext> pContext; CComPtr<IContextCallback> pContextCallback; hr = CoGetObjectContext(IID_PPV_ARGS(&pContext)); hr = CoGetObjectContext(IID_PPV_ARGS(&pContextCallback));
One of interfaces you can get is IContextCallback
with only one
method - ContextCallback
. As you might already guessed, we just need
to get IContextCallback
in target execution context and invoke
ContextCallback
method in any other context:
pContextCallback.p->AddRef(); _beginthread(&myThread, 65536, pContextCallback.p); HANDLE h[] = { CreateEvent(NULL, TRUE, FALSE, NULL) }; DWORD dwIndex; CoWaitForMultipleHandles(0, INFINITE, _countof(h), h, &dwIndex); [...] HRESULT _stdcall contextCall(ComCallData *pParam) { OutputDebugString(_T("contextCall\n")); return S_OK; } void __cdecl myThread(LPVOID p) { CoInitialize(NULL); CComPtr<IContextCallback> pContextCallback; pContextCallback.Attach(reinterpret_cast<IContextCallback *>(p)); ComCallData cd = { 0, 0, NULL }; pContextCallback->ContextCallback(&contextCall, &cd, IID_NULL, 0, NULL); CoUninitialize(); }
Here I'm starting a separate thread to make cross context call and using
CoWaitForMultipleHandles
OLE32 function to trigger message loop to
accept cross thread COM calls (regular message loop is surely enough, I'm just reluctant
to write one). Here are resulting call stacks:
Main thread: > Win32ConsoleApplication.exe!contextCall(tagComCallData * pParam) Line 227 C++ ole32.dll!CRemoteUnknown::DoCallback(struct tagXAptCallback *) Unknown rpcrt4.dll!_Invoke@12 () Unknown rpcrt4.dll!_NdrStubCall2@16 () Unknown ole32.dll!_CStdStubBuffer_Invoke@12 () Unknown ole32.dll!SyncStubInvoke(struct tagRPCOLEMESSAGE *,struct _GUID const &,class CIDObject *,void *,struct IRpcChannelBuffer *,struct IRpcStubBuffer *,unsigned long *) Unknown ole32.dll!StubInvoke(struct tagRPCOLEMESSAGE *,class CStdIdentity *,struct IRpcStubBuffer *,struct IRpcChannelBuffer *,struct tagIPIDEntry *,unsigned long *) Unknown ole32.dll!CCtxComChnl::ContextInvoke(struct tagRPCOLEMESSAGE *,struct IRpcStubBuffer *,struct tagIPIDEntry *,unsigned long *) Unknown ole32.dll!MTAInvoke(struct tagRPCOLEMESSAGE *,unsigned long,struct IRpcStubBuffer *,class IInternalChannelBuffer *,struct tagIPIDEntry *,unsigned long *) Unknown ole32.dll!STAInvoke(struct tagRPCOLEMESSAGE *,unsigned long,struct IRpcStubBuffer *,class IInternalChannelBuffer *,void *,struct tagIPIDEntry *,unsigned long *) Unknown ole32.dll!AppInvoke(class CMessageCall *,class CRpcChannelBuffer *,struct IRpcStubBuffer *,void *,void *,struct tagIPIDEntry *,struct LocalThis *) Unknown ole32.dll!ComInvokeWithLockAndIPID(class CMessageCall *,struct tagIPIDEntry *) Unknown ole32.dll!ComInvoke(class CMessageCall *) Unknown ole32.dll!ThreadDispatch(void *) Unknown ole32.dll!ThreadWndProc(struct HWND__ *,unsigned int,unsigned int,long) Unknown user32.dll!_InternalCallWinProc@20 () Unknown user32.dll!_UserCallWinProcCheckWow@32 () Unknown user32.dll!_DispatchMessageWorker@8 () Unknown user32.dll!_DispatchMessageW@4 () Unknown ole32.dll!CCliModalLoop::PeekRPCAndDDEMessage(void) Unknown ole32.dll!CCliModalLoop::FindMessage(unsigned long) Unknown ole32.dll!CCliModalLoop::HandleWakeForMsg(void) Unknown ole32.dll!CCliModalLoop::BlockFn(void * *,unsigned long,unsigned long *) Unknown ole32.dll!_CoWaitForMultipleHandles@20 () Unknown Win32ConsoleApplication.exe!wmain(int argc, wchar_t * * argv) Line 284 C++ Win32ConsoleApplication.exe!__tmainCRTStartup() Line 533 C Win32ConsoleApplication.exe!wmainCRTStartup() Line 377 C kernel32.dll!@BaseThreadInitThunk@12 () Unknown ntdll.dll!___RtlUserThreadStart@8 () Unknown ntdll.dll!__RtlUserThreadStart@8 () Unknown Worker thread: ntdll.dll!_NtWaitForMultipleObjects@20 () Unknown ntdll.dll!_NtWaitForMultipleObjects@20 () Unknown KernelBase.dll!_WaitForMultipleObjectsEx@20 () Unknown kernel32.dll!_WaitForMultipleObjectsExImplementation@20 () Unknown user32.dll!_RealMsgWaitForMultipleObjectsEx@20 () Unknown ole32.dll!CCliModalLoop::BlockFn(void * *,unsigned long,unsigned long *) Unknown ole32.dll!ModalLoop(class CMessageCall *) Unknown ole32.dll!SwitchSTA(class OXIDEntry *,class CMessageCall * *) Unknown ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall(class CMessageCall * *) Unknown ole32.dll!CRpcChannelBuffer::SendReceive2(struct tagRPCOLEMESSAGE *,unsigned long *) Unknown ole32.dll!CCliModalLoop::SendReceive(struct tagRPCOLEMESSAGE *,unsigned long *,class IInternalChannelBuffer *) Unknown ole32.dll!CAptRpcChnl::SendReceive(struct tagRPCOLEMESSAGE *,unsigned long *) Unknown ole32.dll!CCtxComChnl::SendReceive(struct tagRPCOLEMESSAGE *,unsigned long *) Unknown ole32.dll!NdrExtpProxySendReceive(void *,struct _MIDL_STUB_MESSAGE *) Unknown rpcrt4.dll!@NdrpProxySendReceive@4 () Unknown rpcrt4.dll!_NdrClientCall2 () Unknown ole32.dll!_ObjectStublessClient@8 () Unknown ole32.dll!_ObjectStubless@0 () Unknown ole32.dll!CObjectContext::InternalContextCallback(long (*)(void *),void *,struct _GUID const &,int,struct IUnknown *) Unknown ole32.dll!CObjectContext::ContextCallback(long (*)(struct tagComCallData *),struct tagComCallData *,struct _GUID const &,int,struct IUnknown *) Unknown > Win32ConsoleApplication.exe!myThread(void * p) Line 239 C++ msvcr110d.dll!_callthreadstart() Line 255 C msvcr110d.dll!_threadstart(void * ptd) Line 239 C kernel32.dll!@BaseThreadInitThunk@12 () Unknown ntdll.dll!___RtlUserThreadStart@8 () Unknown ntdll.dll!__RtlUserThreadStart@8 () Unknown
Windows OS has many hidden features, used by Microsoft products. Are we any worse?
5 коммент.:
Magnificent site. Plenty of helpful information here.
I am sending it to a few buddies ans additionally sharing in delicious.
And of course, thank you on your effort!
Look into my web page ... GFI Norte
I'm very pleased to uncover this page. I wanted to thank you for your time for this wonderful read!! I definitely liked every little bit of it and i also have you saved as a favorite to see new information on your site.
Feel free to surf to my page ... laser cellulite treatment
IID_NULL and 0 parameters to ContextCallback and totally wrong. Don't use this but lookup Raymond Chen's articles.
Thanks for sharing, nice post! Post really provice useful information!
Công ty vận chuyển hàng nước ngoài FadoExpress hàng đầu chuyên vận chuyển, chuyển phát nhanh siêu tốc đi khắp thế giới, nổi bật là dịch vụ gửi hàng đi mỹ, gửi hàng đi nhật và gửi hàng đi pháp và dịch vụ chuyển phát nhanh đi hàn quốc uy tín, giá rẻ
Сегодня вставая утром без прогноза погоды не обойтись, так как это очень удобно по внешней температуре понимать что одевать выходя на улицу Важность прогноза погоды в Украине https://www.gismeteo.ua/ недооценена!
Отправить комментарий