Figures
Figure 2 Application Debugger Interfaces
Interface
Description
IDebugSessionProvider
Interface used by third-party clients to establish a debug session for a running application
IApplicationDebugger
Main interface that is called when debugging events occur within the system
Figure 3 Language Engine Interfaces
Interface
Description
IActiveScriptDebug
Gives indication of debugging support and provides syntax coloring and code context enumeration
IActiveScriptErrorDebug
Abstracts compile-time and runtime errors that occur within code
IDebugCodeContext
Thread virtual instruction pointer that's used to set breakpoints and get context for property enumeration
IEnumDebugCodeContexts
Enumerator that maintains a set of debug code contexts
IDebugStackFrame
Represents a given stack frame (and execution context) in an application
IDebugExpressionContext
Provides runtime context for expression evaluation
IDebugExpression
Expression that is to be evaluated within a given expression context
IDebugExpressionCallBack
Notification mechanism used by language engine when an expression has completed its evaluation
Figure 4 Process Debug Manager Interfaces
Interface
Description
IProcessDebugManager
Used to create, add, and remove virtual applications from a process, enumerate stack frames, application threads, and so on
IRemoteDebugApplication
Abstracts an application that can run on a machine
IDebugApplication
Provides more specific, machine-dependent access to an IRemoteDebugApplication
IRemoteDebugApplicationThread
Abstracts a thread within the operating system that an application executes on
IDebugApplicationThread
Provides more specific, machine-dependent access to an IRemoteDebugApplicationThread
IEnumRemoteDebug-ApplicationThreads
Enumerator that maintains a set of application threads
IDebugApplicationNode
Maintains a position of a document in a document tree
IEnumDebugApplicationNodes
Enumerator that maintains a set of application nodes
IEnumDebugStackFrames
Enumerator that maintains a set of stack frames
IDebugDocumentHelper
Provides helper support for implementing smart hosts
Figure 5 Machine Debug Manager Interfaces
Interface
Description
IEnumRemoteDebugApplications
Enumerator that maintains a set of applications
IMachineDebugManager
Main interface used to add and remove applications from the MDM task list
IMachineDebuggerEvents
Fires events when the MDM task list changes
IMachineDebuggerCookie
Has the same functionality as IMachineDebugManager, except it uses cookies instead of interface pointers for adding and removing applications
Figure 7 COM Interfaces Implemented by Smart Hosts
Interface
Description
IDebugDocumentInfo
Provides information on a given document (such as a name)
IDebugDocumentProvider
Allows lazy instantiation of documents
IDebugDocument
Abstract interface that represents a document in the system
IDebugDocumentText
Represents the textual contents of a document
IDebugDocumentTextEvents
Connection point interface used to notify when a given document's contents change
IDebugDocumentContext
Represents a location within a given document
IDebugApplicationNode
Represents a single document in a hierarchy of documents
IDebugApplicationNodeEvents
Connection point interface used to notify when a document hierarchy changes
Figure 9 onHandleBreakPoint Circumstance Flags
Enumerated Value
Description
BREAKREASON_STEP
Caused when step into or step out of resume actions are used for resuming an application thread that was interrupted with a breakpoint
BREAKREASON_BREAKPOINT
Caused when an explicit breakpoint configured by IDebugCodeContext::Set-BreakPoint is hit
BREAKREASON_DEBUGGER_BLOCK
Caused by another thread in the application breaking
BREAKREASON_HOST_INITIATED
Caused by a host requested break
BREAKREASON_LANGUAGE_INITIATED
Caused by a statement in code to break (such as a Stop procedure in VBScript)
BREAKREASON_DEBUGGER_HALT
Caused by the debugger IDE requesting a break
BREAKREASON_ERROR
Caused by a code execution error
Figure 11 Retrieve Source Text
ULONG numLines;
ULONG numChars;
ULONG charsRcd = 0;

// Figure out how much memory to allocate by seeing how big document text is
hRes = ddt->GetSize(&numLines,&numChars);

WCHAR *sourceText = new WCHAR[numChars];
SOURCE_TEXT_ATTR *sourceTextAttr = new SOURCE_TEXT_ATTR[numChars];

hRes = ddt->GetText(position,       // cCharacterPosition
                    sourceText,     // pcharText
                    sourceTextAttr, // pstaTextAttr
                    &charsRcd,      // pcNumChars
                    numChars        // cMaxChars
                    );

// Do something with source text retrieved

delete [] sourceText;
delete [] sourceTextAttr;
Figure 12 Application Resume Flags
Enumerated Value
Description
BREAKRESUMEACTION_ABORT
Causes the application to immediately abort.
BREAKRESUMEACTION_CONTINUE
Causes the application to continue running (until either the next breakpoint or completion).
BREAKRESUMEACTION_STEP_INTO
Causes the application to step into the next available procedure. This will generate another breakpoint notification to onHandleBreakPoint once the step into operation finishes.
BREAKRESUMEACTION_STEP_OVER
Causes the application to step over the next available procedure. This will generate another breakpoint notification to onHandleBreakPoint once the step over operation finishes.
BREAKRESUMEACTION_STEP_OUT
Causes the application to step out of the current procedure. This will generate another breakpoint notification to onHandleBreakPoint once the step out operation finishes.
Figure 15 OnInitDialog
BOOL CCallStackDlg::OnInitDialog() 
{
    // local variables
    HRESULT hRes;                   // Return code from COM calls
    BSTR functionName;              // Name of function for stack frame
    IEnumDebugStackFrames *stackFrameEnum;  // Stack frame enumerator 
                                            // for thread
    DebugStackFrameDescriptor stackFrame;   // Particular stack 
                                            // frame in enumerator
    ULONG numFetched;               // Number of stack frames 
                                    // from enumerator

    // BEGIN
    USES_CONVERSION;

    CDialog::OnInitDialog();

    hRes = m_remoteApplicationThread->EnumStackFrames(&stackFrameEnum);
    hRes = stackFrameEnum->Reset();

    while(stackFrameEnum->Next(1,
                     &stackFrame,
                     &numFetched
                     ) == S_OK
          )
    {
        CString callStackEntry;

        // Get the description of the function from the call stack.
        // Note that the first parameter being true indicates that
        // the stack frame should return variable information if 
        // possible.
        stackFrame.pdsf->GetDescriptionString(true,
                                              &functionName
                                              );

        callStackEntry.Format(_T("0x%08X\t%s"),
                              stackFrame.dwMin,
                              OLE2T(functionName)
                              );

        m_callStackList.AddString(callStackEntry);

        // We need to manually clean up all parameters returned from
        // stack frame descriptor
        ::SysFreeString(functionName);
        stackFrame.pdsf->Release();

    } // end while(dsfs->Next(nextFrame,&dsf,&nextFrame) == S_OK)

    stackFrameEnum->Release();

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE

} // end CCallStackDlg::OnInitDialog
Figure 17 OnBtnEvaluate
void CImmediateDlg::OnBtnEvaluate() 
{
    // local variables
    IEnumDebugStackFrames *stackFrames; // Thread stack frame enumerator
    DebugStackFrameDescriptor sfd;      // Stack frame to execute
                                        // expression in 
    ULONG numFetched;                   // Stack frames count 
                                        // from enumerator
    HRESULT hRes;                       // COM call result
    IDebugExpressionContext *ec;        // Context expression is 
                                        // evaluated in
    IDebugExpression *debugExpression;  // expression to evaluate
    // Callback object used to wait for expression evaluation completion
    CComObject<CDebugExpressionCallback> *debugCallback;

    // BEGIN
    // It all starts with a stack frame...
    hRes = m_remoteApplicationThread->EnumStackFrames(&stackFrames);

    // We only need the top stack frame because that's where all
    // the variables of interest are
    hRes = stackFrames->Reset();
    hRes = stackFrames->Next(1,
                             &sfd,
                             &numFetched
                             );

    if(hRes == S_OK)
    {
        USES_CONVERSION;

        CComObject<CDebugExpressionCallback>::
            CreateInstance(&debugCallback);

        // Expression context is related to the stack frame
        hRes = sfd.pdsf->QueryInterface(IID_IDebugExpressionContext,
                                        (LPVOID*)&ec
                                        );

        UpdateData(TRUE);

        // Load the expression text into the expression context
        hRes = ec->ParseLanguageText(
                   T2OLE(m_expression),   // Expression
                   10,                    // Radix
                   NULL,                  // Text delimiter
                   DEBUG_TEXT_RETURNVALUE | // Need return
                   DEBUG_TEXT_ISEXPRESSION,
                   &debugExpression   // Expression result
                   );

        // Actually start the expression.
        hRes = debugExpression->Start(debugCallback);

        // Use our callback class to wait for the result to return.
        debugCallback->WaitForCompletion();

        HRESULT returnResult;
        BSTR returnValue;

        // Get the results of the expression evaluation
        hRes = debugExpression->GetResultAsString(&returnResult,
                                                  &returnValue
                                                  );

        m_result = OLE2T(returnValue);

        // Naturally, release all resources returned
        ::SysFreeString(returnValue);

        UpdateData(FALSE);
    } // end if(hRes == S_OK)

} // end CImmediateDlg::OnBtnEvaluate
Figure 19 IDebugProperty Definition
IDebugProperty : public IUnknown
{

public:
    virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo( 
        /* [in] */ DBGPROP_INFO_FLAGS dwFieldSpec,
        /* [in] */ UINT nRadix,
        /* [out] */ DebugPropertyInfo __RPC_FAR *pPropertyInfo) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE GetExtendedInfo( 
        /* [in] */ ULONG cInfos,
        /* [size_is][in] */ GUID __RPC_FAR *rgguidExtendedInfo,
        /* [size_is][out] */ VARIANT __RPC_FAR *rgvar) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE SetValueAsString( 
        /* [in] */ LPCOLESTR pszValue,
        /* [in] */ UINT nRadix) = 0;
    
    virtual HRESULT STDMETHODCALLTYPE EnumMembers( 
        /* [in] */ DBGPROP_INFO_FLAGS dwFieldSpec,
        /* [in] */ UINT nRadix,
        /* [in] */ REFIID refiid,
        /* [out] */ IEnumDebugPropertyInfo __RPC_FAR *__RPC_FAR *ppepi) = 
                    0;
    
    virtual HRESULT STDMETHODCALLTYPE GetParent( 
        /* [out] */ IDebugProperty __RPC_FAR *__RPC_FAR *ppDebugProp) = 
                    0;
        
};
Figure 20 AddPropertyToList
void CVariablesDlg::AddPropertyToList(HTREEITEM parent,
                                      IDebugProperty *debugProperty)
{
    // local variables
    IEnumDebugPropertyInfo *debugPropertyInfo;
    HRESULT hRes;
    ULONG numFetched = 0;

    // BEGIN
    USES_CONVERSION;

    // Get known members
    hRes = debugProperty->EnumMembers(DBGPROP_INFO_STANDARD | 
                                      DBGPROP_INFO_DEBUGPROP,
                                      10,
                                      IID_IEnumDebugPropertyInfo,
                                      &debugPropertyInfo);

    if(hRes == S_OK)
    {
        hRes = debugPropertyInfo->Reset();

        ULONG propertyCount;

        hRes = debugPropertyInfo->GetCount(&propertyCount);

        // Allocate array of properties to store enumeration results in
        DebugPropertyInfo *property = new 
            DebugPropertyInfo[propertyCount];

        // We batch process debug property members
        hRes = debugPropertyInfo->Next(propertyCount,
                                       property,
                                       &numFetched);
        debugPropertyInfo->Release();

        if(hRes == S_OK)
        {
            for(ULONG i = 0; i < numFetched; i++)
            {
                // Tree control code removed

                // See if there are subproperties to process
                if(property[i].m_pDebugProp != NULL)
                {
                    AddPropertyToList(variableItem,
                                      property[i].m_pDebugProp
                                      );

                } // end if(property[i].m_pDebugProp != NULL)

            } // end for

        } // end if(hRes == S_OK)

    } // end if(hRes == S_OK)

} // end CVariablesDlg::AddPropertyToList
Page view tracker