We have an application that either runs some COM hosting in the main thread or in a different thread (async), and we would like to connect to this (connectable) object by using the standard ConnectionPoint interfaces in order to get its events.
Up to Windows 10 SP 1903, it did work.
But when testing the application in the "1903 update" the
IConnectionPoint->Advise()
fails with CONNECT_E_CANNOTCONNECT when the code is run in a different thread than the starting thread - while Advise() is called, the event server asks a lot of interfaces I do not support, I only support IUnknown, IDispatch and the event interface as should be.
There are a lot of interfaces queried when the whole thing is run in the non-STA main thread, less in < 1903, and in 1903 these are:
clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({2132B005-C604-4354-85BD-8F2E24181B0C}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IMarshal) failed
clsEventSink(Dialog_)::QueryInterface(IID_INoMarshal) failed
clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({2132B005-C604-4354-85BD-8F2E24181B0C}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IMarshal) failed
clsEventSink(Dialog_)::QueryInterface({0000001B-0000-0000-C000-000000000046}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IUnknown) succeeded
clsEventSink::AddRef(1)
clsEventSink::AddRef(2)
clsEventSink(Dialog_)::QueryInterface(IID_IStdMarshalInfo) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({00000040-0000-0000-C000-000000000046}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface(IID_IAgileObject) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({77DD1250-139C-2BC3-BD95-900ACED61BE5}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({BFD60505-5A1F-4E41-88BA-A6FB07202DA9}) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrame) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrameManager) failed
clsEventSink(Dialog_)::QueryInterface(IApplicationFrameEventHandler) failed
clsEventSink(Dialog_)::QueryInterface(IStreamGroup) failed
clsEventSink(Dialog_)::QueryInterface(iaudiodevicegraph) failed
clsEventSink(Dialog_)::QueryInterface({4F4F92B5-6DED-4E9B-A93F-013891B3A8B7}) failed
clsEventSink(Dialog_)::QueryInterface({9BC79C93-2289-4BB5-ABF4-3287FD9CAE39}) failed
clsEventSink(Dialog_)::QueryInterface({1868091E-AB5A-415F-A02F-5C4DD0CF901D}) failed
clsEventSink(Dialog_)::QueryInterface({11456F96-09D1-4909-8F36-4EB74E42B93E}) failed
clsEventSink(Dialog_)::QueryInterface(IEUserBroker) failed
clsEventSink(Dialog_)::QueryInterface({35BD3360-1B35-4927-BAE4-B10E70D99EFF}) failed
clsEventSink(Dialog_)::QueryInterface(IVerbStateTaskCallBack) failed
clsEventSink(Dialog_)::QueryInterface({334D391F-0E79-3B15-C9FF-EAC65DD07C42}) failed
clsEventSink(Dialog_)::QueryInterface({03FB5C57-D534-45F5-A1F4-D39556983875}) failed
clsEventSink(Dialog_)::QueryInterface({2C258AE7-50DC-49FF-9D1D-2ECB9A52CDD7}) failed
clsEventSink(Dialog_)::QueryInterface(IExternalConnection) failed
clsEventSink(Dialog_)::QueryInterface({4C1E39E1-E3E3-4296-AA86-EC938D896E92}) failed
clsEventSink(Dialog_)::QueryInterface({AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}) failed
Advise() is then giving up and returning the error code mentioned above. Thus I cannot create an event sink any more in a different thread than the application' main STA thread.
More explicitly, we have a relationship manager application that wants to show a nonmodal dialog in a different thread, i.e.
So if there's marshalling to do, my guess now is that it is inside the dialog control which must marshal the pointer I pass to Advise(), at least that's what I read in the depth of the WWW. As we do not do anything here, it uses a standard marshaller, the marshalling is being done (or at least tried to do) by combase!CStdMarshal:CreateStub() which seemingly does not succeed any more. The stack when I'm asked for one the interfaces (above) is
> cmSC24.dll!clsEventSink::QueryInterface(const _GUID & riid={...}, void * * ppv=0x04c5cf60) Line 121 C++
combase.dll!CStdMarshal::CreateStub(tagIPIDEntry * pEntry=0x0b87c388, IRpcStubBuffer * * ppStub=0x04c5d030, void * * ppv=0x04c5d034, int * pfNonNDR=0x04c5d038, IUnknown * pUnkUseInner=0x00000000) Line 6628 C++
[Inline Frame] combase.dll!CStdMarshal::ConnectSrvIPIDEntry(tagIPIDEntry *) Line 2600 C++
combase.dll!CStdMarshal::MarshalServerIPID(const _GUID & riid={...}, unsigned long cRefs=5, unsigned long mshlflags=0, tagIPIDEntry * * ppEntry=0x04c5d070, IUnknown * pUnkUseInner=0x00000000, PreventRundownBiasContainer * pBiasContainer=0x00000000, bool bApplyDirectMarshalingMitigation=false) Line 1539 C++
[Inline Frame] combase.dll!CStdMarshal::MarshalIPID(const _GUID &) Line 1391 C++
combase.dll!CRemoteUnknown::RemQueryInterface(const _GUID & ripid={...}, unsigned long cRefs=5, unsigned short cIids=1, _GUID * iids=0x0d7820fc, tagREMQIRESULT * * ppQIResults=0x04c5d4c8) Line 510 C++
rpcrt4.dll!_Invoke@12() Unknown
rpcrt4.dll!_NdrStubCall2@16() Unknown
combase.dll!CStdStubBuffer_Invoke(IRpcStubBuffer * This=0x0e17f408, tagRPCOLEMESSAGE * prpcmsg=0x0e1e38b0, IRpcChannelBuffer * pRpcChannelBuffer=0x0e0bc540) Line 1531 C++
[Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_ee1df801181086a03fa4f8f75bd5617f>::operator()() Line 1385 C++
combase.dll!ObjectMethodExceptionHandlingAction<<lambda_ee1df801181086a03fa4f8f75bd5617f> >(InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_ee1df801181086a03fa4f8f75bd5617f> action={...}, ObjectMethodExceptionHandlingInfo * pExceptionHandlingInfo=0x04c5d61c, ExceptionHandlingResult * pExceptionHandlingResult=0x04c5d600, void *) Line 87 C++
[Inline Frame] combase.dll!InvokeStubWithExceptionPolicyAndTracing(IRpcStubBuffer * pMsg=0x0e1e38b0, tagRPCOLEMESSAGE *) Line 1383 C++
combase.dll!DefaultStubInvoke(bool bIsAsyncBeginMethod=false, IServerCall * pServerCall=0x0dcc3f64, IRpcChannelBuffer * pChannel=0x0e0bc540, IRpcStubBuffer * pStub=0x0e17f408, unsigned long * pdwFault=0x04c5da08) Line 1452 C++
[Inline Frame] combase.dll!SyncStubCall::Invoke(IServerCall *) Line 1509 C++
[Inline Frame] combase.dll!SyncServerCall::StubInvoke(IRpcChannelBuffer *) Line 825 C++
[Inline Frame] combase.dll!StubInvoke(tagRPCOLEMESSAGE * pMsg=0x80004002, CStdIdentity * pStdID=0x0e2381e8, IRpcStubBuffer *) Line 1734 C++
combase.dll!ServerCall::ContextInvoke(tagRPCOLEMESSAGE * pMessage=0x0e1e38b0, IRpcStubBuffer * pStub=0x0e17f408, CServerChannel * pChannel=0x0e0bc540, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, unsigned long * pdwFault=0x04c5da08) Line 1418 C++
[Inline Frame] combase.dll!CServerChannel::ContextInvoke(tagRPCOLEMESSAGE *) Line 1327 C++
[Inline Frame] combase.dll!DefaultInvokeInApartment(tagRPCOLEMESSAGE *) Line 3352 C++
combase.dll!ReentrantSTAInvokeInApartment(tagRPCOLEMESSAGE * pMsg=0x0e1e38b0, unsigned long dwCallCat=1, bool bIsTouchedASTACall=false, IRpcStubBuffer * pStub=0x0e17f408, CServerChannel * pChnl=0x0e0bc540, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, unsigned long * pdwFault=0x04c5da08) Line 112 C++
combase.dll!AppInvoke(ServerCall * pServerCall=0x0dcc3f50, CServerChannel * pChannel=0x0e0bc540, IRpcStubBuffer * pStub=0x0e17f408, void * pStubBuffer=0x0d7820e0, void * pIPIDEntry=0x0d8e8d98, tagIPIDEntry * pLocalb=0x0d782080, WireLocalThis *) Line 1182 C++
combase.dll!ComInvokeWithLockAndIPID(ServerCall * pServerCall=0x0dcc3f50, tagIPIDEntry * pIPIDEntry=0x0d8e8d98, bool * pbCallerResponsibleForRequestMessageCleanup=0x04c5dc3f) Line 2290 C++
[Inline Frame] combase.dll!ComInvoke(ServerCall *) Line 1803 C++
[Inline Frame] combase.dll!ThreadDispatch(ServerCall *) Line 416 C++
combase.dll!ThreadWndProc(HWND__ * window=0x000707d2, unsigned int message=1024, unsigned int wparam=47806, long params=231489368) Line 744 C++
user32.dll!__InternalCallWinProc@20() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchMessageWorker() Unknown
user32.dll!_DispatchMessageW@4() Unknown
[Inline Frame] combase.dll!CCliModalLoop::MyDispatchMessage(tagMSG *) Line 3057 C++
combase.dll!CCliModalLoop::PeekRPCAndDDEMessage() Line 2693 C++
combase.dll!CCliModalLoop::FindMessage(unsigned long dwStatus=524296) Line 2764 C++
combase.dll!CCliModalLoop::HandleWakeForMsg() Line 2379 C++
combase.dll!CCliModalLoop::BlockFn(void * * ahEvent=0x04c5dfc0, unsigned long cEvents=1, unsigned long * lpdwSignaled=0x04c5dfa8) Line 2316 C++
combase.dll!ModalLoop(CSyncClientCall * pClientCall=0x0d74fc40) Line 166 C++
combase.dll!ClassicSTAThreadDispatchCrossApartmentCall(tagRPCOLEMESSAGE * pMessage=0x04c5e408, OXIDEntry * pOXIDEntry=0x0b87b5c0, CSyncClientCall * pClientCall=0x0d74fc40) Line 321 C++
[Inline Frame] combase.dll!CSyncClientCall::SwitchAptAndDispatchCall(tagRPCOLEMESSAGE * pMessage=0x04c5e408) Line 5696 C++
combase.dll!CSyncClientCall::SendReceive2(tagRPCOLEMESSAGE * pMessage=0x04c5e408, unsigned long * pstatus=0x04c5e3e4) Line 5377 C++
[Inline Frame] combase.dll!SyncClientCallRetryContext::SendReceiveWithRetry(tagRPCOLEMESSAGE *) Line 1617 C++
[Inline Frame] combase.dll!CSyncClientCall::SendReceiveInRetryContext(SyncClientCallRetryContext *) Line 567 C++
combase.dll!ClassicSTAThreadSendReceive(CSyncClientCall * pClientCall=0x0d74fc40, tagRPCOLEMESSAGE * pMsg=0x04c5e408, unsigned long * pulStatus=0x04c5e3e4) Line 549 C++
combase.dll!CSyncClientCall::SendReceive(tagRPCOLEMESSAGE * pMessage=0x04c5e408, unsigned long * pulStatus=0x04c5e3e4) Line 778 C++
[Inline Frame] combase.dll!CClientChannel::SendReceive(tagRPCOLEMESSAGE *) Line 653 C++
combase.dll!NdrExtpProxySendReceive(void * pThis=0x0e0703ec, _MIDL_STUB_MESSAGE * pStubMsg=0x04c5e4e8) Line 1998 C++
rpcrt4.dll!NdrClientCall2() Unknown
combase.dll!ObjectStublessClient(void * ParamAddress=0x04c5e910, long Method=5) Line 227 C++
combase.dll!_ObjectStubless@0() Line 171 Unknown
cmSC24.dll!clsEventSink::Connect(IUnknown * pUnknown=0x0e238d94, const String & sObject={...}, const String & sPrefix={...}, unsigned int * pnErrArg=0x04c5efa0, tagEXCEPINFO * pExepInfo=0x04c5efa4) Line 313 C++
cmSC24.dll!Connect(IUnknown * pUnknown=0x0e238d94, const String & sObject={...}, const String & sPrefix={...}, unsigned int * pnErrArg=0x04c5efa0, tagEXCEPINFO * pExepInfo=0x04c5efa4, clsScriptingHost * pHost=0x0e2f1fe8) Line 462 C++
which I interprete as combase trying to set up a default marshalling, and somewhere failing in the 1903 update. So my question is, why could it be failing, and what does my class need to supply when I all Advise()?
Or is it that the server (connectable object) is created in the STA main thread and must be changed somehow to support the marshalling into the new thread's event sink calling Advise()?
Nearly the same stack is found in previous versions, but it succeeded.
Ah, well - using VS 2019 and _MERGE_PROXYSTUB (and some tweaking) in the dialog object did the trick... The standard proxy is maybe wrong here, so it needs to supply its own? What the heck, I'm glad it works.
@Raymond: thanks for answering - it was the correct track you lead me!
User contributions licensed under CC BY-SA 3.0