views:

31

answers:

1

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::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++
A: 

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.

bdonlan