Adding the Debug Engine Object
In a typical implementation, the session debug manager (SDM) instantiates the debug engine after the program to be debugged is physically loaded and then attaches the debug engine to the program. The debug engine may or may not already be running as an ATL COM object (the process of instantiating it loads and runs the debug engine if it is not already running).
In TextInterpreter, since the debug engine is in the same module as the interpreter, it is instantiated as an ATL COM object when the interpreter is loaded and started, rather than letting Visual Studio handle that task.
All debug engines are derived from the IDebugEngine2 interface. In TextInterpreter, the CDebugEngine class implements this interface.
To add the debug engine object
In Solution Explorer, right-click the TextInterpreter project and click Add Class.
Click the ATL category on the left, click ATL Simple Object on the right, and click Add.
Type Engine for the short name; the other fields automatically fill in.
Clear the Attributed option.
Change the Interface to IDebugEngine2.
Click Next or click the Options link on the left.
Change the Interface from Dual to Custom.
Click Finish to add the ATL object to the project.
Open the TextInterpreter.idl file.
Add the following bold line:
import "ocidl.idl"; import "msdbg.idl";
From the TextInterpreter.idl, remove the IDebugEngine2 interface declaration; it will look similar to the following lines (the uuid may be different).
[ object, uuid(F5BD02C0-3B02-4737-8496-BDFA138D7FD7), helpstring("IDebugEngine2 Interface"), pointer_default(unique) ] interface IDebugEngine2 : IUnknown{ };
Open the Engine.h file and add the following bold lines. These are the declarations of all the methods on the IDebugEngine2 interface.
END_COM_MAP() //////////////////////////////////////////////////////////// //IDebugEngine2 STDMETHOD(EnumPrograms)(IEnumDebugPrograms2** ppEnum); STDMETHOD(Attach)( IDebugProgram2 **rgpPrograms, IDebugProgramNode2 **rgpProgramNodes, DWORD celtPrograms, IDebugEventCallback2 *pCallback, ATTACH_REASON dwReason); STDMETHOD(CreatePendingBreakpoint)( IDebugBreakpointRequest2 *pBPRequest, IDebugPendingBreakpoint2** ppPendingBP); STDMETHOD(SetException)(EXCEPTION_INFO* pException); STDMETHOD(RemoveSetException)(EXCEPTION_INFO* pException); STDMETHOD(RemoveAllSetExceptions)(REFGUID guidType); STDMETHOD(GetEngineId)(GUID *pguidEngine); STDMETHOD(DestroyProgram)(IDebugProgram2* pProgram); STDMETHOD(ContinueFromSynchronousEvent)(IDebugEvent2* pEvent); STDMETHOD(SetLocale)(WORD wLangID); STDMETHOD(SetRegistryRoot)(LPCOLESTR pszRegistryRoot); STDMETHOD(SetMetric)(LPCOLESTR pszMetric, VARIANT varValue); STDMETHOD(CauseBreak)( void);
Open the Engine.cpp file and add the following bold lines. These are the definitions for all the methods (all will be returning E_NOTIMPL for now, and only a couple will eventually be implemented in this project).
// CEngine ////////////////////////////////////////////////////////////////////////////// //IDebugEngine2 methods HRESULT CEngine::EnumPrograms(IEnumDebugPrograms2** ppEnum) { return E_NOTIMPL; } HRESULT CEngine::SetException(EXCEPTION_INFO* pException) { return E_NOTIMPL; } HRESULT CEngine::RemoveSetException(EXCEPTION_INFO* pException) { return E_NOTIMPL; } HRESULT CEngine::RemoveAllSetExceptions(REFGUID guidType) { return E_NOTIMPL; } HRESULT CEngine::GetEngineId(GUID *pguidEngine) { return E_NOTIMPL; } HRESULT CEngine::DestroyProgram(IDebugProgram2* pProgram) { return E_NOTIMPL; } HRESULT CEngine::SetLocale(WORD wLangID) { return E_NOTIMPL; } HRESULT CEngine::SetRegistryRoot(LPCOLESTR pszRegistryRoot) { return E_NOTIMPL; } HRESULT CEngine::SetMetric(LPCOLESTR pszMetric, VARIANT varValue) { return E_NOTIMPL; } HRESULT CEngine::CauseBreak(void) { return E_NOTIMPL; } HRESULT CEngine::Attach( IDebugProgram2 **rgpPrograms, IDebugProgramNode2 **rgpProgramNodes, DWORD celtPrograms, IDebugEventCallback2 *pCallback, ATTACH_REASON dwReason) { // TODO: IMPLEMENT ATTACH return E_NOTIMPL; } HRESULT CEngine::ContinueFromSynchronousEvent(IDebugEvent2* pEvent) { //TODO: IMPLEMENT CONTINUE return E_NOTIMPL ; } HRESULT CEngine::CreatePendingBreakpoint( IDebugBreakpointRequest2 *pBPRequest, IDebugPendingBreakpoint2** ppPendingBP) { //TODO: IMPLEMENT BREAKPOINT CREATION return E_NOTIMPL ; }
Build the project to make sure there are no errors.