Using COM RPC from within CView::OnBeginPrinting
I've inherited maintenance for a program which currently queries an ADODB database from within its CView::OnBeginPrinting
override. However, when the ADODB database handle is a proxy for an out-of-process database connection, this crashes frequently - apparently, while waiting for an RPC response, a paint message causes it to reenter CView's rendering processing, causing things to get very confused.
Is there a way to safely use COM out of process objects from CView::OnBeginPrinting
? For example, if I could block window messages to the window in question until the COM call finished, that would probably work...
Here is a stack trace of where the assert occurs:
mfc100d.dll!CPreviewDC::ReleaseOutputDC() Line 138 C++ (asserts here)
mfc100d.dll!CPreviewView::OnDraw(CDC * pDC) Line 801 C++
mfc100d.dll!CView::OnPaint() Line 189 C++
mfc100d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) Line 2354 C++
mfc100d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2067 + 0x20 bytes C++
mfc100d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 248 + 0x1c bytes C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 411 C++
mfc100d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 420 + 0x15 bytes C++
user32.dll!_InternalCallWinProc@20() + 0x28 bytes
user32.dll!_UserCallWinProcCheckWow@32() + 0xa2 bytes
user32.dll!_DispatchClientMessage@20() + 0x4b bytes
user32.dll!___fnDWORD@4() + 0x24 bytes
ntdll.dll!_KiUserCallbackDispatcher@12() + 0x2e bytes
user32.dll!_NtUserDispatchMessage@4() + 0xc bytes
user32.dll!_DispatchMessageA@4() + 0xf bytes
mfc100d.dll!COleMessageFilter::OnMessagePending(const tagMSG * __formal) Line 114 C++
mfc100d.dll!COleMessageFilter::XMessageFilter::MessagePending(HTASK__ * htaskCallee, unsigned long dwTickCount, unsigned long __formal) Line 312 C++
ole32.dll!CCliModalLoop::HandlePendingMessage() + 0x91de bytes
ole32.dll!CCliModalLoop::HandleWakeForMsg() + 0x46 bytes
ole32.dll!CCliModalLoop::BlockFn() - 0x34d92 bytes
ole32.dll!ModalLoop() + 0x5b bytes
ole32.dll!ThreadSendReceive() + 0x36c bytes
ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall() + 0x4d bytes
ole32.dll!CRpcChannelBuffer::SendReceive2() + 0x8d bytes
ole32.dll!CCliModalLoop::SendReceive() + 0x1e bytes
ole32.dll!CAptRpcChnl::SendReceive() + 0x1a25 bytes
ole32.dll!CCtxComChnl::SendReceive() + 0x47 bytes
rpcrt4.dll!_NdrProxySendReceive@8() + 0x40 bytes
rpcrt4.dll!_NdrClientCall2() - 0xa83 bytes
rpcrt4.dll!_ObjectStublessClient@8() + 0x5d bytes
rpcrt4.dll!_ObjectStubless@0() + 0xf bytes
ole32.dll!CStdMarshal::Begin_RemQIAndUnmarshal1() + 0x91 bytes
ole32.dll!CStdMarshal::Begin_QueryRemoteInterfaces() + 0x46 bytes
ole32.dll!CStdMarshal::QueryRemoteInterfaces() + 0x37 bytes
ole32.dll!CStdIdentity::CInternalUnk::QueryMultipleInterfaces() - 0x2adf0 bytes
ole32.dll!CStdIdentity::CInternalUnk::QueryInterface() + 0x30 bytes
rpcrt4.dll!_IUnknown_QueryInterface_Proxy@12() + 0x16 bytes
jscript.dll!VAR::SetHeapObject() + 0x31 bytes
jscript.dll!VAR::Import() + 0x45d bytes
jscript.dll!VarList::ImportVar() + 0x2e bytes
jscript.dll!VarList::ImportRgvar() - 0x160fb bytes
jscript.dll!CSession::Execute() + 0xd6 bytes
jscript.dll!NameTbl开发者_StackOverflow社区::InvokeDef() + 0x146 bytes
jscript.dll!NameTbl::InvokeEx() - 0x42f bytes
jscript.dll!IDispatchExInvokeEx2() + 0x8e bytes
jscript.dll!IDispatchExInvokeEx() + 0x4f bytes
jscript.dll!NameTbl::InvokeEx() - 0x18653 bytes
msscript.ocx!CScriptControl::ModuleRun() + 0x171 bytes
msscript.ocx!CScriptControl::Run() + 0x5d bytes
[several levels of my code, which I cannot reveal]
myapp.exe!MyView::OnBeginPrinting(CDC * pDC, CPrintInfo * pInfo) Line 92 C++
mfc100d.dll!CPreviewView::SetPrintView(CView * pPrintView) Line 370 C++
mfc100d.dll!CView::DoPrintPreview(unsigned int nIDResource, CView * pPrintView, CRuntimeClass * pPreviewViewClass, CPrintPreviewState * pState) Line 218 + 0xc bytes C++
mfc100d.dll!AFXPrintPreview(CView * pView) Line 298 + 0x1b bytes C++
In the end, I ended up deriving from CPreviewView as described in TN030, and suppressing WM_DRAW messages while I was busy doing RPCs. I can't say I'm too happy about this solution, but it seems to work.
精彩评论