context: //---------------------------------------------------------------------
  //  This file is part of the CLR Managed Debugger (mdbg) Sample.
  // 
  //  Copyright (C) Microsoft Corporation.  All rights reserved.
  //---------------------------------------------------------------------
  using System;
  using System.Collections;
  using System.Diagnostics;
  
  using Microsoft.Samples.Debugging.CorDebug.NativeApi;
  using System.Runtime.Serialization;
  
  namespace Microsoft.Samples.Debugging.CorDebug
  {
  
      public struct CorActiveFunction
      {
          public int ILoffset
          { 
              get 
              {
                  return m_ilOffset; 
              } 
          }
          private int m_ilOffset;
              
          public CorFunction Function
          { 
              get 
              {
                  return m_function; 
              } 
          }
          private CorFunction m_function;
              
          public CorModule Module
          { 
              get 
              {
                  return m_module; 
              } 
          }
          private CorModule m_module;
  
          internal CorActiveFunction(int ilOffset,CorFunction managedFunction,CorModule managedModule)
          {
              m_ilOffset = ilOffset;
              m_function = managedFunction;
              m_module = managedModule;
          }
      }
  
      public enum CorStackWalkType
      {
          PureV3StackWalk,        // true representation of the V3 ICorDebugStackWalk API
          ExtendedV3StackWalk     // V3 ICorDebugStackWalk API with internal frames interleaved
      }
  
      /** A thread in the debugged process. */
      public sealed class CorThread : WrapperBase
      {
          internal CorThread (ICorDebugThread thread)
              :base(thread)
          {
              m_th = thread;
          }
  
          internal ICorDebugThread GetInterface ()
          {
              return m_th;
          }
  
          
          /** The process that this thread is in. */
          public CorProcess Process
          {
              get 
              {
                  ICorDebugProcess p = null;
                  m_th.GetProcess (out p);
                  return CorProcess.GetCorProcess(p);
              }
          }
  
          /** the OS id of the thread. */
          public int Id
          {
              get 
              {
                  uint id = 0;
                  m_th.GetID (out id);
                  return (int) id;
              }
          }
  
          /** The handle of the active part of the thread. */
          public IntPtr Handle
          {
              get 
              {
                  IntPtr h = IntPtr.Zero;
                  m_th.GetHandle (out h);
                  return h;
              }
          }
  
          /** The AppDomain that owns the thread. */
          public CorAppDomain AppDomain
          {
              get 
              {
                  ICorDebugAppDomain ad = null;
                  m_th.GetAppDomain (out ad);
                  return new CorAppDomain (ad);
              }
          }
  
          /** Set the current debug state of the thread. */
          [CLSCompliant(false)]
          public CorDebugThreadState DebugState
          {
              get 
              {
                  CorDebugThreadState s = CorDebugThreadState.THREAD_RUN;
                  m_th.GetDebugState (out s);
                  return s;
              }
              set 
              {
                  m_th.SetDebugState (value);
              }
          }
  
          /** the user state. */
          [CLSCompliant(false)]
          public CorDebugUserState UserState
          {
              get 
              {
                  CorDebugUserState s = CorDebugUserState.USER_STOP_REQUESTED;
                  m_th.GetUserState (out s);
                  return s;
              }
          }
  
          /** the exception object which is currently being thrown by the thread. */
          public CorValue CurrentException
          {
              get 
              {
                  ICorDebugValue v = null;
                  m_th.GetCurrentException (out v);
                  return (v==null) ? null : new CorValue (v);
              }
          }
  
          /** 
           * Clear the current exception object, preventing it from being thrown.
           */
          public void ClearCurrentException ()
          {
              m_th.ClearCurrentException ();
          }
  
          /** 
           * Intercept the current exception.
           */
          public void InterceptCurrentException(CorFrame frame)
          {
              ICorDebugThread2 m_th2 = (ICorDebugThread2)m_th;
              m_th2.InterceptCurrentException(frame.m_frame);
          }
  
          /** 
           * create a stepper object relative to the active frame in this thread.
           */
          public CorStepper CreateStepper ()
          {
              ICorDebugStepper s = null;
              m_th.CreateStepper (out s);
              return new CorStepper (s);
          }
  
          /** All stack chains in the thread. */
          public IEnumerable Chains
          {
              get 
              {
                  ICorDebugChainEnum ec = null;
                  m_th.EnumerateChains (out ec);
                  return (ec==null)?null:new CorChainEnumerator (ec);
              }
          }
          
          /** The most recent chain in the thread, if any. */
          public CorChain ActiveChain
          {
              get 
              {
                  ICorDebugChain ch = null;
                  m_th.GetActiveChain (out ch);
                  return ch == null ? null : new CorChain (ch);
              }
          }
  
          /** Get the active frame. */
          public CorFrame ActiveFrame
          {
              get 
              {
                  ICorDebugFrame f = null;
                  m_th.GetActiveFrame (out f);
                  return f==null ? null : new CorFrame (f);
              }
          }
  
          /** Get the register set for the active part of the thread. */
          public CorRegisterSet RegisterSet
          {
              get 
              {
                  ICorDebugRegisterSet r = null;
                  m_th.GetRegisterSet (out r);
                  return r==null?null:new CorRegisterSet (r);
              }
          }
  
          /** Creates an evaluation object. */
          public CorEval CreateEval ()
          {
              ICorDebugEval e = null;
              m_th.CreateEval (out e);
              return e==null?null:new CorEval (e);
          }
  
          /** Get the runtime thread object. */
          public CorValue ThreadVariable
          {
              get 
              {
                  ICorDebugValue v = null;
                  m_th.GetObject (out v);
                  return new CorValue (v);
              }
          }
  
          public CorActiveFunction[] GetActiveFunctions()
          {
              ICorDebugThread2 m_th2 = (ICorDebugThread2) m_th;
              UInt32 pcFunctions;
              m_th2.GetActiveFunctions(0,out pcFunctions,null);
              COR_ACTIVE_FUNCTION[] afunctions = new COR_ACTIVE_FUNCTION[pcFunctions];
              m_th2.GetActiveFunctions(pcFunctions,out pcFunctions,afunctions);
              CorActiveFunction[] caf = new CorActiveFunction[pcFunctions];
              for(int i=0;i<pcFunctions;++i)
              {
                  caf[i] = new CorActiveFunction((int) afunctions[i].ilOffset,
                                                 new CorFunction((ICorDebugFunction)afunctions[i].pFunction),
                                                 afunctions[i].pModule==null?null:new CorModule(afunctions[i].pModule)
                                                 );
              }
              return caf;
          }
          private ICorDebugThread m_th;
  
      } /* class Thread */
  
  
  
      public enum CorFrameType
      {
          ILFrame, NativeFrame, InternalFrame,
      }
  
      
      public sealed class CorFrame : WrapperBase
      {
          internal CorFrame(ICorDebugFrame frame)
              :base(frame)
          {
              m_frame = frame;
          }
  
          
          public CorStepper CreateStepper()
          {
              ICorDebugStepper istepper;
              m_frame.CreateStepper(out istepper);
              return ( istepper==null ? null : new CorStepper(istepper) );
          }
  
          public CorFrame Callee
          {
              get 
              {
                  ICorDebugFrame iframe;
                  m_frame.GetCallee(out iframe);
                  return ( iframe==null ? null : new CorFrame(iframe) );
              }
          }
  
          public CorFrame Caller
          {
              get 
              {
                  ICorDebugFrame iframe;
                  m_frame.GetCaller(out iframe);
                  return ( iframe==null ? null : new CorFrame(iframe) );
              }
          }
  
          public CorChain Chain
          {
              get 
              {
                  ICorDebugChain ichain;
                  m_frame.GetChain(out ichain);
                  return ( ichain==null ? null : new CorChain(ichain) );
              }
          }
  
          public CorCode Code
          {
              get
              {
                  ICorDebugCode icode;
                  m_frame.GetCode(out icode);
                  return ( icode==null ? null : new CorCode(icode) );
              }
          }
  
          public CorFunction Function
          {
              get 
              {
                  ICorDebugFunction ifunction;
                  m_frame.GetFunction(out ifunction);
                  return ( ifunction==null ? null : new CorFunction(ifunction) );
              }
          }
  
          public int FunctionToken
          {
              get 
              {
                  uint token;
                  m_frame.GetFunctionToken(out token);
                  return (int)token;
              }
          }
  
          public CorFrameType FrameType
          {
              get 
              {
                  ICorDebugILFrame ilframe = GetILFrame();
                  if (ilframe != null)
                      return CorFrameType.ILFrame;
                  
                  ICorDebugInternalFrame iframe = GetInternalFrame();
                  if (iframe != null)
                      return CorFrameType.InternalFrame;
  
                  return CorFrameType.NativeFrame;
              }
          }
          
          [CLSCompliant(false)]
          public CorDebugInternalFrameType InternalFrameType
          {
              get
              {
                  ICorDebugInternalFrame iframe = GetInternalFrame();
                  CorDebugInternalFrameType ft;
                  
                  if(iframe==null)
                      throw new CorException("Cannot get frame type on non-internal frame");
                  
                  iframe.GetFrameType(out ft);
                  return ft;
              }
          }
  
      
          [CLSCompliant(false)]
          public void GetStackRange(out UInt64 startOffset,out UInt64 endOffset)
          {
              m_frame.GetStackRange(out startOffset,out endOffset);
          }
  
          [CLSCompliant(false)]
          public void GetIP(out uint offset, out CorDebugMappingResult mappingResult)
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if(ilframe==null) 
              {
                  offset = 0;
                  mappingResult = CorDebugMappingResult.MAPPING_NO_INFO;
              }
              else
                  ilframe.GetIP(out offset, out mappingResult);
          }
  
          public void SetIP(int offset)
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if(ilframe==null)
                  throw new CorException("Cannot set an IP on non-il frame");
              ilframe.SetIP((uint)offset);
          }
  
          public bool CanSetIP(int offset)
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if( ilframe==null )
                  return false;
              return (ilframe.CanSetIP((uint)offset)==(int)HResult.S_OK);
          }
  
          public bool CanSetIP(int offset, out int hresult)
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if( ilframe==null )
              {
                  hresult = (int)HResult.E_FAIL;
                  return false;
              }
              hresult = ilframe.CanSetIP((uint)offset);
              return (hresult==(int)HResult.S_OK);
          }
  
          [CLSCompliant(false)]
          public void GetNativeIP(out uint offset)
          {
              ICorDebugNativeFrame nativeFrame = m_frame as ICorDebugNativeFrame;
              Debug.Assert( nativeFrame!=null );
              nativeFrame.GetIP(out offset);
          }
      
          public CorValue GetLocalVariable(int index)
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if(ilframe==null)
                  return null;
              
              ICorDebugValue value;
              try
              {
                  ilframe.GetLocalVariable((uint)index,out value);
              }
              catch(System.Runtime.InteropServices.COMException e)
              {
                  // If you are stopped in the Prolog, the variable may not be available.
                  // CORDBG_E_IL_VAR_NOT_AVAILABLE is returned after dubugee triggers StackOverflowException
                  if(e.ErrorCode == (int)HResult.CORDBG_E_IL_VAR_NOT_AVAILABLE)
                  {
                      return null;
                  }
                  else
                  {
                      throw;
                  }
              }
              return (value==null)?null:new CorValue(value);
          }
  
          public int GetLocalVariablesCount()
          {
              ICorDebugILFrame ilframe = GetILFrame();
              if(ilframe==null)
                  return -1;
  
              ICorDebugValueEnum ve;
              ilframe.EnumerateLocalVariables(out ve);
              uint count;
              ve.GetCount(out count);
              return (int)count;
          }
  
          public CorValue GetArgument(int index)
          {
  
gt:             ICorDebugILFrame ilframe = GetILFrame();