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.
18 # if defined(__has_feature) && __has_feature(address_sanitizer)
19 # define HAS_ADDRESS_SANITIZER
26 // I'd very much like for this to go away. Its used to disable all THROWS contracts within whatever DLL this
27 // function is called from. That's obviously very, very bad, since there's no validation of those macros. But it
28 // can be difficult to remove this without actually fixing every violation at the same time.
30 // When this flag is finally removed, remove RealCLRThrowsExceptionWorker() too and put CONTRACT_THROWS() in place
34 static BOOL dbg_fDisableThrowCheck = FALSE;
36 void DisableThrowCheck()
38 LIMITED_METHOD_CONTRACT;
40 dbg_fDisableThrowCheck = TRUE;
43 #ifdef HAS_ADDRESS_SANITIZER
44 // use the functionality from address santizier (which does not throw exceptions)
47 #define CLRThrowsExceptionWorker() RealCLRThrowsExceptionWorker(__FUNCTION__, __FILE__, __LINE__)
49 static void RealCLRThrowsExceptionWorker(__in_z const char *szFunction,
50 __in_z const char *szFile,
55 if (dbg_fDisableThrowCheck)
60 CONTRACT_THROWSEX(szFunction, szFile, lineNum);
63 #endif // HAS_ADDRESS_SANITIZER
66 #if defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS_IMPL)
68 // Fls callback to deallocate ClrDebugState when our FLS block goes away.
69 void FreeClrDebugState(LPVOID pTlsData)
72 ClrDebugState *pClrDebugState = (ClrDebugState*)pTlsData;
74 // Make sure the ClrDebugState was initialized by a compatible version of
75 // utilcode.lib. If it was initialized by an older version, we just let it leak.
76 if (pClrDebugState && (pClrDebugState->ViolationMask() & CanFreeMe) && !(pClrDebugState->ViolationMask() & BadDebugState))
81 // Since "!(pClrDebugState->m_violationmask & BadDebugState)", we know we have
82 // a valid m_pLockData
83 _ASSERTE(pClrDebugState->GetDbgStateLockData() != NULL);
84 ::HeapFree (GetProcessHeap(), 0, pClrDebugState->GetDbgStateLockData());
86 ::HeapFree (GetProcessHeap(), 0, pClrDebugState);
87 #define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem)
88 #define GetProcessHeap() Dont_Use_GetProcessHeap()
93 // This is a drastic shutoff toggle that forces all new threads to fail their CLRInitDebugState calls.
94 // We only invoke this if FLS can't allocate its master block, preventing us from tracking the shutoff
95 // on a per-thread basis.
96 BYTE* GetGlobalContractShutoffFlag()
100 static BYTE gGlobalContractShutoffFlag = 0;
101 return &gGlobalContractShutoffFlag;
102 #else //!SELF_NO_HOST
103 HINSTANCE hmod = GetCLRModule();
108 typedef BYTE*(__stdcall * PGETSHUTOFFADDRFUNC)();
109 PGETSHUTOFFADDRFUNC pGetContractShutoffFlagFunc = (PGETSHUTOFFADDRFUNC)GetProcAddress(hmod, "GetAddrOfContractShutoffFlag");
110 if (!pGetContractShutoffFlagFunc)
114 return pGetContractShutoffFlagFunc();
115 #endif //!SELF_NO_HOST
118 static BOOL AreContractsShutoff()
120 BYTE *pShutoff = GetGlobalContractShutoffFlag();
127 return 0 != *pShutoff;
131 static VOID ShutoffContracts()
133 BYTE *pShutoff = GetGlobalContractShutoffFlag();
140 //=============================================================================================
141 // Used to initialize the per-thread ClrDebugState. This is called once per thread (with
142 // possible exceptions for OOM scenarios.)
144 // No matter what, this function will not return NULL. If it can't do its job because of OOM reasons,
145 // it will return a pointer to &gBadClrDebugState which effectively disables contracts for
147 //=============================================================================================
148 ClrDebugState *CLRInitDebugState()
152 // The existing Fls apis didn't provide the support we need and adding support cleanly is
153 // messy because of the brittleness of IExecutionEngine.
155 // To understand this function, you need to know that the Fls routines have special semantics
156 // for the TlsIdx_ClrDebugState slot:
158 // - FlsSetValue will never throw. If it fails due to OOM on creation of the slot storage,
159 // it will silently bail. Thus, we must do a confirming FlsGetValue before we can conclude
160 // that the SetValue succeeded.
162 // - FlsAssociateCallback will not complain about multiple sets of the callback.
164 // - The mscorwks implemention of FlsAssociateCallback will ignore the passed in value
165 // and use the version of FreeClrDebugState compiled into mscorwks. This is needed to
166 // avoid dangling pointer races on shutdown.
169 // This is our global "bad" debug state that thread use when they OOM on CLRInitDebugState.
170 // We really only need to initialize it once but initializing each time is convenient
171 // and has low perf impact.
172 static ClrDebugState gBadClrDebugState;
173 gBadClrDebugState.ViolationMaskSet( AllViolation );
174 gBadClrDebugState.SetOkToThrow();
176 ClrDebugState *pNewClrDebugState = NULL;
177 ClrDebugState *pClrDebugState = NULL;
178 DbgStateLockData *pNewLockData = NULL;
180 // We call this first partly to force a CheckThreadState. We've hopefully chased out all the
181 // recursive contract calls inside here but if we haven't, it's best to get them out of the way
183 ClrFlsAssociateCallback(TlsIdx_ClrDebugState, FreeClrDebugState);
186 if (AreContractsShutoff())
188 pNewClrDebugState = NULL;
192 // Yuck. We cannot call the hosted allocator for ClrDebugState (it is impossible to maintain a guarantee
193 // that none of code paths, many of them called conditionally, don't themselves trigger a ClrDebugState creation.)
194 // We have to call the OS directly for this.
196 #undef GetProcessHeap
197 pNewClrDebugState = (ClrDebugState*)::HeapAlloc(GetProcessHeap(), 0, sizeof(ClrDebugState));
198 if (pNewClrDebugState != NULL)
200 // Only allocate a DbgStateLockData if its owning ClrDebugState was successfully allocated
201 pNewLockData = (DbgStateLockData *)::HeapAlloc(GetProcessHeap(), 0, sizeof(DbgStateLockData));
203 #define GetProcessHeap() Dont_Use_GetProcessHeap()
204 #define HeapAlloc(hHeap, dwFlags, dwBytes) Dont_Use_HeapAlloc(hHeap, dwFlags, dwBytes)
206 if ((pNewClrDebugState != NULL) && (pNewLockData != NULL))
208 // Both allocations succeeded, so initialize the structures, and have
209 // pNewClrDebugState point to pNewLockData. If either of the allocations
210 // failed, we'll use gBadClrDebugState for this thread, and free whichever of
211 // pNewClrDebugState or pNewLockData actually did get allocated (if either did).
212 // (See code in this function below, outside this block.)
214 pNewClrDebugState->SetStartingValues();
215 pNewClrDebugState->ViolationMaskSet( CanFreeMe );
216 _ASSERTE(!(pNewClrDebugState->ViolationMask() & BadDebugState));
218 pNewLockData->SetStartingValues();
219 pNewClrDebugState->SetDbgStateLockData(pNewLockData);
224 // This is getting really diseased. All the one-time host init stuff inside the ClrFlsStuff could actually
225 // have caused mscorwks contracts to be executed since the last time we actually checked to see if the ClrDebugState
228 // So we must make one last check to see if the ClrDebugState still needs creating.
230 ClrDebugState *pTmp = (ClrDebugState*)(ClrFlsGetValue(TlsIdx_ClrDebugState));
233 // Recursive call set up ClrDebugState for us
234 pClrDebugState = pTmp;
236 else if ((pNewClrDebugState != NULL) && (pNewLockData != NULL))
238 // Normal case: our new ClrDebugState will be the one we just allocated.
239 // Note that we require BOTH the ClrDebugState and the DbgStateLockData
240 // structures to have been successfully allocated for contracts to be
241 // enabled for this thread.
242 _ASSERTE(!(pNewClrDebugState->ViolationMask() & BadDebugState));
243 _ASSERTE(pNewClrDebugState->GetDbgStateLockData() == pNewLockData);
244 pClrDebugState = pNewClrDebugState;
248 // OOM case: HeapAlloc of newClrDebugState failed.
249 pClrDebugState = &gBadClrDebugState;
252 _ASSERTE(pClrDebugState != NULL);
255 ClrFlsSetValue(TlsIdx_ClrDebugState, (LPVOID)pClrDebugState);
257 // For the ClrDebugState index, ClrFlsSetValue does *not* throw on OOM.
258 // Instead, it silently throws away the value. So we must now do a confirming
259 // FlsGet to learn if our Set succeeded.
260 if (ClrFlsGetValue(TlsIdx_ClrDebugState) == NULL)
262 // Our FlsSet didn't work. That means it couldn't allocate the master FLS block for our thread.
263 // Now we're a bad state because not only can't we succeed, we can't record that we didn't succeed.
264 // And it's invalid to return a BadClrDebugState here only to return a good debug state later.
266 // So we now take the drastic step of forcing all future ClrInitDebugState calls to return the OOM state.
268 pClrDebugState = &gBadClrDebugState;
270 // Try once more time to set the FLS (if it doesn't work, the next call will keep cycling through here
271 // until it does succeed.)
272 ClrFlsSetValue(TlsIdx_ClrDebugState, &gBadClrDebugState);
277 // The ClrDebugState we allocated above made it into FLS iff
278 // the DbgStateLockData we allocated above made it into
279 // the FLS's ClrDebugState::m_pLockData
280 // These debug-only checks enforce this invariant
282 if (pClrDebugState != NULL)
284 // If we're here, then typically pClrDebugState is what's in FLS. However,
285 // it's possible that pClrDebugState is gBadClrDebugState, and FLS is NULL
286 // (if the last ClrFlsSetValue() failed). Either way, our checks below
287 // are valid ones to make.
289 if (pClrDebugState == pNewClrDebugState)
291 // ClrDebugState we allocated above made it into FLS, so DbgStateLockData
292 // must be there, too
293 _ASSERTE(pNewLockData != NULL);
294 _ASSERTE(pClrDebugState->GetDbgStateLockData() == pNewLockData);
298 // ClrDebugState we allocated above did NOT make it into FLS,
299 // so the DbgStateLockData we allocated must not be there, either
300 _ASSERTE(pClrDebugState->GetDbgStateLockData() == NULL || pClrDebugState->GetDbgStateLockData() != pNewLockData);
304 // One more invariant: Because of ordering & conditions around the HeapAllocs above,
305 // we'll never have a DbgStateLockData without a ClrDebugState
306 _ASSERTE((pNewLockData == NULL) || (pNewClrDebugState != NULL));
311 #undef GetProcessHeap
312 if (pNewClrDebugState != NULL && pClrDebugState != pNewClrDebugState)
314 // We allocated a ClrDebugState which didn't make it into FLS, so free it.
315 ::HeapFree (GetProcessHeap(), 0, pNewClrDebugState);
316 if (pNewLockData != NULL)
318 // We also allocated a DbgStateLockData that didn't make it into FLS, so
319 // free it, too. (Remember, we asserted above that we can only have
320 // this unused DbgStateLockData if we had an unused ClrDebugState
321 // as well (which we just freed).)
322 ::HeapFree (GetProcessHeap(), 0, pNewLockData);
325 #define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem)
326 #define GetProcessHeap() Dont_Use_GetProcessHeap()
328 // Not necessary as TLS slots are born NULL and potentially problematic for OOM cases as we can't
329 // take an exception here.
330 //ClrFlsSetValue(TlsIdx_OwnedCrstsChain, NULL);
332 return pClrDebugState;
333 } // CLRInitDebugState
335 #endif //defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS_IMPL)
337 const NoThrow nothrow = { 0 };
339 #ifdef HAS_ADDRESS_SANITIZER
340 // use standard heap functions for address santizier
344 operator new(size_t n)
347 CLRThrowsExceptionWorker();
350 STATIC_CONTRACT_THROWS;
351 STATIC_CONTRACT_GC_NOTRIGGER;
352 STATIC_CONTRACT_FAULT;
353 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
355 void * result = ClrAllocInProcessHeap(0, S_SIZE_T(n));
356 if (result == NULL) {
364 operator new[](size_t n)
367 CLRThrowsExceptionWorker();
370 STATIC_CONTRACT_THROWS;
371 STATIC_CONTRACT_GC_NOTRIGGER;
372 STATIC_CONTRACT_FAULT;
373 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
375 void * result = ClrAllocInProcessHeap(0, S_SIZE_T(n));
376 if (result == NULL) {
383 #endif // HAS_ADDRESS_SANITIZER
385 void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT
387 #ifdef HAS_ADDRESS_SANITIZER
388 // use standard heap functions for address santizier (which doesn't provide for NoThrow)
389 void * result = operator new(n);
391 STATIC_CONTRACT_NOTHROW;
392 STATIC_CONTRACT_GC_NOTRIGGER;
393 STATIC_CONTRACT_FAULT;
394 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
396 INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN()));
398 void * result = ClrAllocInProcessHeap(0, S_SIZE_T(n));
399 #endif // HAS_ADDRESS_SANITIZER
404 void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT
406 #ifdef HAS_ADDRESS_SANITIZER
407 // use standard heap functions for address santizier (which doesn't provide for NoThrow)
408 void * result = operator new[](n);
410 STATIC_CONTRACT_NOTHROW;
411 STATIC_CONTRACT_GC_NOTRIGGER;
412 STATIC_CONTRACT_FAULT;
413 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
415 INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN()));
417 void * result = ClrAllocInProcessHeap(0, S_SIZE_T(n));
418 #endif // HAS_ADDRESS_SANITIZER
423 #ifdef HAS_ADDRESS_SANITIZER
424 // use standard heap functions for address santizier
427 operator delete(void *p) NOEXCEPT
429 STATIC_CONTRACT_NOTHROW;
430 STATIC_CONTRACT_GC_NOTRIGGER;
431 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
434 ClrFreeInProcessHeap(0, p);
439 operator delete[](void *p) NOEXCEPT
441 STATIC_CONTRACT_NOTHROW;
442 STATIC_CONTRACT_GC_NOTRIGGER;
443 STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY;
446 ClrFreeInProcessHeap(0, p);
450 #endif // HAS_ADDRESS_SANITIZER
453 /* ------------------------------------------------------------------------ *
454 * New operator overloading for the executable heap
455 * ------------------------------------------------------------------------ */
459 const CExecutable executable = { 0 };
461 void * __cdecl operator new(size_t n, const CExecutable&)
463 #if defined(_DEBUG_IMPL)
464 CLRThrowsExceptionWorker();
467 STATIC_CONTRACT_THROWS;
468 STATIC_CONTRACT_GC_NOTRIGGER;
469 STATIC_CONTRACT_FAULT;
471 HANDLE hExecutableHeap = ClrGetProcessExecutableHeap();
472 if (hExecutableHeap == NULL) {
476 void * result = ClrHeapAlloc(hExecutableHeap, 0, S_SIZE_T(n));
477 if (result == NULL) {
484 void * __cdecl operator new[](size_t n, const CExecutable&)
486 #if defined(_DEBUG_IMPL)
487 CLRThrowsExceptionWorker();
490 STATIC_CONTRACT_THROWS;
491 STATIC_CONTRACT_GC_NOTRIGGER;
492 STATIC_CONTRACT_FAULT;
494 HANDLE hExecutableHeap = ClrGetProcessExecutableHeap();
495 if (hExecutableHeap == NULL) {
499 void * result = ClrHeapAlloc(hExecutableHeap, 0, S_SIZE_T(n));
500 if (result == NULL) {
507 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&)
509 STATIC_CONTRACT_NOTHROW;
510 STATIC_CONTRACT_GC_NOTRIGGER;
511 STATIC_CONTRACT_FAULT;
513 INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN()));
515 HANDLE hExecutableHeap = ClrGetProcessExecutableHeap();
516 if (hExecutableHeap == NULL)
519 void * result = ClrHeapAlloc(hExecutableHeap, 0, S_SIZE_T(n));
524 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&)
526 STATIC_CONTRACT_NOTHROW;
527 STATIC_CONTRACT_GC_NOTRIGGER;
528 STATIC_CONTRACT_FAULT;
530 INCONTRACT(_ASSERTE(!ARE_FAULTS_FORBIDDEN()));
532 HANDLE hExecutableHeap = ClrGetProcessExecutableHeap();
533 if (hExecutableHeap == NULL)
536 void * result = ClrHeapAlloc(hExecutableHeap, 0, S_SIZE_T(n));
541 #endif // FEATURE_PAL
545 // This is a DEBUG routing to verify that a memory region complies with executable requirements
546 BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length)
548 #if defined(CROSSGEN_COMPILE) || defined(FEATURE_PAL)
549 // No NX support on PAL or for crossgen compilations.
551 #else // !(CROSSGEN_COMPILE || FEATURE_PAL)
552 BYTE *regionStart = (BYTE*) ALIGN_DOWN((BYTE*)lpMem, GetOsPageSize());
553 BYTE *regionEnd = (BYTE*) ALIGN_UP((BYTE*)lpMem+length, GetOsPageSize());
554 _ASSERTE(length > 0);
555 _ASSERTE(regionStart < regionEnd);
557 while(regionStart < regionEnd)
559 MEMORY_BASIC_INFORMATION mbi;
561 SIZE_T cbBytes = ClrVirtualQuery(regionStart, &mbi, sizeof(mbi));
564 // The pages must have EXECUTE set
565 if(!(mbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)))
568 _ASSERTE((BYTE*)mbi.BaseAddress + mbi.RegionSize > regionStart);
569 regionStart = (BYTE*)mbi.BaseAddress + mbi.RegionSize;
573 #endif // CROSSGEN_COMPILE || FEATURE_PAL
581 // Access various ExecutionEngine support services, like a logical TLS that abstracts
582 // fiber vs. thread issues. We obtain it from a DLL export via the shim.
584 typedef IExecutionEngine * (__stdcall * IEE_FPTR) ();
587 // Access various ExecutionEngine support services, like a logical TLS that abstracts
588 // fiber vs. thread issues.
589 // From an IExecutionEngine is possible to get other services via QueryInterfaces such
590 // as memory management
592 IExecutionEngine *g_pExecutionEngine = NULL;
595 BYTE g_ExecutionEngineInstance[sizeof(UtilExecutionEngine)];
599 IExecutionEngine *GetExecutionEngine()
601 STATIC_CONTRACT_NOTHROW;
602 STATIC_CONTRACT_GC_NOTRIGGER;
603 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
604 SUPPORTS_DAC_HOST_ONLY;
606 if (g_pExecutionEngine == NULL)
608 IExecutionEngine* pExecutionEngine;
610 // Create a local copy on the stack and then copy it over to the static instance.
611 // This avoids race conditions caused by multiple initializations of vtable in the constructor
612 UtilExecutionEngine local;
613 memcpy((void*)&g_ExecutionEngineInstance, (void*)&local, sizeof(UtilExecutionEngine));
614 pExecutionEngine = (IExecutionEngine*)(UtilExecutionEngine*)&g_ExecutionEngineInstance;
616 // statically linked.
617 VALIDATECORECLRCALLBACKS();
618 pExecutionEngine = g_CoreClrCallbacks.m_pfnIEE();
619 #endif // SELF_NO_HOST
621 //We use an explicit memory barrier here so that the reference g_pExecutionEngine is valid when
622 //it is used, This ia a requirement on platforms with weak memory model . We cannot use VolatileStore
623 //because they are the same as normal assignment for DAC builds [see code:VOLATILE]
626 g_pExecutionEngine = pExecutionEngine;
629 // It's a bug to ask for the ExecutionEngine interface in scenarios where the
630 // ExecutionEngine cannot be loaded.
631 _ASSERTE(g_pExecutionEngine);
632 return g_pExecutionEngine;
633 } // GetExecutionEngine
635 IEEMemoryManager * GetEEMemoryManager()
637 STATIC_CONTRACT_GC_NOTRIGGER;
638 STATIC_CONTRACT_NOTHROW;
639 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
640 SUPPORTS_DAC_HOST_ONLY;
642 static IEEMemoryManager *pEEMemoryManager = NULL;
643 if (NULL == pEEMemoryManager) {
644 IExecutionEngine *pExecutionEngine = GetExecutionEngine();
645 _ASSERTE(pExecutionEngine);
647 // It is dangerous to pass a global pointer to QueryInterface. The pointer may be set
648 // to NULL in the call. Imagine that thread 1 calls QI, and get a pointer. But before thread 1
649 // returns the pointer to caller, thread 2 calls QI and the pointer is set to NULL.
650 IEEMemoryManager *pEEMM;
651 pExecutionEngine->QueryInterface(IID_IEEMemoryManager, (void**)&pEEMM);
652 pEEMemoryManager = pEEMM;
654 // It's a bug to ask for the MemoryManager interface in scenarios where it cannot be loaded.
655 _ASSERTE(pEEMemoryManager);
656 return pEEMemoryManager;
659 // should return some error code or exception
660 void SetExecutionEngine(IExecutionEngine *pExecutionEngine)
662 STATIC_CONTRACT_NOTHROW;
663 STATIC_CONTRACT_GC_NOTRIGGER;
665 _ASSERTE(pExecutionEngine && !g_pExecutionEngine);
666 if (!g_pExecutionEngine) {
667 g_pExecutionEngine = pExecutionEngine;
668 g_pExecutionEngine->AddRef();
672 void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback)
676 GetExecutionEngine()->TLS_AssociateCallback(slot, callback);
679 LPVOID *ClrFlsGetBlockGeneric()
683 return (LPVOID *) GetExecutionEngine()->TLS_GetDataBlock();
686 CLRFLSGETBLOCK __ClrFlsGetBlock = ClrFlsGetBlockGeneric;
688 CRITSEC_COOKIE ClrCreateCriticalSection(CrstType crstType, CrstFlags flags)
692 return GetExecutionEngine()->CreateLock(NULL, (LPCSTR)crstType, flags);
695 HRESULT ClrDeleteCriticalSection(CRITSEC_COOKIE cookie)
698 GetExecutionEngine()->DestroyLock(cookie);
702 void ClrEnterCriticalSection(CRITSEC_COOKIE cookie)
706 return GetExecutionEngine()->AcquireLock(cookie);
709 void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie)
713 return GetExecutionEngine()->ReleaseLock(cookie);
716 EVENT_COOKIE ClrCreateAutoEvent(BOOL bInitialState)
720 return GetExecutionEngine()->CreateAutoEvent(bInitialState);
723 EVENT_COOKIE ClrCreateManualEvent(BOOL bInitialState)
727 return GetExecutionEngine()->CreateManualEvent(bInitialState);
730 void ClrCloseEvent(EVENT_COOKIE event)
734 GetExecutionEngine()->CloseEvent(event);
737 BOOL ClrSetEvent(EVENT_COOKIE event)
741 return GetExecutionEngine()->ClrSetEvent(event);
744 BOOL ClrResetEvent(EVENT_COOKIE event)
748 return GetExecutionEngine()->ClrResetEvent(event);
751 DWORD ClrWaitEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable)
755 return GetExecutionEngine()->WaitForEvent(event, dwMilliseconds, bAlertable);
758 SEMAPHORE_COOKIE ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax)
762 return GetExecutionEngine()->ClrCreateSemaphore(dwInitial, dwMax);
765 void ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore)
769 GetExecutionEngine()->ClrCloseSemaphore(semaphore);
772 BOOL ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount)
776 return GetExecutionEngine()->ClrReleaseSemaphore(semaphore, lReleaseCount, lpPreviousCount);
779 DWORD ClrWaitSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable)
783 return GetExecutionEngine()->ClrWaitForSemaphore(semaphore, dwMilliseconds, bAlertable);
786 MUTEX_COOKIE ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,
792 return GetExecutionEngine()->ClrCreateMutex(lpMutexAttributes, bInitialOwner, lpName);
795 void ClrCloseMutex(MUTEX_COOKIE mutex)
799 GetExecutionEngine()->ClrCloseMutex(mutex);
802 BOOL ClrReleaseMutex(MUTEX_COOKIE mutex)
806 return GetExecutionEngine()->ClrReleaseMutex(mutex);
809 DWORD ClrWaitForMutex(MUTEX_COOKIE mutex, DWORD dwMilliseconds, BOOL bAlertable)
813 return GetExecutionEngine()->ClrWaitForMutex(mutex, dwMilliseconds, bAlertable);
816 DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable)
820 return GetExecutionEngine()->ClrSleepEx(dwMilliseconds, bAlertable);
823 LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect)
827 LPVOID result = GetEEMemoryManager()->ClrVirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
828 LOG((LF_EEMEM, LL_INFO100000, "ClrVirtualAlloc (0x%p, 0x%06x, 0x%06x, 0x%02x) = 0x%p\n", lpAddress, dwSize, flAllocationType, flProtect, result));
833 BOOL ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType)
837 LOG((LF_EEMEM, LL_INFO100000, "ClrVirtualFree (0x%p, 0x%06x, 0x%04x)\n", lpAddress, dwSize, dwFreeType));
838 BOOL result = GetEEMemoryManager()->ClrVirtualFree(lpAddress, dwSize, dwFreeType);
843 SIZE_T ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
847 LOG((LF_EEMEM, LL_INFO100000, "ClrVirtualQuery (0x%p)\n", lpAddress));
848 return GetEEMemoryManager()->ClrVirtualQuery(lpAddress, lpBuffer, dwLength);
851 BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect)
855 LOG((LF_EEMEM, LL_INFO100000, "ClrVirtualProtect(0x%p, 0x%06x, 0x%02x)\n", lpAddress, dwSize, flNewProtect));
856 return GetEEMemoryManager()->ClrVirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect);
859 HANDLE ClrGetProcessHeap()
863 return GetEEMemoryManager()->ClrGetProcessHeap();
866 HANDLE ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize)
870 return GetEEMemoryManager()->ClrHeapCreate(flOptions, dwInitialSize, dwMaximumSize);
873 BOOL ClrHeapDestroy(HANDLE hHeap)
877 return GetEEMemoryManager()->ClrHeapDestroy(hHeap);
880 LPVOID ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, S_SIZE_T dwBytes)
884 if(dwBytes.IsOverflow()) return NULL;
886 LPVOID result = GetEEMemoryManager()->ClrHeapAlloc(hHeap, dwFlags, dwBytes.Value());
891 BOOL ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
895 BOOL result = GetEEMemoryManager()->ClrHeapFree(hHeap, dwFlags, lpMem);
900 BOOL ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
904 return GetEEMemoryManager()->ClrHeapValidate(hHeap, dwFlags, lpMem);
907 HANDLE ClrGetProcessExecutableHeap()
911 return GetEEMemoryManager()->ClrGetProcessExecutableHeap();
914 void GetLastThrownObjectExceptionFromThread(void **ppvException)
918 GetExecutionEngine()->GetLastThrownObjectExceptionFromThread(ppvException);