Converting Stopping Events to Messages
The Load Complete event is a synchronous event. When the session debug manager (SDM) has finished processing this event, it calls IDebugEngine2::ContinueFromSynchronousEvent. However, in order for the SDM to finish processing the event, it has to wait for input from the user, who decides whether to start the program being debugged (possibly to run it to a breakpoint) or step into the program. Based on the user's decision, the SDM calls either IDebugProgram2::Execute to start the program or IDebugProgram2::Step to step into the program. Each of these methods sets the stage for the time when the SDM calls IDebugEngine2::ContinueFromSynchronousEvent and the program being debugged can execute.
Note
Before the Load Complete event has completed, the SDM establishes any pending breakpoints the user may have set before selecting Start or Step. Breakpoints are implemented in a later procedure.
TextInterpreter does not support the concept of single-stepping through the code: either the program is running or it is stopped. So the main message pump (as implemented in CTextInterpreterModule::MonitorShutdown) watches for a single message to be sent, which indicates that the program being debugged should be continued. TextInterpreter's implementation of IDebugProgram2::Execute, IDebugProgram2::Continue, and IDebugProgram2::Step all post that same continue message to the current thread (which MonitorShutdown is running on) and do nothing else.
In a more typical scenario, IDebugProgram2::Execute, IDebugProgram2::Continue, and IDebugProgram2::Step might each send a different message to the main message pump, which would in turn call different methods on the program object depending on the message. Or IDebugProgram2::Execute, IDebugProgram2::Continue and IDebugProgram2::Step might set a state variable within the program object, and an implementation of CProgram::Go would use that state variable to take the appropriate action. However these are implemented, the debug engine does not ultimately call CProgram::Go (or its equivalent) until IDebugEngine2::ContinueFromSynchronousEvent has been called to finish the synchronous event handling.
To convert stopping events to messages
Open the stdafx.h file and add the following bold line to the end of the file:
#define WM_CONTINUE_SYNC_EVENT WM_USER + 0x99 #define WM_CONTINUE WM_USER + 0x9A
Open the Program.cpp file, find CProgram::Execute, and replace the line //TODO: BEGIN EXECUTION as well as the following return statement with the following:
PostThreadMessage(GetCurrentThreadId(), WM_CONTINUE, 0, (LPARAM)this); return S_OK;
In the method CProgram::Continue, replace the line //TODO: CONTINUE EXECUTION as well as the following return statement with the following:
PostThreadMessage(GetCurrentThreadId(), WM_CONTINUE, 0, (LPARAM)this); return S_OK;
In the method CProgram::Step, replace the line //TODO: STEP EXECUTION as well as the following return statement with the following:
PostThreadMessage(GetCurrentThreadId(), WM_CONTINUE, 0, (LPARAM)this); return S_OK;
In Class View, right-click the CProgram class, select Add Function, and add a function with the Function name Go, a Return type of void, an Access type of public, and no parameters. This method will be implemented later.
Open the TextInterpreter.cpp file, find CTextInterpreterModule::MonitorShutdown, and replace the line //TODO: IMPLEMENT CONTINUE with the following:
if (WM_CONTINUE == msg.message) ((CProgram *) msg.lParam)->Go();
Build the project to make sure there are no errors.