OLE is not uninitialized correctly when you try to use the RichEdit control in an application that calls OleInitialize (238989)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++, 32-bit Enterprise Edition 5.0
- Microsoft Visual C++, 32-bit Enterprise Edition 6.0
- Microsoft Visual C++, 32-bit Professional Edition 5.0
- Microsoft Visual C++, 32-bit Professional Edition 6.0
- Microsoft Visual C++, 32-bit Learning Edition 6.0
- Microsoft Visual C++ .NET (2002)
- Microsoft Visual C++ .NET (2003)
This article was previously published under Q238989 Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. SYMPTOMS When using the RichEdit control in an application that
calls OleInitialize, if the control is destroyed during a Component Object Model
(COM) call, then OLE will not be uninitialized correctly.CAUSE The problem occurs because the RichEdit control, by
default, calls OleInitialize when it is initialized, and calls OleUninitialize when it is destroyed. If the application is in the context of a
COM call when it destroys the RichEdit window, then OleUninitialize will not run correctly, because OleUninitialize ends up calling CoUninitialize, and CoUninitialize will return immediately if the thread is in the context of
another COM call. This results in an unbalanced call to CoInitialize, and therefore the OLE libraries are not uninitialized
correctly.
Please note this problem applies only to RichEdit 1.0.
A known issue with this problem is if the RichEdit control
is used in an Active Document Server, and the server destroys the RichEdit
control within the context of the IOleObject::Close call. This happens in MFC when the RichEdit control is destroyed
when the view, or the document, is being destroyed. WORKAROUND To work around this problem, the RichEdit control should be
created so that it will not call OleInitialize and OleUninitialize. To do this, set the ES_EX_NOCALLOLEINIT style during the WM_NCCREATE message, before the RichEdit control
handles this message. The following steps describe how to do this in
MFC:
- Create a class that is derived from CRichEditCtrl:
class CMyRichEdit : public CRichEditCtrl
{
DECLARE_DYNCREATE(CMyRichEdit)
public:
CMyRichEdit(){};
~CMyRichEdit(){};
//{{AFX_MSG(CMyRichEdit)
afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
- Add the message map and entries as follows in the *.cpp
file for the class:
IMPLEMENT_DYNCREATE(CMyRichEdit, CRichEditCtrl)
BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
//{{AFX_MSG_MAP(CMyRichEdit)
ON_WM_NCCREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
- Handle the OnNcCreate function as follows:
BOOL CMyRichEdit::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
LONG gwlEx = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
gwlEx |= ES_EX_NOCALLOLEINIT;
gwlEx = ::SetWindowLong(m_hWnd, GWL_EXSTYLE, gwlEx);
if (!CRichEditCtrl::OnNcCreate(lpCreateStruct))
return FALSE;
return TRUE;
}
Use GetWindowLong and SetWindowLong to add the ES_EX_NOCALLOLEINIT style to the control. This method
must be used because the RichEdit control does not pay attention to this
extended style when creating the control through CreateWindowEx. STATUS
This behavior is by design.
Modification Type: | Major | Last Reviewed: | 9/2/2005 |
---|
Keywords: | kbOLEApp kbtshoot kbActiveDocs kbContainer kbCtrl kbprb kbRichEdit KB238989 kbAudDeveloper |
---|
|