Implementing EnumFrameInfo
When the session debug manager (SDM) receives a breakpoint event, it eventually calls IDebugThread2::EnumFrameInfo to obtain an enumeration for accessing the stack frame information (as represented by the FRAMEINFO structure).
Because there is only one thread in the program being debugged by TextInterpreter, IDebugThread2::EnumFrameInfo is implemented on the program object by CProgram::EnumFrameInfo. This method creates a single FRAMEINFO structure that contains an IDebugStackFrame2 interface (which is implemented on TextInterpreter’s CTIStackFrame class).
The CProgram::EnumFrameInfo method obtains the necessary document context from the saved, bound breakpoint as stored in a global variable by the CPendingBreakpoint::Bind method. In TextInterpreter’s implementation of CProgram::EnumFrameInfo, the steps needed to gain access to the document context from the breakpoint are clearly shown.
In a more typical implementation, the breakpoint that was encountered would be retained by the debug engine, probably in the class representing the IDebugThread2 interface. This breakpoint would then be readily accessible to the implementation of IDebugThread2::EnumFrameInfo.
To implement EnumFrameInfo
Open the Program.cpp file and add the following bold lines after the last #include line:
#include "Breakpoint.h" #include "TIStackFrame.h" #include "Context.h"
In Program.cpp, find CProgram::EnumFrameInfo and replace the line //TODO: RETURN ENUMERATION OF FRAMES as well as the following return statement with the following:
// Create a single stack frame. FRAMEINFO *pFrameInfo = (FRAMEINFO *) malloc(sizeof(FRAMEINFO)); if (NULL == pFrameInfo) return E_OUTOFMEMORY; memset(pFrameInfo, 0, sizeof(FRAMEINFO)); FRAMEINFO_FLAGS fi = FIF_LANGUAGE | FIF_FUNCNAME | FIF_STACKRANGE | FIF_FRAME; pFrameInfo->m_dwValidFields = fi; pFrameInfo->m_bstrLanguage = SysAllocString(L"Simple Language"); pFrameInfo->m_bstrFuncName = SysAllocString(L"Simple Function"); CComObject<CTIStackFrame> *pFrame; CComObject<CTIStackFrame>::CreateInstance(&pFrame); pFrame->AddRef(); pFrameInfo->m_pFrame = (IDebugStackFrame2 *) pFrame; // Initialize code and doc contexts here. // Get sbstrFile and pos. CComPtr<IDebugBreakpointResolution2> pBPResolution; gpBP->GetBreakpointResolution(&pBPResolution); BP_RESOLUTION_INFO bpResInfo; pBPResolution->GetResolutionInfo(BPRESI_ALLFIELDS, &bpResInfo); IDebugDocumentContext2 *pDocContext; bpResInfo.bpResLocation.bpResLocation.bpresCode.pCodeContext-> GetDocumentContext(&pDocContext); bpResInfo.bpResLocation.bpResLocation.bpresCode.pCodeContext-> Release(); CComBSTR sbstrDoc; TEXT_POSITION posBeg; pDocContext->GetName(GN_FILENAME, &sbstrDoc); pDocContext->GetSourceRange(&posBeg, NULL); pDocContext->Release(); CComObject<CDebugContext> *pContext; CComObject<CDebugContext>::CreateInstance(&pContext); pContext->AddRef(); pContext->Initialize(sbstrDoc, posBeg); pFrame->Init(pContext); pContext->Release(); // Create and initialize enumerator. CComObject<CEnumFrameInfo> *pEnum; CComObject<CEnumFrameInfo>::CreateInstance(&pEnum); pEnum->AddRef(); pEnum->Init(pFrameInfo); // Free frame resources. SysFreeString(pFrameInfo->m_bstrLanguage); SysFreeString(pFrameInfo->m_bstrFuncName); pFrame->Release(); free(pFrameInfo); *ppEnum = pEnum; return S_OK;
Build the project to make sure there are no errors.