private List<string> GetCallStack(CorThread thread)
        {
            List<string> stackTrace = new List<string>();

            foreach (CorFunctionFrame fnFrame in thread.StackFrames){
                if (fnFrame.Function != null) {
                   string funName = MetadataMgr.GetFullName(fnFrame.Function);
                    stackTrace.Add(funName);
                }
            }

            if (stackTrace.Count == 0){
                stackTrace.Add(thread.StackFailureReason);
            }
            return stackTrace;
        }
  internal void PostExceptionNotification(
      CorThread thread, 
      CorFunctionFrame frame, 
      Interfaces.CorDebugExceptionCallbackType exState, 
      uint offset
 )
  {
      if (m_ExceptionNotification == null) return;
      ExceptioNotificationResult expRes = new ExceptioNotificationResult();
      string strException = thread.ExceptionString;
      string sourceLine = string.Empty;
      if (frame.Function != null && exState == CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE){
          try{
              CorSourcePosition src = frame.Function.GetSourcePositionFromIP((int)offset);
              //expRes.SourceLine = GetCurrentSourceCode(src);
          }catch{
              /*Ignore*/
          }
      }
      expRes.ExceptionType = strException;
      expRes.StackTrace = GetCallStack(thread);
      expRes.ThreadID = thread.ID;
      switch (exState){
          case Interfaces.CorDebugExceptionCallbackType.DEBUG_EXCEPTION_FIRST_CHANCE:
          case Interfaces.CorDebugExceptionCallbackType.DEBUG_EXCEPTION_USER_FIRST_CHANCE:
              expRes.State = ExceptioNotificationResult.EXCEPTIONSTATE.FIRSTCHANCE; break;
          case Interfaces.CorDebugExceptionCallbackType.DEBUG_EXCEPTION_CATCH_HANDLER_FOUND:
              expRes.State = ExceptioNotificationResult.EXCEPTIONSTATE.HANDLED; break;
          case Interfaces.CorDebugExceptionCallbackType.DEBUG_EXCEPTION_UNHANDLED:
              expRes.State = ExceptioNotificationResult.EXCEPTIONSTATE.UNHANDLED;break;
      }
      ThreadPool.QueueUserWorkItem(
          new WaitCallback(SendNotifications),
          new InnerObject(m_ExceptionNotification, expRes)
          );
  }
        internal void PostBreakPoint(CorThread thread)
        {
            string moduleName = thread.ActiveFrame.Function.Module.Name;
            MetaType type = new MetaType(
                thread.ActiveFrame.Function.Module.Importer, (int)thread.ActiveFrame.Function.Class.Token);
            string className = type.Name;
            string methodName = type.FindMethod((int)thread.ActiveFrame.Function.Token).Name;

            methodName = methodName.Substring(methodName.LastIndexOf('.')+1);
            string identifier = BreakPointManager.getUID(moduleName, className, methodName);
            INotification notification = m_bpManger.GetNotificaiton(identifier);
            if (notification != null) {
                InnerObject innerObject
                    = new InnerObject(
                        notification,
                        new BreakPointNotificationResult(
                            m_ProcessID,
                            thread.ID,
                            moduleName,
                            className,
                            methodName));
                ThreadPool.QueueUserWorkItem(new WaitCallback(SendNotifications), innerObject);
            }
            //List<BreakPointInfo> m_bpManger.GetBreakPointInfo(identifier);
        }
 /// <summary>
 /// Returns a list of threads waiting for the monitor event associated with this object
 /// </summary>
 /// <returns>The list of waiting threads. The first thread in the list will be released on the
 /// next call to Monitor.Pulse, and each succesive call will release the next thread in the list</returns>
 public CorThread[] GetMonitorEventWaitList()
 {
     if (m_heapVal as ICorDebugHeapValue3 == null)
         throw new NotSupportedException();
     ICorDebugThreadEnum rawThreadEnum;
     (m_heapVal as ICorDebugHeapValue3).GetMonitorEventWaitList(out rawThreadEnum);
     uint threadCount;
     rawThreadEnum.GetCount(out threadCount);
     ICorDebugThread[] rawThreads = new ICorDebugThread[threadCount];
     uint countReceived;
     rawThreadEnum.Next(threadCount, rawThreads, out countReceived);
     Debug.Assert(countReceived == threadCount);
     CorThread[] threads = new CorThread[threadCount];
     for (int i = 0; i < threadCount; i++)
     {
         threads[i] = new CorThread(rawThreads[i]);
     }
     return threads;
 }
 void debug_ThreadNotification(CorDebugAppDomain app, CorThread thread, bool isAlive)
 {
     THREAD _thread = new THREAD();
     _thread.Id = thread.ID;
     _thread.ProcessId = debug.Process.ID;
     if (isAlive){
         _thread.State = THREADSTATE.RUNNING;
         liveThreads.Add(thread.ID, thread);
     } else {
         _thread.State = THREADSTATE.TERMINATED;
         liveThreads.Remove(thread.ID);
         deadThreads.Add(thread.ID, GetCallStack(thread));
     }
     ThreadNotification(_thread);
 }
 void debug_FuntionBreakPoint(CorThread thread)
 {
     BREAKPOINT bp = new BREAKPOINT();
     bp.Threadid = thread.ID;
     bp.frame = MetadataMgr.GetFullName(thread.StackFrames[0].Function);
     BreakPointFunctionNotifcation(bp);
 }