| 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 | |
| 6 | // |
| 7 | |
| 8 | |
| 9 | #ifndef __CLRHOST_H__ |
| 10 | #define __CLRHOST_H__ |
| 11 | |
| 12 | #include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions |
| 13 | #ifdef CreateSemaphore |
| 14 | #undef CreateSemaphore |
| 15 | #endif |
| 16 | #include "mscoree.h" |
| 17 | #include "clrinternal.h" |
| 18 | #include "switches.h" |
| 19 | #include "holder.h" |
| 20 | #include "new.hpp" |
| 21 | #include "staticcontract.h" |
| 22 | #include "predeftlsslot.h" |
| 23 | #include "safemath.h" |
| 24 | #include "debugreturn.h" |
| 25 | |
| 26 | #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) |
| 27 | #define _DEBUG_IMPL 1 |
| 28 | #endif |
| 29 | |
| 30 | #define BEGIN_PRESERVE_LAST_ERROR \ |
| 31 | { \ |
| 32 | DWORD __dwLastError = ::GetLastError(); \ |
| 33 | DEBUG_ASSURE_NO_RETURN_BEGIN(PRESERVE_LAST_ERROR); \ |
| 34 | { |
| 35 | |
| 36 | #define END_PRESERVE_LAST_ERROR \ |
| 37 | } \ |
| 38 | DEBUG_ASSURE_NO_RETURN_END(PRESERVE_LAST_ERROR); \ |
| 39 | ::SetLastError(__dwLastError); \ |
| 40 | } |
| 41 | |
| 42 | // |
| 43 | // TRASH_LASTERROR macro sets bogus last error in debug builds to help find places that fail to save it |
| 44 | // |
| 45 | #ifdef _DEBUG |
| 46 | |
| 47 | #define LAST_ERROR_TRASH_VALUE 42424 /* = 0xa5b8 */ |
| 48 | |
| 49 | #define TRASH_LASTERROR \ |
| 50 | SetLastError(LAST_ERROR_TRASH_VALUE) |
| 51 | |
| 52 | #else // _DEBUG |
| 53 | |
| 54 | #define TRASH_LASTERROR |
| 55 | |
| 56 | #endif // _DEBUG |
| 57 | |
| 58 | IExecutionEngine *GetExecutionEngine(); |
| 59 | IEEMemoryManager *GetEEMemoryManager(); |
| 60 | |
| 61 | LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); |
| 62 | BOOL ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); |
| 63 | SIZE_T ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); |
| 64 | BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); |
| 65 | LPVOID ClrDebugAlloc (size_t size, LPCSTR pszFile, int iLineNo); |
| 66 | HANDLE ClrGetProcessHeap(); |
| 67 | HANDLE ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize); |
| 68 | BOOL ClrHeapDestroy(HANDLE hHeap); |
| 69 | LPVOID ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, S_SIZE_T dwBytes); |
| 70 | BOOL ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); |
| 71 | BOOL ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); |
| 72 | HANDLE ClrGetProcessExecutableHeap(); |
| 73 | |
| 74 | |
| 75 | #ifdef FAILPOINTS_ENABLED |
| 76 | extern int RFS_HashStack(); |
| 77 | #endif |
| 78 | |
| 79 | |
| 80 | void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback); |
| 81 | |
| 82 | typedef LPVOID* (*CLRFLSGETBLOCK)(); |
| 83 | extern CLRFLSGETBLOCK __ClrFlsGetBlock; |
| 84 | |
| 85 | // Combining getter/setter into a single call |
| 86 | inline void ClrFlsIncrementValue(DWORD slot, int increment) |
| 87 | { |
| 88 | STATIC_CONTRACT_NOTHROW; |
| 89 | STATIC_CONTRACT_GC_NOTRIGGER; |
| 90 | STATIC_CONTRACT_MODE_ANY; |
| 91 | STATIC_CONTRACT_CANNOT_TAKE_LOCK; |
| 92 | STATIC_CONTRACT_SO_TOLERANT; |
| 93 | |
| 94 | _ASSERTE(increment != 0); |
| 95 | |
| 96 | void **block = (*__ClrFlsGetBlock)(); |
| 97 | size_t value; |
| 98 | |
| 99 | if (block != NULL) |
| 100 | { |
| 101 | value = (size_t) block[slot]; |
| 102 | |
| 103 | _ASSERTE((increment > 0) || (value + increment < value)); |
| 104 | block[slot] = (void *) (value + increment); |
| 105 | } |
| 106 | else |
| 107 | { |
| 108 | BEGIN_PRESERVE_LAST_ERROR; |
| 109 | |
| 110 | ANNOTATION_VIOLATION(SOToleranceViolation); |
| 111 | |
| 112 | IExecutionEngine * pEngine = GetExecutionEngine(); |
| 113 | value = (size_t) pEngine->TLS_GetValue(slot); |
| 114 | |
| 115 | _ASSERTE((increment > 0) || (value + increment < value)); |
| 116 | pEngine->TLS_SetValue(slot, (void *) (value + increment)); |
| 117 | |
| 118 | END_PRESERVE_LAST_ERROR; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | |
| 123 | inline void * ClrFlsGetValue (DWORD slot) |
| 124 | { |
| 125 | STATIC_CONTRACT_NOTHROW; |
| 126 | STATIC_CONTRACT_GC_NOTRIGGER; |
| 127 | STATIC_CONTRACT_MODE_ANY; |
| 128 | STATIC_CONTRACT_CANNOT_TAKE_LOCK; |
| 129 | STATIC_CONTRACT_SO_TOLERANT; |
| 130 | |
| 131 | void **block = (*__ClrFlsGetBlock)(); |
| 132 | if (block != NULL) |
| 133 | { |
| 134 | return block[slot]; |
| 135 | } |
| 136 | else |
| 137 | { |
| 138 | ANNOTATION_VIOLATION(SOToleranceViolation); |
| 139 | |
| 140 | void * value = GetExecutionEngine()->TLS_GetValue(slot); |
| 141 | return value; |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | |
| 146 | inline BOOL ClrFlsCheckValue(DWORD slot, void ** pValue) |
| 147 | { |
| 148 | STATIC_CONTRACT_NOTHROW; |
| 149 | STATIC_CONTRACT_GC_NOTRIGGER; |
| 150 | STATIC_CONTRACT_MODE_ANY; |
| 151 | STATIC_CONTRACT_SO_TOLERANT; |
| 152 | |
| 153 | #ifdef _DEBUG |
| 154 | *pValue = ULongToPtr(0xcccccccc); |
| 155 | #endif //_DEBUG |
| 156 | void **block = (*__ClrFlsGetBlock)(); |
| 157 | if (block != NULL) |
| 158 | { |
| 159 | *pValue = block[slot]; |
| 160 | return TRUE; |
| 161 | } |
| 162 | else |
| 163 | { |
| 164 | ANNOTATION_VIOLATION(SOToleranceViolation); |
| 165 | BOOL result = GetExecutionEngine()->TLS_CheckValue(slot, pValue); |
| 166 | return result; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | inline void ClrFlsSetValue(DWORD slot, void *pData) |
| 171 | { |
| 172 | STATIC_CONTRACT_NOTHROW; |
| 173 | STATIC_CONTRACT_GC_NOTRIGGER; |
| 174 | STATIC_CONTRACT_MODE_ANY; |
| 175 | STATIC_CONTRACT_CANNOT_TAKE_LOCK; |
| 176 | STATIC_CONTRACT_SO_TOLERANT; |
| 177 | |
| 178 | void **block = (*__ClrFlsGetBlock)(); |
| 179 | if (block != NULL) |
| 180 | { |
| 181 | block[slot] = pData; |
| 182 | } |
| 183 | else |
| 184 | { |
| 185 | BEGIN_PRESERVE_LAST_ERROR; |
| 186 | |
| 187 | ANNOTATION_VIOLATION(SOToleranceViolation); |
| 188 | GetExecutionEngine()->TLS_SetValue(slot, pData); |
| 189 | |
| 190 | END_PRESERVE_LAST_ERROR; |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | typedef LPVOID (*FastAllocInProcessHeapFunc)(DWORD dwFlags, SIZE_T dwBytes); |
| 195 | extern FastAllocInProcessHeapFunc __ClrAllocInProcessHeap; |
| 196 | inline LPVOID ClrAllocInProcessHeap(DWORD dwFlags, S_SIZE_T dwBytes) |
| 197 | { |
| 198 | STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; |
| 199 | if (dwBytes.IsOverflow()) |
| 200 | { |
| 201 | return NULL; |
| 202 | } |
| 203 | |
| 204 | #ifndef SELF_NO_HOST |
| 205 | return __ClrAllocInProcessHeap(dwFlags, dwBytes.Value()); |
| 206 | #else |
| 207 | #undef HeapAlloc |
| 208 | #undef GetProcessHeap |
| 209 | static HANDLE ProcessHeap = NULL; |
| 210 | if (ProcessHeap == NULL) |
| 211 | ProcessHeap = GetProcessHeap(); |
| 212 | return ::HeapAlloc(ProcessHeap,dwFlags,dwBytes.Value()); |
| 213 | #define HeapAlloc(hHeap, dwFlags, dwBytes) Dont_Use_HeapAlloc(hHeap, dwFlags, dwBytes) |
| 214 | #define GetProcessHeap() Dont_Use_GetProcessHeap() |
| 215 | #endif |
| 216 | } |
| 217 | |
| 218 | typedef BOOL (*FastFreeInProcessHeapFunc)(DWORD dwFlags, LPVOID lpMem); |
| 219 | extern FastFreeInProcessHeapFunc __ClrFreeInProcessHeap; |
| 220 | inline BOOL ClrFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem) |
| 221 | { |
| 222 | STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; |
| 223 | #ifndef SELF_NO_HOST |
| 224 | return __ClrFreeInProcessHeap(dwFlags, lpMem); |
| 225 | #else |
| 226 | #undef HeapFree |
| 227 | #undef GetProcessHeap |
| 228 | static HANDLE ProcessHeap = NULL; |
| 229 | if (ProcessHeap == NULL) |
| 230 | ProcessHeap = GetProcessHeap(); |
| 231 | return (BOOL)(BYTE)::HeapFree(ProcessHeap, dwFlags, lpMem); |
| 232 | #define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem) |
| 233 | #define GetProcessHeap() Dont_Use_GetProcessHeap() |
| 234 | #endif |
| 235 | } |
| 236 | |
| 237 | // Critical section support for CLR DLLs other than the the EE. |
| 238 | // Include the header defining each Crst type and its corresponding level (relative rank). This is |
| 239 | // auto-generated from a tool that takes a high-level description of each Crst type and its dependencies. |
| 240 | #include "crsttypes.h" |
| 241 | |
| 242 | // critical section api |
| 243 | CRITSEC_COOKIE ClrCreateCriticalSection(CrstType type, CrstFlags flags); |
| 244 | HRESULT ClrDeleteCriticalSection(CRITSEC_COOKIE cookie); |
| 245 | void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); |
| 246 | void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); |
| 247 | |
| 248 | // event api |
| 249 | EVENT_COOKIE ClrCreateAutoEvent(BOOL bInitialState); |
| 250 | EVENT_COOKIE ClrCreateManualEvent(BOOL bInitialState); |
| 251 | void ClrCloseEvent(EVENT_COOKIE event); |
| 252 | BOOL ClrSetEvent(EVENT_COOKIE event); |
| 253 | BOOL ClrResetEvent(EVENT_COOKIE event); |
| 254 | DWORD ClrWaitEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable); |
| 255 | |
| 256 | // semaphore api |
| 257 | SEMAPHORE_COOKIE ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax); |
| 258 | void ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore); |
| 259 | BOOL ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount); |
| 260 | DWORD ClrWaitSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable); |
| 261 | |
| 262 | // mutex api |
| 263 | MUTEX_COOKIE ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName); |
| 264 | void ClrCloseMutex(MUTEX_COOKIE mutex); |
| 265 | BOOL ClrReleaseMutex(MUTEX_COOKIE mutex); |
| 266 | DWORD ClrWaitForMutex(MUTEX_COOKIE mutex,DWORD dwMilliseconds,BOOL bAlertable); |
| 267 | DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable); |
| 268 | |
| 269 | // Rather than use the above APIs directly, it is recommended that holder classes |
| 270 | // be used. This guarantees that the locks will be vacated when the scope is popped, |
| 271 | // either on exception or on return. |
| 272 | |
| 273 | typedef Holder<CRITSEC_COOKIE, ClrEnterCriticalSection, ClrLeaveCriticalSection, NULL> CRITSEC_Holder; |
| 274 | |
| 275 | // Use this holder to manage CRITSEC_COOKIE allocation to ensure it will be released if anything goes wrong |
| 276 | FORCEINLINE void VoidClrDeleteCriticalSection(CRITSEC_COOKIE cs) { if (cs != NULL) ClrDeleteCriticalSection(cs); } |
| 277 | typedef Wrapper<CRITSEC_COOKIE, DoNothing<CRITSEC_COOKIE>, VoidClrDeleteCriticalSection, NULL> CRITSEC_AllocationHolder; |
| 278 | |
| 279 | class Event { |
| 280 | public: |
| 281 | Event () |
| 282 | : m_event(NULL) |
| 283 | {STATIC_CONTRACT_LEAF;} |
| 284 | ~Event () |
| 285 | { |
| 286 | STATIC_CONTRACT_WRAPPER; |
| 287 | CloseEvent(); |
| 288 | } |
| 289 | |
| 290 | void CreateAutoEvent(BOOL bInitialState) |
| 291 | { |
| 292 | STATIC_CONTRACT_WRAPPER; |
| 293 | m_event = ClrCreateAutoEvent(bInitialState); |
| 294 | } |
| 295 | void CreateManualEvent(BOOL bInitialState) |
| 296 | { |
| 297 | STATIC_CONTRACT_WRAPPER; |
| 298 | m_event = ClrCreateManualEvent(bInitialState); |
| 299 | } |
| 300 | void CloseEvent() |
| 301 | { |
| 302 | STATIC_CONTRACT_WRAPPER; |
| 303 | if (m_event != NULL) |
| 304 | ClrCloseEvent(m_event); |
| 305 | m_event = NULL; |
| 306 | } |
| 307 | |
| 308 | BOOL Set() |
| 309 | { |
| 310 | STATIC_CONTRACT_WRAPPER; |
| 311 | return ClrSetEvent(m_event); |
| 312 | } |
| 313 | BOOL Reset() |
| 314 | { |
| 315 | STATIC_CONTRACT_WRAPPER; |
| 316 | return ClrResetEvent(m_event); |
| 317 | } |
| 318 | DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) |
| 319 | { |
| 320 | STATIC_CONTRACT_WRAPPER; |
| 321 | return ClrWaitEvent(m_event, dwMilliseconds, bAlertable); |
| 322 | } |
| 323 | |
| 324 | private: |
| 325 | EVENT_COOKIE m_event; |
| 326 | }; |
| 327 | |
| 328 | class Semaphore { |
| 329 | public: |
| 330 | Semaphore () |
| 331 | : m_semaphore(NULL) |
| 332 | {STATIC_CONTRACT_LEAF;} |
| 333 | ~Semaphore () |
| 334 | { |
| 335 | STATIC_CONTRACT_WRAPPER; |
| 336 | Close(); |
| 337 | } |
| 338 | |
| 339 | void Create(DWORD dwInitial, DWORD dwMax) |
| 340 | { |
| 341 | STATIC_CONTRACT_WRAPPER; |
| 342 | m_semaphore = ClrCreateSemaphore(dwInitial, dwMax); |
| 343 | } |
| 344 | void Close() |
| 345 | { |
| 346 | STATIC_CONTRACT_WRAPPER; |
| 347 | if (m_semaphore != NULL) |
| 348 | ClrCloseSemaphore(m_semaphore); |
| 349 | m_semaphore = NULL; |
| 350 | } |
| 351 | |
| 352 | BOOL Release(LONG lReleaseCount, LONG* lpPreviousCount) |
| 353 | { |
| 354 | STATIC_CONTRACT_WRAPPER; |
| 355 | return ClrReleaseSemaphore(m_semaphore, lReleaseCount, lpPreviousCount); |
| 356 | } |
| 357 | DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) |
| 358 | { |
| 359 | STATIC_CONTRACT_WRAPPER; |
| 360 | return ClrWaitSemaphore(m_semaphore, dwMilliseconds, bAlertable); |
| 361 | } |
| 362 | |
| 363 | private: |
| 364 | SEMAPHORE_COOKIE m_semaphore; |
| 365 | }; |
| 366 | |
| 367 | HMODULE GetCLRModule (); |
| 368 | |
| 369 | #ifndef FEATURE_NO_HOST |
| 370 | /* |
| 371 | Here we start the list of functions we want to deprecate. |
| 372 | We use a define to generate a linker error. |
| 373 | We must insure to include the header file that has the definition we are about |
| 374 | to deprecate before we use the #define otherwise we will run into a linker error |
| 375 | when legitimately undef'ing the function |
| 376 | */ |
| 377 | |
| 378 | // |
| 379 | // following are windows deprecates |
| 380 | // |
| 381 | #include <windows.h> |
| 382 | |
| 383 | /* |
| 384 | If you are reading this, you have probably tracked down the fact that memory Alloc, |
| 385 | etc. don't work inside your DLL because you are using src\inc & src\utilcode |
| 386 | services. |
| 387 | You need to use the ClrXXX equivalent functions to properly guarantee your code |
| 388 | works correctly wrt hosting and others execution engine requirements. |
| 389 | Check the list of Clr functions above |
| 390 | */ |
| 391 | |
| 392 | #define GetProcessHeap() \ |
| 393 | Dont_Use_GetProcessHeap() |
| 394 | |
| 395 | #define VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect) \ |
| 396 | Dont_Use_VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect) |
| 397 | |
| 398 | #define VirtualFree(lpAddress, dwSize, dwFreeType) \ |
| 399 | Dont_Use_VirtualFree(lpAddress, dwSize, dwFreeType) |
| 400 | |
| 401 | #define VirtualQuery(lpAddress, lpBuffer, dwLength) \ |
| 402 | Dont_Use_VirtualQuery(lpAddress, lpBuffer, dwLength) |
| 403 | |
| 404 | #define VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect) \ |
| 405 | Dont_Use_VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect) |
| 406 | |
| 407 | #define HeapCreate(flOptions, dwInitialSize, dwMaximumSize) \ |
| 408 | Dont_Use_HeapCreate(flOptions, dwInitialSize, dwMaximumSize) |
| 409 | |
| 410 | #define HeapDestroy(hHeap) \ |
| 411 | Dont_Use_HeapDestroy(hHeap) |
| 412 | |
| 413 | #define HeapAlloc(hHeap, dwFlags, dwBytes) \ |
| 414 | Dont_Use_HeapAlloc(hHeap, dwFlags, dwBytes) |
| 415 | |
| 416 | #define HeapReAlloc(hHeap, dwFlags, lpMem, dwBytes) \ |
| 417 | Dont_Use_HeapReAlloc(hHeap, dwFlags, lpMem, dwBytes) |
| 418 | |
| 419 | #define HeapFree(hHeap, dwFlags, lpMem) \ |
| 420 | Dont_Use_HeapFree(hHeap, dwFlags, lpMem) |
| 421 | |
| 422 | #define HeapValidate(hHeap, dwFlags, lpMem) \ |
| 423 | Dont_Use_HeapValidate(hHeap, dwFlags, lpMem) |
| 424 | |
| 425 | #define LocalAlloc(uFlags, uBytes) \ |
| 426 | Dont_Use_LocalAlloc(uFlags, uBytes) |
| 427 | |
| 428 | #define LocalFree(hMem) \ |
| 429 | Dont_Use_LocalFree(hMem) |
| 430 | |
| 431 | #define LocalReAlloc(hMem, uBytes, uFlags) \ |
| 432 | Dont_Use_LocalReAlloc(hMem, uBytes, uFlags) |
| 433 | |
| 434 | #define GlobalAlloc(uFlags, dwBytes) \ |
| 435 | Dont_Use_GlobalAlloc(uFlags, dwBytes) |
| 436 | |
| 437 | #define GlobalFree(hMem) \ |
| 438 | Dont_Use_GlobalFree(hMem) |
| 439 | |
| 440 | //#define ExitThread Dont_Use_ExitThread |
| 441 | |
| 442 | #define ExitProcess Dont_Use_ExitProcess |
| 443 | |
| 444 | /* |
| 445 | If you are reading this, you have probably tracked down the fact that TlsAlloc, |
| 446 | etc. don't work inside your DLL because you are using src\inc & src\utilcode |
| 447 | services. |
| 448 | |
| 449 | This is because the CLR can operate in a fiberized environment under host control. |
| 450 | When this is the case, logical thread local storage must be fiber-relative rather |
| 451 | than thread-relative. |
| 452 | |
| 453 | Although the OS provides FLS routines on .NET Server, it does not yet provide |
| 454 | those services on WinXP or Win2K. So you cannot just use fiber routines from |
| 455 | the OS. |
| 456 | |
| 457 | Instead, you must use the ClrFls_ routines described above. However, there are |
| 458 | some important differences between these EE-provided services and the OS TLS |
| 459 | services that you are used to: |
| 460 | |
| 461 | 1) There is no TlsAlloc/FlsAlloc equivalent. You must statically describe |
| 462 | your needs via the PredefinedTlsSlots below. If you have dynamic requirements, |
| 463 | you should give yourself a single static slot and then build your dynamic |
| 464 | requirements on top of this. The lack of a dynamic API is a deliberate |
| 465 | choice on my part, rather than lack of time. |
| 466 | |
| 467 | 2) You can provide a cleanup routine, which we will call on your behalf. However, |
| 468 | this can be called on a different thread than the "thread" (fiber or thread) |
| 469 | which holds the data. It can be called after that thread has actually been |
| 470 | terminated. It can be called before you see a DLL_THREAD_DETACH on your |
| 471 | physical thread. The circumstances vary based on whether the process is hosted |
| 472 | and based on whether TS_WeOwn is set on the internal Thread object. Make |
| 473 | no assumptions here. |
| 474 | */ |
| 475 | #define TlsAlloc() \ |
| 476 | Dont_Use_TlsAlloc() |
| 477 | |
| 478 | #define TlsSetValue(dwTlsIndex, lpTlsValue) \ |
| 479 | Dont_Use_TlsSetValue(dwTlsIndex, lpTlsValue) |
| 480 | |
| 481 | #define TlsGetValue(dwTlsIndex) \ |
| 482 | Dont_Use_TlsGetValue(dwTlsIndex) |
| 483 | |
| 484 | #define TlsFree(dwTlsIndex) \ |
| 485 | Dont_Use_TlsFree(dwTlsIndex) |
| 486 | |
| 487 | |
| 488 | /* |
| 489 | If you are reading this, you have probably tracked down the fact that synchronization objects |
| 490 | and critical sections don't work inside your DLL because you are using src\inc & src\utilcode services. |
| 491 | Please refer to the ClrXXX functions described above to make proper use of synchronization obejct, etc. |
| 492 | |
| 493 | Also it's extremely useful to look at the Holder classes defined above. |
| 494 | Those classes provide a nice encapsulation for synchronization object that allows automatic release of locks. |
| 495 | */ |
| 496 | #define InitializeCriticalSection(lpCriticalSection) \ |
| 497 | Dont_Use_InitializeCriticalSection(lpCriticalSection) |
| 498 | |
| 499 | #define InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount) \ |
| 500 | Dont_Use_InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount) |
| 501 | |
| 502 | #define DeleteCriticalSection(lpCriticalSection) \ |
| 503 | Dont_Use_DeleteCriticalSection(lpCriticalSection) |
| 504 | |
| 505 | #define EnterCriticalSection(lpCriticalSection) \ |
| 506 | Dont_Use_EnterCriticalSection(lpCriticalSection) |
| 507 | |
| 508 | #define TryEnterCriticalSection(lpCriticalSection) \ |
| 509 | Dont_Use_TryEnterCriticalSection(lpCriticalSection) |
| 510 | |
| 511 | #define LeaveCriticalSection(lpCriticalSection) \ |
| 512 | Dont_Use_LeaveCriticalSection(lpCriticalSection) |
| 513 | |
| 514 | #ifdef CreateEvent |
| 515 | #undef CreateEvent |
| 516 | #endif |
| 517 | #define CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) \ |
| 518 | Dont_Use_CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName) |
| 519 | |
| 520 | #ifdef OpenEvent |
| 521 | #undef OpenEvent |
| 522 | #endif |
| 523 | #define OpenEvent(dwDesiredAccess, bInheritHandle, lpName) \ |
| 524 | Dont_Use_OpenEvent(dwDesiredAccess, bInheritHandle, lpName) |
| 525 | |
| 526 | #define ResetEvent(hEvent) \ |
| 527 | Dont_Use_ResetEvent(hEvent) |
| 528 | |
| 529 | #define SetEvent(hEvent) \ |
| 530 | Dont_Use_SetEvent(hEvent) |
| 531 | |
| 532 | #define PulseEvent(hEvent) \ |
| 533 | Dont_Use_PulseEvent(hEvent) |
| 534 | |
| 535 | #ifdef CreateSemaphore |
| 536 | #undef CreateSemaphore |
| 537 | #endif |
| 538 | #define CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName) \ |
| 539 | Dont_Use_CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName) |
| 540 | |
| 541 | #ifdef OpenSemaphore |
| 542 | #undef OpenSemaphore |
| 543 | #endif |
| 544 | #define OpenSemaphore(dwDesiredAccess, bInheritHandle, lpName) \ |
| 545 | Dont_Use_OpenSemaphore(dwDesiredAccess, bInheritHandle, lpName) |
| 546 | |
| 547 | #define ReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount) \ |
| 548 | Dont_Use_ReleaseSemaphore(hSemaphore, lReleaseCount, lpPreviousCount) |
| 549 | |
| 550 | #ifdef Sleep |
| 551 | #undef Sleep |
| 552 | #endif |
| 553 | #define Sleep(dwMilliseconds) \ |
| 554 | Dont_Use_Sleep(dwMilliseconds) |
| 555 | |
| 556 | #ifdef SleepEx |
| 557 | #undef SleepEx |
| 558 | #endif |
| 559 | #define SleepEx(dwMilliseconds,bAlertable) \ |
| 560 | Dont_Use_SleepEx(dwMilliseconds,bAlertable) |
| 561 | |
| 562 | // |
| 563 | // following are clib deprecates |
| 564 | // |
| 565 | #include <stdlib.h> |
| 566 | #include <malloc.h> |
| 567 | |
| 568 | #ifdef malloc |
| 569 | #undef malloc |
| 570 | #endif |
| 571 | |
| 572 | #define _CRT_EXCEPTION_NO_MALLOC |
| 573 | #define malloc(size) \ |
| 574 | Dont_Use_malloc(size) |
| 575 | |
| 576 | #ifdef realloc |
| 577 | #undef realloc |
| 578 | #endif |
| 579 | #define realloc(memblock, size) \ |
| 580 | Dont_Use_realloc(memblock, size) |
| 581 | |
| 582 | #ifdef free |
| 583 | #undef free |
| 584 | #endif |
| 585 | #define free(memblock) \ |
| 586 | Dont_Use_free(memblock) |
| 587 | |
| 588 | #endif //!FEATURE_NO_HOST |
| 589 | |
| 590 | extern void IncCantAllocCount(); |
| 591 | extern void DecCantAllocCount(); |
| 592 | |
| 593 | class CantAllocHolder |
| 594 | { |
| 595 | public: |
| 596 | CantAllocHolder () |
| 597 | { |
| 598 | IncCantAllocCount (); |
| 599 | } |
| 600 | ~CantAllocHolder() |
| 601 | { |
| 602 | DecCantAllocCount (); |
| 603 | } |
| 604 | }; |
| 605 | |
| 606 | // At places where want to allocate stress log, we need to first check if we are allowed to do so. |
| 607 | // If ClrTlsInfo doesn't exist for this thread, we take it as can alloc |
| 608 | inline bool IsInCantAllocRegion () |
| 609 | { |
| 610 | size_t count = 0; |
| 611 | if (ClrFlsCheckValue(TlsIdx_CantAllocCount, (LPVOID *)&count)) |
| 612 | { |
| 613 | _ASSERTE (count >= 0); |
| 614 | return count > 0; |
| 615 | } |
| 616 | return false; |
| 617 | } |
| 618 | // for stress log the rule is more restrict, we have to check the global counter too |
| 619 | extern BOOL IsInCantAllocStressLogRegion(); |
| 620 | |
| 621 | #include "genericstackprobe.inl" |
| 622 | |
| 623 | #endif |
| 624 | |