Implementing CEnumFrameInfo
When the session debug manager (SDM) receives a breakpoint event (as represented by the IDebugBreakpointEvent2 interface), it enumerates through the bound breakpoints supplied by a call to IDebugBreakpointEvent2::EnumBreakpoints. From each bound breakpoint, it obtains the breakpoint resolution information (as represented by the IDebugBreakpointResolution2 interface, as returned by IDebugBoundBreakpoint2::GetBreakpointResolution). From the resolution information, the SDM obtains the IDebugThread2 interface and calls IDebugThread2::EnumFrameInfo, which returns an IEnumDebugFrameInfo2 interface. From the FRAMEINFO structures enumerated by the IEnumDebugFrameInfo2 interface, the SDM can extract the document context (as represented by the IDebugDocumentContext2 interface).
TextInterpreter implements the IEnumDebugFrameInfo2 interface on the CEnumFrameInfo class. Because there is only one stack frame in TextInterpreter, CEnumFrameInfo handles only one FRAMEINFO structure.
To implement CEnumFrameInfo
In Solution Explorer, right-click the TextInterpreter project, click Add Class, click an ATL Simple Object, and click Add.
For the Short name, type EnumFrameInfo.
Modify the .h file to be TIStackFrame.h and the .cpp file to be TIStackFrame.cpp.
Clear the Attributed option.
Change the Interface to IEnumDebugFrameInfo2.
Click Next or click the Options link on the left. Answer Yes if asked whether to merge with the contents of the TIStackframe file.
Change the Interface from Dual to Custom.
Click Finish to add the ATL object to the project. Answer Yes if asked whether to merge with the contents of the TIStackframe file.
Open the TextInterpreter.idl file and remove the declaration for the interface IEnumDebugFrameInfo2, which looks similar to the following (the uuid may be different):
[ object, uuid(A3A3270A-D92C-47CF-ABE2-42487251D349), helpstring("IEnumDebugFrameInfo2 Interface"), pointer_default(unique) ] interface IEnumDebugFrameInfo2 : IUnknown{ };
In Class View, right-click the new CEnumFrameInfo class, click Add Variable, and add a variable with the Variable name m_FrameInfo, the Variable type of FRAMEINFO, and an Access type of protected.
In Class View, right-click the CEnumFrameInfo class and click Add Function to add a function with the Function Name Init, a Return type of void, an Access type of public, and the following parameter (click Add before clicking Finish). Make sure that the .cpp file says TIStackFrame.cpp.
Parameter type
Parameter name
FRAMEINFO *
pFrameInfo
In Class View, right-click the CEnumFrameInfo class and click Add Function to add another function, this one private with the Function Name CopyEnumElement, a Return type of void, an Access type of private, and the following parameters (click Add between each parameter):
Parameter type
Parameter name
FRAMEINFO *
pDest
FRAMEINFO *
pSrc
Open TIStackFrame.h, find the CEnumFrameInfo class, and add the following bold lines. These are the declarations for the methods on the IEnumDebugFrameInfo2 interface.
END_COM_MAP() //////////////////////////////////////////////////////////// // IEnumDebugFrameInfo2 STDMETHOD(Next)(ULONG celt, FRAMEINFO *rgelt, ULONG* pceltFetched); STDMETHOD(Skip)(ULONG celt); STDMETHOD(Reset)(); STDMETHOD(Clone)(IEnumDebugFrameInfo2** ppEnum); STDMETHOD(GetCount)(ULONG* pcelt);
Also in the CEnumFrameInfo class, find the FinalRelease method and add the following to it:
SysFreeString(m_FrameInfo.m_bstrLanguage); SysFreeString(m_FrameInfo.m_bstrFuncName); (m_FrameInfo.m_pFrame)->Release();
Open the TIStackFrame.cpp file, find the definition for the new CEnumFrameInfo class, and insert the following bold lines. These are the definitions for the methods on the IEnumDebugFrameInfo2 interface.
// CEnumFrameInfo ////////////////////////////////////////////////////////////////////////////// // IEnumDebugFrameInfo2 HRESULT CEnumFrameInfo::Skip(ULONG celt) { return E_NOTIMPL; } HRESULT CEnumFrameInfo::Clone(IEnumDebugFrameInfo2** ppEnum) { return E_NOTIMPL; } HRESULT CEnumFrameInfo::Reset() { return S_OK; } HRESULT CEnumFrameInfo::GetCount(ULONG* pcelt) { *pcelt = 1; return S_OK; } HRESULT CEnumFrameInfo::Next(ULONG celt, FRAMEINFO *rgelt, ULONG* pceltFetched) { // Return only one frame. if (celt == 0 || celt > 1) return E_NOTIMPL; CopyEnumElement(&rgelt[0], &m_FrameInfo); *pceltFetched = 1; return S_OK; }
In TIStackFrame.cpp, find the definition for CEnumStackInfo::Init and add the following bold lines:
void CEnumFrameInfo::Init(FRAMEINFO * pFrameInfo) { // Copy source FRAMEINFO to member FRAMEINFO. CopyEnumElement(&m_FrameInfo, pFrameInfo); }
Find the definition for CEnumStackInfo::CopyEnumElement and add the following:
void CEnumFrameInfo::CopyEnumElement(FRAMEINFO * pDest, FRAMEINFO * pSrc) { if ((NULL != pSrc) && (NULL != pDest) ) { // Start with rough copy. *pDest = *pSrc; pDest->m_bstrFuncName = SysAllocString(pSrc->m_bstrFuncName); pDest->m_bstrLanguage = SysAllocString(pSrc->m_bstrLanguage); pDest->m_pFrame = pSrc->m_pFrame; if (pDest->m_pFrame) pDest->m_pFrame->AddRef(); } }
Build the project to make sure there are no errors.