BUG: You receive an "ASSERT in wincore.cpp" assert when an MFC application calls a function in MFC regular DLL in Visual C++ (194300)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
This article was previously published under Q194300 SYMPTOMS When an MFC EXE SDI/MDI application in the context of a
command handler calls an exported function in MFC regular DLL, which creates a
MFC modal dialog box, the following asserts may be triggered:
ASSERT in wincore.cpp line 884 ASSERT in
wincore.cpp line 883 If the asserts are ignored, the behavior of the
application is normal. The EXE and regular DLL must be dynamically linked to
MFC. CAUSE When a parent is not explicitly specified for a modal
dialog box, MFC in the PreModal() call determines the parent with a call to
CWnd::GetSafeOwner_(). This call returns the routing frame
(AfxGetThreadState()->m_pRoutingFrame). m_pRoutingFrame is assigned in a
command handler. [See CPushRoutingFrame in CFrameWnd::OnCmdMsg()].
The routing frame is set in the command handler in the EXE, to a frame window
of the EXE. Because the thread state is the same in the EXE and the DLL,
AfxGetThreadState()->m_pRoutingFrame returns the EXE frame window. A
temporary CWnd is created, in the temporary handle map of the DLL, for the
routing frame in the CDialog::PreModal() call when calling
CWnd::FromHandle(::GetActiveWindow()). This assert, in CWnd::AssertValid(), is
caused by the fact that routing frame does not match the temporary CWnd present
in the temporary handle map of the regular DLL.
This problem affects
all modal windows that are created in a command handler in the context of a
regular DLL, where CWnd::GetSafeOwner_() is called. CWnd::GetSafeOwner_() is
called during the creation of modal windows. This includes MFC message boxes,
OLE property sheets, CDatabase::Connect, dialogs boxes, property sheets, and
OLE busy dialog boxes. Note that this problem does not affect modeless windows
because CWnd::GetSafeOwner_() is not called in this context. RESOLUTION One workaround is to temporarily set
AfxGetThreadState()->m_pRoutingFrame to NULL for the duration of the
DoModal() call. The following code can be used:
class tempRoutingFrame {
CFrameWnd* m_pFrame ;
public:
tempRoutingFrame(CFrameWnd * pWnd= NULL)
{
// Save current value
m_pFrame = AfxGetThreadState()->m_pRoutingFrame;
// Set to value passed in. NULL by default.
AfxGetThreadState()->m_pRoutingFrame = pWnd;
}
~tempRoutingFrame()
{
// Restore m_pRoutingFrame to original value.
AfxGetThreadState()->m_pRoutingFrame = m_pFrame;
}
};
extern "C" void __declspec(dllexport) TestFunction();
void TestFunction()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
#ifdef _DEBUG
// Workaround for ASSERT in WINCORE.CPP 884 (CWnd::AssertValid)
tempRoutingFrame rframe;
#endif
CMyDialog dlg;
dlg.DoModal();
}
Another workaround, in the case of dialog boxes and property sheets, is
to explicitly set the parent of the dialog box as follows:
void TestFunction()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
CMyDialog dlg(AfxGetMainWnd());
dlg.DoModal();
}
STATUSMicrosoft has confirmed that this is a bug in the Microsoft
products that are listed at the beginning of this article.
This
bug was corrected in Visual Studio 6.0 Service Pack 3.
For more information about Visual Studio service packs, click the following article numbers to view the articles in the Microsoft Knowledge Base:
194022
Visual Studio 6.0 service packs, what, where, why
194295 How to tell that a Visual Studio service pack is installed
REFERENCES TN058: MFC Module State Implementation
Modification Type: | Major | Last Reviewed: | 6/2/2005 |
---|
Keywords: | kbtshoot kbArchitecture kbbug kbDLL kbDocView kbfix kbNoUpdate kbVS600sp3fix KB194300 kbAudDeveloper |
---|
|