Crash during "scalar deleting destructor" with IDocHostUIHandler!
Sorry for the cross-post, I'm not sure where this problem is coming from, so
I don't know which group is most likely to be able to help.
In my MFC C++ app, I'm creating a browser window inside a dialog, and I want
to have it be able to communicate with my application. It seems like the
way to do this, is to create a class that implements IDocHostUIHandler, pass
it into the ICustomDoc::SetUIHandler(), and then implement a dispatch class
(one that implements IDispatch) which I return when the HTML control calls
my IDocHostUIHandler::GetExternal.
So far so good. I have a class that implements IDocHostUIHandler, and it is
getting called on a variety of methods (ShowUI, HideUI, etc.) so that's
working.
However, now I have a class that derives from CCmdTarget and calls
EnableAutomation in its constructor, so it should be a happy IDispatch kind
of guy. When my IDocHostUIHandler::GetExternal is called, I 'new' up one of
those, call its InternalAddRef(), and then store its address into the
ppDispatch passed to me in the GetExternal call. I can step through that
with the debugger, but as soon as that function returns, I get a C0000005
exception.
Is there something special I need to be doing in this CCmdTarget-derived
class? Or something different I need to do in my
IDocHostUIHandler::GetExternal?
Thanks!
Chris
=======================
class CDocHostUIHandler : public IDocHostUIHandler, IOleCommandTarget
....
virtual HRESULT STDMETHODCALLTYPE GetExternal(
/* [out] */ IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
{
TRACE(L"CDocHostUIHandler::GetExternal(ppDispatch=%p)\n", ppDispatch);
External* pExt = new External;
pExt->InternalAddRef();
*ppDispatch = (IDispatch*)pExt;
return S_OK;
}
....
====================
class External : public CCmdTarget
{
DECLARE_DYNAMIC(External)
public:
External(void);
virtual ~External();
// Attributes
public:
protected:
#ifdef _DEBUG
///// NOTICE - NONE OF THESE FUNCTIONS EVER GET CALLED
virtual BOOL GetDispatchIID(IID* pIID)
{
TRACE(L"External::GetDispatchIID()\n");
return CCmdTarget::GetDispatchIID(pIID);
}
virtual UINT GetTypeInfoCount()
{
TRACE(L"External::GetTypeInfoCount()\n");
return CCmdTarget::GetTypeInfoCount();
}
virtual CTypeLibCache* GetTypeLibCache()
{
TRACE(L"External::GetTypeLibCache()\n");
return CCmdTarget::GetTypeLibCache();
}
virtual HRESULT GetTypeLib(LCID lcid, LPTYPELIB* ppTypeLib)
{
TRACE(L"External::GetTypeLib()\n");
return CCmdTarget::GetTypeLib(lcid, ppTypeLib);
}
#endif
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(External)
public:
virtual void OnFinalRelease();
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(External)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
// Generated OLE dispatch map functions
//{{AFX_DISPATCH(External)
afx_msg void PopulateWindow(LPCTSTR lpszSection);
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()
};
=====================================
// External.cpp : implementation file
//
#include "stdafx.h"
#include "External.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
// External
IMPLEMENT_DYNAMIC(External, CCmdTarget)
External::External(void)
{
TRACE(L"External::External() entered [this=%p]\n", this);
EnableAutomation();
}
External::~External()
{
// =============== NEVER GETS CALLED
TRACE(L"External::~External() entered [this=%p]\n", this);
}
void External::OnFinalRelease()
{
///// ====== NEVER GETS CALLED
TRACE(L"External::OnFinalRelease()\n");
// When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// deletes the object. Add additional cleanup required for your
// object before calling the base class.
CCmdTarget::OnFinalRelease();
}
BEGIN_MESSAGE_MAP(External, CCmdTarget)
//{{AFX_MSG_MAP(External)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(External, CCmdTarget)
//{{AFX_DISPATCH_MAP(External)
DISP_FUNCTION(External, "PopulateWindow", PopulateWindow, VT_EMPTY,
VTS_BSTR)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
// {27FD7E29-B451-46c9-8234-F285DAEE2567}
static const IID IID_IExternal =
{ 0x27fd7e29, 0xb451, 0x46c9, { 0x82, 0x34, 0xf2, 0x85, 0xda, 0xee, 0x25,
0x67 } };
BEGIN_INTERFACE_MAP(External, CCmdTarget)
INTERFACE_PART(External, IID_IExternal, Dispatch)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// External message handlers
void External::PopulateWindow(LPCTSTR lpszSection)
{
TRACE(L"External::PopulateWindow(lpszSection=\"%s\")\n", lpszSection);
}