Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / debug / di / rsmain.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
5 // File: RsMain.cpp
6 // 
7
8 // Random RS utility stuff, plus root ICorCordbug implementation
9 //
10 //*****************************************************************************
11 #include "stdafx.h"
12 #include "primitives.h"
13 #include "safewrap.h"
14
15 #include "check.h"
16
17 #include <tlhelp32.h>
18 #include "wtsapi32.h"
19
20 #ifndef SM_REMOTESESSION
21 #define SM_REMOTESESSION 0x1000
22 #endif
23
24 #include "corpriv.h"
25 #include "../../dlls/mscorrc/resource.h"
26 #include <limits.h>
27
28
29 // The top level Cordb object is built around the Shim
30 #include "shimpriv.h"
31
32 //-----------------------------------------------------------------------------
33 // For debugging ease, cache some global values.
34 // Include these in retail & free because that's where we need them the most!!
35 // Optimized builds may not let us view locals & parameters. So Having these
36 // cached as global values should let us inspect almost all of
37 // the interesting parts of the RS even in a Retail build!
38 //-----------------------------------------------------------------------------
39
40 RSDebuggingInfo g_RSDebuggingInfo_OutOfProc = {0 }; // set to NULL
41 RSDebuggingInfo * g_pRSDebuggingInfo = &g_RSDebuggingInfo_OutOfProc;
42
43 // The following instances are used for invoking overloaded new/delete
44 forDbiWorker forDbi;
45
46 #ifdef _DEBUG
47 // For logs, we can print the string name for the debug codes.
48 const char * GetDebugCodeName(DWORD dwCode)
49 {
50     if (dwCode < 1 || dwCode > 9)
51     {
52         return "!Invalid Debug Event Code!";
53     }
54
55     static const char * const szNames[] = {
56         "(1) EXCEPTION_DEBUG_EVENT",
57         "(2) CREATE_THREAD_DEBUG_EVENT",
58         "(3) CREATE_PROCESS_DEBUG_EVENT",
59         "(4) EXIT_THREAD_DEBUG_EVENT",
60         "(5) EXIT_PROCESS_DEBUG_EVENT",
61         "(6) LOAD_DLL_DEBUG_EVENT",
62         "(7) UNLOAD_DLL_DEBUG_EVENT",
63         "(8) OUTPUT_DEBUG_STRING_EVENT"
64         "(9) RIP_EVENT",// <-- only on Win9X
65     };
66
67     return szNames[dwCode - 1];
68 }
69
70 #endif
71
72
73 //-----------------------------------------------------------------------------
74 // Per-thread state for Debug builds...
75 //-----------------------------------------------------------------------------
76 #ifdef RSCONTRACTS
77 DWORD DbgRSThread::s_TlsSlot = TLS_OUT_OF_INDEXES;
78 LONG DbgRSThread::s_Total = 0;
79
80 DbgRSThread::DbgRSThread()
81 {
82     m_cInsideRS         = 0;
83     m_fIsInCallback     = false;
84     m_fIsUnrecoverableErrorCallback = false;
85
86     m_cTotalDbgApiLocks = 0;
87     for(int i = 0; i < RSLock::LL_MAX; i++)
88     {
89         m_cLocks[i] = 0;
90     }
91
92     // Initialize Identity info
93     m_Cookie = COOKIE_VALUE;
94     m_tid = GetCurrentThreadId();
95 }
96
97 // NotifyTakeLock & NotifyReleaseLock are called by RSLock to update the per-thread locking context.
98 // This will assert if the operation is unsafe (ie, violates lock order).
99 void DbgRSThread::NotifyTakeLock(RSLock * pLock)
100 {
101     if (pLock->HasLock())
102     {
103         return;
104     }
105     
106     int iLevel = pLock->GetLevel();
107
108     // Is it safe to take this lock?
109     // Must take "bigger" locks first. We shouldn't hold any locks at our current level either.
110     // If this lock is re-entrant and we're double-taking it, we would have returned already.
111     // And the locking model on the RS forbids taking multiple locks at the same level.
112     for(int i = iLevel; i >= 0; i --)
113     {
114         bool fHasLowerLock = m_cLocks[i] > 0;
115         CONSISTENCY_CHECK_MSGF(!fHasLowerLock, (
116             "RSLock violation. Trying to take lock '%s (%d)', but already have smaller lock at level %d'\n",
117             pLock->Name(), iLevel,
118             i));
119     }
120
121     // Update the counts
122     _ASSERTE(m_cLocks[iLevel] == 0);
123     m_cLocks[iLevel]++;
124
125     if (pLock->IsDbgApiLock())
126         m_cTotalDbgApiLocks++;
127 }
128
129 void DbgRSThread::NotifyReleaseLock(RSLock * pLock)
130 {
131     if (pLock->HasLock())
132     {
133         return;
134     }
135     
136     int iLevel = pLock->GetLevel();
137     m_cLocks[iLevel]--;
138     _ASSERTE(m_cLocks[iLevel] == 0);
139
140     if (pLock->IsDbgApiLock())
141         m_cTotalDbgApiLocks--;
142
143     _ASSERTE(m_cTotalDbgApiLocks >= 0);
144 }
145
146 void DbgRSThread::TakeVirtualLock(RSLock::ERSLockLevel level)
147 {
148     m_cLocks[level]++;
149 }
150
151 void DbgRSThread::ReleaseVirtualLock(RSLock::ERSLockLevel level)
152 {
153     m_cLocks[level]--;
154     _ASSERTE(m_cLocks[level] >= 0);
155 }
156
157
158 // Get a DbgRSThread for the current OS thread id; lazily create if needed.
159 DbgRSThread * DbgRSThread::GetThread()
160 {
161     _ASSERTE(DbgRSThread::s_TlsSlot != TLS_OUT_OF_INDEXES);
162
163     void * p2 = TlsGetValue(DbgRSThread::s_TlsSlot);
164     if (p2 == NULL)
165     {
166         // We lazily create for threads that haven't gone through DllMain
167         // Since this is per-thread, we don't need to lock.
168         p2 = DbgRSThread::Create();
169     }
170     DbgRSThread * p = reinterpret_cast<DbgRSThread*> (p2);
171
172     _ASSERTE(p->m_Cookie == COOKIE_VALUE);
173
174     return p;
175 }
176
177
178
179 #endif // RSCONTRACTS
180
181
182
183
184
185
186 #ifdef _DEBUG
187 LONG CordbCommonBase::s_TotalObjectCount = 0;
188 LONG CordbCommonBase::s_CordbObjectUID = 0;
189
190
191 LONG CordbCommonBase::m_saDwInstance[enumMaxDerived];
192 LONG CordbCommonBase::m_saDwAlive[enumMaxDerived];
193 PVOID CordbCommonBase::m_sdThis[enumMaxDerived][enumMaxThis];
194
195 #endif
196
197 #ifdef _DEBUG_IMPL
198 // Mem tracking
199 LONG Cordb::s_DbgMemTotalOutstandingCordb            = 0;
200 LONG Cordb::s_DbgMemTotalOutstandingInternalRefs     = 0;
201 #endif
202
203 #ifdef TRACK_OUTSTANDING_OBJECTS
204 void *Cordb::s_DbgMemOutstandingObjects[MAX_TRACKED_OUTSTANDING_OBJECTS] = { NULL };
205 LONG Cordb::s_DbgMemOutstandingObjectMax = 0;
206 #endif
207
208 // Default implementation for neutering left-side resources.
209 void CordbBase::NeuterLeftSideResources()
210
211     LIMITED_METHOD_CONTRACT;   
212     
213     RSLockHolder lockHolder(GetProcess()->GetProcessLock());
214     Neuter();
215 }
216
217 // Default implementation for neutering.
218 // All derived objects should eventually chain to this.
219 void CordbBase::Neuter()
220 {
221     // Neutering occurs under the process lock. Neuter can be called twice
222     // and so locking protects against races in double-delete.
223     // @dbgtodo - , some CordbBase objects (Cordb, CordbProcessEnum),
224     // don't have process affinity these should eventually be hoisted to the shim, 
225     // and then we can enforce.
226     CordbProcess * pProcess = GetProcess();
227     if (pProcess != NULL)
228     {
229         _ASSERTE(pProcess->ThreadHoldsProcessLock());
230     }
231     CordbCommonBase::Neuter(); 
232 }
233
234 //-----------------------------------------------------------------------------
235 // NeuterLists
236 //-----------------------------------------------------------------------------
237
238 NeuterList::NeuterList()
239 {
240     m_pHead = NULL;
241 }
242
243 NeuterList::~NeuterList()
244 {
245     // Our owner should have neutered us before deleting us.
246     // Thus we should be empty.
247     CONSISTENCY_CHECK_MSGF(m_pHead == NULL, ("NeuterList not empty on shutdown. this=0x%p", this));
248 }
249
250 // Wrapper around code:NeuterList::UnsafeAdd 
251 void NeuterList::Add(CordbProcess * pProcess, CordbBase * pObject)
252 {
253     CONTRACTL
254     {
255         THROWS;
256     }
257     CONTRACTL_END;
258
259     UnsafeAdd(pProcess, pObject);
260 }
261
262 //
263 // Add an object to be neutered.
264 //
265 // Arguments:
266 //     pProcess - process that holds lock that will protect the neuter list
267 //     pObject - object to add
268 //
269 // Returns:
270 //     Throws on error.
271 //  
272 // Notes:
273 //     This will add it to the list and maintain an internal reference to it.
274 //     This will take the process lock.
275 //
276 void NeuterList::UnsafeAdd(CordbProcess * pProcess, CordbBase * pObject)
277 {
278     _ASSERTE(pObject != NULL);
279     
280     // Lock if needed. 
281     RSLock * pLock = (pProcess != NULL) ? pProcess->GetProcessLock() : NULL;
282     RSLockHolder lockHolder(pLock, FALSE);
283     if (pLock != NULL) lockHolder.Acquire();
284
285     
286     Node * pNode = new Node(); // throws on error.
287     pNode->m_pObject.Assign(pObject);
288     pNode->m_pNext = m_pHead;
289
290     m_pHead = pNode;
291 }
292
293 // Neuter everything on the list and clear it
294 //
295 // Arguments:
296 //     pProcess - process tree that this neuterlist belongs in
297 //     ticket - neuter ticket proving caller ensured we're safe to neuter.
298 //
299 // Assumptions:
300 //     Caller ensures we're safe to neuter (required to obtain NeuterTicket)
301 //
302 // Notes:
303 //     This will release all internal references and empty the list.
304 void NeuterList::NeuterAndClear(CordbProcess * pProcess)
305 {
306     RSLock * pLock = (pProcess != NULL) ? pProcess->GetProcessLock() : NULL;        
307     (void)pLock; //prevent "unused variable" error from GCC
308     _ASSERTE((pLock == NULL) || pLock->HasLock());
309         
310     while (m_pHead != NULL)
311     {
312         Node * pTemp = m_pHead;
313         m_pHead = m_pHead->m_pNext;
314
315         pTemp->m_pObject->Neuter();
316         delete pTemp; // will implicitly release
317     }
318 }
319
320 // Only neuter objects that are marked.
321 // Removes neutered objects from the list.
322 void NeuterList::SweepAllNeuterAtWillObjects(CordbProcess * pProcess)
323 {
324     _ASSERTE(pProcess != NULL);
325     RSLock * pLock = pProcess->GetProcessLock();
326     RSLockHolder lockHolder(pLock);
327
328     Node ** ppLast = &m_pHead;
329     Node * pCur = m_pHead;
330
331     while (pCur != NULL)
332     {
333         CordbBase * pObject = pCur->m_pObject;
334         if (pObject->IsNeuterAtWill() || pObject->IsNeutered())
335         {
336             // Delete
337             pObject->Neuter();
338
339             Node * pNext = pCur->m_pNext;
340             delete pCur; // dtor will implicitly release the internal ref to pObject
341             pCur =  *ppLast = pNext;
342         }
343         else
344         {
345             // Move to next.
346             ppLast = &pCur->m_pNext;
347             pCur = pCur->m_pNext;
348         }
349     }
350 }
351
352 //-----------------------------------------------------------------------------
353 // Neuters all objects in the list and empties the list.
354 // 
355 // Notes:
356 //    See also code:LeftSideResourceCleanupList::SweepNeuterLeftSideResources,
357 //    which only neuters objects that have been marked as NeuterAtWill (external
358 //    ref count has gone to 0).
359 void LeftSideResourceCleanupList::NeuterLeftSideResourcesAndClear(CordbProcess * pProcess)
360 {
361     // Traversal protected under Process-lock.
362     // SG-lock must already be held to do neutering.
363     // Stop-Go lock is bigger than Process-lock. 
364     // Neutering requires the Stop-Go lock (until we get rid of IPC events)
365     // But we want to be able to add to the Neuter list under the Process-lock. 
366     // So we just need to protected m_pHead under process-lock.
367
368     // "Privatize" the list under the lock.
369     _ASSERTE(pProcess != NULL);
370     RSLock * pLock = pProcess->GetProcessLock();
371
372     Node * pCur = NULL;
373     {
374         RSLockHolder lockHolder(pLock); // only acquire lock if we have one
375         pCur = m_pHead;
376         m_pHead = NULL;
377     }
378
379     // @dbgtodo - eventually everything can be under the process lock.
380     _ASSERTE(!pLock->HasLock()); // Can't hold Process lock while calling NeuterLeftSideResources
381     
382     // Now we're operating on local data, so traversing doesn't need to be under the lock.
383     while (pCur != NULL)
384     {
385         Node * pTemp = pCur;
386         pCur = pCur->m_pNext;
387
388         pTemp->m_pObject->NeuterLeftSideResources();
389         delete pTemp; // will implicitly release
390     }
391   
392 }
393
394 //-----------------------------------------------------------------------------
395 // Only neuter objects that are marked. Removes neutered objects from the list.
396 // 
397 // Arguments:
398 //    pProcess - non-null process owning the objects in the list
399 //    
400 // Notes:
401 //    this cleans up left-side resources held by objects in the list. 
402 //    It may send IPC events to do this.
403 void LeftSideResourceCleanupList::SweepNeuterLeftSideResources(CordbProcess * pProcess)
404 {
405     _ASSERTE(pProcess != NULL);
406
407     // Must be safe to send IPC events.
408     _ASSERTE(pProcess->GetStopGoLock()->HasLock()); // holds this for neutering
409     _ASSERTE(pProcess->GetSynchronized());
410
411     RSLock * pLock = pProcess->GetProcessLock();
412
413     // Lock while we "privatize" the head.
414     RSLockHolder lockHolder(pLock);
415     Node * pHead = m_pHead;
416     m_pHead = NULL; 
417     lockHolder.Release();
418
419     Node ** ppLast = &pHead;
420     Node * pCur = pHead;
421     
422     // Can't hold the process-lock while calling Neuter.
423     while (pCur != NULL)
424     {
425         CordbBase * pObject = pCur->m_pObject;
426         if (pObject->IsNeuterAtWill() || pObject->IsNeutered())
427         {
428             // HeavyNueter can not be done under the process-lock because
429             // it may take the Stop-Go lock and send events.
430             pObject->NeuterLeftSideResources();
431
432             // Delete
433             Node * pNext = pCur->m_pNext;
434             delete pCur; // dtor will implicitly release the internal ref to pObject
435             pCur =  *ppLast = pNext;
436         }
437         else
438         {
439             // Move to next.
440             ppLast = &pCur->m_pNext;
441             pCur = pCur->m_pNext;
442         }
443     }
444
445     // Now link back in. m_pHead may have changed while we were unlocked.
446     // The list does not need to be ordered.
447         
448     lockHolder.Acquire();
449     *ppLast = m_pHead;
450     m_pHead = pHead;
451 }
452
453
454
455 /* ------------------------------------------------------------------------- *
456  * CordbBase class
457  * ------------------------------------------------------------------------- */
458
459 // Do any initialization necessary for both CorPublish and CorDebug
460 // This includes enabling logging and adding the SEDebug priv.
461 void CordbCommonBase::InitializeCommon()
462 {
463     static bool IsInitialized = false;
464     if( IsInitialized )
465     {
466         return;
467     }
468     
469 #ifdef STRESS_LOG
470     {
471         bool fStressLog = false;
472
473 #ifdef _DEBUG
474         // default for stress log is on debug build
475         fStressLog = true;
476 #endif // DEBUG
477
478         // StressLog will turn on stress logging for the entire runtime.
479         // RSStressLog is only used here and only effects just the RS.
480         fStressLog =
481             (REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLog, fStressLog) != 0) ||
482             (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_RSStressLog) != 0);
483
484         if (fStressLog == true)
485         {
486             unsigned facilities = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_LogFacility, LF_ALL);
487             unsigned level = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::EXTERNAL_LogLevel, LL_INFO1000);
488             unsigned bytesPerThread = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLogSize, STRESSLOG_CHUNK_SIZE * 2);
489             unsigned totalBytes = REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_TotalStressLogSize, STRESSLOG_CHUNK_SIZE * 1024);
490 #ifndef FEATURE_PAL
491             StressLog::Initialize(facilities, level, bytesPerThread, totalBytes, GetModuleInst());
492 #else
493             StressLog::Initialize(facilities, level, bytesPerThread, totalBytes, NULL);
494 #endif
495         }
496     }
497
498 #endif // STRESS_LOG
499
500 #ifdef LOGGING
501     InitializeLogging();
502 #endif
503
504     // Add debug privilege. This will let us call OpenProcess() on anything, regardless of ACL.
505     AddDebugPrivilege();
506         
507     IsInitialized = true;
508 }
509
510 // Adjust the permissions of this process to ensure that we have
511 // the debugging priviledge. If we can't make the adjustment, it
512 // only means that we won't be able to attach to a service under
513 // NT, so we won't treat that as a critical failure. 
514 // This also will let us call OpenProcess() on anything, regardless of DACL. This allows an
515 // Admin debugger to attach to a debuggee in the guest account.
516 // Ideally, the debugger would set this (and we wouldn't mess with privileges at all). However, we've been
517 // setting this since V1.0 and removing it may be a breaking change.
518 void CordbCommonBase::AddDebugPrivilege()
519 {
520 #ifndef FEATURE_PAL
521     HANDLE hToken;
522     TOKEN_PRIVILEGES Privileges;
523     BOOL fSucc;
524
525     LUID SeDebugLuid = {0, 0};
526
527     fSucc = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &SeDebugLuid);
528     DWORD err = GetLastError();
529     
530     if (!fSucc)
531     {
532         STRESS_LOG1(LF_CORDB, LL_INFO1000, "Unable to adjust permissions of this process to include SE_DEBUG. Lookup failed %d\n", err);
533         return;
534     }
535     
536     
537     // Retrieve a handle of the access token
538     fSucc = OpenProcessToken(GetCurrentProcess(),
539                              TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
540                              &hToken);
541
542     if (fSucc)
543     {
544         Privileges.PrivilegeCount = 1;
545         Privileges.Privileges[0].Luid = SeDebugLuid;
546         Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
547
548         AdjustTokenPrivileges(hToken,
549                               FALSE,
550                               &Privileges,
551                               sizeof(TOKEN_PRIVILEGES),
552                               (PTOKEN_PRIVILEGES) NULL,
553                               (PDWORD) NULL);
554         err = GetLastError();
555         // The return value of AdjustTokenPrivileges cannot be tested.
556         if (err != ERROR_SUCCESS)
557         {
558             STRESS_LOG1(LF_CORDB, LL_INFO1000, 
559                 "Unable to adjust permissions of this process to include SE_DEBUG. Adjust failed %d\n", err);
560         }
561         else
562         {
563             LOG((LF_CORDB, LL_INFO1000, "Adjusted process permissions to include SE_DEBUG.\n"));
564         }
565         CloseHandle(hToken);
566     }
567 #endif
568
569
570
571 namespace
572 {
573
574     //
575     // DefaultManagedCallback2
576     //
577     // In the event that the debugger is of an older version than the Right Side & Left Side, the Right Side may issue
578     // new callbacks that the debugger is not expecting. In this case, we need to provide a default behavior for those
579     // new callbacks, if for nothing else than to force the debugger to Continue().
580     //
581     class DefaultManagedCallback2 : public ICorDebugManagedCallback2
582     {
583     public:
584         DefaultManagedCallback2(ICorDebug* pDebug);
585         virtual ~DefaultManagedCallback2() { }
586         virtual HRESULT __stdcall QueryInterface(REFIID iid, void** pInterface);
587         virtual ULONG __stdcall AddRef();
588         virtual ULONG __stdcall Release();
589         COM_METHOD FunctionRemapOpportunity(ICorDebugAppDomain* pAppDomain,
590                                                  ICorDebugThread* pThread,
591                                                  ICorDebugFunction* pOldFunction,
592                                                  ICorDebugFunction* pNewFunction,
593                                                  ULONG32 oldILOffset);
594         COM_METHOD FunctionRemapComplete(ICorDebugAppDomain *pAppDomain,
595                                     ICorDebugThread *pThread,
596                                     ICorDebugFunction *pFunction);
597
598         COM_METHOD CreateConnection(ICorDebugProcess *pProcess,
599                                     CONNID dwConnectionId,
600                                     __in_z WCHAR* pConnectionName);
601         COM_METHOD ChangeConnection(ICorDebugProcess *pProcess, CONNID dwConnectionId);
602         COM_METHOD DestroyConnection(ICorDebugProcess *pProcess, CONNID dwConnectionId);
603
604         COM_METHOD Exception(ICorDebugAppDomain *pAddDomain,
605                              ICorDebugThread *pThread,
606                              ICorDebugFrame *pFrame,
607                              ULONG32 nOffset,
608                              CorDebugExceptionCallbackType eventType,
609                              DWORD dwFlags );
610
611         COM_METHOD ExceptionUnwind(ICorDebugAppDomain *pAddDomain,
612                                    ICorDebugThread *pThread,
613                                    CorDebugExceptionUnwindCallbackType eventType,
614                                    DWORD dwFlags );
615         COM_METHOD MDANotification(
616                             ICorDebugController * pController,
617                             ICorDebugThread *pThread,
618                             ICorDebugMDA * pMDA
619         ) { return E_NOTIMPL; }
620
621     private:
622         // not implemented
623         DefaultManagedCallback2(const DefaultManagedCallback2&);
624         DefaultManagedCallback2& operator=(const DefaultManagedCallback2&);
625
626         ICorDebug* m_pDebug;
627         LONG m_refCount;
628     };
629
630
631
632
633     DefaultManagedCallback2::DefaultManagedCallback2(ICorDebug* pDebug) : m_pDebug(pDebug), m_refCount(0)
634     {
635     }
636
637     HRESULT
638     DefaultManagedCallback2::QueryInterface(REFIID iid, void** pInterface)
639     {
640         if (IID_ICorDebugManagedCallback2 == iid)
641         {
642             *pInterface = static_cast<ICorDebugManagedCallback2*>(this);
643         }
644         else if (IID_IUnknown == iid)
645         {
646             *pInterface = static_cast<IUnknown*>(this);
647         }
648         else
649         {
650             *pInterface = NULL;
651             return E_NOINTERFACE;
652         }
653
654         this->AddRef();
655         return S_OK;
656     }
657
658     ULONG
659     DefaultManagedCallback2::AddRef()
660     {
661         return InterlockedIncrement(&m_refCount);
662     }
663
664     ULONG
665     DefaultManagedCallback2::Release()
666     {
667         ULONG ulRef = InterlockedDecrement(&m_refCount);
668         if (0 == ulRef)
669         {
670             delete this;
671         }
672
673         return ulRef;
674     }
675
676     HRESULT
677     DefaultManagedCallback2::FunctionRemapOpportunity(ICorDebugAppDomain* pAppDomain,
678                                                       ICorDebugThread* pThread,
679                                                       ICorDebugFunction* pOldFunction,
680                                                       ICorDebugFunction* pNewFunction,
681                                                       ULONG32 oldILOffset)
682     {
683
684         //
685         // In theory, this function should never be reached. To get here, we'd have to have a debugger which doesn't
686         // support edit and continue somehow turn on edit & continue features.
687         //
688         _ASSERTE(!"Edit & Continue callback reached when debugger doesn't support Edit And Continue");
689
690
691         // If you ignore this assertion, or you're in a retail build, there are two options as far as how to proceed
692         // from this point
693         //  o We can do nothing, and let the debugee process hang, or
694         //  o We can silently ignore the FunctionRemapOpportunity, and tell the debugee to Continue running.
695         //
696         // For now, we'll silently ignore the function remapping.
697         pAppDomain->Continue(false);
698         pAppDomain->Release();
699
700         return S_OK;
701     }
702
703
704     HRESULT
705     DefaultManagedCallback2::FunctionRemapComplete(ICorDebugAppDomain *pAppDomain,
706                           ICorDebugThread *pThread,
707                           ICorDebugFunction *pFunction)
708     {
709         //
710         // In theory, this function should never be reached. To get here, we'd have to have a debugger which doesn't
711         // support edit and continue somehow turn on edit & continue features.
712         //
713         _ASSERTE(!"Edit & Continue callback reached when debugger doesn't support Edit And Continue");
714         return E_NOTIMPL;
715     }
716
717     //
718     // <TODO>
719     // These methods are current left unimplemented.
720     //
721     // Create/Change/Destroy Connection *should* force the Process/AppDomain/Thread to Continue(). Currently the
722     // arguments to these functions don't provide the relevant Process/AppDomain/Thread, so there is no way to figure
723     // out which Threads should be forced to Continue().
724     //
725     // </TODO>
726     //
727     HRESULT
728     DefaultManagedCallback2::CreateConnection(ICorDebugProcess *pProcess,
729                                               CONNID dwConnectionId,
730                                               __in_z WCHAR* pConnectionName)
731     {
732         _ASSERTE(!"DefaultManagedCallback2::CreateConnection not implemented");
733         return E_NOTIMPL;
734     }
735
736     HRESULT
737     DefaultManagedCallback2::ChangeConnection(ICorDebugProcess *pProcess, CONNID dwConnectionId)
738     {
739         _ASSERTE(!"DefaultManagedCallback2::ChangeConnection not implemented");
740         return E_NOTIMPL;
741     }
742
743     HRESULT
744     DefaultManagedCallback2::DestroyConnection(ICorDebugProcess *pProcess, CONNID dwConnectionId)
745     {
746         _ASSERTE(!"DefaultManagedCallback2::DestroyConnection not implemented");
747         return E_NOTIMPL;
748     }
749
750     HRESULT
751     DefaultManagedCallback2::Exception(ICorDebugAppDomain *pAppDomain,
752                                        ICorDebugThread *pThread,
753                                        ICorDebugFrame *pFrame,
754                                        ULONG32 nOffset,
755                                        CorDebugExceptionCallbackType eventType,
756                                        DWORD dwFlags )
757     {
758         //
759         // Just ignore and continue the process.
760         //
761         pAppDomain->Continue(false);
762         return S_OK;
763     }
764
765     HRESULT
766     DefaultManagedCallback2::ExceptionUnwind(ICorDebugAppDomain *pAppDomain,
767                                              ICorDebugThread *pThread,
768                                              CorDebugExceptionUnwindCallbackType eventType,
769                                              DWORD dwFlags )
770     {
771         //
772         // Just ignore and continue the process.
773         //
774         pAppDomain->Continue(false);
775         return S_OK;
776     }
777
778     //
779     // DefaultManagedCallback3
780     //
781     // In the event that the debugger is of an older version than the Right Side & Left Side, the Right Side may issue
782     // new callbacks that the debugger is not expecting. In this case, we need to provide a default behavior for those
783     // new callbacks, if for nothing else than to force the debugger to Continue().
784     //
785     class DefaultManagedCallback3 : public ICorDebugManagedCallback3
786     {
787     public:
788         DefaultManagedCallback3(ICorDebug* pDebug);
789         virtual ~DefaultManagedCallback3() { }
790         virtual HRESULT __stdcall QueryInterface(REFIID iid, void** pInterface);
791         virtual ULONG __stdcall AddRef();
792         virtual ULONG __stdcall Release();
793         COM_METHOD CustomNotification(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain);
794     private:
795         // not implemented
796         DefaultManagedCallback3(const DefaultManagedCallback3&);
797         DefaultManagedCallback3& operator=(const DefaultManagedCallback3&);
798
799         ICorDebug* m_pDebug;
800         LONG m_refCount;
801     };
802
803     DefaultManagedCallback3::DefaultManagedCallback3(ICorDebug* pDebug) : m_pDebug(pDebug), m_refCount(0)
804     {
805     }
806
807     HRESULT
808     DefaultManagedCallback3::QueryInterface(REFIID iid, void** pInterface)
809     {
810         if (IID_ICorDebugManagedCallback3 == iid)
811         {
812             *pInterface = static_cast<ICorDebugManagedCallback3*>(this);
813         }
814         else if (IID_IUnknown == iid)
815         {
816             *pInterface = static_cast<IUnknown*>(this);
817         }
818         else
819         {
820             *pInterface = NULL;
821             return E_NOINTERFACE;
822         }
823
824         this->AddRef();
825         return S_OK;
826     }
827
828     ULONG
829     DefaultManagedCallback3::AddRef()
830     {
831         return InterlockedIncrement(&m_refCount);
832     }
833
834     ULONG
835     DefaultManagedCallback3::Release()
836     {
837         ULONG ulRef = InterlockedDecrement(&m_refCount);
838         if (0 == ulRef)
839         {
840             delete this;
841         }
842
843         return ulRef;
844     }
845
846     HRESULT
847     DefaultManagedCallback3::CustomNotification(ICorDebugThread * pThread, ICorDebugAppDomain * pAppDomain)
848     {
849         //
850         // Just ignore and continue the process.
851         //
852         pAppDomain->Continue(false);
853         return S_OK;
854     }
855 }
856
857 /* ------------------------------------------------------------------------- *
858  * Cordb class
859  * ------------------------------------------------------------------------- */
860
861
862 Cordb::Cordb(CorDebugInterfaceVersion iDebuggerVersion)
863   : CordbBase(NULL, 0, enumCordb),
864     m_processes(11),
865     m_initialized(false),
866     m_debuggerSpecifiedVersion(iDebuggerVersion)
867     ,
868     m_targetCLR(0)
869 {
870     g_pRSDebuggingInfo->m_Cordb = this;
871
872 #ifdef _DEBUG_IMPL
873     // Memory leak detection
874     InterlockedIncrement(&s_DbgMemTotalOutstandingCordb);
875 #endif
876 }
877
878 Cordb::~Cordb()
879 {
880     LOG((LF_CORDB, LL_INFO10, "C::~C Terminating Cordb object.\n"));
881     g_pRSDebuggingInfo->m_Cordb = NULL;
882 }
883
884 void Cordb::Neuter()
885 {
886     if (this->IsNeutered())
887     {
888         return;
889     }
890
891     
892     RSLockHolder lockHolder(&m_processListMutex);
893     m_pProcessEnumList.NeuterAndClear(NULL);
894     
895
896     HRESULT hr = S_OK;
897     EX_TRY // @dbgtodo push this up. 
898     {
899         // Iterating needs to be done under the processList lock (small), while neutering
900         // needs to be able to take the process lock (big).
901         RSPtrArray<CordbProcess> list;
902         m_processes.TransferToArray(&list); // throws
903
904         // can't hold list lock while calling CordbProcess::Neuter (which
905         // will take the Process-lock).
906         lockHolder.Release(); 
907
908         list.NeuterAndClear();
909         // List dtor calls release on each element
910     }    
911     EX_CATCH_HRESULT(hr);
912     SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); 
913
914     CordbCommonBase::Neuter();
915
916     // Implicit release from smart ptr.
917 }
918
919 #ifdef _DEBUG_IMPL
920 void CheckMemLeaks()
921 {
922     // Memory leak detection.
923     LONG l = InterlockedDecrement(&Cordb::s_DbgMemTotalOutstandingCordb);
924     if (l == 0)
925     {
926         // If we just released our final Cordb root object,  then we expect no internal references at all.
927         // Note that there may still be external references (and thus not all objects may have been
928         // deleted yet).
929         bool fLeakedInternal = (Cordb::s_DbgMemTotalOutstandingInternalRefs > 0);
930
931         // Some Cordb objects (such as CordbValues) may not be rooted, and thus we can't neuter
932         // them and thus an external ref may keep them alive. Since these objects may have internal refs,
933         // This means that external refs can keep internal refs.
934         // Thus this assert must be tempered if unrooted objects are leaked. (But that means we can always
935         // assert the tempered version; regardless of bugs in Cordbg).
936         CONSISTENCY_CHECK_MSGF(!fLeakedInternal,
937             ("'%d' Outstanding internal references at final Cordb::Terminate\n",
938             Cordb::s_DbgMemTotalOutstandingInternalRefs));
939
940         DWORD dLeakCheck = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgLeakCheck);
941         if (dLeakCheck > 0)
942         {
943             // We have 1 ref for this Cordb root object. All other refs should have been deleted.
944             CONSISTENCY_CHECK_MSGF(Cordb::s_TotalObjectCount == 1, ("'%d' total cordbBase objects are leaked.\n",
945                 Cordb::s_TotalObjectCount-1));
946         }
947     }
948 }
949 #endif
950
951 // This shuts down ICorDebug.
952 // All CordbProcess objects owned by this Cordb object must have either:
953 // - returned for a Detach() call
954 // - returned from dispatching the ExitProcess() callback.
955 // In both cases, CordbProcess::NeuterChildren has been called, although the Process object itself
956 // may not yet be neutered.  This condition will ensure that the CordbProcess objects don't need
957 // any resources that we're about to release.
958 HRESULT Cordb::Terminate()
959 {
960     LOG((LF_CORDB, LL_INFO10000, "[%x] Terminating Cordb\n", GetCurrentThreadId()));
961
962     if (!m_initialized)
963         return E_FAIL;
964
965     FAIL_IF_NEUTERED(this);
966
967     // We can't terminate the debugging services from within a callback. 
968     // Caller is supposed to be out of all callbacks when they call this.
969     // This also avoids a deadlock because we'll shutdown the RCET, which would block if we're
970     // in the RCET.
971     if (m_rcEventThread->IsRCEventThread())
972     {
973         STRESS_LOG0(LF_CORDB, LL_INFO10, "C::T: failed on RCET\n");
974         _ASSERTE(!"Gross API Misuse: Debugger shouldn't call ICorDebug::Terminate from within a managed callback.");
975         return CORDBG_E_CANT_CALL_ON_THIS_THREAD;
976     }
977
978     // @todo - do we need to throw some switch to prevent new processes from being added now?
979
980     // VS must stop all debugging before terminating. Fail if we have any non-neutered processes
981     // (b/c those processes should have been either shutdown or detached).
982     // We are in an undefined state if this check fails.
983     // Process are removed from this list before Process::Detach() returns and before the ExitProcess callback is dispatched.
984     // Thus any processes in this list should be live or have an unrecoverable error.
985     {
986         RSLockHolder ch(&m_processListMutex);
987
988         HASHFIND hfDT;
989         CordbProcess * pProcess;
990
991         for (pProcess=  (CordbProcess*) m_processes.FindFirst(&hfDT);
992              pProcess != NULL;
993              pProcess = (CordbProcess*) m_processes.FindNext(&hfDT))
994         {
995             _ASSERTE(pProcess->IsSafeToSendEvents() || pProcess->m_unrecoverableError);
996             if (pProcess->IsSafeToSendEvents() && !pProcess->m_unrecoverableError)
997             {
998                 CONSISTENCY_CHECK_MSGF(false, ("Gross API misuses. Callling terminate with live process:0x%p\n", pProcess));
999                 STRESS_LOG1(LF_CORDB, LL_INFO10, "Cordb::Terminate b/c of non-neutered process '%p'\n", pProcess);
1000                 // This is very bad.
1001                 // GROSS API MISUSES - Debugger is calling ICorDebug::Terminate while there
1002                 // are still outstanding (non-neutered) ICorDebugProcess.
1003                 // ICorDebug is now in an undefined state.
1004                 // We will also leak memory b/c we're leaving the EventThreads up (which will in turn
1005                 // keep a reference to this Cordb object).
1006                 return ErrWrapper(CORDBG_E_ILLEGAL_SHUTDOWN_ORDER);
1007             }
1008         }
1009     }
1010
1011     // @todo- ideally, we'd wait for all threads to get outside of ICorDebug before we proceed.
1012     // That's tough to implement in practice; but we at least wait for both ET to exit. As these
1013     // guys dispatch callbacks, that means at least we'll wait until VS is outside of any callback.
1014     //
1015     // Stop the event handling threads.
1016     //
1017     if (m_rcEventThread != NULL)
1018     {
1019         // Stop may do significant work b/c if it drains the worker queue.
1020         m_rcEventThread->Stop();
1021         delete m_rcEventThread;
1022         m_rcEventThread = NULL;
1023     }
1024
1025
1026 #ifdef _DEBUG
1027     // @todo - this disables thread-safety asserts on the process-list-hash. We clearly
1028     // can't hold the lock while neutering it. (lock violation since who knows what neuter may do)
1029     // @todo- we may have races beteen Cordb::Terminate and Cordb::CreateProcess as both
1030     // modify the process list. This is mitigated since Terminate is supposed to be the last method called.
1031     m_processes.DebugSetRSLock(NULL);
1032 #endif
1033
1034     //
1035     // We expect the debugger to neuter all processes before calling Terminate(), so do not neuter them here.
1036     //
1037
1038 #ifdef _DEBUG
1039     {
1040         HASHFIND find;
1041         _ASSERTE(m_processes.FindFirst(&find) == NULL); // should be emptied by neuter
1042     }
1043 #endif //_DEBUG
1044
1045     // Officially mark us as neutered.
1046     this->Neuter();
1047
1048     m_processListMutex.Destroy();
1049
1050     //
1051     // Release the callbacks
1052     //
1053     m_managedCallback.Clear();
1054     m_managedCallback2.Clear();
1055     m_managedCallback3.Clear();
1056     m_unmanagedCallback.Clear();
1057
1058     // The Shell may still have outstanding references, so we don't want to shutdown logging yet.
1059     // But everything should be neutered anyways.
1060
1061     m_initialized = FALSE;
1062
1063
1064     // After this, all outstanding Cordb objects should be neutered.
1065     LOG((LF_CORDB, LL_EVERYTHING, "Cordb finished terminating.\n"));
1066
1067 #if defined(_DEBUG)
1068     //
1069     // Assert that there are no outstanding object references within the debugging
1070     // API itself.
1071     //
1072     CheckMemLeaks();
1073 #endif
1074
1075     return S_OK;
1076 }
1077
1078 HRESULT Cordb::QueryInterface(REFIID id, void **pInterface)
1079 {
1080     if (id == IID_ICorDebug)
1081         *pInterface = static_cast<ICorDebug*>(this);
1082     else if (id == IID_IUnknown)
1083         *pInterface = static_cast<IUnknown*>(static_cast<ICorDebug*>(this));
1084     else
1085     {
1086         *pInterface = NULL;
1087         return E_NOINTERFACE;
1088     }
1089
1090     ExternalAddRef();
1091     return S_OK;
1092 }
1093
1094
1095
1096 //
1097 // Initialize -- setup the ICorDebug object by creating any objects
1098 // that the object needs to operate and starting the two needed IPC
1099 // threads.
1100 //
1101 HRESULT Cordb::Initialize(void)
1102 {
1103     HRESULT hr = S_OK;
1104
1105     FAIL_IF_NEUTERED(this);
1106
1107     if (!m_initialized)
1108     {
1109         CordbCommonBase::InitializeCommon();
1110         
1111         // Since logging wasn't active when we called CordbBase, do it now.
1112         LOG((LF_CORDB, LL_EVERYTHING, "Memory: CordbBase object allocated: this=%p, count=%d, RootObject\n", this, s_TotalObjectCount));
1113         LOG((LF_CORDB, LL_INFO10, "Initializing ICorDebug...\n"));
1114
1115         // Ensure someone hasn't messed up the IPC buffer size
1116         _ASSERTE(sizeof(DebuggerIPCEvent) <= CorDBIPC_BUFFER_SIZE);
1117
1118         //
1119         // Init things that the Cordb will need to operate
1120         //
1121         m_processListMutex.Init("Process-List Lock", RSLock::cLockReentrant, RSLock::LL_PROCESS_LIST_LOCK);
1122
1123 #ifdef _DEBUG
1124         m_processes.DebugSetRSLock(&m_processListMutex);
1125 #endif
1126
1127         //
1128         // Create the runtime controller event listening thread
1129         //
1130         m_rcEventThread = new (nothrow) CordbRCEventThread(this);
1131
1132         if (m_rcEventThread == NULL)
1133         {
1134             hr = E_OUTOFMEMORY;
1135         }
1136         else
1137         {
1138             // This stuff only creates events & starts the thread
1139             hr = m_rcEventThread->Init();
1140
1141             if (SUCCEEDED(hr))
1142                 hr = m_rcEventThread->Start();
1143
1144             if (FAILED(hr))
1145             {
1146                 delete m_rcEventThread;
1147                 m_rcEventThread = NULL;
1148             }
1149         }
1150
1151         if (FAILED(hr))
1152             goto exit;
1153
1154        m_initialized = TRUE;
1155     }
1156
1157 exit:
1158     return hr;
1159 }
1160
1161 //---------------------------------------------------------------------------------------
1162 //
1163 // Throw if no more process can be debugged with this Cordb object.
1164 //
1165 // Notes:
1166 //     This is highly dependent on the wait sets in the Win32 & RCET threads.
1167 //     @dbgtodo-  this will end up in the shim.
1168
1169 void Cordb::EnsureAllowAnotherProcess()
1170 {
1171     CONTRACTL
1172     {
1173         THROWS;
1174     }
1175     CONTRACTL_END;
1176
1177     RSLockHolder ch(&m_processListMutex);
1178
1179     // Cordb, Win32, and RCET all have process sets, but Cordb's is the
1180     // best count of total debuggees. The RCET set is volatile (processes
1181     // are added / removed when they become synchronized), and Win32's set
1182     // doesn't include all processes.
1183     int cCurProcess = GetProcessList()->GetCount();
1184
1185     // In order to accept another debuggee, we must have a free slot in all
1186     // wait sets. Currently, we don't expose the size of those sets, but
1187     // we know they're MAXIMUM_WAIT_OBJECTS. Note that we lose one slot
1188     // to the control event.
1189     if (cCurProcess >= MAXIMUM_WAIT_OBJECTS - 1)
1190     {
1191         ThrowHR(CORDBG_E_TOO_MANY_PROCESSES);
1192     }
1193 }
1194
1195 //---------------------------------------------------------------------------------------
1196 //
1197 // Add process to the list.
1198 //
1199 // Notes:
1200 //     AddProcess -- add a process object to this ICorDebug's hash of processes.
1201 //     This also tells this ICorDebug's runtime controller thread that the
1202 //     process set has changed so it can update its list of wait events.
1203 //
1204 void Cordb::AddProcess(CordbProcess* process)
1205 {
1206     // At this point, we should have already checked that we
1207     // can have another debuggee.
1208     STRESS_LOG1(LF_CORDB, LL_INFO10, "Cordb::AddProcess %08x...\n", process);
1209
1210     if ((m_managedCallback == NULL) || (m_managedCallback2 == NULL) || (m_managedCallback3 == NULL))
1211     {
1212         ThrowHR(E_FAIL);
1213     }
1214
1215
1216
1217     RSLockHolder lockHolder(&m_processListMutex);
1218
1219     // Once we add another process, all outstanding process-enumerators become invalid.
1220     m_pProcessEnumList.NeuterAndClear(NULL);
1221
1222     GetProcessList()->AddBaseOrThrow(process);
1223     m_rcEventThread->ProcessStateChanged();
1224 }
1225
1226 //
1227 // RemoveProcess -- remove a process object from this ICorDebug's hash of
1228 // processes. This also tells this ICorDebug's runtime controller thread
1229 // that the process set has changed so it can update its list of wait events.
1230 //
1231 void Cordb::RemoveProcess(CordbProcess* process)
1232 {
1233     STRESS_LOG1(LF_CORDB, LL_INFO10, "Cordb::RemoveProcess %08x...\n", process);
1234
1235     LockProcessList();
1236     GetProcessList()->RemoveBase((ULONG_PTR)process->m_id);
1237
1238     m_rcEventThread->ProcessStateChanged();
1239
1240     UnlockProcessList();
1241 }
1242
1243 //
1244 // LockProcessList -- Lock the process list.
1245 //
1246 void Cordb::LockProcessList(void)
1247 {
1248     m_processListMutex.Lock();
1249 }
1250
1251 //
1252 // UnlockProcessList -- Unlock the process list.
1253 //
1254 void Cordb::UnlockProcessList(void)
1255 {
1256     m_processListMutex.Unlock();
1257 }
1258
1259 #ifdef _DEBUG
1260 // Return true iff this thread owns the ProcessList lock
1261 bool Cordb::ThreadHasProcessListLock()
1262 {
1263     return m_processListMutex.HasLock();
1264 }
1265 #endif
1266
1267
1268 // Get the hash that has the process.
1269 CordbSafeHashTable<CordbProcess> *Cordb::GetProcessList()
1270 {
1271     // If we're accessing the hash, we'd better be locked.
1272     _ASSERTE(ThreadHasProcessListLock());
1273
1274     return &m_processes;
1275 }
1276
1277
1278 HRESULT Cordb::SendIPCEvent(CordbProcess * pProcess,
1279                             DebuggerIPCEvent * pEvent,
1280                             SIZE_T eventSize)
1281 {
1282     HRESULT hr = S_OK;
1283
1284     LOG((LF_CORDB, LL_EVERYTHING, "SendIPCEvent in Cordb called\n"));
1285     EX_TRY
1286     {
1287         hr = m_rcEventThread->SendIPCEvent(pProcess, pEvent, eventSize);
1288     }
1289     EX_CATCH_HRESULT(hr)
1290     return hr;
1291 }
1292
1293
1294 void Cordb::ProcessStateChanged(void)
1295 {
1296     m_rcEventThread->ProcessStateChanged();
1297 }
1298
1299
1300 HRESULT Cordb::WaitForIPCEventFromProcess(CordbProcess* process,
1301                                           CordbAppDomain *pAppDomain,
1302                                           DebuggerIPCEvent* event)
1303 {
1304     return m_rcEventThread->WaitForIPCEventFromProcess(process,
1305                                                        pAppDomain,
1306                                                        event);
1307 }
1308
1309 HRESULT Cordb::SetTargetCLR(HMODULE hmodTargetCLR)
1310 {
1311     if (m_initialized)
1312         return E_FAIL;
1313
1314     m_targetCLR = hmodTargetCLR;
1315
1316     // @REVIEW: are we happy with this workaround?  It allows us to use the existing
1317     // infrastructure for instance name decoration, but it really doesn't fit
1318     // the same model because coreclr.dll isn't in this process and hmodTargetCLR
1319     // is the debuggee target, not the coreclr.dll to bind utilcode to..
1320
1321     CoreClrCallbacks cccallbacks;
1322     cccallbacks.m_hmodCoreCLR               = hmodTargetCLR;
1323     cccallbacks.m_pfnIEE                    = NULL;
1324     cccallbacks.m_pfnGetCORSystemDirectory  = NULL;    
1325     cccallbacks.m_pfnGetCLRFunction         = NULL;
1326     InitUtilcode(cccallbacks);
1327
1328     return S_OK;
1329 }
1330
1331 //-----------------------------------------------------------
1332 // ICorDebug
1333 //-----------------------------------------------------------
1334
1335 // Set the handler for callbacks on managed events
1336 // This can not be NULL.
1337 // If we're debugging V2.0 apps, pCallback must implement ICDManagedCallback2
1338 // @todo- what if somebody calls this after we've already initialized? (eg, changes
1339 // the callback underneath us)
1340 HRESULT Cordb::SetManagedHandler(ICorDebugManagedCallback *pCallback)
1341 {
1342     if (!m_initialized)
1343         return E_FAIL;
1344
1345     FAIL_IF_NEUTERED(this);
1346     VALIDATE_POINTER_TO_OBJECT(pCallback, ICorDebugManagedCallback*);
1347
1348     m_managedCallback.Clear();
1349     m_managedCallback2.Clear();
1350     m_managedCallback3.Clear();
1351
1352     // For SxS, V2.0 debuggers must implement ManagedCallback2 to handle v2.0 debug events.
1353     // For Single-CLR, A v1.0 debugger may actually geta V2.0 debuggee.
1354     pCallback->QueryInterface(IID_ICorDebugManagedCallback2, (void **)&m_managedCallback2);
1355     if (m_managedCallback2 == NULL)
1356     {
1357         if (GetDebuggerVersion() >= CorDebugVersion_2_0)
1358         {
1359             // This will leave our internal callbacks null, which future operations (Create/Attach) will
1360             // use to know that we're not sufficiently initialized.
1361             return E_NOINTERFACE;
1362         }
1363         else
1364         {
1365             // This should only be used in a single-CLR shimming scenario.
1366             m_managedCallback2.Assign(new (nothrow) DefaultManagedCallback2(this));
1367
1368             if (m_managedCallback2 == NULL)
1369             {
1370                 return E_OUTOFMEMORY;
1371             }
1372         }
1373     }
1374
1375
1376     pCallback->QueryInterface(IID_ICorDebugManagedCallback3, (void **)&m_managedCallback3);
1377     if (m_managedCallback3 == NULL)
1378     {
1379         m_managedCallback3.Assign(new (nothrow) DefaultManagedCallback3(this));
1380     }
1381
1382     if (m_managedCallback3 == NULL)
1383     {
1384         return E_OUTOFMEMORY;
1385     }
1386
1387     m_managedCallback.Assign(pCallback);
1388     return S_OK;
1389 }
1390
1391 HRESULT Cordb::SetUnmanagedHandler(ICorDebugUnmanagedCallback *pCallback)
1392 {
1393     if (!m_initialized)
1394         return E_FAIL;
1395
1396     FAIL_IF_NEUTERED(this);
1397     VALIDATE_POINTER_TO_OBJECT_OR_NULL(pCallback, ICorDebugUnmanagedCallback*);
1398
1399     m_unmanagedCallback.Assign(pCallback);
1400
1401     return S_OK;
1402 }
1403
1404 // CreateProcess() isn't supported on Windows CoreCLR.
1405 // It is currently supported on Mac CoreCLR, but that may change.
1406 bool Cordb::IsCreateProcessSupported()
1407 {
1408 #if !defined(FEATURE_DBGIPC_TRANSPORT_DI)
1409     return false;
1410 #else 
1411     return true;
1412 #endif
1413 }
1414
1415 // Given everything we know about our configuration, can we support interop-debugging
1416 bool Cordb::IsInteropDebuggingSupported()
1417 {
1418     // We explicitly refrain from checking the unmanaged callback. See comment in
1419     // ICorDebug::SetUnmanagedHandler for details.
1420 #ifdef FEATURE_INTEROP_DEBUGGING
1421
1422
1423     return true;
1424 #else
1425     return false;
1426 #endif
1427 }
1428
1429
1430 //---------------------------------------------------------------------------------------
1431 //
1432 // Implementation of ICorDebug::CreateProcess.
1433 // Creates a process.
1434 //
1435 // Arguments:
1436 //    The following arguments are passed thru unmodified to the OS CreateProcess API and 
1437 //       are defined by that API.
1438 //           lpApplicationName
1439 //           lpCommandLine
1440 //           lpProcessAttributes
1441 //           lpThreadAttributes
1442 //           bInheritHandles
1443 //           dwCreationFlags
1444 //           lpCurrentDirectory
1445 //           lpStartupInfo
1446 //           lpProcessInformation
1447 //           debuggingFlags
1448 //
1449 //    ppProcess - Space to fill in for the resulting process, returned as a valid pointer
1450 //      on any success HRESULT.
1451 //
1452 // Return Value:
1453 //    Normal HRESULT semantics.
1454 //
1455 //---------------------------------------------------------------------------------------
1456 HRESULT Cordb::CreateProcess(LPCWSTR lpApplicationName,
1457                              __in_z LPWSTR lpCommandLine,
1458                              LPSECURITY_ATTRIBUTES lpProcessAttributes,
1459                              LPSECURITY_ATTRIBUTES lpThreadAttributes,
1460                              BOOL bInheritHandles,
1461                              DWORD dwCreationFlags,
1462                              PVOID lpEnvironment,
1463                              LPCWSTR lpCurrentDirectory,
1464                              LPSTARTUPINFOW lpStartupInfo,
1465                              LPPROCESS_INFORMATION lpProcessInformation,
1466                              CorDebugCreateProcessFlags debuggingFlags,
1467                              ICorDebugProcess **ppProcess)
1468 {
1469     return CreateProcessCommon(NULL,
1470                                lpApplicationName,
1471                                lpCommandLine,
1472                                lpProcessAttributes,
1473                                lpThreadAttributes,
1474                                bInheritHandles,
1475                                dwCreationFlags,
1476                                lpEnvironment,
1477                                lpCurrentDirectory,
1478                                lpStartupInfo,
1479                                lpProcessInformation,
1480                                debuggingFlags,
1481                                ppProcess);
1482 }
1483
1484 HRESULT Cordb::CreateProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
1485                                    LPCWSTR lpApplicationName,
1486                                    __in_z LPWSTR lpCommandLine,
1487                                    LPSECURITY_ATTRIBUTES lpProcessAttributes,
1488                                    LPSECURITY_ATTRIBUTES lpThreadAttributes,
1489                                    BOOL bInheritHandles,
1490                                    DWORD dwCreationFlags,
1491                                    PVOID lpEnvironment,
1492                                    LPCWSTR lpCurrentDirectory,
1493                                    LPSTARTUPINFOW lpStartupInfo,
1494                                    LPPROCESS_INFORMATION lpProcessInformation,
1495                                    CorDebugCreateProcessFlags debuggingFlags,
1496                                    ICorDebugProcess ** ppProcess)
1497 {
1498     // If you hit this assert, it means that you are attempting to create a process without specifying the version
1499     // number.
1500     _ASSERTE(CorDebugInvalidVersion != m_debuggerSpecifiedVersion);
1501
1502     PUBLIC_API_ENTRY(this);
1503     FAIL_IF_NEUTERED(this);
1504     VALIDATE_POINTER_TO_OBJECT(ppProcess, ICorDebugProcess**);
1505
1506     HRESULT hr = S_OK;
1507
1508     EX_TRY
1509     {
1510         if (!m_initialized)
1511         {
1512             ThrowHR(E_FAIL);
1513         }
1514
1515         // Check that we support the debugger version
1516         CheckCompatibility();
1517
1518     #ifdef FEATURE_INTEROP_DEBUGGING
1519         // DEBUG_PROCESS (=0x1) means debug this process & all future children.
1520         // DEBUG_ONLY_THIS_PROCESS =(0x2) means just debug the immediate process.
1521         // If we want to support DEBUG_PROCESS, then we need to have the RS sniff for new CREATE_PROCESS
1522         // events and spawn new CordbProcess for them.
1523         switch(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
1524         {
1525             // 1) managed-only debugging
1526             case 0:
1527                 break;
1528
1529             // 2) failure - returns E_NOTIMPL. (as this would involve debugging all of our children processes).
1530             case DEBUG_PROCESS:
1531                 ThrowHR(E_NOTIMPL);
1532
1533             // 3) Interop-debugging.
1534             // Note that MSDN (at least as of Jan 2003) is wrong about this flag. MSDN claims
1535             // DEBUG_ONLY_THIS_PROCESS w/o DEBUG_PROCESS should be ignored.
1536             // But it really should do launch as a debuggee (but not auto-attach to child processes).
1537             case DEBUG_ONLY_THIS_PROCESS:
1538                 // Emprically, this is the common case for native / interop-debugging.
1539                 break;
1540
1541             // 4) Interop.
1542             // The spec for ICorDebug::CreateProcess says this is the one to use for interop-debugging.
1543             case DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS:
1544                 // Win2k does not honor these flags properly. So we just use
1545                 // It treats (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS) as if it were DEBUG_PROCESS.
1546                 // We'll just always touch up the flags, even though WinXP and above is fine here.
1547                 // Per win2k issue, strip off DEBUG_PROCESS, so that we're just left w/ DEBUG_ONLY_THIS_PROCESS.
1548                 dwCreationFlags &= ~(DEBUG_PROCESS);
1549                 break;
1550
1551             default:
1552                 __assume(0);
1553         }
1554
1555     #endif // FEATURE_INTEROP_DEBUGGING
1556
1557         // Must have a managed-callback by now.
1558         if ((m_managedCallback == NULL) || (m_managedCallback2 == NULL) || (m_managedCallback3 == NULL))
1559         {
1560             ThrowHR(E_FAIL);
1561         }
1562
1563         if (!IsCreateProcessSupported())
1564         {
1565             ThrowHR(E_NOTIMPL);
1566         }
1567
1568         if (!IsInteropDebuggingSupported() &&
1569             ((dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) != 0))
1570         {
1571             ThrowHR(CORDBG_E_INTEROP_NOT_SUPPORTED);
1572         }
1573
1574         // Check that we can even accept another debuggee before trying anything.
1575         EnsureAllowAnotherProcess();
1576
1577     } EX_CATCH_HRESULT(hr);
1578     if (FAILED(hr))
1579     {
1580         return hr;
1581     }
1582
1583     hr = ShimProcess::CreateProcess(this,
1584                                     pRemoteTarget,
1585                                     lpApplicationName,
1586                                     lpCommandLine,
1587                                     lpProcessAttributes,
1588                                     lpThreadAttributes,
1589                                     bInheritHandles,
1590                                     dwCreationFlags,
1591                                     lpEnvironment,
1592                                     lpCurrentDirectory,
1593                                     lpStartupInfo,
1594                                     lpProcessInformation,
1595                                     debuggingFlags
1596                                    );
1597
1598     LOG((LF_CORDB, LL_EVERYTHING, "Handle in Cordb::CreateProcess is: %.I64x\n", lpProcessInformation->hProcess));
1599
1600     if (SUCCEEDED(hr))
1601     {
1602         LockProcessList();
1603
1604         CordbProcess * pProcess = GetProcessList()->GetBase(lpProcessInformation->dwProcessId);
1605
1606         UnlockProcessList();
1607
1608         PREFIX_ASSUME(pProcess != NULL);
1609
1610         pProcess->ExternalAddRef();
1611         *ppProcess = (ICorDebugProcess *)pProcess;
1612     }
1613
1614     return hr;
1615 }
1616
1617
1618 HRESULT Cordb::CreateProcessEx(ICorDebugRemoteTarget * pRemoteTarget,
1619                                LPCWSTR lpApplicationName,
1620                                __in_z LPWSTR lpCommandLine,
1621                                LPSECURITY_ATTRIBUTES lpProcessAttributes,
1622                                LPSECURITY_ATTRIBUTES lpThreadAttributes,
1623                                BOOL bInheritHandles,
1624                                DWORD dwCreationFlags,
1625                                PVOID lpEnvironment,
1626                                LPCWSTR lpCurrentDirectory,
1627                                LPSTARTUPINFOW lpStartupInfo,
1628                                LPPROCESS_INFORMATION lpProcessInformation,
1629                                CorDebugCreateProcessFlags debuggingFlags,
1630                                ICorDebugProcess ** ppProcess)
1631 {
1632     if (pRemoteTarget == NULL)
1633     {
1634         return E_INVALIDARG;
1635     }
1636
1637     return CreateProcessCommon(pRemoteTarget,
1638                                lpApplicationName,
1639                                lpCommandLine,
1640                                lpProcessAttributes,
1641                                lpThreadAttributes,
1642                                bInheritHandles,
1643                                dwCreationFlags,
1644                                lpEnvironment,
1645                                lpCurrentDirectory,
1646                                lpStartupInfo,
1647                                lpProcessInformation,
1648                                debuggingFlags,
1649                                ppProcess);
1650 }
1651
1652
1653 //---------------------------------------------------------------------------------------
1654 //
1655 // Attachs to an existing process.
1656 //
1657 // Arguments:
1658 //    dwProcessID - The PID to attach to
1659 //    fWin32Attach - Flag to tell whether to attach as the Win32 debugger or not.
1660 //    ppProcess - Space to fill in for the resulting process, returned as a valid pointer
1661 //      on any success HRESULT.
1662 //
1663 // Return Value:
1664 //    Normal HRESULT semantics.
1665 //
1666 //---------------------------------------------------------------------------------------
1667 HRESULT Cordb::DebugActiveProcess(DWORD dwProcessId,
1668                                   BOOL fWin32Attach,
1669                                   ICorDebugProcess **ppProcess)
1670 {
1671     return DebugActiveProcessCommon(NULL, dwProcessId, fWin32Attach, ppProcess);
1672 }
1673
1674 HRESULT Cordb::DebugActiveProcessCommon(ICorDebugRemoteTarget * pRemoteTarget,
1675                                         DWORD dwProcessId,
1676                                         BOOL fWin32Attach,
1677                                         ICorDebugProcess ** ppProcess)
1678 {
1679     PUBLIC_API_ENTRY(this);
1680     FAIL_IF_NEUTERED(this);
1681     VALIDATE_POINTER_TO_OBJECT(ppProcess, ICorDebugProcess **);
1682
1683     HRESULT hr = S_OK;
1684
1685     EX_TRY
1686     {
1687         if (!m_initialized)
1688         {
1689             ThrowHR(E_FAIL);
1690         }
1691
1692         // Must have a managed-callback by now.
1693         if ((m_managedCallback == NULL) || (m_managedCallback2 == NULL) || (m_managedCallback3 == NULL))
1694         {
1695             ThrowHR(E_FAIL);
1696         }
1697
1698         // See the comment in Cordb::CreateProcess
1699         _ASSERTE(CorDebugInvalidVersion != m_debuggerSpecifiedVersion);
1700
1701         // Check that we support the debugger version
1702         CheckCompatibility();
1703
1704         // Check that we can even accept another debuggee before trying anything.
1705         EnsureAllowAnotherProcess();
1706
1707         // Check if we're allowed to do interop.
1708         bool fAllowInterop = IsInteropDebuggingSupported();
1709
1710         if (!fAllowInterop && fWin32Attach)
1711         {
1712             ThrowHR(CORDBG_E_INTEROP_NOT_SUPPORTED);
1713         }
1714
1715     } EX_CATCH_HRESULT(hr)
1716     if (FAILED(hr))
1717     {
1718         return hr;
1719     }
1720
1721     hr = ShimProcess::DebugActiveProcess(
1722         this,
1723         pRemoteTarget,
1724         dwProcessId,
1725         fWin32Attach == TRUE);
1726
1727     // If that worked, then there will be a process object...
1728     if (SUCCEEDED(hr))
1729     {
1730         LockProcessList();
1731         CordbProcess * pProcess = GetProcessList()->GetBase(dwProcessId);
1732
1733         if (pProcess != NULL)
1734         {
1735             // Add a reference now so process won't go away
1736             pProcess->ExternalAddRef();
1737         }
1738         UnlockProcessList();
1739
1740         if (pProcess == NULL)
1741         {
1742             // This can happen if we add the process into process hash in
1743             // SendDebugActiveProcessEvent and then process exit
1744             // before we attemp to retrieve it again from GetBase.
1745             //
1746             *ppProcess = NULL;
1747             return S_FALSE;
1748         }
1749
1750 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
1751         // This is where we queue the managed attach event in Whidbey.  In the new architecture, the Windows 
1752         // pipeline gets a loader breakpoint when native attach is completed, and that's where we queue the 
1753         // managed attach event.  See how we handle the loader breakpoint in code:ShimProcess::DefaultEventHandler.
1754         // However, the Mac debugging transport gets no such breakpoint, and so we need to do this here.
1755         // 
1756         // @dbgtodo  Mac - Ideally we should hide this in our pipeline implementation, or at least move 
1757         // this to the shim.  
1758         _ASSERTE(!fWin32Attach);
1759         {
1760             pProcess->Lock();
1761             hr = pProcess->QueueManagedAttach();
1762             pProcess->Unlock();
1763         }
1764 #endif // FEATURE_DBGIPC_TRANSPORT_DI
1765         
1766         *ppProcess = (ICorDebugProcess*) pProcess;
1767     }
1768
1769     return hr;
1770 }
1771
1772 // Make sure we want to support the debugger that's using us
1773 void Cordb::CheckCompatibility()
1774 {
1775     // Get the debugger version specified by the startup APIs and convert it to a CLR major version number
1776     CorDebugInterfaceVersion debuggerVersion = GetDebuggerVersion();
1777     DWORD clrMajor;
1778     if (debuggerVersion <= CorDebugVersion_1_0 || debuggerVersion == CorDebugVersion_1_1)
1779         clrMajor = 1;
1780     else if (debuggerVersion <= CorDebugVersion_2_0)
1781         clrMajor = 2;
1782     else if (debuggerVersion <= CorDebugVersion_4_0)
1783         clrMajor = 4;
1784     else 
1785         clrMajor = 5;   // some unrecognized future version
1786
1787     if(!CordbProcess::IsCompatibleWith(clrMajor))
1788     {
1789         // Carefully choose our error-code to get an appropriate error-message from VS 2008
1790         // If GetDebuggerVersion is >= 4, we could consider using the more-appropriate (but not
1791         // added until V4) HRESULT CORDBG_E_UNSUPPORTED_FORWARD_COMPAT that is used by 
1792         // OpenVirtualProcess, but it's probably simpler to keep ICorDebug APIs returning
1793         // consistent error codes.
1794         ThrowHR(CORDBG_E_INCOMPATIBLE_PROTOCOL);
1795     }
1796 }
1797
1798 HRESULT Cordb::DebugActiveProcessEx(ICorDebugRemoteTarget * pRemoteTarget, 
1799                                     DWORD dwProcessId, 
1800                                     BOOL fWin32Attach, 
1801                                     ICorDebugProcess ** ppProcess)
1802 {
1803     if (pRemoteTarget == NULL)
1804     {
1805         return E_INVALIDARG;
1806     }
1807
1808     return DebugActiveProcessCommon(pRemoteTarget, dwProcessId, fWin32Attach, ppProcess);
1809 }
1810
1811
1812 HRESULT Cordb::GetProcess(DWORD dwProcessId, ICorDebugProcess **ppProcess)
1813 {
1814     PUBLIC_API_ENTRY(this);
1815     FAIL_IF_NEUTERED(this);
1816     VALIDATE_POINTER_TO_OBJECT(ppProcess, ICorDebugProcess**);
1817
1818     if (!m_initialized)
1819     {
1820         return E_FAIL;
1821     }
1822
1823     LockProcessList();
1824     CordbProcess *p = GetProcessList()->GetBase(dwProcessId);
1825     UnlockProcessList();
1826
1827     if (p == NULL)
1828         return E_INVALIDARG;
1829
1830     p->ExternalAddRef();
1831     *ppProcess = static_cast<ICorDebugProcess*> (p);
1832
1833     return S_OK;
1834 }
1835
1836 HRESULT Cordb::EnumerateProcesses(ICorDebugProcessEnum **ppProcesses)
1837 {
1838     PUBLIC_API_ENTRY(this);
1839     FAIL_IF_NEUTERED(this);
1840     VALIDATE_POINTER_TO_OBJECT(ppProcesses, ICorDebugProcessEnum **);
1841
1842     HRESULT hr = S_OK;
1843     EX_TRY
1844     {
1845         if (!m_initialized)
1846         {
1847             ThrowHR(E_FAIL);
1848         }
1849
1850         // Locking here just means that the enumerator gets initialized against a consistent
1851         // process-list. If we add/remove processes w/ an outstanding enumerator, things
1852         // could still get out of sync.
1853         RSLockHolder lockHolder(&this->m_processListMutex);
1854
1855         RSInitHolder<CordbHashTableEnum> pEnum;
1856         CordbHashTableEnum::BuildOrThrow(
1857             this, 
1858             &m_pProcessEnumList, 
1859             GetProcessList(),
1860             IID_ICorDebugProcessEnum,
1861             pEnum.GetAddr());
1862         
1863
1864         pEnum.TransferOwnershipExternal(ppProcesses);
1865     }
1866     EX_CATCH_HRESULT(hr);
1867     return hr;
1868 }
1869
1870
1871 //
1872 // Note: the following defs and structs are copied from various NT headers. I wasn't able to include those headers (like
1873 // ntexapi.h) due to loads of redef problems and other conflicts with headers that we already pull in.
1874 //
1875 typedef LONG NTSTATUS;
1876
1877 #ifndef FEATURE_PAL
1878 typedef BOOL (*NTQUERYSYSTEMINFORMATION)(SYSTEM_INFORMATION_CLASS SystemInformationClass,
1879                                          PVOID SystemInformation,
1880                                          ULONG SystemInformationLength,
1881                                          PULONG ReturnLength);
1882 #endif
1883
1884 // Implementation of ICorDebug::CanLaunchOrAttach
1885 // @dbgtodo-  this all goes away in V3.
1886 // @dbgtodo-  this should go away in Dev11.
1887 HRESULT Cordb::CanLaunchOrAttach(DWORD dwProcessId, BOOL fWin32DebuggingEnabled)
1888 {
1889     PUBLIC_API_ENTRY(this);
1890     FAIL_IF_NEUTERED(this);
1891
1892     HRESULT hr = S_OK;
1893     EX_TRY
1894     {
1895         EnsureCanLaunchOrAttach(fWin32DebuggingEnabled);
1896     } 
1897     EX_CATCH_HRESULT(hr);
1898
1899     return hr;
1900 }
1901
1902 //---------------------------------------------------------------------------------------
1903 //
1904 // Throw an expcetion if we can't launch/attach.
1905 //
1906 // Arguments:
1907 //    fWin32DebuggingEnabled - true if interop-debugging, else false
1908 //
1909 // Return Value:
1910 //    None. If this returns, then it's safe to launch/attach.
1911 //    Else this throws an exception on failure.
1912 //
1913 // Assumptions:
1914 //
1915 // Notes:
1916 //    It should always be safe to launch/attach except in exceptional cases.
1917 //    @dbgtodo-  this all goes away in V3.
1918 //    @dbgtodo-  this should go away in Dev11.
1919 //
1920 void Cordb::EnsureCanLaunchOrAttach(BOOL fWin32DebuggingEnabled)
1921 {
1922     CONTRACTL
1923     {
1924         THROWS;
1925     }
1926     CONTRACTL_END;
1927     if (!m_initialized)
1928     {
1929         ThrowHR(E_FAIL);
1930     }
1931
1932     EnsureAllowAnotherProcess();
1933
1934     if (!IsInteropDebuggingSupported() && fWin32DebuggingEnabled)
1935     {
1936         ThrowHR(CORDBG_E_INTEROP_NOT_SUPPORTED);
1937     }
1938
1939     // Made it this far, we succeeded.
1940 }
1941
1942 HRESULT Cordb::CreateObjectV1(REFIID id, void **object)
1943 {
1944     return CreateObject(CorDebugVersion_1_0, id, object);
1945 }
1946
1947 #if defined(FEATURE_DBGIPC_TRANSPORT_DI)
1948 // CoreCLR activates debugger objects via direct COM rather than the shim (just like V1). For now we share the
1949 // same debug engine version as V2, though this may change in the future.
1950 HRESULT Cordb::CreateObjectTelesto(REFIID id, void ** pObject)
1951 {
1952     return CreateObject(CorDebugVersion_2_0, id, pObject);
1953 }
1954 #endif // FEATURE_DBGIPC_TRANSPORT_DI
1955
1956 // Static
1957 // Used to create an instance for a ClassFactory (thus an external ref).
1958 HRESULT Cordb::CreateObject(CorDebugInterfaceVersion iDebuggerVersion, REFIID id, void **object)
1959 {
1960     if (id != IID_IUnknown && id != IID_ICorDebug)
1961         return (E_NOINTERFACE);
1962
1963     Cordb *db = new (nothrow) Cordb(iDebuggerVersion);
1964
1965     if (db == NULL)
1966         return (E_OUTOFMEMORY);
1967
1968     *object = static_cast<ICorDebug*> (db);
1969     db->ExternalAddRef();
1970
1971     return (S_OK);
1972 }
1973
1974
1975 // This is the version of the ICorDebug APIs that the debugger believes it's consuming.
1976 // If this is a different version than that of the debuggee, we have the option of shimming
1977 // behavior.
1978 CorDebugInterfaceVersion
1979 Cordb::GetDebuggerVersion() const
1980 {
1981     return m_debuggerSpecifiedVersion;
1982 }
1983
1984 //***********************************************************************
1985 //              ICorDebugTMEnum (Thread and Module enumerator)
1986 //***********************************************************************
1987 CordbEnumFilter::CordbEnumFilter(CordbBase * pOwnerObj, NeuterList * pOwnerList)
1988     : CordbBase (pOwnerObj->GetProcess(), 0),
1989     m_pOwnerObj(pOwnerObj),
1990     m_pOwnerNeuterList(pOwnerList),
1991     m_pFirst (NULL),
1992     m_pCurrent (NULL),
1993     m_iCount (0)
1994 {
1995     _ASSERTE(m_pOwnerNeuterList != NULL);
1996     
1997     HRESULT hr = S_OK;
1998     EX_TRY
1999     {
2000         m_pOwnerNeuterList->Add(pOwnerObj->GetProcess(), this);
2001     } 
2002     EX_CATCH_HRESULT(hr);
2003     SetUnrecoverableIfFailed(GetProcess(), hr);
2004
2005 }
2006
2007 CordbEnumFilter::CordbEnumFilter(CordbEnumFilter *src)
2008     : CordbBase (src->GetProcess(), 0),
2009     m_pOwnerObj(src->m_pOwnerObj),
2010     m_pOwnerNeuterList(src->m_pOwnerNeuterList),
2011     m_pFirst (NULL),
2012     m_pCurrent (NULL)
2013 {
2014     _ASSERTE(m_pOwnerNeuterList != NULL);
2015     
2016     HRESULT hr = S_OK;
2017     EX_TRY
2018     {
2019         m_pOwnerNeuterList->Add(src->GetProcess(), this);
2020     } 
2021     EX_CATCH_HRESULT(hr);
2022     SetUnrecoverableIfFailed(GetProcess(), hr);
2023     
2024
2025
2026     int iCountSanityCheck = 0;
2027     EnumElement *pElementCur = NULL;
2028     EnumElement *pElementNew = NULL;
2029     EnumElement *pElementNewPrev = NULL;
2030
2031     m_iCount = src->m_iCount;
2032
2033     pElementCur = src->m_pFirst;
2034
2035     while (pElementCur != NULL)
2036     {
2037         pElementNew = new (nothrow) EnumElement;
2038         if (pElementNew == NULL)
2039         {
2040             // Out of memory. Clean up and bail out.
2041             goto Error;
2042         }
2043
2044         if (pElementNewPrev == NULL)
2045         {
2046             m_pFirst = pElementNew;
2047         }
2048         else
2049         {
2050             pElementNewPrev->SetNext(pElementNew);
2051         }
2052
2053         pElementNewPrev = pElementNew;
2054
2055         // Copy the element, including the AddRef part
2056         pElementNew->SetData(pElementCur->GetData());
2057         IUnknown *iu = (IUnknown *)pElementCur->GetData();
2058         iu->AddRef();
2059
2060         if (pElementCur == src->m_pCurrent)
2061             m_pCurrent = pElementNew;
2062
2063         pElementCur = pElementCur->GetNext();
2064         iCountSanityCheck++;
2065     }
2066
2067     _ASSERTE(iCountSanityCheck == m_iCount);
2068
2069     return;
2070 Error:
2071     // release all the allocated memory before returning
2072     pElementCur = m_pFirst;
2073
2074     while (pElementCur != NULL)
2075     {
2076         pElementNewPrev = pElementCur;
2077         pElementCur = pElementCur->GetNext();
2078
2079         ((ICorDebugModule *)pElementNewPrev->GetData())->Release();
2080         delete pElementNewPrev;
2081     }
2082 }
2083
2084 CordbEnumFilter::~CordbEnumFilter()
2085 {
2086     _ASSERTE(this->IsNeutered());
2087
2088     _ASSERTE(m_pFirst == NULL);
2089 }
2090
2091 void CordbEnumFilter::Neuter()
2092 {
2093     EnumElement *pElement = m_pFirst;
2094     EnumElement *pPrevious = NULL;
2095
2096     while (pElement != NULL)
2097     {
2098         pPrevious = pElement;
2099         pElement = pElement->GetNext();
2100         delete pPrevious;
2101     }
2102
2103     // Null out the head in case we get neutered again.
2104     m_pFirst = NULL;
2105     m_pCurrent = NULL;
2106
2107     CordbBase::Neuter();
2108 }
2109
2110
2111
2112 HRESULT CordbEnumFilter::QueryInterface(REFIID id, void **ppInterface)
2113 {
2114     // if we QI with the IID of the base type, we can't just return a pointer ICorDebugEnum directly, because
2115     // the cast is ambiguous. This happens because CordbEnumFilter implements both ICorDebugModuleEnum and 
2116     // ICorDebugThreadEnum, both of which derive in turn from ICorDebugEnum. This produces a diamond inheritance
2117     // graph. Thus we need a double cast. It doesn't really matter whether we pick ICorDebugThreadEnum or 
2118     // ICorDebugModuleEnum, because it will be backed by the same object regardless. 
2119     if (id == IID_ICorDebugEnum)
2120         *ppInterface = static_cast<ICorDebugEnum *>(static_cast<ICorDebugThreadEnum *>(this));
2121     else if (id == IID_ICorDebugModuleEnum)
2122         *ppInterface = (ICorDebugModuleEnum*)this;
2123     else if (id == IID_ICorDebugThreadEnum)
2124         *ppInterface = (ICorDebugThreadEnum*)this;
2125     else if (id == IID_IUnknown)
2126         *ppInterface = this;
2127     else
2128     {
2129         *ppInterface = NULL;
2130         return E_NOINTERFACE;
2131     }
2132
2133     ExternalAddRef();
2134     return S_OK;
2135 }
2136
2137 HRESULT CordbEnumFilter::Skip(ULONG celt)
2138 {
2139     HRESULT hr = S_OK;
2140     PUBLIC_API_BEGIN(this);
2141     {
2142         while ((celt-- > 0) && (m_pCurrent != NULL))
2143         {
2144             m_pCurrent = m_pCurrent->GetNext();
2145         }
2146     }
2147     PUBLIC_API_END(hr);
2148     return hr;
2149 }
2150
2151 HRESULT CordbEnumFilter::Reset()
2152 {
2153     HRESULT hr = S_OK;
2154     PUBLIC_API_BEGIN(this);
2155     {
2156         m_pCurrent = m_pFirst;
2157     }
2158     PUBLIC_API_END(hr);
2159     return hr;
2160 }
2161
2162 HRESULT CordbEnumFilter::Clone(ICorDebugEnum **ppEnum)
2163 {
2164     HRESULT hr = S_OK;
2165     PUBLIC_API_BEGIN(this);
2166     {
2167         ValidateOrThrow(ppEnum);
2168
2169         CordbEnumFilter * pClone = new CordbEnumFilter(this);
2170
2171         // Ambigous conversion from CordbEnumFilter to ICorDebugEnum, so 
2172         // we explicitly convert it through ICorDebugThreadEnum.
2173         pClone->ExternalAddRef();
2174         (*ppEnum) = static_cast<ICorDebugThreadEnum *> (pClone);
2175     }
2176     PUBLIC_API_END(hr);
2177     return hr;
2178 }
2179
2180 HRESULT CordbEnumFilter::GetCount(ULONG *pcelt)
2181 {
2182     HRESULT hr = S_OK;
2183     PUBLIC_API_BEGIN(this);
2184     {
2185         ValidateOrThrow(pcelt);
2186         *pcelt = (ULONG)m_iCount;
2187     }
2188     PUBLIC_API_END(hr);
2189     return hr;
2190 }
2191
2192 HRESULT CordbEnumFilter::Next(ULONG celt,
2193                 ICorDebugModule *objects[],
2194                 ULONG *pceltFetched)
2195 {
2196     HRESULT hr = S_OK;
2197     PUBLIC_API_BEGIN(this);
2198     {
2199         hr = NextWorker(celt, objects, pceltFetched);
2200     }
2201     PUBLIC_API_END(hr);
2202     return hr;
2203 }
2204
2205 HRESULT CordbEnumFilter::NextWorker(ULONG celt, ICorDebugModule *objects[], ULONG *pceltFetched)
2206 {
2207     // <TODO>
2208     //
2209     // nickbe 11/20/2002 10:43:39
2210     // This function allows you to enumerate threads that "belong" to a
2211     // particular AppDomain. While this operation makes some sense, it makes
2212     // very little sense to
2213     //  (a) enumerate the list of threads in the enter process
2214     //  (b) build up a hand-rolled singly linked list (grrr)
2215     // </TODO>
2216     VALIDATE_POINTER_TO_OBJECT_ARRAY(objects, ICorDebugModule *,
2217         celt, true, true);
2218     VALIDATE_POINTER_TO_OBJECT_OR_NULL(pceltFetched, ULONG *);
2219
2220     if ((pceltFetched == NULL) && (celt != 1))
2221     {
2222         return E_INVALIDARG;
2223     }
2224
2225     if (celt == 0)
2226     {
2227         if (pceltFetched != NULL)
2228         {
2229             *pceltFetched = 0;
2230         }
2231         return S_OK;
2232     }
2233
2234     HRESULT hr = S_OK;
2235
2236     ULONG count = 0;
2237
2238     while ((m_pCurrent != NULL) && (count < celt))
2239     {
2240         objects[count] = (ICorDebugModule *)m_pCurrent->GetData();
2241         m_pCurrent = m_pCurrent->GetNext();
2242         count++;
2243     }
2244
2245     if (pceltFetched != NULL)
2246     {
2247         *pceltFetched = count;
2248     }
2249
2250     //
2251     // If we reached the end of the enumeration, but not the end
2252     // of the number of requested items, we return S_FALSE.
2253     //
2254     if (count < celt)
2255     {
2256         return S_FALSE;
2257     }
2258
2259     return hr;
2260 }
2261
2262
2263 HRESULT CordbEnumFilter::Next(ULONG celt,
2264                 ICorDebugThread *objects[],
2265                 ULONG *pceltFetched)
2266 {
2267     HRESULT hr = S_OK;
2268     PUBLIC_API_BEGIN(this);
2269     {
2270         hr = NextWorker(celt, objects, pceltFetched);
2271     }
2272     PUBLIC_API_END(hr);
2273     return hr;
2274 }
2275
2276 HRESULT CordbEnumFilter::NextWorker(ULONG celt, ICorDebugThread *objects[], ULONG *pceltFetched)
2277 {
2278     // @TODO remove this class
2279     VALIDATE_POINTER_TO_OBJECT_ARRAY(objects, ICorDebugThread *, celt, true, true);
2280     VALIDATE_POINTER_TO_OBJECT_OR_NULL(pceltFetched, ULONG *);
2281
2282     if ((pceltFetched == NULL) && (celt != 1))
2283     {
2284         return E_INVALIDARG;
2285     }
2286
2287     if (celt == 0)
2288     {
2289         if (pceltFetched != NULL)
2290         {
2291             *pceltFetched = 0;
2292         }
2293         return S_OK;
2294     }
2295
2296     HRESULT hr = S_OK;
2297
2298     ULONG count = 0;
2299
2300     while ((m_pCurrent != NULL) && (count < celt))
2301     {
2302         objects[count] = (ICorDebugThread *)m_pCurrent->GetData();
2303         m_pCurrent = m_pCurrent->GetNext();
2304         count++;
2305     }
2306
2307     if (pceltFetched != NULL)
2308     {
2309         *pceltFetched = count;
2310     }
2311
2312     //
2313     // If we reached the end of the enumeration, but not the end
2314     // of the number of requested items, we return S_FALSE.
2315     //
2316     if (count < celt)
2317     {
2318         return S_FALSE;
2319     }
2320
2321     return hr;
2322 }
2323
2324
2325
2326 HRESULT CordbEnumFilter::Init (ICorDebugModuleEnum * pModEnum, CordbAssembly *pAssembly)
2327 {
2328     INTERNAL_API_ENTRY(GetProcess());
2329
2330     ICorDebugModule *pCorModule = NULL;
2331     CordbModule *pModule = NULL;
2332     ULONG ulDummy = 0;
2333
2334     HRESULT hr = pModEnum->Next(1, &pCorModule, &ulDummy);
2335
2336     //
2337     // Next returns E_FAIL if there is no next item, along with
2338     // the count being 0.  Convert that to just being S_OK.
2339     //
2340     if ((hr == E_FAIL) && (ulDummy == 0))
2341     {
2342         hr = S_OK;
2343     }
2344
2345     if (FAILED (hr))
2346         return hr;
2347
2348     EnumElement *pPrevious = NULL;
2349     EnumElement *pElement = NULL;
2350
2351     while (ulDummy != 0)
2352     {
2353         pModule = (CordbModule *)(ICorDebugModule *)pCorModule;
2354         // Is this module part of the assembly for which we're enumerating?
2355         if (pModule->m_pAssembly == pAssembly)
2356         {
2357             pElement = new (nothrow) EnumElement;
2358             if (pElement == NULL)
2359             {
2360                 // Out of memory. Clean up and bail out.
2361                 hr = E_OUTOFMEMORY;
2362                 goto Error;
2363             }
2364
2365             pElement->SetData ((void *)pCorModule);
2366             m_iCount++;
2367
2368             if (m_pFirst == NULL)
2369             {
2370                 m_pFirst = pElement;
2371             }
2372             else
2373             {
2374                 PREFIX_ASSUME(pPrevious != NULL);
2375                 pPrevious->SetNext (pElement);
2376             }
2377             pPrevious = pElement;
2378         }
2379         else
2380             ((ICorDebugModule *)pModule)->Release();
2381
2382         hr = pModEnum->Next(1, &pCorModule, &ulDummy);
2383
2384         //
2385         // Next returns E_FAIL if there is no next item, along with
2386         // the count being 0.  Convert that to just being S_OK.
2387         //
2388         if ((hr == E_FAIL) && (ulDummy == 0))
2389         {
2390             hr = S_OK;
2391         }
2392
2393         if (FAILED (hr))
2394             goto Error;
2395     }
2396
2397     m_pCurrent = m_pFirst;
2398
2399     return S_OK;
2400
2401 Error:
2402     // release all the allocated memory before returning
2403     pElement = m_pFirst;
2404
2405     while (pElement != NULL)
2406     {
2407         pPrevious = pElement;
2408         pElement = pElement->GetNext();
2409
2410         ((ICorDebugModule *)pPrevious->GetData())->Release();
2411         delete pPrevious;
2412     }
2413
2414     return hr;
2415 }
2416
2417 HRESULT CordbEnumFilter::Init (ICorDebugThreadEnum *pThreadEnum, CordbAppDomain *pAppDomain)
2418 {
2419     INTERNAL_API_ENTRY(GetProcess());
2420
2421     ICorDebugThread *pCorThread = NULL;
2422     CordbThread *pThread = NULL;
2423     ULONG ulDummy = 0;
2424
2425     HRESULT hr = pThreadEnum->Next(1, &pCorThread, &ulDummy);
2426
2427     //
2428     // Next returns E_FAIL if there is no next item, but we want to consider this
2429     // ok in this context.
2430     //
2431     if ((hr == E_FAIL) && (ulDummy == 0))
2432     {
2433         hr = S_OK;
2434     }
2435
2436     if (FAILED(hr))
2437     {
2438         return hr;
2439     }
2440
2441     EnumElement *pPrevious = NULL;
2442     EnumElement *pElement = NULL;
2443
2444     while (ulDummy > 0)
2445     {
2446         pThread = (CordbThread *)(ICorDebugThread *) pCorThread;
2447
2448         // Is this module part of the appdomain for which we're enumerating?
2449         // Note that this is rather inefficient (we call into the left side for every AppDomain),
2450         // but the whole idea of enumerating the threads of an AppDomain is pretty bad,
2451         // and we don't expect this to be used much if at all.
2452         CordbAppDomain* pThreadDomain;
2453         hr = pThread->GetCurrentAppDomain( &pThreadDomain );
2454         if( FAILED(hr) )
2455         {
2456             goto Error;
2457         }
2458        
2459         if (pThreadDomain == pAppDomain)
2460         {
2461             pElement = new (nothrow) EnumElement;
2462             if (pElement == NULL)
2463             {
2464                 // Out of memory. Clean up and bail out.
2465                 hr = E_OUTOFMEMORY;
2466                 goto Error;
2467             }
2468
2469             pElement->SetData ((void *)pCorThread);
2470             m_iCount++;
2471
2472             if (m_pFirst == NULL)
2473             {
2474                 m_pFirst = pElement;
2475             }
2476             else
2477             {
2478                 PREFIX_ASSUME(pPrevious != NULL);
2479                 pPrevious->SetNext (pElement);
2480             }
2481
2482             pPrevious = pElement;
2483         }
2484         else
2485         {
2486             ((ICorDebugThread *)pThread)->Release();
2487         }
2488
2489         //  get the next thread in the thread list
2490         hr = pThreadEnum->Next(1, &pCorThread, &ulDummy);
2491
2492         //
2493         // Next returns E_FAIL if there is no next item, along with
2494         // the count being 0.  Convert that to just being S_OK.
2495         //
2496         if ((hr == E_FAIL) && (ulDummy == 0))
2497         {
2498             hr = S_OK;
2499         }
2500
2501         if (FAILED (hr))
2502             goto Error;
2503     }
2504
2505     m_pCurrent = m_pFirst;
2506
2507     return S_OK;
2508
2509 Error:
2510     // release all the allocated memory before returning
2511     pElement = m_pFirst;
2512
2513     while (pElement != NULL)
2514     {
2515         pPrevious = pElement;
2516         pElement = pElement->GetNext();
2517
2518         ((ICorDebugThread *)pPrevious->GetData())->Release();
2519         delete pPrevious;
2520     }
2521
2522     return hr;
2523 }
2524