// ==++==
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
/*****************************************************************************
 **                                                                         **
 ** Cordebug.idl - Common Language Runtime Debugging interfaces.            **
 **                                                                         **
 *****************************************************************************/


/* ------------------------------------------------------------------------- *
 * Imported types
 * ------------------------------------------------------------------------- */

#if !DEFINITIONS_FROM_NON_IMPORTABLE_PLACES

cpp_quote("#if 0")

import "unknwn.idl";
import "objidl.idl";

typedef UINT32 mdToken;
typedef mdToken mdModule;
typedef SIZE_T  mdScope;
typedef mdToken mdTypeDef;
typedef mdToken mdSourceFile;
typedef mdToken mdMemberRef;
typedef mdToken mdMethodDef;
typedef mdToken mdFieldDef;
typedef mdToken mdSignature;
typedef ULONG CorElementType;
typedef SIZE_T PCCOR_SIGNATURE;

typedef SIZE_T LPDEBUG_EVENT;

typedef SIZE_T LPSTARTUPINFOW;
typedef SIZE_T LPPROCESS_INFORMATION;


cpp_quote("#endif")

typedef [wire_marshal(unsigned long)] void *HPROCESS;
typedef [wire_marshal(unsigned long)] void *HTHREAD;

typedef UINT64 TASKID;
typedef DWORD CONNID;




#endif

cpp_quote("#ifndef _COR_IL_MAP")
cpp_quote("#define _COR_IL_MAP")

// Note that this structure is also defined in CorProf.idl - PROPOGATE CHANGES
// BOTH WAYS, or this'll become a really insidious bug some day.
typedef struct _COR_IL_MAP
{
    ULONG32 oldOffset;      // Old IL offset relative to beginning of function
    ULONG32 newOffset;      // New IL offset relative to beginning of function
    BOOL    fAccurate;      // TRUE if mapping is known to be good, FALSE otherwise
} COR_IL_MAP;

cpp_quote("#endif //_COR_IL_MAP")

cpp_quote("#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_")
cpp_quote("#define _COR_DEBUG_IL_TO_NATIVE_MAP_")

/* ICorDebugCode:: GetILToNativeMapping returns an array of
 * COR_DEBUG_IL_TO_NATIVE_MAP structures.  In order to convey that certain
 * ranges of native instructions correspond to special regions of code (for
 * example, the prolog), an entry in the array may have it's ilOffset field set
 * to one of these values.
 */
typedef enum CorDebugIlToNativeMappingTypes
{
    NO_MAPPING = -1,
    PROLOG     = -2,
    EPILOG     = -3
} CorDebugIlToNativeMappingTypes;

typedef struct COR_DEBUG_IL_TO_NATIVE_MAP
{
    ULONG32 ilOffset;
    ULONG32 nativeStartOffset;
    ULONG32 nativeEndOffset;
} COR_DEBUG_IL_TO_NATIVE_MAP;

cpp_quote("#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_")

cpp_quote("#define REMOTE_DEBUGGING_DLL_ENTRY L\"Software\\\\Microsoft\\\\.NETFramework\\\\Debugger\\\\ActivateRemoteDebugging\"")


typedef enum CorDebugJITCompilerFlags
{
   CORDEBUG_JIT_DEFAULT = 0x1,                  // Track info, enable optimizations
   CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3,     // Includes track info, disable opts,
   CORDEBUG_JIT_ENABLE_ENC = 0x7                // Includes track & disable opt & Edit and Continue.
} CorDebugJITCompilerFlags;

typedef enum CorDebugJITCompilerFlagsDecprecated
{
   CORDEBUG_JIT_TRACK_DEBUG_INFO  = 0x1,          // Use CORDEBUG_JIT_DEFAULT instead
} CorDebugJITCompilerFlagsDeprecated;


/* ------------------------------------------------------------------------- *
 * Forward declarations
 * ------------------------------------------------------------------------- */
#pragma warning(push)
#pragma warning(disable:28718)    //Unable to annotate as this is not a local interface

interface ICorDebug;

interface ICorDebugController;
interface ICorDebugProcess;
interface ICorDebugProcess2;
interface ICorDebugAppDomain;
interface ICorDebugAssembly;
interface ICorDebugAssembly2;
interface ICorDebugBreakpoint;
interface ICorDebugFunctionBreakpoint;
interface ICorDebugModuleBreakpoint;
interface ICorDebugValueBreakpoint;
interface ICorDebugStepper;
interface ICorDebugEval;
interface ICorDebugEval2;
interface ICorDebugThread;
interface ICorDebugThread2;
interface ICorDebugThread3;
interface ICorDebugThread4;
interface ICorDebugStackWalk;
interface ICorDebugChain;
interface ICorDebugFrame;
interface ICorDebugILFrame;
interface ICorDebugInternalFrame;
interface ICorDebugInternalFrame2;
interface ICorDebugNativeFrame;
interface ICorDebugNativeFrame2;
interface ICorDebugRuntimeUnwindableFrame;
interface ICorDebugContext;
interface ICorDebugModule;
interface ICorDebugFunction;
interface ICorDebugFunction2;
interface ICorDebugCode;
interface ICorDebugClass;
interface ICorDebugType;

interface ICorDebugValue;
interface ICorDebugGenericValue;
interface ICorDebugReferenceValue;
interface ICorDebugHeapValue;
interface ICorDebugHeapValue2;
interface ICorDebugHeapValue3;
interface ICorDebugHandleValue;
interface ICorDebugObjectValue;
interface ICorDebugStringValue;
interface ICorDebugArrayValue;

interface ICorDebugEnum;
interface ICorDebugObjectEnum;
interface ICorDebugProcessEnum;
interface ICorDebugBreakpointEnum;
interface ICorDebugStepperEnum;
interface ICorDebugModuleEnum;
interface ICorDebugThreadEnum;
interface ICorDebugChainEnum;
interface ICorDebugTypeEnum;
interface ICorDebugCodeEnum;
interface ICorDebugFrameEnum;
interface ICorDebugValueEnum;
interface ICorDebugAppDomainEnum;
interface ICorDebugAssemblyEnum;
interface ICorDebugBlockingObjectEnum;

interface ICorDebugErrorInfoEnum;
interface ICorDebugMDA;

/* DEPRECATED */
interface ICorDebugEditAndContinueSnapshot;
/* DEPRECATED */
interface ICorDebugEditAndContinueErrorInfo;

#pragma warning(pop)

// All target addresses in ICorDebug are represented as 0-extended 64-bit integer values.
typedef ULONG64 CORDB_ADDRESS;

typedef ULONG64 CORDB_REGISTER;

typedef enum CorDebugBlockingReason {
    BLOCKING_NONE                     = 0x0,
    BLOCKING_MONITOR_CRITICAL_SECTION = 0x1,
    BLOCKING_MONITOR_EVENT            = 0x2
} CorDebugBlockingReason;

typedef struct CorDebugBlockingObject {
    ICorDebugValue         *pBlockingObject;
    DWORD                   dwTimeout;
    CorDebugBlockingReason  blockingReason;
} CorDebugBlockingObject;

/*
 * Callback interface for providing access to a particular target process. The
 * debugging services will call functions on this interface to access memory 
 * and other data in the target process.  The debugger client must implement 
 * this interface as appropriate for the particular target (for example, a live
 * process or a memory dump).  The DataTarget will only be invoked from within
 * the implementation of other ICorDebug APIs (i.e. the debugger client has 
 * control over which thread it is invoked on, and when) 
 *
 * Error HRESULTS returned by DataTarget APIs will propagate up and be returned
 * by the active ICorDebug API call.
 *
 * The DataTarget implementation must always return up-to-date information
 * about the target.  The target process should be stopped (not changing 
 * in any way) while ICorDebug APIs (and hence DataTarget APIs) are being 
 * called.  If the target is a live process and it's state changes,
 * OpenVirtualProcess needs to be called again to provide a replacement
 * ICorDebugProcess instance.
 */
[
    object,
    local,
    uuid(FE06DC28-49FB-4636-A4A3-E80DB4AE116C),
    pointer_default(unique)
]
interface ICorDebugDataTarget : IUnknown
{
    /*
     * GetPlatform returns the processor architecture and operating system on 
     * which the target process is (or was) running.  
     *
     * This is used by ICorDebug to determine details of the target process 
     * such as its pointer size, address space layout, register set, 
     * instruction format, context layout, and calling conventions, etc.
     * This platforms in this list are the only ones supported by this version
     * of ICorDebug, but more may be added in future versions.
     *
     * Note that this may actually indicate the platform which is being 
     * emulated for the target, not the actual hardware in use.  For example,
     * a process running in the WOW on Windows x64 should use 
     * CORDB_PLATFORM_WINDOWS_X86.
     *
     * Implementations should be sure to describe what the platform of the
     * target actually is, not just what the host expects it to be.
     *
     * This function must succeed.  If it fails, the DataTarget is unusable.
     */
    typedef enum CorDebugPlatform
    {
        CORDB_PLATFORM_WINDOWS_X86,       // Windows on Intel x86
        CORDB_PLATFORM_WINDOWS_AMD64,     // Windows x64 (Amd64, Intel EM64T)
        CORDB_PLATFORM_WINDOWS_IA64,      // Windows on Intel IA-64
        CORDB_PLATFORM_MAC_PPC,           // MacOS on PowerPC
        CORDB_PLATFORM_MAC_X86            // MacOS on Intel x86
    } CorDebugPlatform;

    HRESULT GetPlatform([out] CorDebugPlatform * pTargetPlatform);

    /*
     * ReadVirtual - Read virtual memory from the target process.
     *
     * Requests contiguous memory starting at the specified target address to 
     * be read from the target process into the supplied buffer.  If at least 
     * the first byte (at the specified start address) can be read, the call 
     * should return success (to support efficient reading of data structures
     * with self-describing length, like null-terminated strings).
     *
     * On success, the actual number of bytes read must be stored into 
     * pBytesRead.
     */
    HRESULT ReadVirtual([in] CORDB_ADDRESS address,
                        [out, size_is(bytesRequested), length_is(*pBytesRead)] BYTE * pBuffer,
                        [in] ULONG32 bytesRequested,
                        [out] ULONG32 * pBytesRead);

    /*
     * GetThreadContext - Get the thread context (register values) for a thread.
     *
     * Requests the current thread context for the specified (operating-system 
     * defined) thread identifier.  The size and format of the context record 
     * is platform dependant, and is determined by the result of the call to 
     * GetPlatform.  
     * 
     * The context flags specify, in a platform-dependent manor, which portions 
     * of the context should be read.  contextSize specifies the size of the
     * supplied buffer, but the function is free to not fill the whole buffer
     * if it is possible to determine the actual size from the context.
     *
     * On Windows platforms, the buffer must be a CONTEXT structure appropriate
     * for the machine type specified by GetPlatform.  contextFlags has the
     * same values as the ContextFlags field of CONTEXT.
     */
    HRESULT GetThreadContext([in] DWORD dwThreadID,
                             [in] ULONG32 contextFlags,
                             [in] ULONG32 contextSize,
                             [out, size_is(contextSize)] BYTE * pContext);
};


/*
 * Interface used by the data access services layer to locate metadata 
 * of assemblies in a target. 
 *
 * The API client must implement this interface as appropriate for the
 * particular target (for example, a live process or a memory dump).
 *
 */
[
    object,
    local,
    uuid(7cef8ba9-2ef7-42bf-973f-4171474f87d9),
    pointer_default(unique)
]
interface ICorDebugMetaDataLocator : IUnknown
{
    /*
     * Ask the debugger to return the full path to a module whose metadata is
     *  needed to complete an operation the debugger requested.
     *
     * Arguments:
     *  wszImagePath - This buffer will always contain a NULL-terminated string
     *      representing the full path to the file when available, and the
     *      FileName.extension otherwise.
     *  dwImageTimeStamp - The TimeStamp from the image's PE headers; can
     *      potentially be used for a symsrv lookup.
     *  dwImageSize - Size of the image from PE headers; potentially used for
     *      a symsrv lookup.
     *  cchPathBuffer - The count of WCHARs pointed to by wszPathBuffer.
     *  pcchPathBuffer - When the callee returns E_NOT_SUFFICIENT_BUFFER, contains
     *      the count of WCHARs needed to store the path.
     *      For all other return values, pcchPathBuffer contains the count of
     *      WCHARs written to wszPathBuffer.
     *  wszPathBuffer - Pointer to a buffer into which the debugger will copy
     *      the full path to the file containing the requested metadata.
     *      CorOpenFlags.ofReadOnly access to the metadata in this file will
     *      be requested.
     *
     * Assumptions:
     *  The returned file represents a Windows module containing the metadata
     *  needed to complete a request made by the debugger.
     *
     * Return Value:
     *  S_OK on success.  wszPathBuffer contains the full path to the file and
     *      is NULL-terminated.
     *
     *  E_NOT_SUFFICIENT_BUFFER if the current size of wszPathBuffer is not
     *      sufficient to hold the full path.  pcchPathBuffer will contain the
     *      needed count of WCHARs, including the terminating NULL.
     *      In this case GetMetaData will be called a second time with the
     *      requested buffer size.
     *
     *  All other failure HRESULTs are interpreted to mean that the file
     *  is not retrievable.
     *
     * Notes:
     *  If wszImagePath contains a full path for a module from a dump, that
     *  path will be the path from the machine where the dump was collected.
     *  The file may not exist at this location, or an incorrect file with the
     *  same name may be stored on the path.
     */
    HRESULT GetMetaData( [in] LPCWSTR wszImagePath,
                         [in] DWORD   dwImageTimeStamp,
                         [in] DWORD   dwImageSize,
                         [in] ULONG32 cchPathBuffer,
                         [out, annotation("__out")] ULONG32 * pcchPathBuffer,
                         [out, size_is(cchPathBuffer), length_is(*pcchPathBuffer), annotation("__out_ecount_part(cchPathBuffer, *pcchPathBuffer) ")] WCHAR wszPathBuffer[]);
};


/* ------------------------------------------------------------------------- *
 * User Callback interface
 * ------------------------------------------------------------------------- */


#pragma warning(push)
#pragma warning(disable:28718)	/* disable warning 28718 for interface ICorDebugManagedCallback */
/*
 * ICorDebugManagedCallback is implemented by the user of the
 * ICorDebug interfaces in order to respond to events in managed code
 * in the debuggee process.
 * This interface handles manage debug events from v1.0/v1.1
 */

[
    object,
    local,
    uuid(3d6f5f60-7538-11d3-8d5b-00104b35e7ef),
    pointer_default(unique)
]
interface ICorDebugManagedCallback : IUnknown
{
    /*
     * All callbacks are called with the process in the synchronized state
     * All callbacks are serialized, and are called in in the same thread.
     * Each callback implementor must call Continue in a callback to
     *      resume execution.
     * If Continue is not called before returning, the process will
     * remain stopped. Continue must later be called before any more
     * event callbacks will happen.
     *
     */

    /*
     * Breakpoint is called when a breakpoint is hit.
     */

    HRESULT Breakpoint([in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugThread *pThread,
                       [in] ICorDebugBreakpoint *pBreakpoint);

    /*
     * StepComplete is called when a step has completed.  The stepper
     * may be used to continue stepping if desired (except for TERMINATE
     * reasons.)
     *
     * STEP_NORMAL means that stepping completed normally, in the same
     *      function.
     *
     * STEP_RETURN means that stepping continued normally, after the function
     *      returned.
     *
     * STEP_CALL means that stepping continued normally, at the start of
     *      a newly called function.
     *
     * STEP_EXCEPTION_FILTER means that control passed to an exception filter
     *      after an exception was thrown.
     *
     * STEP_EXCEPTION_HANDLER means that control passed to an exception handler
     *      after an exception was thrown.
     *
     * STEP_INTERCEPT means that control passed to an interceptor.
     *
     * STEP_EXIT means that the thread exited before the step completed.
     *      No more stepping can be performed with the stepper.
     */

    typedef enum CorDebugStepReason
    {
        STEP_NORMAL,
        STEP_RETURN,
        STEP_CALL,
        STEP_EXCEPTION_FILTER,
        STEP_EXCEPTION_HANDLER,
        STEP_INTERCEPT,
        STEP_EXIT
    } CorDebugStepReason;

    HRESULT StepComplete([in] ICorDebugAppDomain *pAppDomain,
                         [in] ICorDebugThread *pThread,
                         [in] ICorDebugStepper *pStepper,
                         [in] CorDebugStepReason reason);

    /*
     * Break is called when a break opcode in the code stream is
     * executed.
     */

    HRESULT Break([in] ICorDebugAppDomain *pAppDomain,
                  [in] ICorDebugThread *thread);

    /*
     * Exception is called when an exception is thrown from managed
     * code, The specific exception can be retrieved from the thread object.
     *
     * If unhandled is FALSE, this is a "first chance" exception that
     * hasn't had a chance to be processed by the application.  If
     * unhandled is TRUE, this is an unhandled exception which will
     * terminate the process.
     */

    HRESULT Exception([in] ICorDebugAppDomain *pAppDomain,
                      [in] ICorDebugThread *pThread,
                      [in] BOOL unhandled);

    /*
     * EvalComplete is called when an evaluation is completed.
     */

    HRESULT EvalComplete([in] ICorDebugAppDomain *pAppDomain,
                         [in] ICorDebugThread *pThread,
                         [in] ICorDebugEval *pEval);

    /*
     * EvalException is called when an evaluation terminates with
     * an unhandled exception.
     */

    HRESULT EvalException([in] ICorDebugAppDomain *pAppDomain,
                          [in] ICorDebugThread *pThread,
                          [in] ICorDebugEval *pEval);

    /*
     * CreateProcess is called when a process is first attached to or
     * started.
     *
     * This entry point won't be called until the EE is initialized.
     * Most of the ICorDebug API will return CORDBG_E_NOTREADY prior
     * to the CreateProcess callback.
     */

    HRESULT CreateProcess([in] ICorDebugProcess *pProcess);

    /*
     * ExitProcess is called when a process exits.
     *
     * Note: you don't Continue from an ExitProcess event, and this
     * event may fire asynchronously to other events, while the
     * process appears to be stopped. This can occur if the process
     * dies while stopped, usually due to some external force.
     *
     * If the CLR is already dispatching a managed callback, this event
     * will be delayed until after that callback has returned.
     *
     * This is the only exit/unload event that is guaranteed to get called
     * on shutdown.
     */

    HRESULT ExitProcess([in] ICorDebugProcess *pProcess);

    /*
     * CreateThread is called when a thread first begins executing managed
     * code. The thread will be positioned immediately at the first
     * managed code to be executed.
     */

    HRESULT CreateThread([in] ICorDebugAppDomain *pAppDomain,
                         [in] ICorDebugThread *thread);

    /*
     * ExitThread is called when a thread which has run managed code exits. 
     * Once this callback is fired, the thread no longer will appear in thread enumerations.
     */

    HRESULT ExitThread([in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugThread *thread);

    /*
     * LoadModule is called when a Common Language Runtime module is successfully
     * loaded. This is an appropriate time to examine metadata for the
     * module, set JIT compiler flags, or enable or disable
     * class loading callbacks for the module.
     */

    HRESULT LoadModule([in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugModule *pModule);

    /*
     * UnloadModule is called when a Common Language Runtime module (DLL) is unloaded. The module
     * should not be used after this point.
     */

    HRESULT UnloadModule([in] ICorDebugAppDomain *pAppDomain,
                         [in] ICorDebugModule *pModule);

    /*
     * LoadClass is called when a class finishes loading.  This callback only
     * occurs if ClassLoading has been enabled for the class's module.
     *
     * ClassLoading is always enabled for dynamic modules. This is a good time
     * to update symbols (ICorDebugModule3::CreateReaderForInMemorySymbols) and
     * bind breakpoints to newly generated classes in dynamic modules.
     */

    HRESULT LoadClass([in] ICorDebugAppDomain *pAppDomain,
                      [in] ICorDebugClass *c);

    /*
     * UnloadClass is called immediately before a class is unloaded. The class
     * should not be referenced after this point. This callback only occurs if
     * ClassLoading has been enabled for the class's module.
     */

    HRESULT UnloadClass([in] ICorDebugAppDomain *pAppDomain,
                        [in] ICorDebugClass *c);

    /*
     * DebuggerError is called when an error occurs while attempting to
     * handle an event from the Common Language Runtime. It is very strongly
     * advised that debuggers log this message to the end user because
     * this callback indicates the debugging services have been disabled due to
     * an error.
     *
     * ICorDebugProcess::GetID() will be safe to call, but all other APIs should
     * not be called and will fail if they are.
     * This includes ICorDebugProcess::Terminate and ICorDebug  Process::Detach. The
     * debugger should use OS facilities for terminating processes to shut down the process.
     */
    HRESULT DebuggerError([in] ICorDebugProcess *pProcess,
                          [in] HRESULT errorHR,
                          [in] DWORD errorCode);


    /*
     * Enum defining log message LoggingLevels
     */
    typedef enum LoggingLevelEnum
    {
        LTraceLevel0 = 0,
        LTraceLevel1,
        LTraceLevel2,
        LTraceLevel3,
        LTraceLevel4,
        LStatusLevel0 = 20,
        LStatusLevel1,
        LStatusLevel2,
        LStatusLevel3,
        LStatusLevel4,
        LWarningLevel = 40,
        LErrorLevel = 50,
        LPanicLevel = 100
    } LoggingLevelEnum;


    typedef enum LogSwitchCallReason
    {
        SWITCH_CREATE,
        SWITCH_MODIFY,
        SWITCH_DELETE
    } LogSwitchCallReason;


    /*
     * LogMessage is called when a Common Language Runtime managed thread calls the Log
     * class in the System.Diagnostics package to log an event.
     */
    HRESULT LogMessage([in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugThread *pThread,
                       [in] LONG lLevel,
                       [in] WCHAR *pLogSwitchName,
                       [in] WCHAR *pMessage);

    /*
     * LogSwitch is called when a Common Language Runtime managed thread calls the LogSwitch
     * class in the System.Diagnostics package to create/modify a LogSwitch.
     */
    HRESULT LogSwitch([in] ICorDebugAppDomain *pAppDomain,
                      [in] ICorDebugThread *pThread,
                      [in] LONG lLevel,
                      [in] ULONG ulReason,
                      [in] WCHAR *pLogSwitchName,
                      [in] WCHAR *pParentName);

    /*
     * CreateAppDomain is called when an app domain is created.
     */
    HRESULT CreateAppDomain([in] ICorDebugProcess *pProcess,
                            [in] ICorDebugAppDomain *pAppDomain);

    /*
     * ExitAppDomain is called when an app domain exits.
     */
    HRESULT ExitAppDomain([in] ICorDebugProcess *pProcess,
                          [in] ICorDebugAppDomain *pAppDomain);


    /*
     * LoadAssembly is called when a Common Language Runtime assembly is successfully
     * loaded.
     */
    HRESULT LoadAssembly([in] ICorDebugAppDomain *pAppDomain,
                         [in] ICorDebugAssembly *pAssembly);

    /*
     * UnloadAssembly is called when a Common Language Runtime assembly is unloaded. The assembly
     * should not be used after this point.
     */
    HRESULT UnloadAssembly([in] ICorDebugAppDomain *pAppDomain,
                           [in] ICorDebugAssembly *pAssembly);

    /*
     * ControlCTrap is called if a CTRL-C is trapped in the process being
     * debugged. All appdomains within the process are stopped for
     * this callback.
     * Return values:
     *      S_OK    : Debugger will handle the ControlC Trap
     *      S_FALSE : Debugger won't handle the ControlC Trap
     */
    HRESULT ControlCTrap([in] ICorDebugProcess *pProcess);

    /*
     * NameChange() is called if either an AppDomain's or
     * Thread's name changes.
     */
    HRESULT NameChange([in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugThread *pThread);

    /*
     * UpdateModuleSymbols is called when PDB debug symbols are available for an 
     * in-memory module. This is a debugger's chance to load the symbols 
     * (using ISymUnmanagedBinder::GetReaderForStream), and bind source-level
     * breakpoints for the module.
     * 
     * This callback is no longer dispatched for dynamic modules.  Instead,
     * debuggers should call ICorDebugModule3::CreateReaderForInMemorySymbols
     * to obtain a symbol reader for a dynamic module.  
     */
    HRESULT UpdateModuleSymbols([in] ICorDebugAppDomain *pAppDomain,
                                [in] ICorDebugModule *pModule,
                                [in] IStream *pSymbolStream);


    /*
     * DEPRECATED
     */
    HRESULT EditAndContinueRemap([in] ICorDebugAppDomain *pAppDomain,
                                 [in] ICorDebugThread *pThread,
                                 [in] ICorDebugFunction *pFunction,
                                 [in] BOOL fAccurate);

    /*
     * BreakpointSetError is called if the CLR was unable to accuratley bind a breakpoint that
     * was set before a function was JIT compiled. The given breakpoint will never be hit. The
     * debugger should deactivate it and rebind it appropiatley.
     */
    HRESULT BreakpointSetError([in] ICorDebugAppDomain *pAppDomain,
                               [in] ICorDebugThread *pThread,
                               [in] ICorDebugBreakpoint *pBreakpoint,
                               [in] DWORD dwError);
};
#pragma warning(pop)

#pragma warning(push)

[
    object,
    local,
    uuid(264EA0FC-2591-49AA-868E-835E6515323F),
    pointer_default(unique)
]

interface ICorDebugManagedCallback3 : IUnknown
{
    /* Callback indicating an enabled custom debugger notification has been
     * raised. pThread points to the thread that issued the notification. 
     * A subsequent call to GetCurrentCustomDebuggerNotification will retrieve the object that was passed to 
     * System.Diagnostics.Debugger.CustomNotification, whose type will be one
     * that has been enabled via SetEnableCustomNotification.
     * Note that this will return non-null if and only if we are currently inside a CustomNotification 
     * callback. 
     * The debugger can read type-specific parameters from fields of the data
     * object, and store responses into fields. 
     * ICorDebug imposes no policy on the types of notifications or their
     * contents, and their semantics are strictly a contract between
     * debuggers and applications/frameworks.   
     */
    HRESULT CustomNotification([in] ICorDebugThread * pThread, [in] ICorDebugAppDomain * pAppDomain);
}


#pragma warning(disable:28718)	/* disable warning 28718 for interface ICorDebugManagedCallback2 */

/*
  * ICorDebugManagedCallback2 is a logical extension to ICorDebugManagedCallback.
  * This handles new debug events introduced in V2.0. A debugger's callback object
  * to ICorDebug::SetManagedHandler must implement this interface if it is debugging v2.0 apps.
  */
[
    object,
    local,
    uuid(250E5EEA-DB5C-4C76-B6F3-8C46F12E3203),
    pointer_default(unique)
]
interface ICorDebugManagedCallback2 : IUnknown
{

   /*
     * FunctionRemapOpportunity is fired whenever execution reaches a sequence point in an older version
     * of an edited function. This event gives the debugger an opportunity to remap the IP to its proper
     * place in the new version by calling ICorDebugILFrame2::RemapFunction. If the debugger does not call
     * RemapFunction before calling Continue, the runtime will continue executing the old code and will
     * fire another FunctionRemapOpportunity callback at the next sequence point
     */
    HRESULT FunctionRemapOpportunity([in] ICorDebugAppDomain *pAppDomain,
                                     [in] ICorDebugThread *pThread,
                                     [in] ICorDebugFunction *pOldFunction,
                                     [in] ICorDebugFunction *pNewFunction,
                                     [in] ULONG32 oldILOffset);

    /*
     * CreateConnection is called when a new connection is created.
     */
    HRESULT CreateConnection([in] ICorDebugProcess *pProcess,
                             [in] CONNID dwConnectionId,
                             [in] WCHAR *pConnName);

    /*
     * ChangeConnection is called when a connection's set of tasks changes.
     */
    HRESULT ChangeConnection([in] ICorDebugProcess *pProcess,
                             [in] CONNID dwConnectionId );

    /*
     * DestroyConnection is called when a connection is ended.
     */
    HRESULT DestroyConnection([in] ICorDebugProcess *pProcess,
                              [in] CONNID dwConnectionId );






    typedef enum CorDebugExceptionCallbackType
    {
        DEBUG_EXCEPTION_FIRST_CHANCE = 1,        /* Fired when exception thrown */
        DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2,   /* Fired when search reaches first user code */
        DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3, /* Fired if & when search finds a handler */
        DEBUG_EXCEPTION_UNHANDLED = 4            /* Fired if search doesnt find a handler */
    } CorDebugExceptionCallbackType;


    typedef enum CorDebugExceptionFlags
    {
        DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x0001 /* Indicates interceptable exception */
    } CorDebugExceptionFlags;


    /*
     * Exception is called at various points during the search phase of the
     * exception-handling process.  The exception being processed can be
     * retrieved from the ICorDebugThread.
     */
    HRESULT Exception( [in] ICorDebugAppDomain *pAppDomain,
                       [in] ICorDebugThread *pThread,
                       [in] ICorDebugFrame *pFrame,
                       [in] ULONG32 nOffset,
                       [in] CorDebugExceptionCallbackType dwEventType,
                       [in] DWORD dwFlags );


    typedef enum CorDebugExceptionUnwindCallbackType
    {
        DEBUG_EXCEPTION_UNWIND_BEGIN = 1, /* Fired at the beginning of the unwind */
        DEBUG_EXCEPTION_INTERCEPTED = 2   /* Fired after an exception has been intercepted */
    } CorDebugExceptionUnwindCallbackType;



    /*
     * For non-intercepted exceptions, ExceptionUnwind is called at the beginning of the second pass 
     * when we start to unwind the stack.  For intercepted exceptions, ExceptionUnwind is called when
     * the interception is complete, conceptually at the end of the second pass.
     *
     * dwFlags is not currently used.
     */
    HRESULT ExceptionUnwind( [in] ICorDebugAppDomain *pAppDomain,
                             [in] ICorDebugThread *pThread,
                             [in] CorDebugExceptionUnwindCallbackType dwEventType,
                             [in] DWORD dwFlags );

    /*
     * FunctionRemapComplete is fired whenever execution has completed switching over to a
     * new version of an edited function (as requested by a call to ICorDebugILFrame2::RemapFunction).
     * At this point (and no sooner) steppers can be added to that new version of the function.
     */
    HRESULT FunctionRemapComplete([in] ICorDebugAppDomain *pAppDomain,
                                                                    [in] ICorDebugThread *pThread,
                                                                    [in] ICorDebugFunction *pFunction);

    // Notification that an Managed Debug Assistant (MDA) was hit in the debuggee process.
    // - MDAs are heuristic warnings and do not require any explicit debugger action (other than continue, of course) for proper functionality.
    // - The CLR can change what MDAs are fired (and what data is in any given MDA) at any point.
    // - Therefore, debuggers should not build any specific functionality requiring specific MDAs patterns.
    // - MDAs may be queued and fired "after the fact". This could happen if the runtime needs to slip from when an
    //   MDA occurs to get to a safe point for firing it. It also means the runtime reserves the right to fire a bunch of MDAs
    //   in a single set of callback queue (similar for what we do w/ attach events).
    //
    // See the MDA documentation for how to enable / disable notifications.
    //
    // Parameters:
    // - pController is the controller object (process or appdomain) that the MDA occurred in.
    //     Clients should not make any assumption about whether the controller is a process or appdomain (though they can
    //     always QI to find out).
    //     Call continue on this to resume the debuggee.
    // - pThread - managed thread on which the debug event occured. If the MDA occurred on an unmanaged thread then
    //     this will be null. Get the OS thread ID from the MDA object itself.
    // - pMDA is an object containing MDA information.
    //    Suggested usage is that the client does not keep a reference to the MDA object after returning from this callback
    //    because that lets the CLR quickly recycle the MDA's memory. This could be a performance win if there are
    //    lots of MDAs firing.
    HRESULT MDANotification(
        [in] ICorDebugController * pController,
        [in] ICorDebugThread *pThread,
        [in] ICorDebugMDA * pMDA
    );

};
#pragma warning(pop)

[
    object,
    local,
    uuid(5263E909-8CB5-11d3-BD2F-0000F80849BD),
    pointer_default(unique)
]
interface ICorDebugUnmanagedCallback : IUnknown
{
    /*
     * DebugEvent is called when a DEBUG_EVENT is received which is
     * not directly related to the Common Language Runtime.
     *
     * DO NOT USE any parts of the debugging API from the Win32 Event
     * Thread. Only ICorDebugController::Continue() can be called on
     * the Win32 Event Thread, and only when continuing from an out-of-band
     * event.
     *
     * This callback is an exception to the rules about callbacks.
     * When this callback is called, the process will be in the "raw"
     * OS debug stopped state. The process will not be synchronized.
     * The process will automatically enter the synchronized state when
     * necessary to satisfy certain requests for information about
     * managed code. (Note that this may result in other nested
     * DebugEvent callbacks.)
     *
     * Call ClearCurrentException on the process to ignore an
     * exception event before continuing the process. (Causes
     * DBG_CONTINUE to be sent on continue rather than
     * DBG_EXCEPTION_NOT_HANDLED)
     * Out-of-band Breakpoint and single-step exceptions are automatically cleared.
     *
     * fOutOfBand will be FALSE if the debugging services support
     * interaction with the process's managed state while the process
     * is stopped due to this event. fOutOfBand will be TRUE if
     * interaction with the process's managed state is impossible until
     * the unmanaged event is continued from.
     *
     * Out-Of-Band events can come at anytime; even when there debuggee appears stopped
     * and even when there's already an outstanding inband event.
     *
     * In v2.0, it is strongly recommended that the debugger just immediately
     * continues OOB breakpoint events. The debugger should be using the ICorDebugProcess2
     * SetUnmanagedBreakpoint and ClearUnmanagedBreakpoint APIs to add/remove breakpoints.
     * Those APIs will already skip over any OOB breakpoints automatically. Thus the only
     * oob breakpoints that get dispatched should be raw breakpoints already in the
     * instruction stream (eg, like a call to kernel32!DebugBreak). In these cases,
     * just continuing past the breakpoint is the correct thing to do. Do not try to use
     * any other portion of the API like ClearCurrentException or Get/SetThreadContext.
     *
     */

    HRESULT DebugEvent([in] LPDEBUG_EVENT pDebugEvent,
                       [in] BOOL fOutOfBand);
};

/* ------------------------------------------------------------------------- *
 * Debugger interface
 * ------------------------------------------------------------------------- */


typedef enum CorDebugCreateProcessFlags
{
    DEBUG_NO_SPECIAL_OPTIONS        = 0x0000
} CorDebugCreateProcessFlags;


/* ICorDebugHeapValue::CreateHandle takes a handle flavor.
 * A strong handle will keep an object alive while a weak track resurrection
 * will not.
 */
typedef enum CorDebugHandleType
{
    HANDLE_STRONG = 1,
    HANDLE_WEAK_TRACK_RESURRECTION = 2
} CorDebugHandleType;

#pragma warning(push)
#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebug */
/*
 * ICorDebug represents an event processing loop for a debugger process.
 *
 * The debugger must wait for the ExitProcess callback from all
 * processes being debugged before releasing this interface.
 *
 * The ICorDebug object is the initial object to control all further managed debugging.
 * In v1.0 + v1.1, this object was a CoClass created from COM.
 * In v2.0, this object is no longer a CoClass and must be created from the function:
 *      CreateDebuggingInterfaceFromVersion(
 *          int iDebuggerVersion, // <--- CorDebugVersion_2_0 if Debugger is V2.0
 *          LPCWSTR szDebuggeeVersion, // <--- version string of debuggee. Eg, "v1.1.4322"
 *          IUnknown ** ppCordb
 *      )
 * declared in mscoree.idl.
 * This new creation function is more version-aware. It allows clients to get a
 * specific implementation (as specified by szDebuggeeVersion) of ICorDebug, which
 * also emulates a specific version of the debugging API (as specified by iDebuggerVersion).
 */
[
    object,
    local,
    uuid(3d6f5f61-7538-11d3-8d5b-00104b35e7ef),
    pointer_default(unique)
]
interface ICorDebug : IUnknown
{
    /*
     * The debugger calls this method at creation time to initialize the debugging
     * services, and  must be called at creation time before any other method on
     * ICorDebug is called.
     */

    HRESULT Initialize();

    /*
     * Terminate must be called when the ICorDebug is no longer needed.
     *
     * NOTE: Terminate should not be called until an ExitProcess callback has
     * been received for all processes being debugged.
     *
     */

    HRESULT Terminate();

    /*
     * SetManagedHandler should be called at creation time to specify the
     * event handler object for managed events.
     *
     * Returns:
     * S_OK on success.
     * E_NOINTERFACE - if pCallback does not implement sufficient interfaces
     *     to receive debug events for the version of the API it requested.
     *     Eg, if debugging a V2.0 app, pCallback must implement ICorDebugManagedCallback2.
     *
     */

    HRESULT SetManagedHandler([in] ICorDebugManagedCallback *pCallback);

    /*
     * SetUnmanagedHandler should be called at creation time to specify the
     * event handler object for unmanaged events.
     *
     * This should be set after Initialize and before any calls to CreateProcess or DebugActiveProcess.
     *
     * However, for legacy purposes, it is not absolutely required to set this until 
     * before the first native debug event is fired. Specifically, if CreateProcess has the 
     * CREATE_SUSPENDED flag, native debug events will not be dispatched until the main thread
     * is resumed.
     * DebugActiveProcess will dispatch native debug events immediately, and so the unmanaged callback 
     * must be set before DebugActiveProcess is called.
     *
     * Returns: 
     *    S_OK if callback pointer is successfully updated. 
     *    failure on any failure.
     *
     */

    HRESULT SetUnmanagedHandler([in] ICorDebugUnmanagedCallback *pCallback);

    /*
     * CreateProcess launches a process under the control of the debugger
     * All parameters are the same as the win32 CreateProcess call.
     *
     * To enable unmanaged (mixed-mode) debugging, pass
     * DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS to dwCreationFlags. DEBUG_PROCESS
     * alone is not supported. If only managed debugging is desired, do not set
     * these flags.
     *
     * The debugger and debuggee share a single console, then it's possible for
     * the debuggee to hold "console locks" and then get stopped at a debug event.
     * The debugger will then block trying to use the console. This is only an issue
     * when interop debugging and if debugger + debuggee share the console.
     * It is recommended to use the CREATE_NEW_CONSOLE flag to avoid this problem.
     *
     */

    HRESULT CreateProcess([in] LPCWSTR lpApplicationName,
                          [in] LPWSTR lpCommandLine,
                          [in] LPSECURITY_ATTRIBUTES lpProcessAttributes,
                          [in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
                          [in] BOOL bInheritHandles,
                          [in] DWORD dwCreationFlags,
                          [in] PVOID lpEnvironment,
                          [in] LPCWSTR lpCurrentDirectory,
                          [in] LPSTARTUPINFOW lpStartupInfo,
                          [in] LPPROCESS_INFORMATION lpProcessInformation,
                          [in] CorDebugCreateProcessFlags debuggingFlags,
                          [out] ICorDebugProcess **ppProcess);

    /*
     * DebugActiveProcess is used to attach to an existing process.
     *
     * If win32Attach is TRUE, then the debugger becomes the Win32
     * debugger for the process and will begin dispatching the
     * unmanaged callbacks.
     *
     */

    HRESULT DebugActiveProcess([in] DWORD id,
                               [in] BOOL win32Attach,
                               [out] ICorDebugProcess **ppProcess);

    /*
     * EnumerateProcesses returns an enum of processes being debugged.
     *
     */

    HRESULT EnumerateProcesses([out] ICorDebugProcessEnum **ppProcess);

    /*
     * GetProcess returns the ICorDebugProcess with the given OS Id.
     */

    HRESULT GetProcess([in] DWORD dwProcessId,
                       [out] ICorDebugProcess **ppProcess);

    /*
     * CanLaunchOrAttach returns S_OK if the debugging services believe that
     * launching a new process or attaching to the given process is possible
     * given what it knows about the current machine and runtime configuration.
     *
     * If you plan to launch with win32 debugging enabled, or to attach with
     * win32 debugging enabled then pass in TRUE for win32DebuggineEnabled.
     * The answer may be different if this option will be used.
     *
     * Note: the rest of the API will not stop you from launching or attaching
     * to a process anyway. This function is purely informational.
     *
     * Possible HRESULTs: S_OK, CORDBG_E_DEBUGGING_NOT_POSSIBLE,
     * CORDBG_E_KERNEL_DEBUGGER_PRESENT, CORDBG_E_KERNEL_DEBUGGER_ENABLED
     *
     */

    HRESULT CanLaunchOrAttach([in] DWORD dwProcessId,
                              [in] BOOL win32DebuggingEnabled);
};
#pragma warning(pop)

/*
 * A debugger can implement this interface and pass it to ICorDebugRemote to specify the host name of the 
 * target machine in Mac remote debugging scenarios.  This is only supported on Silverlight.
 */
[
    object,
    local,
    uuid(C3ED8383-5A49-4cf5-B4B7-01864D9E582D),
    pointer_default(unique)
]
interface ICorDebugRemoteTarget : IUnknown
{
    /*
     * Return the host name of the target machine.  The host name can either be a fully qualified domain name or
     * an IPv4 address.  If cchHostName is 0 and szHostName is NULL, this function just returns the number of 
     * characters including the NULL character in the host name.
     *
     * cchHostName is the number of characters in the buffer szHostName.  If this is 0, then szHostName must 
     * be NULL.  If it is not 0, then szHostName must be non-NULL.
     * 
     * pcchHostName returns the number of characters including the NULL character in the host name.  This can 
     * be NULL.
     * 
     * szHostName is the buffer for returning the host name.
     */

    HRESULT GetHostName([in]  ULONG32 cchHostName,
                        [out, annotation("__out")] ULONG32 * pcchHostName,
                        [out, size_is(cchHostName), length_is(*pcchHostName), annotation("__out_ecount_part_opt(cchHostName, *pcchHostName)")] 
                                                     WCHAR szHostName[]);
}

/*
 * A debugger can QI for this interface from an ICorDebug interface in order to specify a target machine in 
 * Mac remote debugging scenarios.  This is only supported on Silverlight.
 */
[
    object,
    local,
    uuid(D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64),
    pointer_default(unique)
]
interface ICorDebugRemote : IUnknown
{
    HRESULT CreateProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget,
                            [in] LPCWSTR lpApplicationName,
                            [in, annotation("__in")] LPWSTR lpCommandLine,
                            [in] LPSECURITY_ATTRIBUTES lpProcessAttributes,
                            [in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
                            [in] BOOL bInheritHandles,
                            [in] DWORD dwCreationFlags,
                            [in] PVOID lpEnvironment,
                            [in] LPCWSTR lpCurrentDirectory,
                            [in] LPSTARTUPINFOW lpStartupInfo,
                            [in] LPPROCESS_INFORMATION lpProcessInformation,
                            [in] CorDebugCreateProcessFlags debuggingFlags,
                            [out] ICorDebugProcess ** ppProcess);


    HRESULT DebugActiveProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget,
                                 [in] DWORD dwProcessId,
                                 [in] BOOL fWin32Attach,
                                 [out] ICorDebugProcess ** ppProcess);
}

typedef struct _COR_VERSION
{
    DWORD dwMajor;
    DWORD dwMinor;
    DWORD dwBuild;
    DWORD dwSubBuild;
} COR_VERSION;


[
    object,
    local,
    uuid(ECCCCF2E-B286-4b3e-A983-860A8793D105),
    pointer_default(unique)
]
/*
 * Sets the maximum version of the runtime supported by the debugger using this
 * object.
 */
interface ICorDebug2 : IUnknown
{
    typedef enum CorDebugInterfaceVersion
    {
        CorDebugInvalidVersion = 0,
        CorDebugVersion_1_0 = CorDebugInvalidVersion + 1,
        ver_ICorDebugManagedCallback = CorDebugVersion_1_0,
        ver_ICorDebugUnmanagedCallback = CorDebugVersion_1_0,
        ver_ICorDebug = CorDebugVersion_1_0,
        ver_ICorDebugController = CorDebugVersion_1_0,
        ver_ICorDebugAppDomain = CorDebugVersion_1_0,
        ver_ICorDebugAssembly = CorDebugVersion_1_0,
        ver_ICorDebugProcess = CorDebugVersion_1_0,
        ver_ICorDebugBreakpoint = CorDebugVersion_1_0,
        ver_ICorDebugFunctionBreakpoint = CorDebugVersion_1_0,
        ver_ICorDebugModuleBreakpoint = CorDebugVersion_1_0,
        ver_ICorDebugValueBreakpoint = CorDebugVersion_1_0,
        ver_ICorDebugStepper = CorDebugVersion_1_0,
        ver_ICorDebugRegisterSet = CorDebugVersion_1_0,
        ver_ICorDebugThread = CorDebugVersion_1_0,
        ver_ICorDebugChain = CorDebugVersion_1_0,
        ver_ICorDebugFrame = CorDebugVersion_1_0,
        ver_ICorDebugILFrame = CorDebugVersion_1_0,
        ver_ICorDebugNativeFrame = CorDebugVersion_1_0,
        ver_ICorDebugModule = CorDebugVersion_1_0,
        ver_ICorDebugFunction = CorDebugVersion_1_0,
        ver_ICorDebugCode = CorDebugVersion_1_0,
        ver_ICorDebugClass = CorDebugVersion_1_0,
        ver_ICorDebugEval = CorDebugVersion_1_0,
        ver_ICorDebugValue = CorDebugVersion_1_0,
        ver_ICorDebugGenericValue = CorDebugVersion_1_0,
        ver_ICorDebugReferenceValue = CorDebugVersion_1_0,
        ver_ICorDebugHeapValue = CorDebugVersion_1_0,
        ver_ICorDebugObjectValue = CorDebugVersion_1_0,
        ver_ICorDebugBoxValue = CorDebugVersion_1_0,
        ver_ICorDebugStringValue = CorDebugVersion_1_0,
        ver_ICorDebugArrayValue = CorDebugVersion_1_0,
        ver_ICorDebugContext = CorDebugVersion_1_0,
        ver_ICorDebugEnum = CorDebugVersion_1_0,
        ver_ICorDebugObjectEnum = CorDebugVersion_1_0,
        ver_ICorDebugBreakpointEnum = CorDebugVersion_1_0,
        ver_ICorDebugStepperEnum = CorDebugVersion_1_0,
        ver_ICorDebugProcessEnum = CorDebugVersion_1_0,
        ver_ICorDebugThreadEnum = CorDebugVersion_1_0,
        ver_ICorDebugFrameEnum = CorDebugVersion_1_0,
        ver_ICorDebugChainEnum = CorDebugVersion_1_0,
        ver_ICorDebugModuleEnum = CorDebugVersion_1_0,
        ver_ICorDebugValueEnum = CorDebugVersion_1_0,
        ver_ICorDebugCodeEnum = CorDebugVersion_1_0,
        ver_ICorDebugTypeEnum = CorDebugVersion_1_0,
        ver_ICorDebugErrorInfoEnum = CorDebugVersion_1_0,
        ver_ICorDebugAppDomainEnum = CorDebugVersion_1_0,
        ver_ICorDebugAssemblyEnum = CorDebugVersion_1_0,
        ver_ICorDebugEditAndContinueErrorInfo = CorDebugVersion_1_0,
        ver_ICorDebugEditAndContinueSnapshot = CorDebugVersion_1_0,

        CorDebugVersion_1_1 = CorDebugVersion_1_0 + 1,
        // no interface definitions in v1.1

        CorDebugVersion_2_0 = CorDebugVersion_1_1 + 1,

        ver_ICorDebugManagedCallback2 = CorDebugVersion_2_0,
        ver_ICorDebugAppDomain2 = CorDebugVersion_2_0,
        ver_ICorDebugAssembly2 = CorDebugVersion_2_0,
        ver_ICorDebugProcess2 = CorDebugVersion_2_0,
        ver_ICorDebugStepper2 = CorDebugVersion_2_0,
        ver_ICorDebugRegisterSet2 = CorDebugVersion_2_0,
        ver_ICorDebugThread2 = CorDebugVersion_2_0,
        ver_ICorDebugILFrame2 = CorDebugVersion_2_0,
        ver_ICorDebugInternalFrame = CorDebugVersion_2_0,
        ver_ICorDebugModule2 = CorDebugVersion_2_0,
        ver_ICorDebugFunction2 = CorDebugVersion_2_0,
        ver_ICorDebugCode2 = CorDebugVersion_2_0,
        ver_ICorDebugClass2 = CorDebugVersion_2_0,
        ver_ICorDebugValue2 = CorDebugVersion_2_0,
        ver_ICorDebugEval2 = CorDebugVersion_2_0,
        ver_ICorDebugObjectValue2 = CorDebugVersion_2_0,

        // CLR v4 - next major CLR version after CLR v2
        // Includes Silverlight 4
        CorDebugVersion_4_0 = CorDebugVersion_2_0 + 1,

        ver_ICorDebugThread3 = CorDebugVersion_4_0,
        ver_ICorDebugThread4 = CorDebugVersion_4_0,
        ver_ICorDebugStackWalk = CorDebugVersion_4_0,
        ver_ICorDebugNativeFrame2 = CorDebugVersion_4_0,
        ver_ICorDebugInternalFrame2 = CorDebugVersion_4_0,
        ver_ICorDebugRuntimeUnwindableFrame = CorDebugVersion_4_0,
        ver_ICorDebugHeapValue3 = CorDebugVersion_4_0,
        ver_ICorDebugBlockingObjectEnum = CorDebugVersion_4_0,

        CorDebugLatestVersion = CorDebugVersion_4_0

    } CorDebugInterfaceVersion;

};

/* ------------------------------------------------------------------------- *
 * Controller interface
 * ------------------------------------------------------------------------- */


/*
 * A thread's DebugState determines whether the debugger lets a thread
 * run or not.  Possible states are:
 *
 * THREAD_RUN - thread runs freely, unless a debug event occurs
 * THREAD_SUSPEND - thread cannot run.
 *
 * NOTE: We allow for message pumping via a callback provided to the Hosting
 *      API, thus we don't need an 'interrupted' state here.
 */

typedef enum CorDebugThreadState
{
    THREAD_RUN,
    THREAD_SUSPEND
} CorDebugThreadState;


/*
 * ICorDebugController represents a scope at which program execution context
 * can be controlled.  It represents either a process or an app domain.
 *
 * If this is the controller of a process, this controller affects all
 * threads in the process.  Otherwise it just affects the threads of
 * a particular app domain
 */

[
    object,
    local,
    uuid(3d6f5f62-7538-11d3-8d5b-00104b35e7ef),
    pointer_default(unique)
]

interface ICorDebugController : IUnknown
{
    /*
     * Stop performs a cooperative stop on all threads running managed
     * code in the process. When managed-only debugging, unmanaged threads may continue
     * to run (but will be blocked when trying to call managed code). When-interop debugging,
     * unmanaged threads will also be stopped.
     * The timeout value is currently ignored and treated as INFINTE (-1).
     * If the cooperative stop fails due to a deadlock, all threads are suspended (and E_TIMEOUT is returned)
     *
     * NOTE: This function is the one function in the debugging API
     * that is synchronous. When Stop returns with S_OK, the process
     * is stopped. (No callback will be given to notify of the stop.)
     * The debugger must call Continue when it wishes to allow
     * the process to resume running.
     *
     * The debugger maintains a "stop-counter". When the counter goes to zero, the
     * Controller is resumed. Each call to Stop() or each dispatched callback will increment
     * the counter. Each call to continue will decrement the counter.
     */

    HRESULT Stop([in] DWORD dwTimeoutIgnored);

    /*
     * Continue continues the process after a call to Stop.
     *
     * Continue continues the process. fIsOutOfBand is set to TRUE
     * if continuing from an unmanaged event that was sent with the
     * fOutOfBand flag in the unmanaged callback and it is set to
     * FALSE if continuing from a managed event or a normal
     * unmanaged event.
     *
     * When doing mixed-mode debugging, Continue cannot be called on
     * the Win32 Event Thread unless it is continuing from an
     * out-of-band event.
     */

    HRESULT Continue([in] BOOL fIsOutOfBand);

    /*
     * IsRunning returns TRUE if the threads in the process are running freely.
     *
     */

    HRESULT IsRunning([out] BOOL *pbRunning);

    /*
     * HasQueuedCallbacks returns TRUE if there are currently managed
     * callbacks which are queued up for the given thread.  These
     * callbacks will be dispatched one at a time, each time Continue
     * is called.
     *
     * The debugger can check this flag if it wishes to report multiple
     * debugging events which occur simultaneously.
     *
     * If NULL is given for the pThread parameter, HasQueuedCallbacks
     * will return TRUE if there are currently managed callbacks
     * queued for any thread.
     *
     * Note that once debug events have been queued, they've already occured,
     * and so the debugger must drain the entire queue to be sure of the state
     * of the debuggee. For example, if the queue contains 2 debug events on thread X,
     * and the debugger suspends thread X after the 1st debug event and then calls continue,
     * the 2nd debug event for thread X will still be dispatched even though the thread
     * is suspended.
     *
     */

    HRESULT HasQueuedCallbacks([in] ICorDebugThread *pThread,
                               [out] BOOL *pbQueued);

    /*
     * EnumerateThreads returns an enum of all managed threads active in the process.
     * A thread is considered Managed threads after the CreateThread callback has been
     * dispatched and before the ExitThread callback has been dispatched.
     * A managed thread may not necessarily have any managed frames on its stack.
     *
     * Threads can be enumerated even before the CreateProcess callback. The enumeration
     * will naturally be empty.
     */

    HRESULT EnumerateThreads([out] ICorDebugThreadEnum **ppThreads);

    /*
     * SetAllThreadsDebugState sets the current debug state of each thread.
     * See ICorDebugThread::SetDebugState for details.
     *
     * The pExceptThisThread parameter allows you to specify one
     * thread which is exempted from the debug state change. Pass NULL
     * if you want to affect all threads.
     *
     * This may affect threads not visible via EnumerateThreads, so threads suspended
     * via this API will need to be resumed via this API too.
     *
     */

    HRESULT SetAllThreadsDebugState([in] CorDebugThreadState state,
                                    [in] ICorDebugThread *pExceptThisThread);

    /*
     * Detach detaches the debugger from the process.  The process
     * continues execution normally. The ICorDebugProcess object is
     * no longer valid and no further callbacks will occur.  This is
     * not implemented for AppDomains (detaching is process-wide).
     *
     * Note that currently if unmanaged debugging is enabled this call will
     * fail due to OS limitations.
     * 
     * Returns S_OK on success.
     *
     */

    HRESULT Detach();

    /*
     * Terminate terminates the process (with extreme prejudice, I might add).
     *
     * NOTE: If the process or appdomain is stopped when Terminate is called,
     * the process or appdomain should be continued using Continue so that the
     * ExitProcess or ExitAppDomain callback is received.
     *
     * NOTE: This method is not implemented by an appdomain.
     */

    HRESULT Terminate([in] UINT exitCode);

    /*
     * DEPRECATED
     */

    HRESULT CanCommitChanges([in] ULONG cSnapshots,
                             [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[],
                             [out] ICorDebugErrorInfoEnum **pError);


    /*
     * DEPRECATED
     */

    HRESULT CommitChanges([in] ULONG cSnapshots,
                          [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[],
                          [out] ICorDebugErrorInfoEnum **pError);

};



#pragma warning(push)
#pragma warning(disable:28718)	/* disable warning 28718 for interface ICorDebugAppDomain */
/* ------------------------------------------------------------------------- *
 *
 * AppDomain interface
 *
 * ------------------------------------------------------------------------- */


[
    object,
    local,
    uuid(3d6f5f63-7538-11d3-8d5b-00104b35e7ef),
    pointer_default(unique)
]
interface ICorDebugAppDomain : ICorDebugController
{
    /*
     * GetProcess returns the process containing the app domain
     */

    HRESULT GetProcess([out] ICorDebugProcess **ppProcess);

    /*
     * EnumerateAssemblies enumerates all assemblies in the app domain
     *
     */

    HRESULT EnumerateAssemblies([out] ICorDebugAssemblyEnum **ppAssemblies);

    /*
     * GetModuleFromMetaDataInterface returns the ICorDebugModule with
     * the given metadata interface.
     */

    HRESULT GetModuleFromMetaDataInterface([in] IUnknown *pIMetaData,
                                           [out] ICorDebugModule **ppModule);

    /*
     * EnumerateBreakpoints returns an enum (ICorDebugBreakpointEnum) of all active
     * breakpoints in the app domain.  This includes all types of breakpoints :
     * function breakpoints, data breakpoints, etc.
     */

    HRESULT EnumerateBreakpoints([out] ICorDebugBreakpointEnum **ppBreakpoints);

    /*
     * EnumerateSteppers returns an enum of all active steppers in the app domain.
     *
     */

    HRESULT EnumerateSteppers([out] ICorDebugStepperEnum **ppSteppers);

    /*
     * DEPRECATED.  Always returns TRUE in V3 (attaching is process-wide).
     */

    HRESULT IsAttached([out] BOOL *pbAttached);


    /*
     * GetName returns the name of the app domain.
     *
     * Usage pattern:
     * *pcchName is always set to the length of pInputString (including NULL) in characters. This lets
     *   callers know the full size of buffer they'd need to allocate to get the full string.
     *
     * if (cchName == 0) then we're in "query" mode:
     *     This fails if szName is non-null or pcchName is null 
     *     Else this function will set pcchName to let the caller know how large of a buffer to allocate
     *     and return S_OK.
     *
     * if (cchName != 0) then 
     *     This fails if szName is null.
     *     Else this copies as much as can fit into szName (it will always null terminate szName) and returns S_OK. 
     *     pcchName can be null. If it's non-null, we set it.
     *
     * The expected usage pattern is that a client will call once to get the size of a buffer needed for the name,
     *  allocate the buffer, and then call a 2nd time to fill in the buffer.
     *
     * The rest of the GetName() functions have the same semantics for the parameters unless otherwise noted.
     */

    HRESULT GetName([in] ULONG32 cchName,
                    [out] ULONG32 *pcchName,
                    [out, size_is(cchName),
                    length_is(*pcchName)] WCHAR szName[]);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetObject([out] ICorDebugValue **ppObject);

    /* 
     * DEPRECATED.  This does nothing in V3.  Attaching is process-wide.
     */

    HRESULT Attach();

    /*
     * Get the ID of this app domain. The ID will be unique within the
     * containing process.
     */

    HRESULT GetID([out] ULONG32 *pId);
};
#pragma warning(pop)

[
    object,
    local,
    uuid(096E81D5-ECDA-4202-83F5-C65980A9EF75),
    pointer_default(unique)
]
interface ICorDebugAppDomain2 : IUnknown
{
    /*
     * GetArrayOrPointerType returns an array, pointer, byref or function pointer type.
     * elementType indicated the kind of type to be created and
     * must be one of ELEMENT_TYPE_PTR, ELEMENT_TYPE_BYREF,
     * ELEMENT_TYPE_ARRAY or ELEMENT_TYPE_SZARRAY.  If used with
     * ELEMENT_TYPE_PTR or ELEMENT_TYPE_BYREF then nRank must be zero.
     */

    HRESULT GetArrayOrPointerType([in] CorElementType elementType,
                                  [in] ULONG32 nRank,
                                  [in] ICorDebugType *pTypeArg,
                                  [out] ICorDebugType **ppType);

    /*
     * GetFunctionPointerType returns a function pointer type.
     * This corresponds to ELEMENT_TYPE_FNPTR.  The first type in the type arguments
     * must be the return type and the remainder the argument types.
     */

     HRESULT GetFunctionPointerType( [in] ULONG32 nTypeArgs,
                                     [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[],
                                     [out] ICorDebugType **ppType);
};

#pragma warning(push)
#pragma warning(disable:28718)	/* disable warning 28718 for interface ICorDebugAssembly */

/* ------------------------------------------------------------------------- *
 * Assembly interface
 * An ICorDebugAssembly instance corresponds to a a managed assembly loaded
 * into a specific AppDomain in the CLR.  For assemblies shared between multiple
 * AppDomains (eg. mscorlib), there will be a separate ICorDebugAssembly instance
 * per AppDomain in which it is used.
 * ------------------------------------------------------------------------- */
[
    object,
    local,
    uuid(df59507c-d47a-459e-bce2-6427eac8fd06),
    pointer_default(unique)
]

interface ICorDebugAssembly : IUnknown
{
    /*
     * GetProcess returns the process containing the assembly
     */

    HRESULT GetProcess([out] ICorDebugProcess **ppProcess);

    /*
     * GetAppDomain returns the app domain containing the assembly.
     */

    HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain);

    /*
     * EnumerateModules enumerates all modules in the assembly
     *
     */

    HRESULT EnumerateModules([out] ICorDebugModuleEnum **ppModules);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetCodeBase([in] ULONG32 cchName,
                        [out] ULONG32 *pcchName,
                        [out, size_is(cchName),
                        length_is(*pcchName)] WCHAR szName[]);

    /*
     * GetName returns the full path and filename of the assembly.
     * If the assembly has no filename (i.e. it is in-memory only),
     * S_FALSE is returned, and a fabricated string is stored into szName. 
     */

    HRESULT GetName([in] ULONG32 cchName,
                    [out] ULONG32 *pcchName,
                    [out, size_is(cchName),
                    length_is(*pcchName)] WCHAR szName[]);
};
#pragma warning(pop)

[
    object,
    local,
    uuid(426d1f9e-6dd4-44c8-aec7-26cdbaf4e398),
    pointer_default(unique)
]
interface ICorDebugAssembly2 : IUnknown
{
	/*
	 * IsFullyTrusted sets a flag indicating whether the assembly has
	 * been granted full trust by the runtime security system.
	 * This may return CORDBG_E_NOTREADY if the security policy for
	 * the assembly has not yet been resolved (eg. no code in the 
	 * assembly has been run yet).
	 */
	HRESULT IsFullyTrusted( [out] BOOL *pbFullyTrusted );
};

/* ------------------------------------------------------------------------- *
 * Process interface
 * ------------------------------------------------------------------------- */

#pragma warning(push)
#pragma warning(disable:28718)	/* suppress warning 28718 for interface ICorDebugProcess */

/*
 * ICorDebugProcess represents a process running some managed code.
 */

[
    object,
    local,
    uuid(3d6f5f64-7538-11d3-8d5b-00104b35e7ef),
    pointer_default(unique)
]
interface ICorDebugProcess : ICorDebugController
{
    /*
     * GetID returns the OS ID of the process.
     */

    HRESULT GetID([out] DWORD *pdwProcessId);

    /*
     * GetHandle returns a handle to the process. This handle is owned
     * by the debugging API; the debugger should duplicate it before
     * using it.
     */

    HRESULT GetHandle([out] HPROCESS *phProcessHandle);

    /*
     * GetThread returns the ICorDebugThread with the given OS Id.
     *
     * Note that eventually there will not be a one to one correspondence
     * between OS threads and runtime threads, so this entry point will
     * go away.
     */

    HRESULT GetThread([in] DWORD dwThreadId, [out] ICorDebugThread **ppThread);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT EnumerateObjects([out] ICorDebugObjectEnum **ppObjects);

    /*
     * IsTransitionStub tests whether an address is inside of a transition stub
     * which will cause a transition to managed code.  This can be used by
     * unmanaged stepping code to decide when to return stepping control to
     * the managed stepper.
     *
     * Note that, tentatively, these stubs may also be able to be identified
     * ahead of time by looking at information in the PE file.
     *
     */

    HRESULT IsTransitionStub([in] CORDB_ADDRESS address,
                             [out] BOOL *pbTransitionStub);


    /*
     * IsOSSuspended returns whether or not the thread has been
     * suspended as part of the debugger logic of stopping the process.
     * (that is, it has had its Win32 suspend count incremented by
     * one.)  The debugger UI may want to take this into account if
     * it shows the user the OS suspend count of the thread.
     *
     * This function only makes sense in the context of
     * unmanaged debugging - during managed debugging threads are not
     * OS suspended. (They are cooperatively suspended.)
 */

    HRESULT IsOSSuspended([in] DWORD threadID, [out] BOOL *pbSuspended);

    /*
     * GetThreadContext returns the context for the given thread.  The
     * debugger should call this function rather than the Win32
     * GetThreadContext, because the thread may actually be in a "hijacked"
     * state where its context has been temporarily changed.
     *
     * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet
     * for threads in managed code.
     *
     * The data returned is a CONTEXT structure for the current platform.
     * (CONTEXT is typically declared in winnt.h) Just as with a call
     * to Win32's GetThreadContext, the caller should initialize the
     * CONTEXT struct before calling.
     *
     */

    HRESULT GetThreadContext([in] DWORD threadID,
                             [in] ULONG32 contextSize,
                             [in, out, length_is(contextSize),
                             size_is(contextSize)] BYTE context[]);

    /*
     * SetThreadContext sets the context for the given thread.  The
     * debugger should call this function rather than the Win32
     * SetThreadContext, because the thread may actually be in a "hijacked"
     * state where its context has been temporarily changed.
     *
     * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet
     * for threads in managed code.
     *
     * This should never be needed to modify the context of a thread during an oob-debug
     * event.
     *
     * The data passed should be a CONTEXT structure for the current platform.
     * (CONTEXT is typically declared in winnt.h)
     *
     * This is a dangerous call which can corrupt the runtime if used
     * improperly.
     *
     */

    HRESULT SetThreadContext([in] DWORD threadID,
                             [in] ULONG32 contextSize,
                             [in, length_is(contextSize),
                             size_is(contextSize)] BYTE context[]);

    /*
     * ReadMemory reads memory from the process.
     * This is primarily intended to be used by interop-debugging to inspect memory
     * regions used by the unmanaged portion of the debuggee.
     *
     * This can also be used to read IL and native jitted code.
     * Any managed breakpoints will be automatically stripped from the returned buffer.
     * No adjustments will be made for Native breakpoints set by ICorDebugProcess2::SetUnmanagedBreakpoint
     *
     * No caching of process memory is peformed.
     * These parameters have the same semantics as kernel32!ReadProcessMemory.
     * The entire range must be read for the function to return success.
     */

    HRESULT ReadMemory([in] CORDB_ADDRESS address, [in] DWORD size,
                       [out, size_is(size), length_is(size)] BYTE buffer[],
                       [out] SIZE_T *read);

    /*
     * WriteMemory writes memory in the process.
     * In v2.0, Native debuggers should *not* use this to inject breakpoints
     * into the instruction stream. Use ICorDebugProcess2::SetUnamangedBreakpoint
     * instead.
     *
     * This is a dangerous call which can corrupt the runtime if used
     * improperly. It is highly recommended that this is only used outside
     * of managed code.
     *
     * These parameters have the same semantics as kernel32!WriteProcessMemory.
     */

    HRESULT WriteMemory([in] CORDB_ADDRESS address, [in] DWORD size,
                        [in, size_is(size)] BYTE buffer[],
                        [out]SIZE_T *written);


    /*
     * ClearCurrentException clears the current unmanaged exception on
     * the given thread. Call this before calling Continue when a
     * thread has reported an unmanaged exception that should be
     * ignored by the debuggee.
     *
     * This will clear both the outstanding IB and OOB events on the given thread.
     * Out-of-band Breakpoint and single-step exceptions are automatically cleared.
     *
     * See ICorDebugThread2::InterceptCurrentException for continuing managed exceptions.
     *
     */

    HRESULT ClearCurrentException([in] DWORD threadID);

    /*
     * EnableLogMessages enables/disables sending of log messages to the
     * debugger for logging.
     * This is only valid after the CreateProcess callback.
     *
     */

    HRESULT EnableLogMessages([in]BOOL fOnOff);

    /*
     * ModifyLogSwitch modifies the specified switch's severity level.
     * This is only valid after the CreateProcess callback.
     *
     */
    HRESULT ModifyLogSwitch([in] WCHAR *pLogSwitchName,
                            [in]LONG lLevel);

    /*
     * EnumerateAppDomains enumerates all app domains in the process.
     * This can be used before the CreateProcess callback.
     *
     */

    HRESULT EnumerateAppDomains([out] ICorDebugAppDomainEnum **ppAppDomains);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetObject([out] ICorDebugValue **ppObject);

    /*
     * DEPRECATED
     */

    HRESULT ThreadForFiberCookie([in] DWORD fiberCookie,
                                 [out] ICorDebugThread **ppThread);

    /*
     * Returns the OS thread id of the debugger's internal helper thread.
     * During managed/unmanaged debugging, it is the debugger's
     * responsibility to ensure that the thread with this ID remains running
     * if it hits a breakpoint placed by the debugger. A debugger may also
     * wish to hide this thread from the user.
     *
     * If there is no helper thread in the process yet, then this method
     * will return zero as the thread id.
     *
     * Note: you cannot cache this value. The ID of the helper thread may
     * change over time, so this value must be re-queried at every stopping
     * event.
     *
     * Note: this value will be correct on every unmanaged CreateThread event.
     * This will allow a debugger to determine the TID of the helper thread
     * and hide it from the user. A thread identified as a helper thread during
     * an unmanaged CreateThread event will never run managed user code.
     */

    HRESULT GetHelperThreadID([out] DWORD *pThreadID);
};
#pragma warning(pop)

[
    object,
    local,
    uuid(AD1B3588-0EF0-4744-A496-AA09A9F80371),
    pointer_default(unique)
]
interface ICorDebugProcess2 : IUnknown
{

    /*
      * Return a ICorDebugThread2 interface given a TASKID
     * Host can set TASKID using ICLRTask::SetTaskIdentifier
      */
    HRESULT GetThreadForTaskID(
       [in] TASKID taskid,
       [out] ICorDebugThread2 **ppThread);


    /*
     * Returns the version of the runtime the debugee process is running.
     */
    HRESULT GetVersion([out] COR_VERSION* version);

    /*
     * Set an unmanaged breakpoint at the given native address. If the address is within
     * the runtime, the breakpoint will be ignored.
     * This allows the CLR to avoid dispatching out-of-band breakpoints for breakpoints
     * set by the debugger.
     * buffer[] returns the opcode at the address that is replaced by the breakpoint.
     */

    HRESULT SetUnmanagedBreakpoint([in] CORDB_ADDRESS address,
                                   [in] ULONG32 bufsize,
                                   [out, size_is(bufsize), length_is(*bufLen)] BYTE buffer[],
                                   [out] ULONG32 * bufLen);

    /*
     * Remove a breakpoint set by SetUnmanagedBreakpoint.
     */
    HRESULT ClearUnmanagedBreakpoint([in] CORDB_ADDRESS address);


    /*
     * SetDesiredNGENCompilerFlags specifies the set of flags that must be set in a pre-JITted
     * image in order for the runtime to load that image into this app domain. If no such image exists,
     * the runtime will load the IL and JIT instead. The flags set by this function are just used to select the
     * correct pre-JITted image; if no suitable image is found the debugger will still need to use
     * ICorDebugModule2::SetJITCompilerFlags to set the flags as desired for JIT.
     *
     * This function must be called during the CreateProcess callback.
     * Attempts to call it after this callback has been delivered will fail.
     */
     HRESULT SetDesiredNGENCompilerFlags( [in] DWORD pdwFlags );

    /*
     * GetDesiredNGENCompilerFlags gets the set of flags that must be set in a pre-JITted image in order
     * for the runtime to load that image into this process.
     */
     HRESULT GetDesiredNGENCompilerFlags( [out] DWORD *pdwFlags );


    /*
    * Gets an ICorDebugReferenceValue object from a raw GC handle value.
    *
    * handle is the IntPtr within a GCHandle. Do not confuse
    * this with a GC reference value. This is a potentially dangerous API and may
    * corrupt both the debugger and debuggee if a bogus handle is passed in.
    * This API does not necessarily validate that the handle is valid.
    *
    * The ICorDebugReferenceValue will behave much like a normal reference. It will
    * be neutered on the next continue; the lifetime of the target object will
    * not be affected by the existence of the ReferenceValue.
    */
    HRESULT GetReferenceValueFromGCHandle( [in] UINT_PTR handle,
                                           [out] ICorDebugReferenceValue **pOutValue);

};


[
    object,
    local,
    uuid(2EE06488-C0D4-42B1-B26D-F3795EF606FB),
    pointer_default(unique)
]

interface ICorDebugProcess3 : IUnknown
{
    /*  Enables (or disables) custom debugger notifications of a specified
     *  type (which implements ICustomDebuggerNotification).  
     *  When this has been enabled, calls to
     *  System.Diagnostics.Debugger.CustomNotification with a data argument
     *  of the specified class will trigger a CustomNotification callback.
     *  Notifications are disabled by default and the debugger must opt-into
     *  any notification types it knows of and wishes to handle.
     *  Since ICorDebugClass is scoped by appdomains, the debugger needs to 
     *  call this API for every appdomain in the process if it’s interested in 
     *  receiving the notification across the entire process. 
     */

    HRESULT SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable);
}


/* ------------------------------------------------------------------------- *
 * Breakpoint interface
 * ------------------------------------------------------------------------- */

/*
 * ICorDebugBreakpoint represents a breakpoint; either a breakpoint
 * set in a function, or a watchpoint set on a value.
 *
 * Note that breakpoints have no direct support for condition
 * expressions.  The debugger must implement this functionality on top of
 * this interface if desired.
 *
 */

[
    object,
    local,
    uuid(CC7BCAE8-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugBreakpoint : IUnknown
{
    /*
     * Sets the active state of the breakpoint
     */
    HRESULT Activate([in] BOOL bActive);

    /*
     * Returns whether the breakpoint is active.
     */
    HRESULT IsActive([out] BOOL *pbActive);
};

[
    object,
    local,
    uuid(CC7BCAE9-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugFunctionBreakpoint : ICorDebugBreakpoint
{
    /*
     * Returns the function on which this breakpoint is set
     */
    HRESULT GetFunction([out] ICorDebugFunction **ppFunction);

    /*
     * Returns the offset of this breakpoint within the function
     */
    HRESULT GetOffset([out] ULONG32 *pnOffset);
};

[
    object,
    local,
    uuid(CC7BCAEA-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugModuleBreakpoint : ICorDebugBreakpoint
{
    /*
     * Returns the module on which this breakpoint is set.
     */
    HRESULT GetModule([out] ICorDebugModule **ppModule);
};

[
    object,
    local,
    uuid(CC7BCAEB-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugValueBreakpoint : ICorDebugBreakpoint
{
    /*
     * Gets the value on which this breakpoint is set.
     */
    HRESULT GetValue([out] ICorDebugValue **ppValue);
};

/* ------------------------------------------------------------------------- *
 * Stepper interface
 * ------------------------------------------------------------------------- */

/*
 * A Stepper object represents a stepping operation being performed by
 * the debugger.  Note that there can be more than one stepper per
 * thread; for instance a breakpoint may be hit in the midst of a
 * stepping over a function, and the user may wish to start a new
 * stepping operation inside that function. (Note that it is up to the
 * debugger how to handle this; it may want to cancel the original
 * stepping operation, or nest them.  This API allows either behavior.)
 *
 * Also, a stepper may migrate between threads if a cross-thread
 * marshalled call is made by the EE.
 *
 * This object serves several purposes.  Its serves as an identifer between a
 * step command issued and the completion of that command. It also
 * provides a central interface to encapsulate all of the stepping
 * that can be performed.  Finally it provides a way to prematurely
 * cancel a stepping operation.
 *
 */

[
    object,
    local,
    uuid(CC7BCAEC-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugStepper : IUnknown
{
    /*
     * IsActive returns whether or not the stepper is active, that is, whether
     * it is currently stepping.
     *
     * Any step action remains active until StepComplete is called.  Note that
     * this automatically deactivates the stepper.
     *
     * A stepper may also be deactivated prematurely by calling
     * Deactivate before a callback condition is reached.
     */

    HRESULT IsActive([out] BOOL *pbActive);

    /*
     * Deactivate causes a stepper to cancel the last stepping command it
     * received.  A new stepping command may then be issued.
     */

    HRESULT Deactivate();

    /*
     * SetInterceptMask controls which intercept code will be stepped
     * into by the stepper. If the bit for an interceptor is set, the
     * stepper will complete with reason STEPPER_INTERCEPT when the
     * given type of intercept occurs.  If the bit is cleared, the
     * intercepting code will be skipped.
     *
     * Note that SetInterceptMask may have unforeseen interactions
     * with SetUnmappedStopMask (from the user's point of view).  For
     * example, if the only visible (ie, non internal) portion of class
     * init code lacks mapping info (STOP_NO_MAPPING_INFO) and
     * STOP_NO_MAPPING_INFO isn't set, then we'll step over the class init.
     *
     * By default, only INTERCEPT_NONE will be used.
     */

    typedef enum CorDebugIntercept
    {
          INTERCEPT_NONE                = 0x0 ,
          INTERCEPT_CLASS_INIT          = 0x01,
          INTERCEPT_EXCEPTION_FILTER    = 0x02,
          INTERCEPT_SECURITY            = 0x04,
          INTERCEPT_CONTEXT_POLICY      = 0x08,
          INTERCEPT_INTERCEPTION        = 0x10,
          INTERCEPT_ALL                 = 0xffff
    } CorDebugIntercept;

    HRESULT SetInterceptMask([in] CorDebugIntercept mask);

    /*
     * SetUnmappedStopMask controls whether the stepper
     * will stop in jitted code which is not mapped to IL.
     *
     * If the given flag is set, then that type of unmapped code
     * will be stopped in.  Otherwise stepping transparently continues.
     *
     * It should be noted that if one doesn't use a stepper to enter a
     * method (for example, the main() method of C++), then one
     * won't neccessarily step over prologs,etc.
     *
     * By default, STOP_OTHER_UNMAPPED will be used.
     *
     * STOP_UNMANAGED is only valid w/ interop debugging.
     */

    typedef enum CorDebugUnmappedStop
    {
        STOP_NONE               = 0x0,
        STOP_PROLOG             = 0x01,
        STOP_EPILOG             = 0x02,
        STOP_NO_MAPPING_INFO    = 0x04,
        STOP_OTHER_UNMAPPED     = 0x08,
        STOP_UNMANAGED          = 0x10,

        STOP_ALL                = 0xffff,

    } CorDebugUnmappedStop;

    HRESULT SetUnmappedStopMask([in] CorDebugUnmappedStop mask);

    /*
     * Step is called when a thread is to be single stepped.  The step
     * will complete at the next managed instruction executed by the
     * EE in the stepper's frame.
     *
     * If bStepIn is TRUE, any function calls made during the step
     * will be stepped into.  Otherwise they will be skipped.
     *
     * If Step is called on a stepper which is not in managed code,
     * the step will complete when the next managed code is executed
     * by the thread. (if bStepIn is FALSE, it will only complete
     * when managed code is returned to, not when it is stepped into.)
     */

    HRESULT Step([in] BOOL bStepIn);

    /*
     * StepRange works just like Step, except it will not complete
     * until code outside the given range is reached.  This can be
     * more efficient than stepping one instruction at a time.
     *
     * Ranges are specified as a list of offset pairs [start, end)
     * (note that end is exclusive) from the start of the stepper's
     * frame's code.
     *
     * Ranges are in relative to the IL code of a method.  Call
     * SetRangeIL(FALSE) to specify ranges relative to the native code
     * of a method.
     */

    typedef struct COR_DEBUG_STEP_RANGE
    {
        ULONG32 startOffset, endOffset;
    } COR_DEBUG_STEP_RANGE;

    HRESULT StepRange([in] BOOL bStepIn,
                      [in,size_is(cRangeCount)] COR_DEBUG_STEP_RANGE ranges[],
                      [in] ULONG32 cRangeCount);

    /*
     * A StepOut operation will complete after the current frame is
     * returned from normally and the previous frame is reactivated.
     *
     * If this is called when in unmanaged code, the step will complete
     * when the calling managed code is returned to.
     *
     * In v2.0, we explicitly forbid StepOut with the STOP_UNMANAGED mask
     * and will fail that. Interop debuggers must do step-out-to-native
     * themselves.
     */

    HRESULT StepOut();

    /*
     * SetRangeIL is used to set whether the ranges passed StepRange are
     * relative to the IL code or the native code for the method being
     * stepped in.
     *
     * By default the range is in IL.
     */

    HRESULT SetRangeIL([in] BOOL bIL);
};

/*
 * ICorDebugStepper2 exposes JMC functionality.
 */
[
    object,
    local,
    uuid(C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7),
    pointer_default(unique)
]
interface ICorDebugStepper2 : IUnknown
{
    HRESULT SetJMC([in] BOOL fIsJMCStepper);
}

/* ------------------------------------------------------------------------- *
 * Program state object interfaces
 * ------------------------------------------------------------------------- */

/*
 * ICorDebugRegisterSet
 */

[
    object,
    local,
    uuid(CC7BCB0B-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugRegisterSet : IUnknown
{
    typedef enum CorDebugRegister
    {
        // registers (potentially) available on all architectures
        // Note that these overlap with the architecture-specific
        // registers
        //
        // NOTE: On IA64, REGISTER_FRAME_POINTER represents the BSP register.

        REGISTER_INSTRUCTION_POINTER = 0,
        REGISTER_STACK_POINTER,
        REGISTER_FRAME_POINTER,


        // X86 registers

        REGISTER_X86_EIP = 0,
        REGISTER_X86_ESP,
        REGISTER_X86_EBP,

        REGISTER_X86_EAX,
        REGISTER_X86_ECX,
        REGISTER_X86_EDX,
        REGISTER_X86_EBX,

        REGISTER_X86_ESI,
        REGISTER_X86_EDI,

        REGISTER_X86_FPSTACK_0,
        REGISTER_X86_FPSTACK_1,
        REGISTER_X86_FPSTACK_2,
        REGISTER_X86_FPSTACK_3,
        REGISTER_X86_FPSTACK_4,
        REGISTER_X86_FPSTACK_5,
        REGISTER_X86_FPSTACK_6,
        REGISTER_X86_FPSTACK_7,


        // AMD64 registers

        REGISTER_AMD64_RIP = 0,
        REGISTER_AMD64_RSP,
        REGISTER_AMD64_RBP,

        REGISTER_AMD64_RAX,
        REGISTER_AMD64_RCX,
        REGISTER_AMD64_RDX,
        REGISTER_AMD64_RBX,

        REGISTER_AMD64_RSI,
        REGISTER_AMD64_RDI,

        REGISTER_AMD64_R8,
        REGISTER_AMD64_R9,
        REGISTER_AMD64_R10,
        REGISTER_AMD64_R11,
        REGISTER_AMD64_R12,
        REGISTER_AMD64_R13,
        REGISTER_AMD64_R14,
        REGISTER_AMD64_R15,

        // Xmm FP

        REGISTER_AMD64_XMM0,
        REGISTER_AMD64_XMM1,
        REGISTER_AMD64_XMM2,
        REGISTER_AMD64_XMM3,
        REGISTER_AMD64_XMM4,
        REGISTER_AMD64_XMM5,
        REGISTER_AMD64_XMM6,
        REGISTER_AMD64_XMM7,
        REGISTER_AMD64_XMM8,
        REGISTER_AMD64_XMM9,
        REGISTER_AMD64_XMM10,
        REGISTER_AMD64_XMM11,
        REGISTER_AMD64_XMM12,
        REGISTER_AMD64_XMM13,
        REGISTER_AMD64_XMM14,
        REGISTER_AMD64_XMM15,


        // IA64 registers

        REGISTER_IA64_BSP = REGISTER_FRAME_POINTER,

        // To get a particular general register, add the register number
        // to REGISTER_IA64_R0.  The same also goes for floating point
        // registers.
        //
        // For example, if you need REGISTER_IA64_R83,
        // use REGISTER_IA64_R0 + 83.
        REGISTER_IA64_R0  = REGISTER_IA64_BSP + 1,
        REGISTER_IA64_F0  = REGISTER_IA64_R0  + 128,


        // other architectures here

    } CorDebugRegister;

    /*
     * GetRegistersAvailable returns a mask indicating which registers
     * are available in the given register set.  Registers may be unavailable
     * if their value is undeterminable for the given situation.  The returned
     * word contains a bit for each register (1 << register index), which will
     * be 1 if the register is available or 0 if it is not.
     */

    HRESULT GetRegistersAvailable([out] ULONG64 *pAvailable);

    /*
     * GetRegisters returns an array of register values corresponding
     * to the given mask.  The registers which have their bit set in
     * the mask will be packed into the resulting array.  (No room is
     * assigned in the array for registers whose mask bit is not set.)
     * Thus, the size of the array should be equal to the number of
     * 1's in the mask.
     *
     * If an unavailable register is indicated by the mask, an indeterminate
     * value will be returned for the corresponding register.
     *
     * registerBufferCount should indicate number of elements in the
     * buffer to receive the register values.  If it is too small for
     * the number of registers indicated by the mask, the higher
     * numbered registers will be truncated from the set.  Or, if it
     * is too large, the unused registerBuffer elements will be
     * unmodified.  */

    HRESULT GetRegisters([in] ULONG64 mask, [in] ULONG32 regCount,
                         [out, size_is(regCount), length_is(regCount)]
                         CORDB_REGISTER regBuffer[]);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT SetRegisters([in] ULONG64 mask,
                         [in] ULONG32 regCount,
                         [in, size_is(regCount)] CORDB_REGISTER regBuffer[]);

    /*
     * GetThreadContext returns the context for the given thread.  The
     * debugger should call this function rather than the Win32
     * GetThreadContext, because the thread may actually be in a "hijacked"
     * state where its context has been temporarily changed.
     *
     * The data returned is a CONTEXT structure for the current platform.
     *
     * For non-leaf frames, clients should check which registers are valid by
     * using GetRegistersAvailable.
     *
     */

    HRESULT GetThreadContext([in] ULONG32 contextSize,
                             [in, out, length_is(contextSize),
                             size_is(contextSize)] BYTE context[]);

    /*
     * Not implemented in v2.0. It is too dangerous to manipulate the context of
     * threads in Managed code. Use other high level operations (like SetIp,
     * ICorDebugValue::SetValue) instead.
     *
     */

    HRESULT SetThreadContext([in] ULONG32 contextSize,
                             [in, length_is(contextSize),
                             size_is(contextSize)] BYTE context[]);
}

/*
 * ICorDebugRegisterSet2 is an extension for hardward platforms with more
 * than 64 registers, since ICorDebugRegisterSet::GetRegisters() only
 * recognizes a 64-bit mask.
 */

[
    object,
    local,
    uuid(6DC7BA3F-89BA-4459-9EC1-9D60937B468D),
    pointer_default(unique)
]
interface ICorDebugRegisterSet2 : IUnknown
{
    /*
     * Given a CorDebugRegister value, its position in the mask is determined as
     * follows:
     *
     * 1) (value >> 3) is used to index the array of BYTEs, and
     * 2) (value &  7) (the least significant three bits) represents the bit position
     *    within the indexed BYTE, where bit 0 is the least significant bit.
     *
     * Or, in code:
     *
     *    #define REGISTER_IA64_MAX              REGISTER_IA64_F0 + 128
     *    #define MAX_MASK_COUNT                 ((REGISTER_IA64_MAX + 7) >> 3)
     *    #define SET_BIT_MASK(_mask, _reg)      _mask[(_reg) >> 3] |=  (1 << ((_reg) & 7))
     *    #define RESET_BIT_MASK(_mask, _reg)    _mask[(_reg) >> 3] &= ~(1 << ((_reg) & 7))
     *    #define IS_SET_BIT_MASK(_mask, _reg)   _mask[(_reg) >> 3] &   (1 << ((_reg) & 7))
     *
     *    CorDebugRegister value = <some value>;
     *    BYTE pAvailable[MAX_MASK_COUNT];
     *
     *    GetRegistersAvailable(MAX_MASK_COUNT, pAvailable);
     *    ASSERT(value < REGISTER_IA64_MAX);
     *    IS_SET_BIT_MASK(pAvailable, value);
     */

    HRESULT GetRegistersAvailable([in] ULONG32 numChunks,
                                  [out, size_is(numChunks)] BYTE availableRegChunks[]);

    HRESULT GetRegisters([in] ULONG32 maskCount,
                         [in, size_is(maskCount)] BYTE mask[],
                         [in] ULONG32 regCount,
                         [out, size_is(regCount)] CORDB_REGISTER regBuffer[]);

    HRESULT SetRegisters([in] ULONG32 maskCount,
                         [in, size_is(maskCount)] BYTE mask[],
                         [in] ULONG32 regCount,
                         [in, size_is(regCount)] CORDB_REGISTER regBuffer[]);
}

/*
 * ICorDebugThread represents a thread in the process.  The lifetime of a
 * thread object is equal to the lifetime of the thread it represents.
 */

[
    object,
    local,
    uuid(938c6d66-7fb6-4f69-b389-425b8987329b),
    pointer_default(unique)
]
interface ICorDebugThread : IUnknown
{
    /*
     * GetProcess returns the process of which this thread is a part.
     */

    HRESULT GetProcess([out] ICorDebugProcess **ppProcess);

    /*
     * GetID returns the current OS ID of the active part of the thread.
     * Note that this may theoretically change as the process executes,
     * and even be different for different parts of the thread.
     */

    HRESULT GetID([out] DWORD *pdwThreadId);

    /*
     * GetHandle returns the current Handle of the active part of the thread.
     * Note that this may theoretically change as the process executes,
     * and even be different for different parts of the thread.
     *
     * This handle is owned by the debugging API. The debugger should duplicate
     * it before using it.
     */

    HRESULT GetHandle([out] HTHREAD *phThreadHandle);

    /*
     * GetAppDomain returns the app domain which the thread is currently
     * executing in.
     */

    HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain);

    /*
     * SetDebugState sets the current debug state of the thread.
     * (The "current debug state"
     * represents the debug state if the process were to be continued,
     * not the actual current state.)
     *
     * The normal value for this is THREAD_RUNNING.  Only the debugger
     * can affect the debug state of a thread.  Debug states do
     * last across continues, so if you want to keep a thread
     * THREAD_SUSPENDed over mulitple continues, you can set it once
     * and thereafter not have to worry about it.
     *
     * Suspending threads and resuming the process can cause deadlocks, though it's
     * usually unlikely. This is an intrinisc quality of threads and processes and is by-design.
     * A debugger can async break and resume the threads to break the deadlock.
     *
     * If the thread's user state includes USER_UNSAFE_POINT, then the thread may block a GC.
     * This means the suspended thread has a mcuh higher chance of causing a deadlock.
     *
     * This may not affect debug events already queued. Thus a debugger should drain the entire 
     * event queue (via calling HasQueuedCallbacks) before suspending or resuming threads. Else it
     * may get events on a thread that it believes it has already suspended.
     *
     */

    HRESULT SetDebugState([in] CorDebugThreadState state);

    /*
     * GetDebugState returns the current debug state of the thread.
     * (If the process is currently stopped, the "current debug state"
     * represents the debug state if the process were to be continued,
     * not the actual current state.)
     */

    HRESULT GetDebugState([out] CorDebugThreadState *pState);

    /*
     * GetUserState returns the user state of the thread, that is, the state
     * which it has when the program being debugged examines it.
     * A thread may have multiple state bits set.
     */

    typedef enum CorDebugUserState
    {
        USER_STOP_REQUESTED     = 0x01,
        USER_SUSPEND_REQUESTED  = 0x02,
        USER_BACKGROUND         = 0x04,
        USER_UNSTARTED          = 0x08,
        USER_STOPPED            = 0x10,
        USER_WAIT_SLEEP_JOIN    = 0x20,
        USER_SUSPENDED          = 0x40,

        // An "unsafe point" is a place where the thread may block a Garbage Collection (GC).
        // Debug events may be dispatched from unsafe points, but suspending a thread at
        // an unsafe spot will very likely cause a deadlock (until the thread is resumed).
        // This is a function of the thread's IP and the available GC info. The exact details
        // of what is safe and unsafe is unspecified and highly determined by jit/gc implementation details.
        USER_UNSAFE_POINT       = 0x80,
    } CorDebugUserState;

    HRESULT GetUserState([out] CorDebugUserState *pState);

    /*
     * GetCurrentException returns the exception object which is
     * currently being thrown by the thread.  This will exist from the time the exception
     * is thrown until the end of the catch block. That range will include filters
     * and finallys.
     *
     * FuncEval will clear out the exception object on setup and restore it on completion.
     *
     * Exceptions can be nested (eg, if an exception is thrown in filter or a func-eval),
     * so there may be multiple outstanding exceptions on a single thread.
     * This returns the most current exception.
     *
     * The exception object and type may change throughout the life of the exception. For example, an
     * exception of type X may be thrown, but then the CLR may run out of memory and promote
     * that to an OutOfMemory exception.
     */

    HRESULT GetCurrentException([out] ICorDebugValue **ppExceptionObject);

    /*
     * This is not implemented.
     */

    HRESULT ClearCurrentException();

    /*
     * CreateStepper creates a stepper object which operates relative
     * to the active frame in the given thread. (Note that this may be
     * unmanaged code.)  The Stepper API must then be used to perform
     * actual stepping.
     *
     */

    HRESULT CreateStepper([out] ICorDebugStepper **ppStepper);

    /*
     * EnumerateChains returns an enum which will return all the stack
     * chains in the thread, starting at the active (most recent) one.
     * These chains represent the physical call stack for the thread.
     *
     * Chain boundaries occur for several reasons:
     *   managed <-> unmanaged transitions
     *   context switches
     *   debugger hijacking of user threads
     *
     * Note that in the simple case for a thread running purely
     * managed code in a single context there will be a one to one
     * correspondence between threads & chains.
     *
     * A debugger may want to rearrange the physical call
     * stacks of all threads into logical call stacks. This would involve
     * sorting all the threads' chains by their caller/callee
     * relationships & regrouping them.
     *
     */

    HRESULT EnumerateChains([out] ICorDebugChainEnum **ppChains);

    /*
     * GetActiveChain is a convenience routine to return the
     * active (most recent) chain on the thread, if any.
     *
     */

    HRESULT GetActiveChain([out] ICorDebugChain **ppChain);

    /*
     * GetActiveFrame is a convenience routine to return the
     * active (most recent) frame on the thread, if any.
     * If there are no frames on the stack, ppFrame will point to NULL
     * and the function still returns S_OK.
     */

    HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame);

    /*
     * GetRegisterSet returns the register set for the active part
     * of the thread.
     *
     */

    HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters);

    /*
     * CreateEval creates an evaluation object which operates on the
     * given thread.  The Eval will push a new chain on the thread before
     * doing its computation.
     *
     * Note that this interrupts the computation currently
     * being performed on the thread until the eval completes.
     *
     */

    HRESULT CreateEval([out] ICorDebugEval **ppEval);

    /*
     * Returns the runtime thread object.
     */

    HRESULT GetObject([out] ICorDebugValue **ppObject);

};

/*
  * ICorDebugThread2 is a logical extension to ICorDebugThread.
  */
[
    object,
    local,
    uuid(2BD956D9-7B07-4bef-8A98-12AA862417C5),
    pointer_default(unique)
]
interface ICorDebugThread2 : IUnknown
{

    typedef struct _COR_ACTIVE_FUNCTION
    {
        ICorDebugAppDomain *pAppDomain;   // Pointer to the owning AppDomain of the below IL Offset.
        ICorDebugModule *pModule;         // Pointer to the owning Module of the below IL Offset.
        ICorDebugFunction2 *pFunction;    // Pointer to the owning Function of the below IL Offset.
        ULONG32 ilOffset;                 // IL Offset of the frame.
        ULONG32 flags;                    // Bit mask of flags, currently unused.  Reserved.
    } COR_ACTIVE_FUNCTION;

    /*
     * Retrieves the active functions for the given threads' frames. This
     * includes AppDomain ID, Module ID, Funtion ID and IL offset for
     * each active statement on the stack.  A flags field is also included
     * for future information about the frame that might need to be conveyed.
     *
     * If pFunctions is NULL, returns only the number of functions that
     * is on the stack in pcFunctions.
     */

    HRESULT GetActiveFunctions([in] ULONG32 cFunctions,
                               [out] ULONG32 *pcFunctions,
                               [in, out, size_is(cFunctions), length_is(*pcFunctions)]
                               COR_ACTIVE_FUNCTION pFunctions[]
                               );
    /*
     * Returns 0 if not part of a connection
     * Maps to a SPID in SQL Server
     */
    HRESULT GetConnectionID(
        [out] CONNID *pdwConnectionId);

    /*
     * Return the TASKID of this thread.
    */
    HRESULT GetTaskID(
        [out] TASKID *pTaskId);

    /*
     * Return the OS Thread ID
     */
    HRESULT GetVolatileOSThreadID(
        [out] DWORD *pdwTid);

    /*
     * Allow the debugger to intercept the current exception on a thread.  It can be
     * called between an Exception callback and the associated call to ICorDebugProcess::Continue.
     *
     * pFrame specifies where we should intercept the exception.  It must be a valid ICDFrame pointer,
     * which can be obtained from a stackwalk.  However, you must not call Continue() between
     * doing the stackwalk and calling this function.
     */
    HRESULT InterceptCurrentException(
        [in] ICorDebugFrame *pFrame);
}



/*
 * ICorDebugThread3 is a logical extension to ICorDebugThread.
 */
[
    object,
    local,
    uuid(F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5),
    pointer_default(unique)
]
interface ICorDebugThread3 : IUnknown
{
    HRESULT CreateStackWalk([out] ICorDebugStackWalk **ppStackWalk);

    HRESULT GetActiveInternalFrames([in] ULONG32 cInternalFrames,
                                    [out] ULONG32 *pcInternalFrames,
                                    [in, out, size_is(cInternalFrames), length_is(*pcInternalFrames)]
                                    ICorDebugInternalFrame2 * ppInternalFrames[]
                                    );
};

/*
 * ICorDebugThread4 is a logical extension to ICorDebugThread.
 */
[
    object,
    local,
    uuid(1A1F204B-1C66-4637-823F-3EE6C744A69C),
    pointer_default(unique)
]
interface ICorDebugThread4 : IUnknown
{
    /*
     * Returns S_OK if ICorDebugThread::GetCurrentException() is non-NULL and the exception
     * it refers to has completed the first pass of exception handling without locating 
     * a catch clause.
     * Returns S_FALSE if there is no exception, it hasn't completed first pass handling,
     * or a catch handler was located
     * Returns an appropriate error HRESULT when the answer can not be determined
     */
    HRESULT HasUnhandledException();

    HRESULT GetBlockingObjects([out] ICorDebugBlockingObjectEnum **ppBlockingObjectEnum);
    /* 
     * Gets the current CustomNotification object on the current thread. This could be NULL if no
     * current notification object exists. If we aren't currently inside a CustomNotification callback,
     * this will always return NULL.
     * A debugger can examine this object to determine how to handle the notification. 
     * See ICorDebugManagedCallback3::CustomNotification for more information about 
     * custom notifications. 
     */
    HRESULT GetCurrentCustomDebuggerNotification([out] ICorDebugValue ** ppNotificationObject);
};

/*
 * The new V3.0 stackwalking API.
 */
[
    object,
    local,
    uuid(A0647DE9-55DE-4816-929C-385271C64CF7),
    pointer_default(unique)
]
interface ICorDebugStackWalk : IUnknown
{
    typedef enum CorDebugSetContextFlag
    {
        SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1,
        SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2,
    } CorDebugSetContextFlag;

    /* 
     * Get the current context of this stack frame.
     * 
     * The CONTEXT is retrieved from the ICorDebugStackWalk.  As unwinding may only restore a subset of the 
     * registers, such as only non-volatile registers, the context may not exactly match the register state at 
     * the time of the actual call.
     */
    HRESULT GetContext([in] ULONG32 contextFlags,
                       [in] ULONG32 contextBufSize,
                       [out] ULONG32* contextSize,
                       [out, size_is(contextBufSize)] BYTE contextBuf[]);

    /* 
     * Change the current context of this stack walk, allowing the
     * debugger to move it to an arbitrary context. Does not actually
     * alter the current context of the thread whose stack is being walked.
     *
     * The CONTEXT has to be a valid CONTEXT of a stack frame on the thread.
     * If the CONTEXT is outside of the current thread's stack range, we'll
     * return a failure HRESULT.  Otherwise, in the case of an invalid CONTEXT, 
     * the result is undefined.
     */
    HRESULT SetContext([in] CorDebugSetContextFlag flag,
                       [in] ULONG32 contextSize,
                       [in, size_is(contextSize)] BYTE context[]);

    /*
     * Attempt to advance the stackwalk to the next frame.  
     * If the current frame type is a native stack frame, Next() will not advance to the caller frame.
     * Instead, Next() will advance to the next managed stack frame or the next internal frame marker.
     *
     * If a debugger wants to unwind unmanaged stack frames, it needs to start from the 
     * native stack frame itself.  It can seed the unwind by calling GetContext().
     *
     * This function will return CORDBG_S_AT_END_OF_STACK when there are no more frames.
     */
    HRESULT Next();

    /*
     * Return the current frame.  If the stackwalker is stopped at a native stack frame, we will return S_FALSE
     * and set pFrame to NULL.
     */
    HRESULT GetFrame([out] ICorDebugFrame ** pFrame);
};


/*
 * ICorDebugChain represents a segment of a physical or logical call
 * stack.  All frames in a chain occupy contiguous stack space, and
 * they share the same thread & context.  A chain may represent either
 * managed or unmanaged code. Chains may be empty. Unmanaged chains are
 * always empty.
 */

[
    object,
    local,
    uuid(CC7BCAEE-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugChain : IUnknown
{
    /*
     * GetThread returns the physical thread which this call chain is
     * part of.
     */

    HRESULT GetThread([out] ICorDebugThread **ppThread);

    /*
     * GetStackRange returns the address range of the stack segment for the
     * call chain.  Note that you cannot make any assumptions about
     * what is actually stored on the stack - the numeric range is to compare
     * stack frame locations only.
     * The start of a stack range is the leafmost boundary of the chain, and 
     * the end of a stack range is the rootmost boundary of the chain.
     */

    HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetContext([out] ICorDebugContext **ppContext);

    /*
     * GetCaller returns a pointer to the chain which called this
     * chain.  Note that this may be a chain on another thread in the
     * case of cross-thread-marshalled calls. The caller will be NULL
     * for spontaneously called chains (e.g. the ThreadProc, a
     * debugger initiated call, etc.)
     */

    HRESULT GetCaller([out] ICorDebugChain **ppChain);

    /*
     * GetCallee returns a pointer to the chain which this chain is
     * waiting on before it resumes. Note that this may be a chain on
     * another thread in the case of cross-thread-marshalled
     * calls. The callee will be NULL if the chain is currently
     * actively running.
     */

    HRESULT GetCallee([out] ICorDebugChain **ppChain);

    /*
     * GetPrevious returns a pointer to the chain which was on this
     * thread before the current one was pushed, if there is one.
     */

    HRESULT GetPrevious([out] ICorDebugChain **ppChain);

    /*
     * GetNext returns a pointer to the chain which was pushed on this
     * thread after the current one, if there is one.
     */

    HRESULT GetNext([out] ICorDebugChain **ppChain);

    /*
     * IsManaged returns whether or not the chain is running managed
     * code.
     */

    HRESULT IsManaged([out] BOOL *pManaged);

    /*
     * These chains represent the physical call stack for the thread.
     * EnumerateFrames returns an iterator which will list all the stack
     * frames in the chain, starting at the active (most recent) one. This
     * should be called only for managed chains.
     *
     * NOTE: The debugging API does not provide methods for obtaining
     * frames contained in unmanaged chains. The debugger needs to use
     * other means to obtain this information.
     */

    HRESULT EnumerateFrames([out] ICorDebugFrameEnum **ppFrames);

    /*
     * GetActiveFrame is a convenience routine to return the
     * active (most recent) frame on the chain, if any.
     *
     * If the active frame is not available, the call will succeed
     * and *ppFrame will be NULL. Active frames will not be available
     * for all CHAIN_ENTER_UNMANAGED chains, and for some
     * CHAIN_CLASS_INIT chains.
     */

    HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame);

    /*
     * GetRegisterSet returns the register set for the beginnning (the leafmost end)
     * of the chain.
     */

    HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters);

    /*
     * GetReason returns the reason for the genesis of this calling chain.
     */

    typedef enum CorDebugChainReason
    {
        // Note that the first five line up with CorDebugIntercept
        CHAIN_NONE              = 0x000,
        CHAIN_CLASS_INIT        = 0x001,
        CHAIN_EXCEPTION_FILTER  = 0x002,
        CHAIN_SECURITY          = 0x004,
        CHAIN_CONTEXT_POLICY    = 0x008,
        CHAIN_INTERCEPTION      = 0x010,
        CHAIN_PROCESS_START     = 0x020,
        CHAIN_THREAD_START      = 0x040,
        CHAIN_ENTER_MANAGED     = 0x080,
        CHAIN_ENTER_UNMANAGED   = 0x100,
        CHAIN_DEBUGGER_EVAL     = 0x200,
        CHAIN_CONTEXT_SWITCH    = 0x400,
        CHAIN_FUNC_EVAL         = 0x800,
    } CorDebugChainReason;

    HRESULT GetReason([out] CorDebugChainReason *pReason);
};


[
    object,
    local,
    uuid(CC7BCAEF-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugFrame : IUnknown
{
    /*
     * GetChain returns the chain of which this stack frame is a part.
     */

    HRESULT GetChain([out] ICorDebugChain **ppChain);

    /*
     * GetCode returns the code which this stack frame is running if any.
     */

    HRESULT GetCode([out] ICorDebugCode **ppCode);

    /*
     * GetFunction returns the function for the code which this stack 
     * frame is running.  
     * For ICorDebugInternalFrames, this may point to a method the 
     * frame is associated with (which may be in a different AppDomain
     * from the frame itself), or may fail if the frame doesn't relate to any
     * particular function.
     */

    HRESULT GetFunction([out] ICorDebugFunction **ppFunction);

    /*
     * GetFunctionToken is a convenience routine to return the token for the
     * function for the code which this stack frame is running.
     * The scope to resolve the token can be gotten from the ICorDebugFunction 
     * associated with this frame.
     */

    HRESULT GetFunctionToken([out] mdMethodDef *pToken);

    /*
     * GetStackRange returns the absolute address range of the stack
     * frame.  (This is useful for piecing together interleaved stack
     * traces gathered from multiple debugging engines.)  Note that you
     * cannot make any assumptions about what is actually stored on
     * the stack - the numeric range is to compare stack frame
     * locations only.
     * The start of a stack range is the leafmost boundary of the frame, and 
     * the end of a stack range is the rootmost boundary of the frame.
     */

    HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd);

    /*
     * GetCaller returns a pointer to the frame in the current chain
     * which called this frame, or NULL if this is the rootmost frame
     * in the chain.
     */

    HRESULT GetCaller([out] ICorDebugFrame **ppFrame);

    /*
     * GetCallee returns a pointer to the frame in the current chain
     * which this frame called, or NULL if this is the leafmost frame
     * in the chain.
     */

    HRESULT GetCallee([out] ICorDebugFrame **ppFrame);

    /*
     * CreateStepper creates a stepper object which operates relative to the
     * frame. The Stepper API must then be used to perform actual stepping.
     *
     * Note that if this frame is not active, the frame will typically have to
     * be returned to before the step is completed.
     *
     */

    HRESULT CreateStepper([out] ICorDebugStepper **ppStepper);
};

[
    object,
    local,
    uuid(B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4),
    pointer_default(unique)
]
interface ICorDebugInternalFrame : ICorDebugFrame
{

    typedef enum CorDebugInternalFrameType
    {
        // This is a 'null' value for GetFrameType and is included for completeness sake.
        // ICorDebugInternalFrame::GetFrameType() should never actually return this.
        STUBFRAME_NONE = 0x00000000,

        // This frame is a M2U stub-frame. This could include both PInvoke
        // and COM-interop calls.
        STUBFRAME_M2U = 0x0000001,

        // This is a U2M stub frame.
        STUBFRAME_U2M = 0x0000002,

        // AppDomain transition.
        STUBFRAME_APPDOMAIN_TRANSITION = 0x00000003,

        // LightWeight method calls.
        STUBFRAME_LIGHTWEIGHT_FUNCTION = 0x00000004,

        // Start of Func-eval. This is included for CHF callbacks.
        // Funcevals also have a chain CHAIN_FUNC_EVAL (legacy from v1.0)
        STUBFRAME_FUNC_EVAL = 0x00000005,

        // Start of an internal call into the CLR.
        STUBFRAME_INTERNALCALL = 0x00000006,

        // start of a class initialization; corresponds to CHAIN_CLASS_INIT
        STUBFRAME_CLASS_INIT = 0x00000007,

        // an exception is thrown; corresponds to CHAIN_EXCEPTION_FILTER
        STUBFRAME_EXCEPTION = 0x00000008,

        // a frame used for code-access security purposes; corresponds to CHAIN_SECURITY
        STUBFRAME_SECURITY = 0x00000009,

        // a frame used to mark that the runtime is jitting a managed method
        STUBFRAME_JIT_COMPILATION = 0x0000000a,
    } CorDebugInternalFrameType;

    // Get the type of internal frame. This will never be STUBFRAME_NONE.
    // Debuggers should gracefully ignore unrecognized internal frame types.
    HRESULT GetFrameType([out] CorDebugInternalFrameType * pType);

};

[
    object,
    local,
    uuid(C0815BDC-CFAB-447e-A779-C116B454EB5B),
    pointer_default(unique)
]
interface ICorDebugInternalFrame2 : IUnknown
{
    /*
     * Returns the stack address of the internal frame marker.
     */
    HRESULT GetAddress([out] CORDB_ADDRESS *pAddress);

/*
     * Check if an internal frame is closer to the leaf than pFrameToCompare.
     */
    HRESULT IsCloserToLeaf([in] ICorDebugFrame * pFrameToCompare, 
                           [out] BOOL * pIsCloser);
};

/*
 * ICorDebugILFrame is a specialized interface of ICorDebugFrame for IL frames or jitted frames.
 * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.)
 */

[
    object,
    local,
    uuid(03E26311-4F76-11d3-88C6-006097945418),
    pointer_default(unique)
]
interface ICorDebugILFrame : ICorDebugFrame
{
    /*
     * GetIP returns the stack frame's offset into the function's IL code.
     * If this stack frame is active, this address is the next
     * instruction to execute.  If this stack frame is not active, this is the
     * next instruction to execute when the stack frame is reactivated.
     *
     * Note that if this a jitted frame, the IP will be determined by
     * mapping backwards from the actual native IP, so the value may
     * be only approximately correct.
     *
     * If pMappingResult is not NULL, A mapping result is returned which
     * indicates the details of how the IP was obtained.  The following values
     * can be returned:
     *
     *  MAPPING_EXACT - the IP is correct; either the frame is
     *  interpreted or there is an exact IL map for the function.
     *
     *  MAPPING_APPROXIMATE - the IP was successfully mapped, but may
     *  be only approximately correct
     *
     *  MAPPING_UNMAPPED_ADDRESS - although there is mapping info for
     *  the function, the current address is not mappable to IL.  An
     *  IP of 0 is returned.
     *
     *  MAPPING_PROLOG - the native code is in the prolog, so an IP of
     *  0 is returned
     *
     *  MAPPING_EPILOG - the native code is in an epilog, so the last
     *  IP of the method is returned
     *
     *  MAPPING_NO_INFO - no mapping info is available for the method,
     *  so an IP of 0 is returned
     *
     */

    typedef enum CorDebugMappingResult
    {
        MAPPING_PROLOG              = 0x1,
        MAPPING_EPILOG              = 0x2,
        MAPPING_NO_INFO             = 0x4,
        MAPPING_UNMAPPED_ADDRESS    = 0x8,
        MAPPING_EXACT               = 0x10,
        MAPPING_APPROXIMATE         = 0x20,
    } CorDebugMappingResult;

    HRESULT GetIP([out] ULONG32 *pnOffset, [out] CorDebugMappingResult *pMappingResult);

    /*
     * SetIP sets the instruction pointer to the IL at the given offset.
     * The debugger will do its best to fix up the state of the executing code
     * so that it is consistent with the new IP as far as the EE is concerned,
     * while preserving as much of the state of the user program as possible.
     *
     * Calling SetIP immediately invalidates all frames and chains for the
     * current thread; the debugger must perform a new stack trace if it
     * requires frame information after calling SetIP.
     *
     */

    HRESULT SetIP([in] ULONG32 nOffset);

    /*
     * EnumerateLocalVariables returns a list of the local variables
     * available in the frame.  Note that this may not include all of
     * the locals in the running function, as some of them may not be
     * active.
     */

    HRESULT EnumerateLocalVariables([out] ICorDebugValueEnum **ppValueEnum);

    /*
     * GetLocalVariable gets the value for a local variable
     * in an IL frame.  This can be used either in an IL
     * frame or a jitted frame.
     */

    HRESULT GetLocalVariable([in] DWORD dwIndex,
                             [out] ICorDebugValue **ppValue);

    /*
     * EnumerateArguments returns a list of the arguments available in the
     * frame.  Note that this will include varargs arguments as well as
     * arguments declared by the function signature (inlucding the implicit 
     * "this" argument if any).
     */

    HRESULT EnumerateArguments([out] ICorDebugValueEnum **ppValueEnum);

    /*
     * GetArgument gets the value for an argument
     * in an IL frame.  This can be used either in an IL
     * frame or a jitted frame.
     * For instance (non-static) methods, argument index 0 is the "this" object,
     * and the normal explicit arguments start with index 1.
     */

    HRESULT GetArgument([in] DWORD dwIndex,
                        [out] ICorDebugValue **ppValue);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetStackDepth([out] ULONG32 *pDepth);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetStackValue([in] DWORD dwIndex,
                          [out] ICorDebugValue **ppValue);

    /*
     * CanSetIP attempts to determine if it's safe to set the instruction pointer
     * to the IL at the given offset. If this returns S_OK, then executing
     * SetIP (see above) will result in a safe, correct, continued execution.
     * If CanSetIP returns anything else, SetIP can still be invoked, but
     * continued, correct execution of the debuggee cannot be guaranteed.
     *
     */

    HRESULT CanSetIP([in] ULONG32 nOffset);
};


/*
 * ICorDebugILFrame2 is a logical extension to ICorDebugILFrame.
 */
[
    object,
    local,
    uuid(5D88A994-6C30-479b-890F-BCEF88B129A5),
    pointer_default(unique)
]
interface ICorDebugILFrame2 : IUnknown
{
    /*
     * Performs an on-stack replacement for an outstanding function remap opportunity.
     * This is used to update execution of an edited function to the latest version, 
     * preserving the current frame state (such as the values of all locals). 
     * This can only be called when a FunctionRemapOpportunity callback has been delivered
     * for this leaf frame, and the callback has not yet been continued.  newILOffset
     * is the offset into the new function at which execution should continue.
     * When the remap has completed, a FunctionRemapComplete callback will be delivered.
     */
    HRESULT RemapFunction([in] ULONG32 newILOffset);

    /*
     * EnumerateTypeParameters returns the type parameters active on a frame.
     * This will include both the class type parameters (if any) followed by the method type
     * parameters (if any).
     * Use the metadata API IMetaDataImport2::EnumGenericParams to determine how many
     * Class type parameters vs. Method Type parameters there are in this list.
     * The type parameters will not always be available.
     */

    HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum);

};

/*
 * ICorDebugNativeFrame is a specialized interface of ICorDebugFrame for jitted frames, i.e. 
 * native frames for managed methods.
 * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.)
 */

[
    object,
    local,
    uuid(03E26314-4F76-11d3-88C6-006097945418),
    pointer_default(unique)
]
interface ICorDebugNativeFrame : ICorDebugFrame
{
    /*
     * GetIP returns the stack frame's offset into the function's
     * native code.  If this stack frame is active, this address is
     * the next instruction to execute.  If this stack frame is not
     * active, this is the next instruction to execute when the stack
     * frame is reactivated.
     */

    HRESULT GetIP([out] ULONG32 *pnOffset);

    /*
     * SetIP sets the instruction pointer to the given native
     * offset. CorDebug will attempt to keep the stack frame in a
     * coherent state.  (Note that even if the frame is in a valid
     * state as far as the runtime is concerned, there still may be
     * problems - e.g. uninitialized local variables, etc.  The caller
     * (or perhaps the user) is responsible for insuring coherency of
     * the running program.)
     *
     * Calling SetIP immediately invalidates all frames and chains for the
     * current thread; the debugger must perform a new stack trace if it
     * requires frame information after calling SetIP.
     */

    HRESULT SetIP([in] ULONG32 nOffset);

    /*
     * GetRegisterSet returns the register set for the given frame.
     *
     */

    HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters);

    /*
     * GetLocalRegisterValue gets the value for a local variable or
     * argument stored in a register of a native frame. This can be
     * used either in a native frame or a jitted frame.
     */

    HRESULT GetLocalRegisterValue([in] CorDebugRegister reg,
                                  [in] ULONG cbSigBlob,
                                  [in] PCCOR_SIGNATURE pvSigBlob,
                                  [out] ICorDebugValue **ppValue);

    /*
     * GetLocalDoubleRegisterValue gets the value for a local variable
     * or argument stored in 2 registers of a native frame. This can
     * be used either in a native frame or a jitted frame.
     */

    HRESULT GetLocalDoubleRegisterValue([in] CorDebugRegister highWordReg,
                                        [in] CorDebugRegister lowWordReg,
                                        [in] ULONG cbSigBlob,
                                        [in] PCCOR_SIGNATURE pvSigBlob,
                                        [out] ICorDebugValue **ppValue);

    /*
     * GetLocalMemoryValue gets the value for a local variable stored
     * at the given address.
     */

    HRESULT GetLocalMemoryValue([in] CORDB_ADDRESS address,
                                [in] ULONG cbSigBlob,
                                [in] PCCOR_SIGNATURE pvSigBlob,
                                [out] ICorDebugValue **ppValue);

    /*
     * GetLocalRegisterMemoryValue gets the value for a local which
     * is stored half in a register and half in memory.
     */

    HRESULT GetLocalRegisterMemoryValue([in] CorDebugRegister highWordReg,
                                        [in] CORDB_ADDRESS lowWordAddress,
                                        [in] ULONG cbSigBlob,
                                        [in] PCCOR_SIGNATURE pvSigBlob,
                                        [out] ICorDebugValue **ppValue);

    /*
     * GetLocalMemoryRegisterValue gets the value for a local which
     * is stored half in a register and half in memory.
     */

    HRESULT GetLocalMemoryRegisterValue([in] CORDB_ADDRESS highWordAddress,
                                        [in] CorDebugRegister lowWordRegister,
                                        [in] ULONG cbSigBlob,
                                        [in] PCCOR_SIGNATURE pvSigBlob,
                                        [out] ICorDebugValue **ppValue);
    /*
     * CanSetIP attempts to determine if it's safe to set the instruction pointer
     * to the given native offset. If this returns S_OK, then executing
     * SetIP (see above) will result in a safe, correct, continued execution.
     * If CanSetIP returns anything else, SetIP can still be invoked, but
     * continued, correct execution of the debuggee cannot be guaranteed.
     *
     */

    HRESULT CanSetIP([in] ULONG32 nOffset);
};

#pragma warning(push)
#pragma warning(disable:28718)	/* suppress warning 28718 for interface ICorDebugModule */
[
    object,
    local,
    uuid(35389FF1-3684-4c55-A2EE-210F26C60E5E),
    pointer_default(unique)
]
interface ICorDebugNativeFrame2 : IUnknown
{
    /*
     * Returns true if the current frame is a child frame.
     */
    HRESULT IsChild([out] BOOL *pIsChild);

    /*
     * Return true if the specified frame is the parent frame of the current frame.
     */
    HRESULT IsMatchingParentFrame([in] ICorDebugNativeFrame2 *pPotentialParentFrame,
                                  [out] BOOL *pIsParent);

    /*
     * Return the stack parameter size on x86.  On other platforms, we return S_FALSE and set pSize to 0.
     * This is because other platforms don't need this information for unwinding.
     */
    HRESULT GetStackParameterSize([out] ULONG32 * pSize);
};

/*
 * ICorDebugModule3 is a logical extension to ICorDebugModule.
 */
[
    object,
    local,
    uuid(86F012BF-FF15-4372-BD30-B6F11CAAE1DD),
    pointer_default(unique)
]
interface ICorDebugModule3 : IUnknown
{
    /*
     * CreateReaderForInMemorySymbols creates a debug symbol reader object (eg. 
     * ISymUnmanagedReader) for a dynamic module.  This symbol reader becomes stale
     * and is usually discarded whenever a LoadClass callback is delivered for the
     * module.
     *
     * Arguments:
     *    riid - The IID of the COM interface to return (typically IID_ISymUnmanagedReader)
     *   ppObj - Where to store the reader interface.
     *
     * Return Value:
     *   S_OK on success
     *   Error hresults otherwise, including:
     *   CORDBG_E_MODULE_LOADED_FROM_DISK if this isn't an in-memory or dynamic module
     *   CORDBG_E_SYMBOLS_NOT_AVAILABLE if symbols weren't supplied by the application or aren't
     *      yet available.
     *
     * Notes:
     *   This API can also be used to create a symbol reader object for in-memory 
     *   (non-dynamic) modules, but only after the symbols are first available
     *   (indicated by the UpdateModuleSymbols callback).
     *
     *   This API returns a new reader instance every time it is called (like CoCreateInstance)
     *   and so the debugger should cache the result and only request a new one when
     *   the underlying data may have changed (i.e. a LoadClass event).
     *
     *   Dynamic modules do not have any symbols available until the first type has been
     *   loaded into them (as indicated by the LoadClass callback).  
     */
    HRESULT CreateReaderForInMemorySymbols([in] REFIID riid,
                                           [out][iid_is(riid)] void **ppObj);
}

/*
 * ICorDebugRuntimeUnwindableFrame is a specialized interface of ICorDebugFrame for unmanaged methods
 * which requires special knowledge to unwind.  They are not jitted code.  When the debugger sees this type
 * of frames, it should use ICorDebugStackWalk::Next() to unwind, but it should do inspection itself.
 * The debugger can call ICorDebugStackWalk::GetContext() to retrieve the CONTEXT of the frame when it gets 
 * an ICorDebugRuntimeUnwindableFrame.
 */

[
    object,
    local,
    uuid(879CAC0A-4A53-4668-B8E3-CB8473CB187F),
    pointer_default(unique)
]
interface ICorDebugRuntimeUnwindableFrame : ICorDebugFrame
{
}

/*
 * ICorDebugModule represents a Common Language Runtime module that is loaded into a
 * specific AppDomain.  Normally this is an executable or a DLL, but it may also be
 * some other file of a multi-module assembly.  There is an ICorDebugModule instance
 * for each AppDomain a module is loaded into, even in the case of shared modules like
 * mscorlib.
 */

[
    object,
    local,
    uuid(dba2d8c1-e5c5-4069-8c13-10a7c6abf43d),
    pointer_default(unique)
]
interface ICorDebugModule : IUnknown
{
    /*
     * GetProcess returns the process of which this module is a part.
     */

    HRESULT GetProcess([out] ICorDebugProcess **ppProcess);

    /*
     * GetBaseAddress returns the base address of the module.
     *
     * For modules loaded from NGEN images, the base address will be 0.
     */

    HRESULT GetBaseAddress([out] CORDB_ADDRESS *pAddress);

    /*
     * GetAssembly returns the assembly of which this module is a part.
     */

    HRESULT GetAssembly([out] ICorDebugAssembly **ppAssembly);

    /*
     * GetName returns a name identifying the module.
     *
     * For on-disk modules this is a full path.  For dynamic modules this 
     * is just the filename if one was provided.  Otherwise, and for other 
     * in-memory modules, this is just the simple name stored in the module's
     * metadata.
     */

    HRESULT GetName([in] ULONG32 cchName,
                    [out] ULONG32 *pcchName,
                    [out, size_is(cchName),
                    length_is(*pcchName)] WCHAR szName[]);

    /*
     * EnableJITDebugging controls whether the jitter preserves
     * debugging information for methods within this module.
     * If bTrackJITInfo is true, then the jitter preserves
     * mapping information between the IL version of a function and
     * the jitted version for functions in the module.  If bAllowJitOpts
     * is true, then the jitter will generate code with certain (JIT-specific)
     * optimizations.
     *
     * JITDebug is enabled by default for all modules loaded when the
     * debugger is active.  Programmatically enabling/disabling these
     * settings will override global settings.
     *
     */
    HRESULT EnableJITDebugging([in] BOOL bTrackJITInfo,
                               [in] BOOL bAllowJitOpts);

    /*
     * EnableClassLoadCallbacks controls whether on not LoadClass and
     * UnloadClass callbacks are called for the particular module.
     * For non-dynamic modules, they are off by default.
     * For dynamic modules, they are on by default and can not be disabled.
     */

    HRESULT EnableClassLoadCallbacks([in] BOOL bClassLoadCallbacks);

    /*
     * GetFunctionFromToken returns the ICorDebugFunction from
     * metadata information. Returns CORDBG_E_FUNCTION_NOT_IL if
     * called with a methodDef that does not refer to an IL method.
     * In the EnC case, this will return the most recent version of the function.
     */

    HRESULT GetFunctionFromToken([in] mdMethodDef methodDef,
                                 [out] ICorDebugFunction **ppFunction);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetFunctionFromRVA([in] CORDB_ADDRESS rva,
                               [out] ICorDebugFunction **ppFunction);

    /*
     * GetClassFromToken returns the ICorDebugClass from metadata information.
     */

    HRESULT GetClassFromToken([in] mdTypeDef typeDef,
                              [out] ICorDebugClass **ppClass);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT CreateBreakpoint([out] ICorDebugModuleBreakpoint **ppBreakpoint);

    /*
     * DEPRECATED
     */

    HRESULT GetEditAndContinueSnapshot([out] ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot);

    /*
     * Return a metadata interface pointer that can be used to examine the
     * metadata for this module.
     */
    HRESULT GetMetaDataInterface([in] REFIID riid, [out] IUnknown **ppObj);


    /*
     * Return the token for the Module table entry for this object.  The token
     * may then be passed to the meta data import api's.
     */
    HRESULT GetToken([out] mdModule *pToken);

    /*
     * If this is a dynamic module, IsDynamic sets *pDynamic to true, otherwise
     * sets *pDynamic to false.
     * Dynamic modules can continue to grow new classes (receive LoadClass callbacks) even after
     * the module is loaded.
     */
    HRESULT IsDynamic([out] BOOL *pDynamic);

    /*
     * GetGlobalVariableValue returns a value object for the given global
     * variable.
     */
    HRESULT GetGlobalVariableValue([in] mdFieldDef fieldDef,
                                   [out] ICorDebugValue **ppValue);

    /*
     * GetSize returns the size, in bytes, of the module.
     *
     * For modules loaded from NGEN images, the size will be 0.
     */
    HRESULT GetSize([out] ULONG32 *pcBytes);

    /*
     * If this is a module that exists only in the debuggee's memory,
     * then pInMemory will be set to TRUE. The Runtime supports
     * loading assemblies from raw streams of bytes. Such modules are
     * called "in memory" modules and they have no on-disk
     * representation.
     */
    HRESULT IsInMemory([out] BOOL *pInMemory);
};
#pragma warning(pop)

/*
 * ICorDebugModule2 is a logical extension to ICorDebugModule.
 */
[
    object,
    local,
    uuid(7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7),
    pointer_default(unique)
]
interface ICorDebugModule2 : IUnknown
{
    /*
     * SetUserCode sets the user-code status of all the functions on all the classes in
     * the module to bIsJustMyCode, except for the functions or classes in the tokens array,
     * which it sets to !bIsJustMyCode.
     * These settings erase all previous JMC settings in this module.
     * JMC status can be refined by calls to SetJMCStatus on the Class and Function.
     * Returns S_OK if all functions were set successfully,
     * CORDBG_E_FUNCTION_NOT_DEBUGGABLE if some function to be marked TRUE was not
     * debuggable.
     */
    HRESULT SetJMCStatus([in] BOOL bIsJustMyCode,
                        [in] ULONG32 cTokens,
                        [in, size_is(cTokens)] mdToken pTokens[]);

   /*
     * ApplyChanges is called to apply an Edit and Continue delta to the running process.
     * An EnC delta consists of a delta metadata blob (created by IMetadataEmit2::SaveDelta)
     * and a delta IL blob (a method body stream just like the one in an on disk assembly).
     * If this operation fails, the debug session is considered to be in an invalid state
     * and must be restarted.
     */
    HRESULT ApplyChanges([in] ULONG cbMetadata,
                         [in, size_is(cbMetadata)] BYTE pbMetadata[],
                         [in] ULONG cbIL,
                         [in, size_is(cbIL)] BYTE pbIL[]);

  /*
   * SetJITCompilerFlags sets the flags that control the JIT compiler. If the set of flags is invalid,
   * the function will fail. This function can only be called from within the true LoadModule callback
   * for the given module. Attempts to call it after this callback has been delivered or in a "faked"
   * LoadModule callback for debugger attach will fail.
   */

    HRESULT SetJITCompilerFlags( [in] DWORD dwFlags );

    /*
    * GetJITCompilerFlags gets the set of flags that control the JIT compiler for this module.
    */

    HRESULT GetJITCompilerFlags( [out] DWORD *pdwFlags );

    /*
     * Resolve an assembly given an AssemblyRef token. Note that
     * this will not trigger the loading of assembly. If assembly is not yet loaded,
     * this will return an CORDBG_E_CANNOT_RESOLVE_ASSEMBLY error
     *
    */
    HRESULT ResolveAssembly([in] mdToken tkAssemblyRef,
							[out] ICorDebugAssembly **ppAssembly);

};


/*
    ICorDebugFunction represents a managed function.
    In the non-EnC case, it is 1:1 with a methoddef metadata token.
    For EnC, each version of a function has its own ICorDebugFunction instance.
    EnCed functions keep the same metadata tokens, but will get new ICorDebugCode instances.

    ICorDebugFunction does not represent generic typeparameters. That means that there's
    an ICDFunction for Func<T>, but not for Func<string> or Func<Bar>. Get the generic
    parameters from ICorDebugIlFrame::EnumerateTypeParameters.
*/
[
    object,
    local,
    uuid(CC7BCAF3-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugFunction : IUnknown
{
    /*
     * GetModule returns the module for the function.
     */

    HRESULT GetModule([out] ICorDebugModule **ppModule);

    /*
     * GetClass returns the class for the function. Returns null if
     * the function is not a member.
     */

    HRESULT GetClass([out] ICorDebugClass **ppClass);

    /*
     * GetToken returns the metadata methodDef token for the function.
     */

    HRESULT GetToken([out] mdMethodDef *pMethodDef);

    /*
     * GetILCode returns the IL code for the function.  Returns null
     * if there is no IL code for the function.  Note that this will
     * get the IL code corresponding to this function's EnC version of
     * the code in the runtime, if this function has been EnC'd.
     */

    HRESULT GetILCode([out] ICorDebugCode **ppCode);

    /*
     * GetNativeCode returns the native code for the function.
     * Returns null if there is no native code for the function
     * (i.e. it is an IL function which has not been jitted)
     * If this function has been jitted multiple times (Eg, generics) this
     * will return a random Native Code object.
     */

    HRESULT GetNativeCode([out] ICorDebugCode **ppCode);

    /*
     * CreateBreakpoint creates a breakpoint at the start of the function.
     *
     */

    HRESULT CreateBreakpoint([out] ICorDebugFunctionBreakpoint **ppBreakpoint);

    /*
     * Returns the token for the local variable signature for this function.
     * If there is no signature (ie, the function doesn't have any local
     * variables), then mdSignatureNil will be returned.
     */

    HRESULT GetLocalVarSigToken([out] mdSignature *pmdSig);


    /*
     * Obtains the latest (largest) EnC version number for this function.
     * If this function has never been edited with EnC, this will return
     * the same value as ICorDebugFunction2::GetVersionNumber.
     */
     HRESULT GetCurrentVersionNumber([out] ULONG32 *pnCurrentVersion);
};

/*
    ICorDebugFunction2 is a logical extension to ICorDebugFunction.
*/
[
    object,
    local,
    uuid(EF0C490B-94C3-4e4d-B629-DDC134C532D8),
    pointer_default(unique)
]
interface ICorDebugFunction2 : IUnknown
{
    /*
     * Sets the User-code status (for JMC stepping) for this function.
     * A JMC stepper will skip non-user code.
     * User code must be a subset of debuggable code.
     * Returns S_OK if successful, CORDBG_E_FUNCTION_NOT_DEBUGGABLE
     * if bIsJustMyCode is TRUE and the function is not debuggable.
     */
    HRESULT SetJMCStatus([in] BOOL bIsJustMyCode);

    /*
     * IsUserCode outputs whether the function is marked as user code.
     * Always outputs FALSE for non-debuggable functions.
     * Returns S_OK if successful.
     */
    HRESULT GetJMCStatus([out] BOOL * pbIsJustMyCode);

    /*
     *    Not yet implemented.
     */

    HRESULT EnumerateNativeCode([out] ICorDebugCodeEnum **ppCodeEnum);

    /*
     * Obtains the EnC version number of the function represented by this ICorDebugFunction2.
     * When a function is edited with EnC, the new function has a larger version number than
     * that of any previous version (not necessarily exactly 1 greater).
     * This function's version number will be less than or equal to the value returned by
     * ICorDebugFunction::GetCurrentVersionNumber.
     */

     HRESULT GetVersionNumber([out] ULONG32 *pnVersion);
};

/*
    ICorDebugCode represents an IL or native code blob.
 
    For methods that take offsets, the units are the same as the units on the CordbCode object.
    (eg, IL offsets for an IL code object, and native offsets for a native code object)
 
    V2 allows multiple code-regions. CordbCode presents an abstraction where these
    are merged together in a single linear, continuous space. So if the code is split
    with 0x5 bytes at address 0x1000, and 0x10 bytes at address 0x2000, 
    then:
    - GetAddress() yields a start address of 0x1000.
    - GetSize() is the size of the merged regions = 0x5+ 0x10 = 0x15 bytes.
    - The (Offset --> Address) mapping is:
           0x0  --> 0x1000
           0x1  --> 0x1001
           0x4  --> 0x1004
           0x5  --> 0x2000
           0x6  --> 0x2001
           0x15 --> 0x2010

    A caller can get the specific code regions via ICorDebugCode2.
*/
[
    object,
    local,
    uuid(CC7BCAF4-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugCode : IUnknown
{
    /*
     * IsIL returns whether the code is IL (as opposed to native.)
     */

    HRESULT IsIL([out] BOOL *pbIL);

    /*
     * GetFunction returns the function for the code.
     */

    HRESULT GetFunction([out] ICorDebugFunction **ppFunction);

    /*
     * GetAddress returns the address of the code.
     */

    HRESULT GetAddress([out] CORDB_ADDRESS *pStart);

    /*
     * GetSize returns the size in bytes of the code.
     */

    HRESULT GetSize([out] ULONG32 *pcBytes);

    /*
     * CreateBreakpoint creates a breakpoint in the function at the
     * given offset. 
     *
     * If this code is IL code, and there is a jitted native version
     * of the code, the breakpoint will be applied in the jitted code
     * as well.  (The same is true if the code is later jitted.)
     *
     */

    HRESULT CreateBreakpoint([in] ULONG32 offset,
                             [out] ICorDebugFunctionBreakpoint **ppBreakpoint);

    /*
     * GetCode returns the code of the method, suitable for disassembly.  Note
     * that instruction boundaries aren't checked.
     * This glues together multiple code-regions into a single binary stream.
     * Caller must use ICorDebugCode2::GetCodeChunks to get (start,size) for
     * code chunks to be able to properly resolve addresses embedded in the instructions.
     */

    HRESULT GetCode([in] ULONG32 startOffset, [in] ULONG32 endOffset,
                    [in] ULONG32 cBufferAlloc,
                    [out, size_is(cBufferAlloc),
                          length_is(*pcBufferSize)] BYTE buffer[],
                    [out] ULONG32 *pcBufferSize);

    /*
     * GetVersionNumber returns the 1 based number identifying the
     * version of the code that this ICorDebugCode corresponds to.  The
     * version number is incremented each time the function is Edit-And-
     * Continue'd.
     */

    HRESULT GetVersionNumber([out] ULONG32 *nVersion);

    /*
     * GetILToNativeMapping returns a map from IL offsets to native
     * offsets for this code. An array of COR_DEBUG_IL_TO_NATIVE_MAP
     * structs will be returned, and some of the ilOffsets in this array
     * map be the values specified in CorDebugIlToNativeMappingTypes.
     *
     * Note: this method is only valid for ICorDebugCodes representing
     * native code that was jitted from IL code.
     * Note: There is no ordering to the array of elements returned, nor
     * should you assume that there is or will be.
     */
    HRESULT GetILToNativeMapping([in] ULONG32 cMap,
                                 [out] ULONG32 *pcMap,
                                 [out, size_is(cMap), length_is(*pcMap)]
                                 COR_DEBUG_IL_TO_NATIVE_MAP map[]);

    /*
     * Not implemented.
     */
    HRESULT GetEnCRemapSequencePoints([in] ULONG32 cMap,
                                      [out] ULONG32 *pcMap,
                                      [out, size_is(cMap), length_is(*pcMap)]
                                      ULONG32 offsets[]);
};

[
    object,
    local,
    uuid(5F696509-452F-4436-A3FE-4D11FE7E2347),
    pointer_default(unique)
]
interface ICorDebugCode2 : IUnknown
{
    typedef struct _CodeChunkInfo
    {
        CORDB_ADDRESS startAddr;
        ULONG32 length;
    } CodeChunkInfo;

    // The native code for a code object may be split up into multiple regions.
    //
    HRESULT GetCodeChunks(
        [in] ULONG32 cbufSize,
        [out] ULONG32 * pcnumChunks,
        [out, size_is(cbufSize), length_is(*pcnumChunks)] CodeChunkInfo chunks[]);


   // GetCompilerFlags returns the flags under which this piece of code was JITted or NGENed.

   HRESULT GetCompilerFlags( [out] DWORD *pdwFlags );
};


/*
 ICorDebugClass represents a Class (mdTypeDef) in the IL image.
 For generic types, it represents the generic type definition (eg. List<T>) not any of 
 the specific instantiations (eg. List<int>). 
 
 Use ICorDebugClass2::GetParameterizedType to build an ICorDebugType from an
 ICorDebugClass and type parameters.

 Classes live in a module and are uniquely identified by a mdTypeDef. 
 In other words, you can round-trip a class like so:
    ICorDebugClass * pClass1 = ...; // some initial class
    
    ICorDebugModule * pModule = NULL;    
    pClass1->GetModule(&pModule);

    mdTypeDef token;
    pClass1->GetToken(&token);
    
    ICorDebugClass * pClass2;
    pModule->GetClassFromToken(token, &pClass2); 
    // Now: pClass1 == pClass2 

*/
[
    object,
    local,
    uuid(CC7BCAF5-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugClass : IUnknown
{
    /*
     * GetModule returns the module for the class.
     */

    HRESULT GetModule([out] ICorDebugModule **pModule);

    /*
     * GetTypeDefToken returns the metadata typedef token for the class.
     */

    HRESULT GetToken([out] mdTypeDef *pTypeDef);

    /*
     * GetStaticFieldValue returns a value object (ICorDebugValue) for the given static field
     * variable. If the static field could possibly be relative to either
     * a thread, context, or appdomain, then pFrame will help the debugger
     * determine the proper value.
     *
     * Note that if the class accepts type parameters, then you should
     * use GetStaticField on an appropriate ICorDebugType rather than on the
     * ICorDebugClass.
     * 
     * Returns:
     *  S_OK on success.
     *  CORDBG_E_FIELD_NOT_STATIC if the field is not static.
     *  CORDBG_E_STATIC_VAR_NOT_AVAILABLE if field is not yet available (storage for statics
     *    may be lazily allocated). 
     *  CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL if the field is actually a metadata literal. In this
     *    case, the debugger should get the value from the metadata.
     *  error on other errors.
     */

    HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef,
                                [in] ICorDebugFrame *pFrame,
                                [out] ICorDebugValue **ppValue);
};

[
    object,
    local,
    uuid(B008EA8D-7AB1-43f7-BB20-FBB5A04038AE),
    pointer_default(unique)
]
interface ICorDebugClass2 : IUnknown
{
    /*
     * GetParameterizedType returns a type that corresponds to this class.
     *
     * If the class is non-generic, i.e. has no type parameters, then
     * this simply gets the type object corresponding to the class.
     * elementType should be set to the correct element type for the
     * class, i.e. ELEMENT_TYPE_VALUETYPE if the class is a value type
     * otherwise ELEMENT_TYPE_CLASS.
     *
     * If the class accepts type parameters, e.g. ArrayList<T>, then
     * this function can be used to construct a type object for an
     * instantiated type such as ArrayList<int>.
     */
    HRESULT GetParameterizedType([in] CorElementType elementType,
                                 [in] ULONG32 nTypeArgs,
                                 [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[],
                                 [out] ICorDebugType **ppType);

    /*
     * Sets the User-code status (for JMC stepping) for all methods
     * in this class. This is functionally equivalent to setting the
     * JMCStatus onall methods in this class.
     * A JMC stepper will skip non-user code.
     * User code must be a subset of debuggable code.
     *
     * Returns S_OK if all methods are set succesfully.
     * Return failure if any are not set.
     * On failure, some may still be set.
     */
    HRESULT SetJMCStatus([in] BOOL bIsJustMyCode);

};

/* ------------------------------------------------------------------------- *
 * Function call interfaces
 * ------------------------------------------------------------------------- */

/*
 * ICorDebugEval collects functionality which requires running code
 * inside the debuggee. Note that the operations do not complete until
 * ICorDebugProcess::Continue is called, and the EvalComplete callback
 * is called.
 *
 * An ICorDebugEval object is created in the context of a specific
 * thread, which will be used to perform the evaluations.
 *
 * If you need to use this functionality without allowing other threads
 * to run, set the DebugState of the program's threads to STOP
 * before calling Continue.
 *
 * Note that since user code is running when the evaluation is in
 * progress, any debug events can occur, including class loads,
 * breakpoints, etc. Callbacks will be called normally in such a
 * case. The state of the Eval will be seen as part of the normal
 * program state inspection, the stack chain will be a CHAIN_FUNC_EVAL chain;
 * the full debugger API continues to operate as normal. Evals can even be nested.
 *
 * Also, the user code may never complete due to deadlock or infinite
 * looping. In this case you will need to Abort the Eval before
 * resuming the program.
 *
 * All objects and types used in a given func-eval must all reside within the
 * same app domain. That app-domain need not be the same as the current
 * app domain of the thread.
 *
 */

[
    object,
    local,
    uuid(CC7BCAF6-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugEval : IUnknown
{
    /*
     * CallFunction sets up a function call.  Note that if the function
     * is virtual, this will perform virtual dispatch.  If the function is
     * not static, then the first argument must be the "this" object.
     * If the function is in an a different AppDomain, a transition will 
     * occur (but all arguments must also be in the target AppDomain)
     */

    HRESULT CallFunction([in] ICorDebugFunction *pFunction,
                         [in] ULONG32 nArgs,
                         [in, size_is(nArgs)] ICorDebugValue *ppArgs[]);

    /*
     * NewObject allocates and calls the constructor for an object.
     */

    HRESULT NewObject([in] ICorDebugFunction *pConstructor,
                      [in] ULONG32 nArgs,
                      [in, size_is(nArgs)] ICorDebugValue *ppArgs[]);

    /*
     * NewObjectNoConstructor allocates a new object without
     * attempting to call any constructor on the object.
     */

    HRESULT NewObjectNoConstructor([in] ICorDebugClass *pClass);

    /*
     * NewString allocates a string object with the given contents.
     * The string is always created in the AppDomain the thread is currently in.
     */

    HRESULT NewString([in] LPCWSTR string);

    /*
     * NewArray allocates a new array with the given element type and
     * dimensions. If the elementType is a primitive, pElementClass
     * may be NULL. Otherwise, pElementClass should be the class of
     * the elements of the array. Note: lowBounds is optional. If
     * omitted, a zero lower bound for each dimension is assumed.
     * The array is always created in the AppDomain the thread is currently in.
     *
     * NOTE: In the current release, rank must be 1.
     */

    HRESULT NewArray([in] CorElementType elementType,
                     [in] ICorDebugClass *pElementClass,
                     [in] ULONG32 rank,
                     [in, size_is(rank)] ULONG32 dims[],
                     [in, size_is(rank)] ULONG32 lowBounds[]);

    /*
     * IsActive returns whether the func-eval is currently executing.
     */

    HRESULT IsActive([out] BOOL *pbActive);

    /*
     * Abort aborts the current computation.  Note that in the case of nested
     * Evals, this may fail unless it is the most recent Eval.
     */

    HRESULT Abort();

    /*
     * GetResult returns the result of the evaluation.  This is only
     * valid after the evaluation is completed.
     *
     * If the evaluation completes normally, the result will be the
     * return value.  If it terminates with an exception, the result
     * is the exception thrown. If the evaluation was for a new object,
     * the return value is the reference to the object.
     */

    HRESULT GetResult([out] ICorDebugValue **ppResult);

    /*
     * GetThread returns the thread on which this eval will run or is running.
     */

    HRESULT GetThread([out] ICorDebugThread **ppThread);

    /*
     * CreateValue creates an ICorDebugValue of the given type for the
     * sole purpose of using it in a function evaluation. These can be
     * used to pass user constants as parameters. The value has a zero
     * or NULL initial value. Use ICorDebugValue::SetValue to
     * set the value.
     *
     * pElementClass is only required for value classes. Pass NULL
     * otherwise.
     *
     * If elementType == ELEMENT_TYPE_CLASS, then you get an
     * ICorDebugReferenceValue representing the NULL object reference.
     * You can use this to pass NULL to evals that have object reference
     * parameters. You cannot set the ICorDebugReferenceValue to
     * anything... it always remains NULL.
     */

    HRESULT CreateValue([in] CorElementType elementType,
                        [in] ICorDebugClass *pElementClass,
                        [out] ICorDebugValue **ppValue);
};

[
    object,
    local,
    uuid(FB0D9CE7-BE66-4683-9D32-A42A04E2FD91),
    pointer_default(unique)
]
interface ICorDebugEval2 : IUnknown
{
    /*
     * CallParameterizedFunction is like CallFunction except the function
     * may be inside a class with type parameters, or may itself take type
     * parameters, or both.  The type arguments should be given for the
     * class first, then the function.
     *
     * If the function is in an a different AppDomain, a transition will occur.
     * However, all type and value arguments must be in the target AppDomain.
     *
     * Func-eval can only be performed in limited scenarios. If Call*Function
     * fails, then the HR makes a best effort at describing the most general
     * possible reason for failure.
     */

    HRESULT CallParameterizedFunction([in] ICorDebugFunction *pFunction,
                      [in] ULONG32 nTypeArgs,
                      [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[],
                      [in] ULONG32 nArgs,
                      [in, size_is(nArgs)] ICorDebugValue *ppArgs[]);

    /*
     * CreateValueForType generalizes CreateValue by allowing you to specify an
     * arbitrary object type including constructed types such as List<int>.
     * Once again the sole purpose is to generate a value to pass for a function evaluation.
     *
     * The element type of the type must be ELEMENT_TYPE_CLASS or
     * ELEMENT_TYPE_VALUE, or one of the simple types.  You cannot use this
     * to create array values or string values.
     */

    HRESULT CreateValueForType([in] ICorDebugType *pType,
                               [out] ICorDebugValue **ppValue);

    /*
    * NewParameterizedObject allocates and calls the constructor for an object.
    * The object may be in a class that includes type parameters.
    */

    HRESULT NewParameterizedObject([in] ICorDebugFunction *pConstructor,
                               [in] ULONG32 nTypeArgs,
                   [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[],
                           [in] ULONG32 nArgs,
                   [in, size_is(nArgs)] ICorDebugValue *ppArgs[]);

    /*
     * NewParameterizedObjectNoConstructor allocates a new object without
     * attempting to call any constructor on the object.
     * The object may be in a class that includes type parameters.
     */

    HRESULT NewParameterizedObjectNoConstructor([in] ICorDebugClass *pClass,
                        [in] ULONG32 nTypeArgs,
                        [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[]);

    /*
     * NewParamaterizedArray allocates a new array whose elements may be instances
     * of a generic type.  The array is always created in the AppDomain the thread is
     * currently in.
     */
    HRESULT NewParameterizedArray([in] ICorDebugType *pElementType,
                  [in] ULONG32 rank,
                  [in, size_is(rank)] ULONG32 dims[],
                  [in, size_is(rank)] ULONG32 lowBounds[]);

   /*
    * NewStringWithLength allocates a string object with the given contents.
    * The length is specified in uiLength. This is used for user to pass in null
    * embedded string. If the string's tailing null is expected to be in
    * the managed string, client has to ensure the length including the tailing null.
    *
    * The string is always created in the AppDomain the thread is currently in.
    */

    HRESULT NewStringWithLength([in] LPCWSTR string,
                               [in] UINT  uiLength);

    /*
     * RudeAbort aborts the current computation.  Any locks the aborted
     * eval was holding are not released, and thus the debugging session
     * is in an unsafe state.
     */

     HRESULT RudeAbort(void);

};


/* ------------------------------------------------------------------------- *
 * Runtime value interfaces
 * ------------------------------------------------------------------------- */

/*
 * ICorDebugValue represents a value in the remote process.  Note that
 * the values can be both Get and Set; they are "lvalues".
 *
 * In general, ownership of a value object is passed when it is returned. The
 * recipient is responsible for removing a reference from the object when
 * finished with it.
 *
 * Depending on where the value was retrieved from, the value may not remain
 * valid after the process is resumed,
 * so in general they shouldn't be held across continues.
 */

[
    object,
    local,
    uuid(CC7BCAF7-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugValue : IUnknown
{
    /*
     * GetType returns the simple type of the value.  If the object
     * has a more complex runtime type, that type may be examined through the
     * appropriate subclasses (e.g. ICorDebugObjectValue can get the class of
     * an object.)
     */

    HRESULT GetType([out] CorElementType *pType);

    /*
     * GetSize returns the size of the value in bytes. Note that for reference
     * types this will be the size of the pointer rather than the size of
     * the object.
     */

    HRESULT GetSize([out] ULONG32 *pSize);

    /*
     * GetAddress returns the address of the value in the debugee
     * process.  This might be useful information for the debugger to
     * show.
     *
     * If the value is unavailable, 0 is returned. This could happen if
     * it is at least partly in registers or stored in a GC Handle.
     */

    HRESULT GetAddress([out] CORDB_ADDRESS *pAddress);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT CreateBreakpoint([out] ICorDebugValueBreakpoint **ppBreakpoint);

};

[
    object,
    local,
    uuid(5E0B54E7-D88A-4626-9420-A691E0A78B49),
    pointer_default(unique)
]
interface ICorDebugValue2 : IUnknown
{
    /*
     * GetExactType returns the runtime type of the object in the value.
     */

    HRESULT GetExactType([out] ICorDebugType **ppType);

};

/*
 * ICorDebugGenericValue is a subclass of ICorDebugValue which applies to
 * all values, and can be used to get & set the value.  It is a
 * separate subinterface because it is non-remotable.
 *
 * Note that for reference types, the value is the reference rather than
 * the contents.
 */

[
    object,
    local,
    uuid(CC7BCAF8-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugGenericValue : ICorDebugValue
{
    /*
     * GetValue copies the value into the specified buffer.  The buffer should
     * be the appropriate size for the simple type.
     */

    HRESULT GetValue([out] void *pTo);

    /*
     * SetValue copies a new value from the specified buffer. The buffer should
     * be the approprirate size for the simple type.
     *
     */

    HRESULT SetValue([in] void *pFrom);
};

/* ISSUE: an remotable interface for each simple type
 *
 * It might be nice to have a subclass with a typesafe Get/Set for each simple
 * type.
 */

/*
 * ICorDebugReferenceValue is a subclass of ICorDebugValue which applies to
 * a reference type.
 * The runtime may Garbage Collect objects once the debuggee is continued. The GC may
 * move objects around in memory.
 *
 * An ICorDebugReference will either cooperate with GCs such that its information is updated
 * after the GC, or it will be implicitly neutered before the GC.
 *
 * The ICorDebugReferenceValue inteface may be implicitly neutered after the debuggee
 * has been continued. The derived ICorDebugHandleValue is not neutered until explicitly
 * released or exposed.
 *
 */

[
    object,
    local,
    uuid(CC7BCAF9-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugReferenceValue : ICorDebugValue
{
    /*
     * IsNull tests whether the reference is null.
     */

    HRESULT IsNull([out] BOOL *pbNull);

    /*
     * GetValue returns the current address of the object referred to by this
     * reference.
     */

    HRESULT GetValue([out] CORDB_ADDRESS *pValue);

    /*
     * SetValue sets this reference to refer to a different address.
     */

    HRESULT SetValue([in] CORDB_ADDRESS value);

    /*
     * Dereference returns a ICorDebugValue representing the value
     * referenced. This is only valid while the interface has not yet been neutered.
     */

    HRESULT Dereference([out] ICorDebugValue **ppValue);

    /*
     * DEPRECATED
     */

    HRESULT DereferenceStrong([out] ICorDebugValue **ppValue);
};

/*
 * ICorDebugHeapValue is a subclass of ICorDebugValue which represents
 * a garbage collected object
 */

[
    object,
    local,
    uuid(CC7BCAFA-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugHeapValue : ICorDebugValue
{
    /*
     * DEPRECATED.
     * All objects are only valid until Continue is called, at which time they are neutered.
     */

    HRESULT IsValid([out] BOOL *pbValid);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT CreateRelocBreakpoint([out]
                                  ICorDebugValueBreakpoint **ppBreakpoint);

};

/*
 * ICorDebugHeapValue2
 */

[
    object,
    local,
    uuid(E3AC4D6C-9CB7-43e6-96CC-B21540E5083C),
    pointer_default(unique)
]
interface ICorDebugHeapValue2 : IUnknown
{

    /*
      * Creates a handle of the given type for this heap value.
      *
      */
    HRESULT CreateHandle([in] CorDebugHandleType type, [out] ICorDebugHandleValue ** ppHandle);

};

/*
 * ICorDebugHeapValue3 - exposes the monitor lock properties of objects
 */

[
    object,
    local,
    uuid(A69ACAD8-2374-46e9-9FF8-B1F14120D296),
    pointer_default(unique)
]
interface ICorDebugHeapValue3 : IUnknown
{

    /* 
     * Gets the owning thread for a monitor lock
     */
    HRESULT GetThreadOwningMonitorLock([out] ICorDebugThread **ppThread, [out] DWORD *pAcquisitionCount);

    /*
     * Gets the list of threads waiting on a monitor event
     */
    HRESULT GetMonitorEventWaitList([out] ICorDebugThreadEnum **ppThreadEnum);
};

/*
 * ICorDebugObjectValue is a subclass of ICorDebugValue which applies to
 * values which contain an object.
 * An ICorDebugObjectValue becomes invalid after the debuggee is continued.
 */

[
    object,
    local,
    uuid(18AD3D6E-B7D2-11d2-BD04-0000F80849BD),
    pointer_default(unique)
]
interface ICorDebugObjectValue : ICorDebugValue
{
    /*
     * GetClass returns the runtime class of the object in the value.
     */

    HRESULT GetClass([out] ICorDebugClass **ppClass);

    /*
     * GetFieldValue returns a value for the given field in the given
     * class. The class must be on the class hierarchy of the object's
     * class, and the field must be a field of that class.
     */

    HRESULT GetFieldValue([in] ICorDebugClass *pClass,
                          [in] mdFieldDef fieldDef,
                          [out] ICorDebugValue **ppValue);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetVirtualMethod([in] mdMemberRef memberRef,
                             [out] ICorDebugFunction **ppFunction);

    /*
     * NOT YET IMPLEMENTED
     */

    HRESULT GetContext([out] ICorDebugContext **ppContext);

    /*
     * IsValueClass returns true if the the class of this object is
     * a value class.
     */

    HRESULT IsValueClass([out] BOOL *pbIsValueClass);

    /*
     * DEPRECATED
     */

    HRESULT GetManagedCopy([out] IUnknown **ppObject);

    /*
     * DEPRECATED
     */

    HRESULT SetFromManagedCopy([in] IUnknown *pObject);
};

[
    object,
    local,
    uuid(49E4A320-4A9B-4eca-B105-229FB7D5009F),
    pointer_default(unique)
]
interface ICorDebugObjectValue2 : IUnknown
{
    /*
     * GetVirtualMethodForType returns the most derived function
     * for the given ref on this object.
     *
     * Note: not yet implemented.
     */

    HRESULT GetVirtualMethodAndType([in] mdMemberRef memberRef,
                                    [out] ICorDebugFunction **ppFunction,
                                    [out] ICorDebugType **ppType);
};

/*
 * ICorDebugBoxValue is a subclass of ICorDebugValue which
 * represents a boxed value class object.
 */

[
    object,
    local,
    uuid(CC7BCAFC-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugBoxValue : ICorDebugHeapValue
{
    /*
     * GetObject returns the value object which is in the box.
     */

    HRESULT GetObject([out] ICorDebugObjectValue **ppObject);
};

#pragma warning(push)
#pragma warning(disable:28718)	/* suppress warning 28718 for interface ICorDebugStringValue */
/*
 * ICorDebugStringValue is a subclass of ICorDebugValue which
 * applies to values which contain a string.  This interface
 * provides an easy way to get the string contents.
 */

[
    object,
    local,
    uuid(CC7BCAFD-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugStringValue : ICorDebugHeapValue
{
    /*
     * GetLength returns the number of characters in the string.
     */

    HRESULT GetLength([out] ULONG32 *pcchString);

    /*
     * GetString returns the contents of the string.
     */

    HRESULT GetString([in] ULONG32 cchString,
                      [out] ULONG32 *pcchString,
                      [out, size_is(cchString),
                      length_is(*pcchString)] WCHAR szString[]);
};
#pragma warning(pop)

/*
 * ICorDebugArrayValue is a subclass of ICorDebugValue which applies
 * to values which contain an array. This interface supports both
 * single and multidimension arrays.
 */

[
    object,
    local,
    uuid(0405B0DF-A660-11d2-BD02-0000F80849BD),
    pointer_default(unique)
]
interface ICorDebugArrayValue : ICorDebugHeapValue
{
    /*
     * GetElementType returns the simple type of the elements in the
     * array.
     */

    HRESULT GetElementType([out] CorElementType *pType);

    /*
     * GetRank returns the number of dimensions in the array.
     */

    HRESULT GetRank([out] ULONG32 *pnRank);

    /*
     * GetCount returns the total number of elements in the array.
     */

    HRESULT GetCount([out] ULONG32 *pnCount);

    /*
     * GetDimensions returns the dimensions of the array.
     */

    HRESULT GetDimensions([in] ULONG32 cdim,
                          [out, size_is(cdim),
                           length_is(cdim)] ULONG32 dims[]);

    /*
     * HasBaseIndicies returns whether or not the array has base indicies.
     * If the answer is no, then all dimensions have a base index of 0.
     */

    HRESULT HasBaseIndicies([out] BOOL *pbHasBaseIndicies);

    /*
     * GetBaseIndicies returns the base index of each dimension in
     * the array
     */

    HRESULT GetBaseIndicies([in] ULONG32 cdim,
                            [out, size_is(cdim),
                            length_is(cdim)] ULONG32 indicies[]);

    /*
     * GetElement returns a value representing the given element in the array.
     * The indices array must not be null.
     */

    HRESULT GetElement([in] ULONG32 cdim,
                       [in, size_is(cdim),
                        length_is(cdim)] ULONG32 indices[],
                       [out] ICorDebugValue **ppValue);
    /*
     * GetElementAtPosition returns the element at the given position,
     * treating the array as a zero-based, single-dimensional array.
     *
     * Multidimensional array layout follows the C++ style of array layout.
     */

    HRESULT GetElementAtPosition([in] ULONG32 nPosition,
                                 [out] ICorDebugValue **ppValue);
};


/*
 * ICorDebugHandleValue represents a reference value that the debugger has
 * explicitly created a GC handle to. It does not represent GC Handles in the debuggee process,

 * A normal ICorDebugReference becomes neutered after the debuggee has been
 * continued. A ICorDebugHandleValue will survive across continues and can be
 * dereferenced until the client explcitly disposes the handle.
 *
 *
 * ICorDebugHeapValu2::CreateHandle will create ICorDebugHandleValue
 */
[
    object,
    local,
    uuid(029596E8-276B-46a1-9821-732E96BBB00B),
    pointer_default(unique)
]
interface ICorDebugHandleValue : ICorDebugReferenceValue
{
    /*
      * returns the type of this handle.
      *
      */
    HRESULT GetHandleType([out] CorDebugHandleType *pType);


    /*
      * The final release of the interface will also dispose of the handle. This
      * API provides the ability for client to early dispose the handle.
      *
      */
    HRESULT Dispose();

};


/*
 * ICorDebugContext represents a context object.
 *
 * Interface TBD.
 */

[
    object,
    local,
    uuid(CC7BCB00-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugContext : ICorDebugObjectValue
{
};


/* ------------------------------------------------------------------------- *
 * Enum interfaces
 * ------------------------------------------------------------------------- */

/*
 * ICorDebugEnum is an abstract enumerator.
 */

[
    object,
    local,
    uuid(CC7BCB01-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugEnum : IUnknown
{
    /*
     * Moves the current position forward the given number of
     * elements.
     */
    HRESULT Skip([in] ULONG celt);

    /*
     * Sets the position of the enumerator to the beginning of the
     * enumeration.
     */
    HRESULT Reset();

    /*
     * Creates another enumerator with the same current position
     * as this one.
     */
    HRESULT Clone([out] ICorDebugEnum **ppEnum);

    /*
     * Gets the number of elements in the enumeration
     */
    HRESULT GetCount([out] ULONG *pcelt);
};

[
    object,
    local,
    uuid(CC7BCB02-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugObjectEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of objects in the enumeration.
     * The actual number of objects retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of objects retrieved is smaller
     * than the number of objects requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt),
                  length_is(*pceltFetched)]  CORDB_ADDRESS objects[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB03-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]

interface ICorDebugBreakpointEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of breakpoints in the enumeration.
     * The actual number of breakpoints retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of breakpoints retrieved is smaller
     * than the number of breakpoints requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugBreakpoint *breakpoints[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB04-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]

interface ICorDebugStepperEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of steppers in the enumeration.
     * The actual number of steppers retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of steppers retrieved is smaller
     * than the number of steppers requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugStepper *steppers[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB05-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugProcessEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of processes in the enumeration.
     * The actual number of processes retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of processes retrieved is smaller
     * than the number of processes requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugProcess *processes[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB06-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugThreadEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of threads in the enumeration.
     * The actual number of threads retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of threads retrieved is smaller
     * than the number of threads requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugThread *threads[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB07-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugFrameEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of frames in the enumeration.
     * The actual number of frames retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of frames retrieved is smaller
     * than the number of frames requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugFrame *frames[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB08-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugChainEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of chains in the enumeration.
     * The actual number of chains retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of chains retrieved is smaller
     * than the number of chains requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugChain *chains[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB09-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugModuleEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of modules in the enumeration.
     * The actual number of modules retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of modules retrieved is smaller
     * than the number of modules requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugModule *modules[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(CC7BCB0A-8A68-11d2-983C-0000F808342D),
    pointer_default(unique)
]
interface ICorDebugValueEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of values in the enumeration.
     * The actual number of values retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of values retrieved is smaller
     * than the number of values requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugValue *values[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(55E96461-9645-45e4-A2FF-0367877ABCDE),
    pointer_default(unique)
]
interface ICorDebugCodeEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of code objects in the enumeration.
     * The actual number of code objects retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of code objects retrieved is smaller
     * than the number of code objects requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugCode *values[],
                 [out] ULONG *pceltFetched);
};

[
    object,
    local,
    uuid(10F27499-9DF2-43ce-8333-A321D7C99CB4),
    pointer_default(unique)
]
interface ICorDebugTypeEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" number of types in the enumeration.
     * The actual number of types retrieved is returned in "pceltFetched".
     * Returns S_FALSE if the actual number of types retrieved is smaller
     * than the number of types requested.
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugType *values[],
                 [out] ULONG *pceltFetched);
};



/*
 * ICorDebugType represents an instantiated type in the debugggee.
 * Unlike ICorDebugClass, it can store type-parameter information and thus can
 * represent instantiated generic types (Eg, List<int>)
 * Use the metadata interfaces to get static (Compile-time) information about the type.
 *
 * A type (and all of its type parameters) lives in an single AppDomain and becomes 
 * invalid once the containing ICorDebugAppDomain is unloaded.
 *
 * Types may be lazily loaded, so if the debugger queries for a type that hasn't been
 * loaded yet, it may be unavailable.
 */
[
    object,
    local,
    uuid(D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5),
    pointer_default(unique)
]
interface ICorDebugType : IUnknown
{
    /*
    * GetType gets the basic type of the generic parameter.  This can be used to
    * determine if it is necessary to call GetClass to find the full information for the
    * generic type parameter.
    */
    HRESULT GetType([out] CorElementType *ty);

    /*
    * GetClass is used if the CorElementType returned by GetType is ELEMENT_TYPE_CLASS,
    * ELEMENT_TYPE_VALUETYPE.  If the type is a constructed type, e.g. List<String>,
    * then this will return the ICorDebugClass for the type constructor, i.e. "List<T>".
    *
    * GetClass should not be used if the element type is anything other than these two element
    * types.  In particular, it may not be used if the element type is ELEMENT_TYPE_STRING.
    */
    HRESULT GetClass([out] ICorDebugClass **ppClass);

    /*
    * EnumerateTypeParameters may be used if the CorElementType
        * returned by GetType is one of ELEMENT_TYPE_CLASS,
        * ELEMENT_TYPE_VALUETYPE, ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY,
    * ELEMENT_TYPE_BYREF, ELEMENT_TYPE_PTR or ELEMENT_TYPE_FNPTR.
        * It returns the parameters specifying further information about
        * the type.  For example, if the type is "class Dict<String,int32>"
    * then EnumerateTypeParameters will return "String" and "int32"
        * in sequence.
    *
     */
    HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum);

    /*
    * GetFirstTypeParameter can be used in those cases where the further
        * information about the type involves at most one type
    * parameter.  You can determine this from the element type returned by
        * GetType.  In particular it may be used with
        * ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY, ELEMENT_TYPE_BYREF
        * or ELEMENT_TYPE_PTR.
     * This can only be called if the type does indeed have a type-parameter.
    */
    HRESULT GetFirstTypeParameter([out] ICorDebugType **value);

    /*
     * GetBase returns the ICorDebugType object for the base type of this type, if it
     * has one, i.e. if the type is a class type.
     * For example, if
     *        class MyStringDict<T> : Dict<String,T>
     * then the base type of "MyStringDict<int32>" will be "Dict<String,int32>".
     *
     * This is a helper function - you could compute this from EnumerateTypeParemeters,
     * GetClass and the relevant metadata, but it is relatively painful: you would
     * have to lookup the class, then the metadata of that class
     * to find the "generic" base type, then instantiate this generic base type by
     * looking up the type paramaters to the initial type,
     * and then perform the appropriate instantiation in the case where the class
     * happens to be either a generic class or a normal class with a constructed type
     * as its parent.  Looking up the base types is useful to implement common
     * debugger functionality, e.g. printing out all the fields of an object, including its
     * superclasses.
     *
     */

    HRESULT GetBase([out] ICorDebugType **pBase);

    /*
     * GetStaticFieldValue returns a value object (ICorDebugValue)
         * for the given static field variable. For non-parameterized
         * types, this is identical to calling GetStaticFieldValue on the
         * ICorDebugClass object returned by ICorDebugType::GetClass.
         * For parameterized types a static field value will be relative to a
         * particular instantiation.  If in addition the static field could
         * possibly be relative to either a thread, context, or appdomain, then pFrame
         * will help the debugger determine the proper value.
         *
         * This may only be used when ICorDebugType::GetType returns
         * ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE.
     */
    HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef,
                                    [in] ICorDebugFrame *pFrame,
                            [out] ICorDebugValue **ppValue);


    /*
     * GetRank returns the number of dimensions in an array type
     */

    HRESULT GetRank([out] ULONG32 *pnRank);

};


/* ------------------------------------------------------------------------- *
 * DEPRECATED
 *
 * ICorDebugErrorInfoEnum interface
 *
 * ------------------------------------------------------------------------- */
[
    object,
    local,
    uuid(F0E18809-72B5-11d2-976F-00A0C9B4D50C),
    pointer_default(unique)
]
interface ICorDebugErrorInfoEnum : ICorDebugEnum
{
    /*
     * DEPRECATED
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugEditAndContinueErrorInfo *errors[],
                 [out] ULONG *pceltFetched);
};

/* ------------------------------------------------------------------------- *
 * AppDomainEnum interface
 * ------------------------------------------------------------------------- */

[
    object,
    local,
    uuid(63ca1b24-4359-4883-bd57-13f815f58744),
    pointer_default(unique)
]

interface ICorDebugAppDomainEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" app domains in the enumeration
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugAppDomain *values[],
                 [out] ULONG *pceltFetched);

};


/* ------------------------------------------------------------------------- *
 * AssemblyEnum interface
 * ------------------------------------------------------------------------- */

[
    object,
    local,
    uuid(4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83),
    pointer_default(unique)
]

interface ICorDebugAssemblyEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" assemblies in the enumeration
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                    ICorDebugAssembly *values[],
                 [out] ULONG *pceltFetched);

};

/* ------------------------------------------------------------------------- *
 * BlockingObjectEnum interface
 * ------------------------------------------------------------------------- */

[
    object,
    local,
    uuid(976A6278-134A-4a81-81A3-8F277943F4C3),
    pointer_default(unique)
]

interface ICorDebugBlockingObjectEnum : ICorDebugEnum
{
    /*
     * Gets the next "celt" blocking objects in the enumeration
     */
    HRESULT Next([in] ULONG celt,
                 [out, size_is(celt), length_is(*pceltFetched)]
                 CorDebugBlockingObject values[],
                 [out] ULONG *pceltFetched);

};


#pragma warning(push)
#pragma warning(disable:28718)
// Represent data for an Managed Debugging Assistant (MDA) notification. See the MDA documentation for MDA-specific information like:
// - enabling / disabling MDAs
// - MDA naming conventions
// - What the contents of an MDA look like, schemas, etc.
[
    object,
    local,
    uuid(CC726F2F-1DB7-459b-B0EC-05F01D841B42),
    pointer_default(unique)
]
interface ICorDebugMDA : IUnknown
{
    // Get the string for the type of the MDA. Never empty.
    // This is a convenient performant alternative to getting the XML stream and extracting
    // the type from that based off the schema.
    HRESULT GetName(
        [in] ULONG32 cchName,
        [out] ULONG32 * pcchName,
        [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]);

    // Get a string description of the MDA. This may be empty (0-length).
    HRESULT GetDescription(
        [in] ULONG32 cchName,
        [out] ULONG32 * pcchName,
        [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]);

    // Get the full associated XML for the MDA. This may be empty.
    // This could be a potentially expensive operation if the xml stream is large.
    // See the MDA documentation for the schema for this XML stream.
    HRESULT GetXML(
        [in] ULONG32 cchName,
        [out] ULONG32 * pcchName,
        [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]);

    // Get the flags associated w/ the MDA. New flags may be added in future versions.
    typedef enum CorDebugMDAFlags
    {
	// If this flag is high, then the thread may have slipped since the MDA was fired. 
	MDA_FLAG_SLIP = 0x2
    } CorDebugMDAFlags;
    HRESULT GetFlags([in] CorDebugMDAFlags * pFlags);

    // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a
    // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread
    // object for it yet)
    HRESULT GetOSThreadId([out] DWORD * pOsTid);
};
#pragma warning(pop)

/* ------------------------------------------------------------------------- *
 * Edit and Continue interfaces
 * DEPRECATED
 * ------------------------------------------------------------------------- */
#pragma warning(push)
#pragma warning(disable:28718)	/* suppress warning 28718 for interface ICorDebugEditAndContinueErrorInfo */
/*
 * DEPRECATED
 *
 * ICorDebugEditAndContinueErrorInfo
 *
 */
[
    object,
    local,
    uuid(8D600D41-F4F6-4cb3-B7EC-7BD164944036),
    pointer_default(unique)
]
interface ICorDebugEditAndContinueErrorInfo : IUnknown
{
    /*
     * DEPRECATED
     */
    HRESULT GetModule([out] ICorDebugModule **ppModule);

    /*
     * DEPRECATED
     */
    HRESULT GetToken([out]mdToken *pToken);

    /*
     * DEPRECATED
     */
    HRESULT GetErrorCode([out]HRESULT *pHr);

    /*
     * DEPRECATED
     */
    HRESULT GetString([in] ULONG32 cchString,
                      [out] ULONG32 *pcchString,
                      [out, size_is(cchString),
                      length_is(*pcchString)] WCHAR szString[]);
}
#pragma warning(pop)

/*
 * DEPRECATED
 *
 * ICorDebugEditAndContinueSnapshot
 */

[
    object,
    local,
    uuid(6DC3FA01-D7CB-11d2-8A95-0080C792E5D8),
    pointer_default(unique)
]
interface ICorDebugEditAndContinueSnapshot : IUnknown
{
    /*
     * DEPRECATED
     */
    HRESULT CopyMetaData([in] IStream *pIStream, [out] GUID *pMvid);

    /*
     * DEPRECATED
     */
    HRESULT GetMvid([out] GUID *pMvid);

    /*
     * DEPRECATED
     */
    HRESULT GetRoDataRVA([out] ULONG32 *pRoDataRVA);

    /*
     * DEPRECATED
     */
    HRESULT GetRwDataRVA([out] ULONG32 *pRwDataRVA);


    /*
     * DEPRECATED
     */
    HRESULT SetPEBytes([in] IStream *pIStream);

    /*
     * DEPRECATED
     */
    HRESULT SetILMap([in] mdToken mdFunction, [in] ULONG cMapSize,
                     [in, size_is(cMapSize)] COR_IL_MAP map[]);

    /*
     * DEPRECATED
     */
    HRESULT SetPESymbolBytes([in] IStream *pIStream);
};


/* ------------------------------------------------------------------------- *
 * Library definition
 * ------------------------------------------------------------------------- */

[
    uuid(53D13620-F417-11d1-9762-A63826A4F255),
    version(1.0),
    helpstring("Common Language Runtime Debugging 1.0 Type Library")
]
library CORDBLib
{
    importlib("stdole32.tlb");

    // There should be no co-class for V2.0 CorDebug at all.
    // Clients should create the ICorDebug object using the shim API
    // CreateDebuggerInterfaceFromVersion defined in mscoree.idl.
    // This guid here is the same as the v1.1 guid for setup / breaking-change purposes.
    [
        uuid(6fef44d0-39e7-4c77-be8e-c9f8cf988630)
    ]
    coclass CorDebug
    {
        [default] interface ICorDebug;
    };

    [
        uuid(211f1254-bc7e-4af5-b9aa-067308d83dd1)
    ]
    coclass EmbeddedCLRCorDebug
    {
        [default] interface ICorDebug;
    };

    interface ICorDebugReferenceValue;
    interface ICorDebugStringValue;
    interface ICorDebugGenericValue;
    interface ICorDebugBoxValue;
    interface ICorDebugArrayValue;
    interface ICorDebugILFrame;
    interface ICorDebugInternalFrame;
    interface ICorDebugInternalFrame2;
    interface ICorDebugNativeFrame;
    interface ICorDebugNativeFrame2;
    interface ICorDebugRuntimeUnwindableFrame;

    interface ICorDebugManagedCallback2;
    interface ICorDebugAppDomain2;
    interface ICorDebugAssembly2;
    interface ICorDebugProcess2 ;
    interface ICorDebugStepper2 ;
    interface ICorDebugThread2 ;
    interface ICorDebugThread3 ;
    interface ICorDebugILFrame2;
    interface ICorDebugModule2 ;
    interface ICorDebugFunction2;
    interface ICorDebugClass2 ;
    interface ICorDebugEval2 ;
    interface ICorDebugValue2;
    interface ICorDebugObjectValue2;
    interface ICorDebugHandleValue;
    interface ICorDebugHeapValue2;

    interface ICorDebugModule3;
};
