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 //*****************************************************************************
7 // Utility functions implemented in UtilCode.lib.
9 //*****************************************************************************
11 #ifndef __UtilCode_h__
12 #define __UtilCode_h__
27 #include "debugmacros.h"
28 #include "corhlprpriv.h"
34 #ifdef PAL_STDCPP_COMPAT
35 #include <type_traits>
37 #include "clr_std/type_traits"
41 #include "entrypoints.h"
47 #define WINDOWS_KERNEL32_DLLNAME_A "kernel32"
48 #define WINDOWS_KERNEL32_DLLNAME_W W("kernel32")
50 #define CoreLibName_W W("System.Private.CoreLib")
51 #define CoreLibName_IL_W W("System.Private.CoreLib.dll")
52 #define CoreLibName_NI_W W("System.Private.CoreLib.ni.dll")
53 #define CoreLibName_TLB_W W("System.Private.CoreLib.tlb")
54 #define CoreLibName_A "System.Private.CoreLib"
55 #define CoreLibName_IL_A "System.Private.CoreLib.dll"
56 #define CoreLibName_NI_A "System.Private.CoreLib.ni.dll"
57 #define CoreLibName_TLB_A "System.Private.CoreLib.tlb"
58 #define CoreLibNameLen 22
59 #define CoreLibSatelliteName_A "System.Private.CoreLib.resources"
60 #define CoreLibSatelliteNameLen 32
61 #define LegacyCoreLibName_A "mscorlib"
63 class StringArrayList;
65 #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
71 // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct
72 // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this
73 // is handled automatically for us by the compiler. When generating and working with code generated
74 // dynamically we have to be careful to set or mask-out this bit as appropriate.
79 // Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff).
80 inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit)
82 _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit));
83 return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1);
86 // Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the
88 inline bool Is32BitInstruction(WORD opcode)
90 return BitExtract(opcode, 15, 11) >= 0x1d;
93 template <typename ResultType, typename SourceType>
94 inline ResultType DataPointerToThumbCode(SourceType pCode)
96 return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE);
99 template <typename ResultType, typename SourceType>
100 inline ResultType ThumbCodeToDataPointer(SourceType pCode)
102 return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE);
105 #endif // _TARGET_ARM_
107 // Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function;
108 // on ARM, this will mask off the THUMB bit.
109 inline TADDR PCODEToPINSTR(PCODE pc)
112 return ThumbCodeToDataPointer<TADDR,PCODE>(pc);
114 return dac_cast<PCODE>(pc);
118 // Convert from a PINSTR to the corresponding PCODE. On many architectures this will be the identity function;
119 // on ARM, this will raise the THUMB bit.
120 inline PCODE PINSTRToPCODE(TADDR addr)
123 return DataPointerToThumbCode<PCODE,TADDR>(addr);
125 return dac_cast<PCODE>(addr);
129 typedef LPCSTR LPCUTF8;
130 typedef LPSTR LPUTF8;
132 #include "nsutilpriv.h"
134 #include "stdmacros.h"
136 //********** Macros. **********************************************************
139 #define FORCEINLINE inline
141 #define FORCEINLINE __forceinline
145 #ifndef DEBUG_NOINLINE
147 #define DEBUG_NOINLINE NOINLINE
149 #define DEBUG_NOINLINE
153 #include <stddef.h> // for offsetof
156 // Number of elements in a fixed-size array
157 #define NumItems(s) (sizeof(s) / sizeof(s[0]))
161 // Number of characters in a string literal. Excludes terminating NULL.
162 #define StrLen(str) (NumItems(str) - 1)
166 #define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9')))
167 #define DIGIT_TO_INT(ch) (ch - W('0'))
168 #define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i))
170 #define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \
171 ((ch >= W('A')) && (ch <= W('F'))))
172 #define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10)
173 #define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10)))
176 // Helper will 4 byte align a value, rounding up.
177 #define ALIGN4BYTE(val) (((val) + 3) & ~0x3)
180 #define DEBUGARG(x) , x
186 // Returns the size of a class or struct member.
187 #define sizeofmember(c,m) (sizeof(((c*)0)->m))
190 //=--------------------------------------------------------------------------=
194 #include "safemath.h"
197 //=--------------------------------------------------------------------------=
201 // given and ANSI String, copy it into a wide buffer.
202 // be careful about scoping when using this macro!
204 // how to use the below two macros:
208 // pszA = MyGetAnsiStringRoutine();
209 // MAKE_WIDEPTR_FROMANSI(pwsz, pszA);
210 // MyUseWideStringRoutine(pwsz);
213 // similarily for MAKE_ANSIPTR_FROMWIDE. note that the first param does not
214 // have to be declared, and no clean up must be done.
217 // We'll define an upper limit that allows multiplication by 4 (the max
218 // bytes/char in UTF-8) but still remains positive, and allows some room for pad.
219 // Under normal circumstances, we should never get anywhere near this limit.
220 #define MAKE_MAX_LENGTH 0x1fffff00
222 #ifndef MAKE_TOOLONGACTION
223 #define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW)
226 #ifndef MAKE_TRANSLATIONFAILED
227 #define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION)
230 // This version throws on conversion errors (ie, no best fit character
231 // mapping to characters that look similar, and no use of the default char
232 // ('?') when printing out unrepresentable characters. Use this method for
233 // most development in the EE, especially anything like metadata or class
234 // names. See the BESTFIT version if you're printing out info to the console.
235 #define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \
236 int __l##ptrname = (int)wcslen(widestr); \
237 if (__l##ptrname > MAKE_MAX_LENGTH) \
238 MAKE_TOOLONGACTION; \
239 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
240 CQuickBytes __CQuickBytes##ptrname; \
241 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
243 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \
244 if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \
245 MAKE_TRANSLATIONFAILED; \
247 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
249 // This version does best fit character mapping and also allows the use
250 // of the default char ('?') for any Unicode character that isn't
251 // representable. This is reasonable for writing to the console, but
252 // shouldn't be used for most string conversions.
253 #define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \
254 int __l##ptrname = (int)wcslen(widestr); \
255 if (__l##ptrname > MAKE_MAX_LENGTH) \
256 MAKE_TOOLONGACTION; \
257 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
258 CQuickBytes __CQuickBytes##ptrname; \
259 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
260 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \
261 if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \
262 MAKE_TRANSLATIONFAILED; \
264 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
266 // Use for anything critical other than output to console, where weird
267 // character mappings are unacceptable.
268 #define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP)
270 // Use for output to the console.
271 #define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP)
273 #define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \
274 CQuickBytes __qb##ptrname; \
276 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
277 if (__l##ptrname > MAKE_MAX_LENGTH) \
278 MAKE_TOOLONGACTION; \
279 LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
280 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \
281 MAKE_TRANSLATIONFAILED; \
284 #define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \
285 CQuickBytes __qb##ptrname; \
286 LPWSTR ptrname = 0; \
288 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
289 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
290 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
292 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \
293 ptrname[__l##ptrname] = 0; \
300 #define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr();
302 #define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \
303 CQuickBytes __qb##ptrname; \
304 int __l##ptrname = (int)wcslen(widestr); \
305 LPUTF8 ptrname = 0; \
306 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
307 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
308 ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \
311 INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \
312 DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \
313 if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \
314 if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \
315 INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \
316 ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \
318 if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \
319 ptrname[__l##ptrname] = 0; \
331 #define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \
332 CQuickBytes __qb##ptrname; \
334 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
335 if (__l##ptrname > MAKE_MAX_LENGTH) \
336 MAKE_TOOLONGACTION; \
337 LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
338 if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \
339 MAKE_TRANSLATIONFAILED; \
341 ptrname[__l##ptrname] = 0;
344 #define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname; _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr();
347 #define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \
348 CQuickBytes __qb##ptrname; \
350 LPWSTR ptrname = 0; \
351 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
352 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
353 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
355 if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \
356 ptrname[__l##ptrname] = 0; \
363 #define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str) MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1)
365 // This method takes the number of characters
366 #define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage) \
367 CQuickBytes __qb##ptrname; \
369 __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL); \
370 if (__l##ptrname > MAKE_MAX_LENGTH) \
371 MAKE_TOOLONGACTION; \
372 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
374 DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname); \
375 if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \
376 MAKE_TRANSLATIONFAILED; \
378 ptrname[__l##ptrname] = 0;
380 #define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage) \
381 CQuickBytes __qb##ptrname; \
383 __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL); \
384 if (__l##ptrname > MAKE_MAX_LENGTH) \
385 MAKE_TOOLONGACTION; \
386 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
387 DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL); \
388 if (_pCnt == 0 && _nCharacters > 0) { \
389 MAKE_TRANSLATIONFAILED; \
391 ptrname[__l##ptrname] = 0;
393 #define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt) \
394 MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP)
398 LPWSTR DuplicateString(
402 STATIC_CONTRACT_NOTHROW;
404 LPWSTR wszDup = NULL;
405 if (wszString != NULL)
407 wszDup = new (nothrow) WCHAR[cchString + 1];
410 wcscpy_s(wszDup, cchString + 1, wszString);
417 LPWSTR DuplicateString(
420 STATIC_CONTRACT_NOTHROW;
422 if (wszString != NULL)
424 return DuplicateString(wszString, wcslen(wszString));
432 void DECLSPEC_NORETURN ThrowOutOfMemory();
435 LPWSTR DuplicateStringThrowing(
439 STATIC_CONTRACT_THROWS;
441 if (wszString == NULL)
444 LPWSTR wszDup = DuplicateString(wszString, cchString);
452 LPWSTR DuplicateStringThrowing(
455 STATIC_CONTRACT_THROWS;
457 if (wszString == NULL)
460 LPWSTR wszDup = DuplicateString(wszString);
468 //*****************************************************************************
469 // Placement new is used to new and object at an exact location. The pointer
470 // is simply returned to the caller without actually using the heap. The
471 // advantage here is that you cause the ctor() code for the object to be run.
472 // This is ideal for heaps of C++ objects that need to get init'd multiple times.
474 // void *pMem = GetMemFromSomePlace();
475 // Foo *p = new (pMem) Foo;
478 //*****************************************************************************
479 #ifndef __PLACEMENT_NEW_INLINE
480 #define __PLACEMENT_NEW_INLINE
481 inline void *__cdecl operator new(size_t, void *_P)
483 LIMITED_METHOD_DAC_CONTRACT;
487 #endif // __PLACEMENT_NEW_INLINE
490 /********************************************************************************/
491 /* portability helpers */
493 #define IN_WIN64(x) x
497 #define IN_WIN32(x) x
500 #ifdef _TARGET_64BIT_
501 #define IN_TARGET_64BIT(x) x
502 #define IN_TARGET_32BIT(x)
504 #define IN_TARGET_64BIT(x)
505 #define IN_TARGET_32BIT(x) x
509 operator new(size_t n);
511 _Ret_bytecap_(n) void * __cdecl
512 operator new[](size_t n);
515 operator delete(void *p) NOEXCEPT;
518 operator delete[](void *p) NOEXCEPT;
521 HRESULT _OutOfMemory(LPCSTR szFile, int iLine);
522 #define OutOfMemory() _OutOfMemory(__FILE__, __LINE__)
524 inline HRESULT OutOfMemory()
526 LIMITED_METHOD_CONTRACT;
527 return (E_OUTOFMEMORY);
531 //*****************************************************************************
532 // Handle accessing localizable resource strings
533 //*****************************************************************************
534 // NOTE: Should use locale names as much as possible. LCIDs don't support
535 // custom cultures on Vista+.
536 // TODO: This should always use the names
537 #ifdef FEATURE_USE_LCID
538 typedef LCID LocaleID;
539 typedef LCID LocaleIDValue;
541 typedef LPCWSTR LocaleID;
542 typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH];
545 // Notes about the culture callbacks:
546 // - The language we're operating in can change at *runtime*!
547 // - A process may operate in *multiple* languages.
548 // (ex: Each thread may have it's own language)
549 // - If we don't care what language we're in (or have no way of knowing),
550 // then return a 0-length name and UICULTUREID_DONTCARE for the culture ID.
551 // - GetCultureName() and the GetCultureId() must be in sync (refer to the
553 // - We have two functions separate functions for better performance.
554 // - The name is used to resolve a directory for MsCorRC.dll.
555 // - The id is used as a key to map to a dll hinstance.
557 // Callback to obtain both the culture name and the culture's parent culture name
558 typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames);
559 #ifdef FEATURE_USE_LCID
560 // Callback to return the culture ID.
561 const LCID UICULTUREID_DONTCARE = (LCID)-1;
563 const LPCWSTR UICULTUREID_DONTCARE = NULL;
566 typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*);
568 HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName);
570 HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
572 BOOL CLRFreeLibrary(HMODULE hModule);
574 // Prevent people from using LoadStringRC & LoadStringRCEx from inside the product since it
575 // causes issues with having the wrong version picked up inside the shim.
576 #define LoadStringRC __error("From inside the CLR, use UtilLoadStringRC; LoadStringRC is only meant to be exported.")
577 #define LoadStringRCEx __error("From inside the CLR, use UtilLoadStringRCEx; LoadStringRC is only meant to be exported.")
579 // Load a string using the resources for the current module.
580 STDAPI UtilLoadStringRC(UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE);
582 #ifdef FEATURE_USE_LCID
583 STDAPI UtilLoadStringRCEx(LCID lcid, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed);
586 // Specify callbacks so that UtilLoadStringRC can find out which language we're in.
587 // If no callbacks specified (or both parameters are NULL), we default to the
588 // resource dll in the root (which is probably english).
589 void SetResourceCultureCallbacks(
590 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
591 FPGETTHREADUICULTUREID fpGetThreadUICultureId
594 void GetResourceCultureCallbacks(
595 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
596 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
599 #if !defined(DACCESS_COMPILE)
600 // Get the MUI ID, on downlevel platforms where MUI is not supported it
601 // returns the default system ID.
602 extern int GetMUILanguageID(LocaleIDValue* pResult);
603 extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames);
605 #endif // !defined(DACCESS_COMPILE)
607 //*****************************************************************************
608 // Use this class by privately deriving from noncopyable to disallow copying of
610 //*****************************************************************************
620 noncopyable(const noncopyable&);
621 const noncopyable& operator=(const noncopyable&);
624 //*****************************************************************************
625 // Must associate each handle to an instance of a resource dll with the int
626 // that it represents
627 //*****************************************************************************
628 typedef HINSTANCE HRESOURCEDLL;
631 class CCulturedHInstance
633 LocaleIDValue m_LangId;
634 HRESOURCEDLL m_hInst;
640 LIMITED_METHOD_CONTRACT;
645 BOOL HasID(LocaleID id)
647 _ASSERTE(m_hInst != NULL || m_fMissing);
648 if (id == UICULTUREID_DONTCARE)
651 #ifdef FEATURE_USE_LCID
652 return id == m_LangId;
654 return wcscmp(id, m_LangId) == 0;
658 HRESOURCEDLL GetLibraryHandle()
665 return m_hInst != NULL;
673 void SetMissing(LocaleID id)
675 _ASSERTE(m_hInst == NULL);
680 void Set(LocaleID id, HRESOURCEDLL hInst)
682 _ASSERTE(m_hInst == NULL);
683 _ASSERTE(m_fMissing == FALSE);
688 void SetId(LocaleID id)
690 #ifdef FEATURE_USE_LCID
693 if (id != UICULTUREID_DONTCARE)
695 wcsncpy_s(m_LangId, NumItems(m_LangId), id, NumItems(m_LangId));
696 m_LangId[NumItems(m_LangId)-1] = W('\0');
700 m_LangId[0] = W('\0');
706 #ifndef DACCESS_COMPILE
707 void AddThreadPreferredUILanguages(StringArrayList* pArray);
709 //*****************************************************************************
710 // CCompRC manages string Resource access for COM+. This includes loading
711 // the MsCorRC.dll for resources as well allowing each thread to use a
712 // a different localized version.
713 //*****************************************************************************
718 enum ResourceCategory
723 // present in Desktop CLR and Core CLR + debug pack, an error
724 // If missing, get a generic error message instead
727 // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing)
728 // if missing, get a generic "resource not found" message instead
731 // present in Desktop CLR, optional for CoreCLR
734 // might not be present, non essential
740 // This constructor will be fired up on startup. Make sure it doesn't
741 // do anything besides zero-out out values.
742 m_bUseFallback = FALSE;
744 m_fpGetThreadUICultureId = NULL;
745 m_fpGetThreadUICultureNames = NULL;
751 m_pResourceFile = NULL;
753 m_pResourceDomain = NULL;
754 #endif // FEATURE_PAL
758 HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE);
761 BOOL ShouldUseFallback()
763 LIMITED_METHOD_CONTRACT;
764 return m_bUseFallback;
767 static void SetIsMscoree() {s_bIsMscoree = TRUE;}
769 HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL);
770 HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed);
772 void SetResourceCultureCallbacks(
773 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
774 FPGETTHREADUICULTUREID fpGetThreadUICultureId
777 void GetResourceCultureCallbacks(
778 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
779 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
782 HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst);
784 // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR)
785 static CCompRC* GetDefaultResourceDll();
786 // Get the generic messages dll (Silverlight only, mscorrc.dll)
787 static CCompRC* GetFallbackResourceDll();
788 static void ShutdownDefaultResourceDll();
789 static void GetDefaultCallbacks(
790 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
791 FPGETTHREADUICULTUREID* fpGetThreadUICultureId)
794 m_DefaultResourceDll.GetResourceCultureCallbacks(
795 fpGetThreadUICultureNames,
796 fpGetThreadUICultureId);
799 static void SetDefaultCallbacks(
800 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
801 FPGETTHREADUICULTUREID fpGetThreadUICultureId)
804 // Either both are NULL or neither are NULL
805 _ASSERTE((fpGetThreadUICultureNames != NULL) ==
806 (fpGetThreadUICultureId != NULL));
808 m_DefaultResourceDll.SetResourceCultureCallbacks(
809 fpGetThreadUICultureNames,
810 fpGetThreadUICultureId);
812 m_FallbackResourceDll.SetResourceCultureCallbacks(
813 fpGetThreadUICultureNames,
814 fpGetThreadUICultureId);
818 #ifdef USE_FORMATMESSAGE_WRAPPER
826 IN DWORD dwMessageId,
827 IN DWORD dwLanguageId,
830 IN va_list *Arguments);
831 #endif // USE_FORMATMESSAGE_WRAPPER
835 HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst);
836 #ifndef DACCESS_COMPILE
837 HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst,
839 HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst);
840 HRESULT LoadLibrary(HRESOURCEDLL * pHInst);
841 HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName);
844 // We do not have global constructors any more
845 static LONG m_dwDefaultInitialized;
846 static CCompRC m_DefaultResourceDll;
847 static LPCWSTR m_pDefaultResource;
849 // fallback resources if debug pack is not installed
850 static LONG m_dwFallbackInitialized;
851 static CCompRC m_FallbackResourceDll;
852 static LPCWSTR m_pFallbackResource;
854 // We must map between a thread's int and a dll instance.
855 // Since we only expect 1 language almost all of the time, we'll special case
856 // that and then use a variable size map for everything else.
857 CCulturedHInstance m_Primary;
858 CCulturedHInstance * m_pHash;
861 CRITSEC_COOKIE m_csMap;
863 LPCWSTR m_pResourceFile;
865 // Resource domain is an ANSI string identifying a native resources file
866 static LPCSTR m_pDefaultResourceDomain;
867 static LPCSTR m_pFallbackResourceDomain;
868 LPCSTR m_pResourceDomain;
869 #endif // FEATURE_PAL
871 // Main accessors for hash
872 HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing);
873 HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE);
875 FPGETTHREADUICULTUREID m_fpGetThreadUICultureId;
876 FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames;
879 static BOOL s_bIsMscoree;
882 HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax);
886 HWND hWnd, // Handle to Owner Window
887 UINT uText, // Resource Identifier for Text message
888 UINT uCaption, // Resource Identifier for Caption
889 UINT uType, // Style of MessageBox
890 BOOL displayForNonInteractive, // Display even if the process is running non interactive
891 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
892 ...); // Additional Arguments
894 int UtilMessageBoxNonLocalized(
895 HWND hWnd, // Handle to Owner Window
896 LPCWSTR lpText, // Resource Identifier for Text message
897 LPCWSTR lpTitle, // Resource Identifier for Caption
898 UINT uType, // Style of MessageBox
899 BOOL displayForNonInteractive, // Display even if the process is running non interactive
900 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
901 ...); // Additional Arguments
903 int UtilMessageBoxVA(
904 HWND hWnd, // Handle to Owner Window
905 UINT uText, // Resource Identifier for Text message
906 UINT uCaption, // Resource Identifier for Caption
907 UINT uType, // Style of MessageBox
908 BOOL displayForNonInteractive, // Display even if the process is running non interactive
909 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
910 va_list args); // Additional Arguments
912 int UtilMessageBoxNonLocalizedVA(
913 HWND hWnd, // Handle to Owner Window
914 LPCWSTR lpText, // Text message
915 LPCWSTR lpCaption, // Caption
916 UINT uType, // Style of MessageBox
917 BOOL displayForNonInteractive, // Display even if the process is running non interactive
918 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
919 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
920 va_list args); // Additional Arguments
922 int UtilMessageBoxNonLocalizedVA(
923 HWND hWnd, // Handle to Owner Window
924 LPCWSTR lpText, // Text message
925 LPCWSTR lpCaption, // Caption
926 LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher).
927 UINT uType, // Style of MessageBox
928 BOOL displayForNonInteractive, // Display even if the process is running non interactive
929 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
930 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
931 va_list args); // Additional Arguments
933 int UtilMessageBoxCatastrophic(
934 UINT uText, // Text for MessageBox
935 UINT uTitle, // Title for MessageBox
936 UINT uType, // Style of MessageBox
937 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
940 int UtilMessageBoxCatastrophicNonLocalized(
941 LPCWSTR lpText, // Text for MessageBox
942 LPCWSTR lpTitle, // Title for MessageBox
943 UINT uType, // Style of MessageBox
944 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
947 int UtilMessageBoxCatastrophicVA(
948 UINT uText, // Text for MessageBox
949 UINT uTitle, // Title for MessageBox
950 UINT uType, // Style of MessageBox
951 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
952 va_list args); // Additional Arguments
954 int UtilMessageBoxCatastrophicNonLocalizedVA(
955 LPCWSTR lpText, // Text for MessageBox
956 LPCWSTR lpTitle, // Title for MessageBox
957 UINT uType, // Style of MessageBox
958 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
959 va_list args); // Additional Arguments
962 // The HRESULT_FROM_WIN32 macro evaluates its arguments three times.
963 // <TODO>TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to
964 // this helper function avoid code bloat</TODO>
965 inline HRESULT HRESULT_FROM_GetLastError()
968 DWORD dw = GetLastError();
969 // Make sure we return a failure
970 if (dw == ERROR_SUCCESS)
972 _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!");
976 return HRESULT_FROM_WIN32(dw);
979 inline HRESULT HRESULT_FROM_GetLastErrorNA()
982 DWORD dw = GetLastError();
983 // Make sure we return a failure
984 if (dw == ERROR_SUCCESS)
987 return HRESULT_FROM_WIN32(dw);
990 inline HRESULT BadError(HRESULT hr)
992 LIMITED_METHOD_CONTRACT;
993 _ASSERTE(!"Serious Error");
997 #define TESTANDRETURN(test, hrVal) \
999 int ___test = (int)(test); \
1004 #define TESTANDRETURNPOINTER(pointer) \
1005 TESTANDRETURN(pointer!=NULL, E_POINTER)
1007 #define TESTANDRETURNMEMORY(pointer) \
1008 TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY)
1010 #define TESTANDRETURNHR(hr) \
1011 TESTANDRETURN(SUCCEEDED(hr), hr)
1013 #define TESTANDRETURNARG(argtest) \
1014 TESTANDRETURN(argtest, E_INVALIDARG)
1016 // Quick validity check for HANDLEs that are returned by Win32 APIs that
1017 // use INVALID_HANDLE_VALUE instead of NULL to indicate an error
1018 inline BOOL IsValidHandle(HANDLE h)
1020 LIMITED_METHOD_CONTRACT;
1021 return ((h != NULL) && (h != INVALID_HANDLE_VALUE));
1024 // Count the bits in a value in order iBits time.
1025 inline int CountBits(int iNum)
1027 LIMITED_METHOD_CONTRACT;
1029 for (iBits=0; iNum; iBits++)
1030 iNum = iNum & (iNum - 1);
1034 #include "bitposition.h"
1036 // Convert the currency to a decimal and canonicalize.
1037 inline void VarDecFromCyCanonicalize(CY cyIn, DECIMAL* dec)
1039 WRAPPER_NO_CONTRACT;
1042 DECIMAL_HI32(*dec) = 0;
1043 if (cyIn.int64 == 0) // For compatibility, a currency of 0 emits the Decimal "0.0000" (scale set to 4).
1045 DECIMAL_SCALE(*dec) = 4;
1046 DECIMAL_LO32(*dec) = 0;
1047 DECIMAL_MID32(*dec) = 0;
1051 if (cyIn.int64 < 0) {
1052 DECIMAL_SIGN(*dec) = DECIMAL_NEG;
1053 cyIn.int64 = -cyIn.int64;
1057 ULONGLONG absoluteCy = (ULONGLONG)cyIn.int64;
1058 while (scale != 0 && ((absoluteCy % 10) == 0))
1063 DECIMAL_SCALE(*dec) = scale;
1064 DECIMAL_LO32(*dec) = (ULONG)absoluteCy;
1065 DECIMAL_MID32(*dec) = (ULONG)(absoluteCy >> 32);
1068 //*****************************************************************************
1070 // Paths functions. Use these instead of the CRT.
1072 //*****************************************************************************
1073 // secure version! Specify the size of the each buffer in count of elements
1074 void SplitPath(const WCHAR *path,
1075 __inout_z __inout_ecount_opt(driveSizeInWords) WCHAR *drive, int driveSizeInWords,
1076 __inout_z __inout_ecount_opt(dirSizeInWords) WCHAR *dir, int dirSizeInWords,
1077 __inout_z __inout_ecount_opt(fnameSizeInWords) WCHAR *fname, size_t fnameSizeInWords,
1078 __inout_z __inout_ecount_opt(extSizeInWords) WCHAR *ext, size_t extSizeInWords);
1080 //*******************************************************************************
1081 // A much more sensible version that just points to each section of the string.
1082 //*******************************************************************************
1083 void SplitPathInterior(
1084 __in LPCWSTR wszPath,
1085 __out_opt LPCWSTR *pwszDrive, __out_opt size_t *pcchDrive,
1086 __out_opt LPCWSTR *pwszDir, __out_opt size_t *pcchDir,
1087 __out_opt LPCWSTR *pwszFileName, __out_opt size_t *pcchFileName,
1088 __out_opt LPCWSTR *pwszExt, __out_opt size_t *pcchExt);
1091 void MakePath(__out CQuickWSTR &path,
1097 WCHAR * FullPath(__out_ecount (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen);
1099 //*****************************************************************************
1101 // SString version of the path functions.
1103 //*****************************************************************************
1104 void SplitPath(__in SString const &path,
1105 __inout_opt SString *drive,
1106 __inout_opt SString *dir,
1107 __inout_opt SString *fname,
1108 __inout_opt SString *ext);
1110 #if !defined(NO_CLRCONFIG)
1112 //*****************************************************************************
1114 // **** REGUTIL - Static helper functions for reading/writing to Windows registry.
1116 //*****************************************************************************
1122 //*****************************************************************************
1126 COR_CONFIG_ENV = 0x01,
1127 COR_CONFIG_USER = 0x02,
1128 COR_CONFIG_MACHINE = 0x04,
1129 COR_CONFIG_FUSION = 0x08,
1131 COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION),
1132 COR_CONFIG_ALL = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE),
1136 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1137 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1139 static DWORD GetConfigDWORD_DontUse_(
1142 CORConfigLevel level = COR_CONFIG_ALL,
1143 BOOL fPrependCOMPLUS = TRUE);
1146 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1147 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1149 static HRESULT GetConfigDWORD_DontUse_(
1152 __out DWORD * result,
1153 CORConfigLevel level = COR_CONFIG_ALL,
1154 BOOL fPrependCOMPLUS = TRUE);
1156 static ULONGLONG GetConfigULONGLONG_DontUse_(
1159 CORConfigLevel level = COR_CONFIG_ALL,
1160 BOOL fPrependCOMPLUS = TRUE);
1163 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1164 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1166 static DWORD GetConfigFlag_DontUse_(
1169 BOOL defValue = FALSE);
1172 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1173 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1175 static LPWSTR GetConfigString_DontUse_(
1177 BOOL fPrependCOMPLUS = TRUE,
1178 CORConfigLevel level = COR_CONFIG_ALL,
1179 BOOL fUsePerfCache = TRUE);
1181 static void FreeConfigString(__in __in_z LPWSTR name);
1184 static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS);
1187 static BOOL UseRegistry();
1190 //*****************************************************************************
1191 // Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that
1192 // you can safely cast to a DWORD if fGetDWORD is TRUE.
1193 //*****************************************************************************
1194 static HRESULT GetConfigInteger(
1197 __out ULONGLONG * result,
1198 BOOL fGetDWORD = TRUE,
1199 CORConfigLevel level = COR_CONFIG_ALL,
1200 BOOL fPrependCOMPLUS = TRUE);
1204 //*****************************************************************************
1205 // (Optional) Initialize the config registry cache
1206 // (see ConfigCacheValueNameSeenPerhaps, below.)
1207 //*****************************************************************************
1208 static void InitOptionalConfigCache();
1213 //*****************************************************************************
1214 // Return TRUE if the registry value name might have been seen in the registry
1216 // return FALSE if the value was definitely not seen at startup.
1218 // Perf Optimization for VSWhidbey:113373.
1219 //*****************************************************************************
1220 static BOOL RegCacheValueNameSeenPerhaps(
1222 //*****************************************************************************
1223 // Return TRUE if the environment variable name might have been seen at startup;
1224 // return FALSE if the value was definitely not seen at startup.
1225 //*****************************************************************************
1226 static BOOL EnvCacheValueNameSeenPerhaps(
1229 static BOOL s_fUseRegCache; // Enable registry cache; if FALSE, CCVNSP
1230 // always returns TRUE.
1231 static BOOL s_fUseEnvCache; // Enable env cache.
1233 static BOOL s_fUseRegistry; // Allow lookups in the registry
1235 // Open the .NetFramework keys once and cache the handles
1236 static HKEY s_hMachineFrameworkKey;
1237 static HKEY s_hUserFrameworkKey;
1240 // need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig
1241 #include "clrconfig.h"
1243 //-----------------------------------------------------------------------------
1244 // Wrapper for configuration strings.
1245 // This serves as a holder to call FreeConfigString.
1246 class ConfigStringHolder
1249 ConfigStringHolder() { m_wszString = NULL; }
1250 ~ConfigStringHolder()
1256 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1257 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1259 void Init_DontUse_(LPCWSTR wszName)
1262 m_wszString = REGUTIL::GetConfigString_DontUse_(wszName);
1268 if (m_wszString != NULL)
1270 REGUTIL::FreeConfigString(m_wszString);
1275 // Get the string value. NULL if not set.
1285 #endif // defined(NO_CLRCONFIG)
1289 #define CLRGetTickCount64() GetTickCount64()
1292 // Use this function to initialize the s_CodeAllocHint
1293 // during startup. base is runtime .dll base address,
1294 // size is runtime .dll virtual size.
1296 void InitCodeAllocHint(SIZE_T base, SIZE_T size, int randomPageOffset);
1300 // Use this function to reset the s_CodeAllocHint
1301 // after unloading an AppDomain
1303 void ResetCodeAllocHint();
1306 // Returns TRUE if p is located in near clr.dll that allows us
1307 // to use rel32 IP-relative addressing modes.
1309 BOOL IsPreferredExecutableRange(void * p);
1312 // Allocate free memory that will be used for executable code
1313 // Handles the special requirements that we have on 64-bit platforms
1314 // where we want the executable memory to be located near mscorwks
1316 BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize,
1317 DWORD flAllocationType,
1321 // Allocate free memory within the range [pMinAddr..pMaxAddr] using
1322 // ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it.
1324 BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
1325 const BYTE *pMaxAddr,
1327 DWORD flAllocationType,
1331 // Allocate free memory with specific alignment
1333 LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment);
1335 //******************************************************************************
1336 // Returns the number of processors that a process has been configured to run on
1337 //******************************************************************************
1341 static BOOL m_enableGCNumaAware;
1342 static BOOL InitNumaNodeInfoAPI();
1345 static BOOL CanEnableGCNumaAware();
1346 static void InitNumaNodeInfo();
1348 #if !defined(FEATURE_REDHAWK)
1349 public: // functions
1351 static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size,
1352 DWORD allocType, DWORD prot, DWORD node);
1353 static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no);
1357 struct CPU_Group_Info
1359 WORD nr_active; // at most 64
1363 DWORD_PTR active_mask;
1365 DWORD activeThreadWeight;
1371 static LONG m_initialization;
1372 static WORD m_nGroups;
1373 static WORD m_nProcessors;
1374 static BOOL m_enableGCCPUGroups;
1375 static BOOL m_threadUseAllCpuGroups;
1376 static WORD m_initialGroup;
1377 static CPU_Group_Info *m_CPUGroupInfoArray;
1378 static bool s_hadSingleProcessorAtStartup;
1380 static BOOL InitCPUGroupInfoArray();
1381 static BOOL InitCPUGroupInfoRange();
1382 static void InitCPUGroupInfo();
1383 static BOOL IsInitialized();
1386 static void EnsureInitialized();
1387 static BOOL CanEnableGCCPUGroups();
1388 static BOOL CanEnableThreadUseAllCpuGroups();
1389 static WORD GetNumActiveProcessors();
1390 static void GetGroupForProcessor(WORD processor_number,
1391 WORD *group_number, WORD *group_processor_number);
1392 static DWORD CalculateCurrentProcessorNumber();
1393 //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
1395 #if !defined(FEATURE_REDHAWK)
1397 static BOOL GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP relationship,
1398 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count);
1399 static BOOL SetThreadGroupAffinity(HANDLE h,
1400 GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity);
1401 static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity);
1402 static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime);
1403 static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf);
1404 static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf);
1405 static BOOL GetCPUGroupRange(WORD group_number, WORD* group_begin, WORD* group_size);
1409 static bool HadSingleProcessorAtStartup()
1411 LIMITED_METHOD_CONTRACT;
1412 return s_hadSingleProcessorAtStartup;
1416 int GetCurrentProcessCpuCount();
1417 DWORD_PTR GetCurrentProcessCpuMask();
1419 uint32_t GetOsPageSize();
1422 //*****************************************************************************
1423 // Return != 0 if the bit at the specified index in the array is on and 0 if
1425 //*****************************************************************************
1426 inline int GetBit(PTR_BYTE pcBits,int iBit)
1428 LIMITED_METHOD_CONTRACT;
1429 return (pcBits[iBit>>3] & (1 << (iBit & 0x7)));
1432 #ifdef DACCESS_COMPILE
1433 inline int GetBit(BYTE const * pcBits,int iBit)
1435 WRAPPER_NO_CONTRACT;
1436 return GetBit(dac_cast<PTR_BYTE>(pcBits), iBit);
1440 //*****************************************************************************
1441 // Set the state of the bit at the specified index based on the value of bOn.
1442 //*****************************************************************************
1443 inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn)
1445 LIMITED_METHOD_CONTRACT;
1447 pcBits[iBit>>3] |= (1 << (iBit & 0x7));
1449 pcBits[iBit>>3] &= ~(1 << (iBit & 0x7));
1452 #ifdef DACCESS_COMPILE
1453 inline void SetBit(BYTE * pcBits,int iBit,int bOn)
1455 WRAPPER_NO_CONTRACT;
1456 SetBit(dac_cast<PTR_BYTE>(pcBits), iBit, bOn);
1460 template<typename T>
1461 class SimpleListNode
1464 SimpleListNode<T>(const T& _t)
1471 SimpleListNode<T>* next;
1474 template<typename T>
1478 typedef SimpleListNode<T> NodeType;
1485 void LinkHead(NodeType* pNode)
1491 NodeType* UnlinkHead()
1493 NodeType* ret = head;
1513 template < typename T, typename U >
1517 typedef Pair< T, U > this_type;
1518 typedef T first_type;
1519 typedef U second_type;
1524 Pair( T const & t, U const & u )
1529 Pair( this_type const & obj )
1530 : m_first( obj.m_first )
1531 , m_second( obj.m_second )
1534 this_type & operator=( this_type const & obj )
1536 m_first = obj.m_first;
1537 m_second = obj.m_second;
1546 T const & First() const
1556 U const & Second() const
1561 bool operator==(const Pair& rhs) const
1563 return ((this->First() == rhs.First()) &&
1564 (this->Second() == rhs.Second()));
1567 bool operator!=(const Pair& rhs) const
1569 return !(*this == rhs);
1574 second_type m_second;
1578 template < typename T, typename U >
1579 Pair< T, U > MakePair( T const & t, U const & u )
1582 return Pair< T, U >( t, u );
1586 //*****************************************************************************
1587 // This class implements a dynamic array of structures for which the order of
1588 // the elements is unimportant. This means that any item placed in the list
1589 // may be swapped to any other location in the list at any time. If the order
1590 // of the items you place in the array is important, then use the CStructArray
1592 //*****************************************************************************
1597 class CUnorderedArrayWithAllocator
1599 int m_iCount; // # of elements used in the list.
1600 int m_iSize; // # of elements allocated in the list.
1602 #ifndef DACCESS_COMPILE
1603 T *m_pTable; // Pointer to the list of elements.
1605 TADDR m_pTable; // Pointer to the list of elements.
1610 #ifndef DACCESS_COMPILE
1612 CUnorderedArrayWithAllocator() :
1617 LIMITED_METHOD_CONTRACT;
1619 ~CUnorderedArrayWithAllocator()
1621 LIMITED_METHOD_CONTRACT;
1622 // Free the chunk of memory.
1623 if (m_pTable != NULL)
1624 ALLOCATOR::Free(this, m_pTable);
1629 WRAPPER_NO_CONTRACT;
1631 if (m_iSize > iGrowInc)
1633 T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc);
1635 ALLOCATOR::Free(this, m_pTable);
1642 void Clear(int iFirst, int iCount)
1644 WRAPPER_NO_CONTRACT;
1647 if (iFirst + iCount < m_iCount)
1648 memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount)));
1652 iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0);
1653 if (m_iSize > iGrowInc && iSize < m_iSize)
1655 T *tmp = ALLOCATOR::AllocNoThrow(this, iSize);
1657 memcpy (tmp, m_pTable, iSize * sizeof(T));
1663 _ASSERTE(m_iCount <= m_iSize);
1668 LIMITED_METHOD_CONTRACT;
1678 // The array should grow, if we can't fit one more element into the array.
1679 if (m_iSize <= m_iCount && GrowNoThrow() == NULL)
1681 return (&m_pTable[m_iCount++]);
1690 // The array should grow, if we can't fit one more element into the array.
1691 if (m_iSize <= m_iCount)
1693 return (&m_pTable[m_iCount++]);
1696 void Delete(const T &Entry)
1698 LIMITED_METHOD_CONTRACT;
1700 for (int i=0; i <= m_iCount; ++i)
1701 if (m_pTable[i] == Entry)
1703 m_pTable[i] = m_pTable[m_iCount];
1707 // Just in case we didn't find it.
1711 void DeleteByIndex(int i)
1713 LIMITED_METHOD_CONTRACT;
1715 m_pTable[i] = m_pTable[m_iCount];
1718 void Swap(int i,int j)
1720 LIMITED_METHOD_CONTRACT;
1726 m_pTable[i] = m_pTable[j];
1734 LIMITED_METHOD_CONTRACT;
1739 void EnumMemoryRegions(void)
1742 DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T));
1745 #endif // #ifndef DACCESS_COMPILE
1749 LIMITED_METHOD_CONTRACT;
1751 _ASSERTE(FitsIn<USHORT>(m_iCount));
1752 return static_cast<USHORT>(m_iCount);
1761 #ifndef DACCESS_COMPILE
1763 //*****************************************************************************
1764 // Increase the size of the array.
1765 //*****************************************************************************
1769 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::GrowNoThrow() // NULL if can't grow.
1771 WRAPPER_NO_CONTRACT;
1774 // try to allocate memory for reallocation.
1775 if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL)
1777 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1778 ALLOCATOR::Free(this, m_pTable);
1780 m_iSize += iGrowInc;
1781 _ASSERTE(m_iSize > 0);
1788 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::Grow() // exception if can't grow.
1790 WRAPPER_NO_CONTRACT;
1793 // try to allocate memory for reallocation.
1794 pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc);
1795 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1796 ALLOCATOR::Free(this, m_pTable);
1798 m_iSize += iGrowInc;
1799 _ASSERTE(m_iSize > 0);
1803 #endif // #ifndef DACCESS_COMPILE
1807 class CUnorderedArray__Allocator
1811 static T *AllocThrowing (void*, int nElements)
1813 return new T[nElements];
1816 static T *AllocNoThrow (void*, int nElements)
1818 return new (nothrow) T[nElements];
1821 static void Free (void*, T *pTable)
1828 template <class T,int iGrowInc>
1829 class CUnorderedArray : public CUnorderedArrayWithAllocator<T, iGrowInc, CUnorderedArray__Allocator<T> >
1835 LIMITED_METHOD_CONTRACT;
1840 //Used by the debugger. Included here in hopes somebody else might, too
1841 typedef CUnorderedArray<SIZE_T, 17> SIZE_T_UNORDERED_ARRAY;
1844 //*****************************************************************************
1845 // This class implements a dynamic array of structures for which the insert
1846 // order is important. Inserts will slide all elements after the location
1847 // down, deletes slide all values over the deleted item. If the order of the
1848 // items in the array is unimportant to you, then CUnorderedArray may provide
1849 // the same feature set at lower cost.
1850 //*****************************************************************************
1853 BYTE *m_pList; // Pointer to the list of elements.
1854 int m_iCount; // # of elements used in the list.
1855 int m_iSize; // # of elements allocated in the list.
1856 int m_iGrowInc; // Growth increment.
1857 short m_iElemSize; // Size of an array element.
1858 bool m_bFree; // true if data is automatically maintained.
1861 CStructArray(short iElemSize, short iGrowInc = 1) :
1865 m_iGrowInc(iGrowInc),
1866 m_iElemSize(iElemSize),
1869 LIMITED_METHOD_CONTRACT;
1873 WRAPPER_NO_CONTRACT;
1877 void *Insert(int iIndex);
1878 void *InsertThrowing(int iIndex);
1880 void *AppendThrowing();
1881 int AllocateBlock(int iCount);
1882 void AllocateBlockThrowing(int iCount);
1883 void Delete(int iIndex);
1886 LIMITED_METHOD_CONTRACT;
1889 void *Get(int iIndex)
1891 WRAPPER_NO_CONTRACT;
1892 _ASSERTE(iIndex < m_iCount);
1893 return ((void *) ((size_t) Ptr() + (iIndex * m_iElemSize)));
1897 LIMITED_METHOD_CONTRACT;
1898 return (m_iCount * m_iElemSize);
1902 LIMITED_METHOD_CONTRACT;
1908 LIMITED_METHOD_CONTRACT;
1912 void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1)
1914 LIMITED_METHOD_CONTRACT;
1915 m_iElemSize = iElemSize;
1916 m_iGrowInc = (short) iGrowInc;
1917 m_pList = (BYTE*)pList;
1924 void Grow(int iCount);
1928 //*****************************************************************************
1929 // This template simplifies access to a CStructArray by removing void * and
1930 // adding some operator overloads.
1931 //*****************************************************************************
1933 class CDynArray : public CStructArray
1936 CDynArray(short iGrowInc=16) :
1937 CStructArray(sizeof(T), iGrowInc)
1939 LIMITED_METHOD_CONTRACT;
1942 T *Insert(int iIndex)
1944 WRAPPER_NO_CONTRACT;
1945 return ((T *)CStructArray::Insert((int)iIndex));
1948 T *InsertThrowing(int iIndex)
1950 WRAPPER_NO_CONTRACT;
1951 return ((T *)CStructArray::InsertThrowing((int)iIndex));
1956 WRAPPER_NO_CONTRACT;
1957 return ((T *)CStructArray::Append());
1962 WRAPPER_NO_CONTRACT;
1963 return ((T *)CStructArray::AppendThrowing());
1968 WRAPPER_NO_CONTRACT;
1969 return ((T *)CStructArray::Ptr());
1974 WRAPPER_NO_CONTRACT;
1975 return (Ptr() + iIndex);
1977 T &operator[](int iIndex)
1979 WRAPPER_NO_CONTRACT;
1980 return (*(Ptr() + iIndex));
1984 WRAPPER_NO_CONTRACT;
1985 return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T));
1987 void Move(int iFrom, int iTo)
1989 WRAPPER_NO_CONTRACT;
1992 _ASSERTE(iFrom >= 0 && iFrom < Count() &&
1993 iTo >= 0 && iTo < Count());
1995 tmp = *(Ptr() + iFrom);
1997 memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T));
1999 memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T));
2000 *(Ptr() + iTo) = tmp;
2004 // Some common arrays.
2005 typedef CDynArray<int> INTARRAY;
2006 typedef CDynArray<short> SHORTARRAY;
2007 typedef CDynArray<int> LONGARRAY;
2008 typedef CDynArray<USHORT> USHORTARRAY;
2009 typedef CDynArray<ULONG> ULONGARRAY;
2010 typedef CDynArray<BYTE> BYTEARRAY;
2011 typedef CDynArray<mdToken> TOKENARRAY;
2013 template <class T> class CStackArray : public CStructArray
2016 CStackArray(short iGrowInc=4) :
2017 CStructArray(sizeof(T), iGrowInc),
2020 LIMITED_METHOD_CONTRACT;
2025 WRAPPER_NO_CONTRACT;
2026 // We should only inc m_curPos after we grow the array.
2027 T *pT = (T *)CStructArray::InsertThrowing(m_curPos);
2034 WRAPPER_NO_CONTRACT;
2037 _ASSERTE(m_curPos > 0);
2039 retPtr = (T *)CStructArray::Get(m_curPos-1);
2040 CStructArray::Delete(m_curPos--);
2047 LIMITED_METHOD_CONTRACT;
2056 //*****************************************************************************
2057 // This template manages a list of free entries by their 0 based offset. By
2058 // making it a template, you can use whatever size free chain will match your
2059 // maximum count of items. -1 is reserved.
2060 //*****************************************************************************
2061 template <class T> class TFreeList
2068 LIMITED_METHOD_CONTRACT;
2076 for (i=0; i<iCount - 1; i++)
2077 m_rgList[i] = i + 1;
2078 m_rgList[i] = (T) -1;
2081 T GetFreeEntry() // Index of free item, or -1.
2083 LIMITED_METHOD_CONTRACT;
2086 if (m_iNext == (T) -1)
2090 m_iNext = m_rgList[m_iNext];
2094 void DelFreeEntry(T iEntry)
2096 LIMITED_METHOD_CONTRACT;
2097 _ASSERTE(iEntry < m_iCount);
2098 m_rgList[iEntry] = m_iNext;
2102 // This function can only be used when it is guaranteed that the free
2103 // array is contigous, for example, right after creation to quickly
2104 // get a range of items from the heap.
2105 void ReserveRange(int iCount)
2107 LIMITED_METHOD_CONTRACT;
2108 _ASSERTE(iCount < m_iCount);
2109 _ASSERTE(m_iNext == 0);
2114 T *m_rgList; // List of free info.
2115 int m_iCount; // How many entries to manage.
2116 T m_iNext; // Next item to get.
2120 //*****************************************************************************
2121 //*****************************************************************************
2122 template <class T> class CQuickSort
2125 T *m_pBase; // Base of array to sort.
2127 SSIZE_T m_iCount; // How many items in array.
2128 SSIZE_T m_iElemSize; // Size of one element.
2131 T *pBase, // Address of first element.
2132 SSIZE_T iCount) : // How many there are.
2135 m_iElemSize(sizeof(T))
2137 LIMITED_METHOD_DAC_CONTRACT;
2140 //*****************************************************************************
2141 // Call to sort the array.
2142 //*****************************************************************************
2145 WRAPPER_NO_CONTRACT;
2146 SortRange(0, m_iCount - 1);
2150 //*****************************************************************************
2151 // Override this function to do the comparison.
2152 //*****************************************************************************
2153 virtual FORCEINLINE int Compare( // -1, 0, or 1
2154 T *psFirst, // First item to compare.
2155 T *psSecond) // Second item to compare.
2157 LIMITED_METHOD_DAC_CONTRACT;
2158 return (memcmp(psFirst, psSecond, sizeof(T)));
2159 // return (::Compare(*psFirst, *psSecond));
2162 virtual FORCEINLINE void Swap(
2166 LIMITED_METHOD_DAC_CONTRACT;
2167 if (iFirst == iSecond) return;
2168 T sTemp( m_pBase[iFirst] );
2169 m_pBase[iFirst] = m_pBase[iSecond];
2170 m_pBase[iSecond] = sTemp;
2174 inline void SortRange(
2178 WRAPPER_NO_CONTRACT;
2180 SSIZE_T i; // loop variable.
2184 // if less than two elements you're done.
2185 if (iLeft >= iRight)
2188 // ASSERT that we now have valid indicies. This is statically provable
2189 // since this private function is only called with valid indicies,
2190 // and iLeft and iRight only converge towards eachother. However,
2191 // PreFast can't detect this because it doesn't know about our callers.
2192 COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount);
2193 COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount);
2195 // The mid-element is the pivot, move it to the left.
2196 Swap(iLeft, (iLeft + iRight) / 2);
2199 // move everything that is smaller than the pivot to the left.
2200 for (i = iLeft + 1; i <= iRight; i++)
2202 if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0)
2208 // Put the pivot to the point where it is in between smaller and larger elements.
2211 // Sort each partition.
2212 SSIZE_T iLeftLast = iLast - 1;
2213 SSIZE_T iRightFirst = iLast + 1;
2214 if (iLeftLast - iLeft < iRight - iRightFirst)
2215 { // Left partition is smaller, sort it recursively
2216 SortRange(iLeft, iLeftLast);
2217 // Tail call to sort the right (bigger) partition
2218 iLeft = iRightFirst;
2223 { // Right partition is smaller, sort it recursively
2224 SortRange(iRightFirst, iRight);
2225 // Tail call to sort the left (bigger) partition
2234 //*****************************************************************************
2235 // Faster and simpler version of the binary search below.
2236 //*****************************************************************************
2238 const T * BinarySearch(const T * pBase, int iCount, const T & find)
2240 WRAPPER_NO_CONTRACT;
2243 int iLast = iCount - 1;
2245 // It is faster to use linear search once we get down to a small number of elements.
2246 while (iLast - iFirst > 10)
2248 int iMid = (iLast + iFirst) / 2;
2250 if (find < pBase[iMid])
2256 for (int i = iFirst; i <= iLast; i++)
2258 if (find == pBase[i])
2261 if (find < pBase[i])
2268 //*****************************************************************************
2269 // This template encapsulates a binary search algorithm on the given type
2271 //*****************************************************************************
2272 template <class T> class CBinarySearch
2275 const T *m_pBase; // Base of array to sort.
2276 int m_iCount; // How many items in array.
2280 const T *pBase, // Address of first element.
2281 int iCount) : // Value to find.
2285 LIMITED_METHOD_CONTRACT;
2288 //*****************************************************************************
2289 // Searches for the item passed to ctor.
2290 //*****************************************************************************
2291 const T *Find( // Pointer to found item in array.
2292 const T *psFind, // The key to find.
2293 int *piInsert = NULL) // Index to insert at.
2295 WRAPPER_NO_CONTRACT;
2296 int iMid, iFirst, iLast; // Loop control.
2297 int iCmp; // Comparison.
2300 iLast = m_iCount - 1;
2301 while (iFirst <= iLast)
2303 iMid = (iLast + iFirst) / 2;
2304 iCmp = Compare(psFind, &m_pBase[iMid]);
2307 if (piInsert != NULL)
2309 return (&m_pBase[iMid]);
2316 if (piInsert != NULL)
2321 //*****************************************************************************
2322 // Override this function to do the comparison if a comparison operator is
2323 // not valid for your data type (such as a struct).
2324 //*****************************************************************************
2325 virtual int Compare( // -1, 0, or 1
2326 const T *psFirst, // Key you are looking for.
2327 const T *psSecond) // Item to compare to.
2329 LIMITED_METHOD_CONTRACT;
2330 return (memcmp(psFirst, psSecond, sizeof(T)));
2331 // return (::Compare(*psFirst, *psSecond));
2335 //*****************************************************************************
2336 // The information that the hash table implementation stores at the beginning
2337 // of every record that can be but in the hash table.
2338 //*****************************************************************************
2339 typedef DPTR(struct HASHENTRY) PTR_HASHENTRY;
2342 ULONG iPrev; // Previous bucket in the chain.
2343 ULONG iNext; // Next bucket in the chain.
2346 typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY;
2347 struct FREEHASHENTRY : HASHENTRY
2352 //*****************************************************************************
2353 // Used by the FindFirst/FindNextEntry functions. These api's allow you to
2354 // do a sequential scan of all entries.
2355 //*****************************************************************************
2358 ULONG iBucket; // The next bucket to look in.
2363 //*****************************************************************************
2364 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2365 // The hashtable implementation that should be used instead is code:SHash.
2366 // If code:SHash does not work for you, talk to mailto:clrdeag.
2367 //*****************************************************************************
2368 // This is a class that implements a chain and bucket hash table.
2370 // The data is actually supplied as an array of structures by the user of this class.
2371 // This allows the buckets to use small indices to point to the chain, instead of pointers.
2373 // Each entry in the array contains a HASHENTRY structure immediately
2374 // followed by the key used to hash the structure.
2376 // The HASHENTRY part of every structure is used to implement the chain of
2377 // entries in a single bucket.
2379 // This implementation does not support rehashing the buckets if the table grows
2381 // @TODO: Fix this by adding an abstract function Hash() which must be implemented
2384 //*****************************************************************************
2387 friend class DebuggerRCThread; //RCthread actually needs access to
2388 //fields of derrived class DebuggerPatchTable
2391 TADDR m_pcEntries; // Pointer to the array of structs.
2392 ULONG m_iEntrySize; // Size of the structs.
2394 ULONG m_iBuckets; // # of chains we are hashing into.
2395 PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains.
2397 INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics
2399 HASHENTRY *EntryPtr(ULONG iEntry)
2401 LIMITED_METHOD_DAC_CONTRACT;
2402 return (PTR_HASHENTRY(m_pcEntries + (iEntry * m_iEntrySize)));
2405 ULONG ItemIndex(HASHENTRY *p)
2408 LIMITED_METHOD_CONTRACT;
2409 return (ULONG)((dac_cast<TADDR>(p) - m_pcEntries) / m_iEntrySize);
2416 ULONG iBuckets) : // # of chains we are hashing into.
2417 m_pcEntries((TADDR)NULL),
2418 m_iBuckets(iBuckets)
2420 LIMITED_METHOD_CONTRACT;
2424 INDEBUG(m_maxSearch = 0;)
2427 CHashTable() : // # of chains we are hashing into.
2428 m_pcEntries((TADDR)NULL),
2431 LIMITED_METHOD_CONTRACT;
2435 INDEBUG(m_maxSearch = 0;)
2438 #ifndef DACCESS_COMPILE
2442 LIMITED_METHOD_CONTRACT;
2443 if (m_piBuckets != NULL)
2445 delete [] m_piBuckets;
2450 //*****************************************************************************
2451 // This is the second part of construction where we do all of the work that
2452 // can fail. We also take the array of structs here because the calling class
2453 // presumably needs to allocate it in its NewInit.
2454 //*****************************************************************************
2455 HRESULT NewInit( // Return status.
2456 BYTE *pcEntries, // Array of structs we are managing.
2457 ULONG iEntrySize); // Size of the entries.
2459 //*****************************************************************************
2460 // This can be called to change the pointer to the table that the hash table
2461 // is managing. You might call this if (for example) you realloc the size
2462 // of the table and its pointer is different.
2463 //*****************************************************************************
2465 BYTE *pcEntries) // Array of structs we are managing.
2467 LIMITED_METHOD_CONTRACT;
2468 m_pcEntries = (TADDR)pcEntries;
2471 //*****************************************************************************
2472 // Clear the hash table as if there were nothing in it.
2473 //*****************************************************************************
2476 LIMITED_METHOD_CONTRACT;
2477 _ASSERTE(m_piBuckets != NULL);
2478 memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG));
2481 //*****************************************************************************
2482 // Add the struct at the specified index in m_pcEntries to the hash chains.
2483 //*****************************************************************************
2484 BYTE *Add( // New entry.
2485 ULONG iHash, // Hash value of entry to add.
2486 ULONG iIndex); // Index of struct in m_pcEntries.
2488 //*****************************************************************************
2489 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2490 //*****************************************************************************
2492 ULONG iHash, // Hash value of entry to delete.
2493 ULONG iIndex); // Index of struct in m_pcEntries.
2496 ULONG iHash, // Hash value of entry to delete.
2497 HASHENTRY *psEntry); // The struct to delete.
2499 //*****************************************************************************
2500 // The item at the specified index has been moved, update the previous and
2502 //*****************************************************************************
2504 ULONG iHash, // Hash value for the item.
2505 ULONG iNew); // New location.
2507 #endif // #ifndef DACCESS_COMPILE
2509 //*****************************************************************************
2510 // Return a boolean indicating whether or not this hash table has been inited.
2511 //*****************************************************************************
2514 LIMITED_METHOD_CONTRACT;
2515 return (m_piBuckets != NULL);
2518 //*****************************************************************************
2519 // Search the hash table for an entry with the specified key value.
2520 //*****************************************************************************
2521 BYTE *Find( // Index of struct in m_pcEntries.
2522 ULONG iHash, // Hash value of the item.
2523 SIZE_T key); // The key to match.
2525 //*****************************************************************************
2526 // Search the hash table for the next entry with the specified key value.
2527 //*****************************************************************************
2528 ULONG FindNext( // Index of struct in m_pcEntries.
2529 SIZE_T key, // The key to match.
2530 ULONG iIndex); // Index of previous match.
2532 //*****************************************************************************
2533 // Returns the first entry in the first hash bucket and inits the search
2534 // struct. Use the FindNextEntry function to continue walking the list. The
2535 // return order is not gauranteed.
2536 //*****************************************************************************
2537 BYTE *FindFirstEntry( // First entry found, or 0.
2538 HASHFIND *psSrch) // Search object.
2540 WRAPPER_NO_CONTRACT;
2541 if (m_piBuckets == 0)
2543 psSrch->iBucket = 1;
2544 psSrch->iNext = m_piBuckets[0];
2545 return (FindNextEntry(psSrch));
2548 //*****************************************************************************
2549 // Returns the next entry in the list.
2550 //*****************************************************************************
2551 BYTE *FindNextEntry( // The next entry, or0 for end of list.
2552 HASHFIND *psSrch); // Search object.
2554 #ifdef DACCESS_COMPILE
2555 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
2560 virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0;
2567 static BYTE *Alloc(int iSize, int iMaxSize)
2569 WRAPPER_NO_CONTRACT;
2570 return (new BYTE[iSize]);
2572 static void Free(BYTE *pPtr, int iSize)
2574 LIMITED_METHOD_CONTRACT;
2577 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2579 WRAPPER_NO_CONTRACT;
2581 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2582 //check for overflow
2583 if(newSize.IsOverflow())
2586 p = new (nothrow) BYTE[newSize.Value()];
2587 if (p == 0) return (0);
2588 memcpy (p, pPtr, iCurSize);
2593 static void Clean(BYTE * pData, int iSize)
2596 static int RoundSize(int iSize)
2598 LIMITED_METHOD_CONTRACT;
2601 static int GrowSize(int iCurSize)
2603 LIMITED_METHOD_CONTRACT;
2604 int newSize = (3 * iCurSize) / 2;
2605 return (newSize < 256) ? 256 : newSize;
2609 class CNewDataNoThrow
2612 static BYTE *Alloc(int iSize, int iMaxSize)
2614 WRAPPER_NO_CONTRACT;
2615 return (new (nothrow) BYTE[iSize]);
2617 static void Free(BYTE *pPtr, int iSize)
2619 LIMITED_METHOD_CONTRACT;
2622 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2624 WRAPPER_NO_CONTRACT;
2626 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2627 //check for overflow
2628 if(newSize.IsOverflow())
2631 p = new (nothrow) BYTE[newSize.Value()];
2632 if (p == 0) return (0);
2633 memcpy (p, pPtr, iCurSize);
2638 static void Clean(BYTE * pData, int iSize)
2641 static int RoundSize(int iSize)
2643 LIMITED_METHOD_CONTRACT;
2646 static int GrowSize(int iCurSize)
2648 LIMITED_METHOD_CONTRACT;
2649 int newSize = (3 * iCurSize) / 2;
2650 return (newSize < 256) ? 256 : newSize;
2655 //*****************************************************************************
2656 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2657 // The hashtable implementation that should be used instead is code:SHash.
2658 // If code:SHash does not work for you, talk to mailto:clrdeag.
2659 //*****************************************************************************
2660 // CHashTable expects the data to be in a single array - this is provided by
2661 // CHashTableAndData.
2662 // The array is allocated using the MemMgr type. CNewData and
2663 // CNewDataNoThrow can be used for this.
2664 //*****************************************************************************
2665 template <class MemMgr>
2666 class CHashTableAndData : public CHashTable
2669 ULONG m_iFree; // Index into m_pcEntries[] of next available slot
2670 ULONG m_iEntries; // size of m_pcEntries[]
2674 CHashTableAndData() :
2677 LIMITED_METHOD_CONTRACT;
2681 ULONG iBuckets) : // # of chains we are hashing into.
2682 CHashTable(iBuckets)
2684 LIMITED_METHOD_CONTRACT;
2687 #ifndef DACCESS_COMPILE
2689 ~CHashTableAndData()
2691 WRAPPER_NO_CONTRACT;
2692 if (m_pcEntries != NULL)
2693 MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize));
2696 //*****************************************************************************
2697 // This is the second part of construction where we do all of the work that
2698 // can fail. We also take the array of structs here because the calling class
2699 // presumably needs to allocate it in its NewInit.
2700 //*****************************************************************************
2701 HRESULT NewInit( // Return status.
2702 ULONG iEntries, // # of entries.
2703 ULONG iEntrySize, // Size of the entries.
2704 int iMaxSize); // Max size of data.
2706 //*****************************************************************************
2707 // Clear the hash table as if there were nothing in it.
2708 //*****************************************************************************
2711 WRAPPER_NO_CONTRACT;
2713 InitFreeChain(0, m_iEntries);
2714 CHashTable::Clear();
2717 //*****************************************************************************
2718 // Grabs a slot for the new entry to be added.
2719 // The caller should fill in the non-HASHENTRY part of the returned slot
2720 //*****************************************************************************
2722 ULONG iHash) // Hash value of entry to add.
2724 WRAPPER_NO_CONTRACT;
2725 FREEHASHENTRY *psEntry;
2727 // Make the table bigger if necessary.
2728 if (m_iFree == UINT32_MAX && !Grow())
2731 // Add the first entry from the free list to the hash chain.
2732 psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree);
2733 m_iFree = psEntry->iFree;
2735 // If we're recycling memory, give our memory-allocator a chance to re-init it.
2737 // Each entry is prefixed with a header - we don't want to trash that.
2738 SIZE_T cbHeader = sizeof(FREEHASHENTRY);
2739 MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader));
2741 return ((BYTE *) psEntry);
2744 //*****************************************************************************
2745 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2746 //*****************************************************************************
2748 ULONG iHash, // Hash value of entry to delete.
2749 ULONG iIndex) // Index of struct in m_pcEntries.
2751 WRAPPER_NO_CONTRACT;
2752 CHashTable::Delete(iHash, iIndex);
2753 ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree;
2758 ULONG iHash, // Hash value of entry to delete.
2759 HASHENTRY *psEntry) // The struct to delete.
2761 WRAPPER_NO_CONTRACT;
2762 CHashTable::Delete(iHash, psEntry);
2763 ((FREEHASHENTRY *) psEntry)->iFree = m_iFree;
2764 m_iFree = ItemIndex(psEntry);
2767 #endif // #ifndef DACCESS_COMPILE
2769 // This is a sad legacy workaround. The debugger's patch table (implemented as this
2770 // class) is shared across process. We publish the runtime offsets of
2771 // some key fields. Since those fields are private, we have to provide
2772 // accessors here. So if you're not using these functions, don't start.
2773 // We can hopefully remove them.
2774 // Note that we can't just make RCThread a friend of this class (we tried
2775 // originally) because the inheritence chain has a private modifier,
2776 // so DebuggerPatchTable::m_pcEntries is illegal.
2777 static SIZE_T helper_GetOffsetOfEntries()
2779 LIMITED_METHOD_CONTRACT;
2780 return offsetof(CHashTableAndData, m_pcEntries);
2783 static SIZE_T helper_GetOffsetOfCount()
2785 LIMITED_METHOD_CONTRACT;
2786 return offsetof(CHashTableAndData, m_iEntries);
2789 #ifdef DACCESS_COMPILE
2790 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2793 CHashTable::EnumMemoryRegions(flags, m_iEntries);
2798 void InitFreeChain(ULONG iStart,ULONG iEnd);
2802 #ifndef DACCESS_COMPILE
2804 //*****************************************************************************
2805 // This is the second part of construction where we do all of the work that
2806 // can fail. We also take the array of structs here because the calling class
2807 // presumably needs to allocate it in its NewInit.
2808 //*****************************************************************************
2809 template<class MemMgr>
2810 HRESULT CHashTableAndData<MemMgr>::NewInit(// Return status.
2811 ULONG iEntries, // # of entries.
2812 ULONG iEntrySize, // Size of the entries.
2813 int iMaxSize) // Max size of data.
2815 WRAPPER_NO_CONTRACT;
2820 // note that this function can throw because it depends on the <M>::Alloc
2822 // Allocate the memory for the entries.
2823 if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize),
2824 MemMgr::RoundSize(iMaxSize))) == 0)
2825 return (E_OUTOFMEMORY);
2826 m_iEntries = iEntries;
2828 // Init the base table.
2829 if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize)))
2830 MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize));
2833 // Init the free chain.
2835 InitFreeChain(0, iEntries);
2840 //*****************************************************************************
2841 // Initialize a range of records such that they are linked together to be put
2842 // on the free chain.
2843 //*****************************************************************************
2844 template<class MemMgr>
2845 void CHashTableAndData<MemMgr>::InitFreeChain(
2846 ULONG iStart, // Index to start initializing.
2847 ULONG iEnd) // Index to stop initializing
2849 LIMITED_METHOD_CONTRACT;
2851 _ASSERTE(iEnd > iStart);
2853 pcPtr = (BYTE*)m_pcEntries + iStart * m_iEntrySize;
2854 for (++iStart; iStart < iEnd; ++iStart)
2856 ((FREEHASHENTRY *) pcPtr)->iFree = iStart;
2857 pcPtr += m_iEntrySize;
2859 ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX;
2862 //*****************************************************************************
2863 // Attempt to increase the amount of space available for the record heap.
2864 //*****************************************************************************
2865 template<class MemMgr>
2866 int CHashTableAndData<MemMgr>::Grow() // 1 if successful, 0 if not.
2868 WRAPPER_NO_CONTRACT;
2869 int iCurSize; // Current size in bytes.
2870 int iEntries; // New # of entries.
2872 _ASSERTE(m_pcEntries != NULL);
2873 _ASSERTE(m_iFree == UINT32_MAX);
2875 // Compute the current size and new # of entries.
2876 S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize);
2877 if( iTotEntrySize.IsOverflow() )
2879 _ASSERTE( !"CHashTableAndData overflow!" );
2882 iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() );
2883 iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize;
2885 if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) )
2887 _ASSERTE( !"CHashTableAndData overflow!" );
2891 // Try to expand the array.
2892 if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0)
2895 // Init the newly allocated space.
2896 InitFreeChain(m_iEntries, iEntries);
2897 m_iFree = m_iEntries;
2898 m_iEntries = iEntries;
2902 #endif // #ifndef DACCESS_COMPILE
2904 //*****************************************************************************
2905 //*****************************************************************************
2907 inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data)
2909 LIMITED_METHOD_DAC_CONTRACT;
2910 return ((currentHash << 5) + currentHash) ^ data;
2913 inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr)
2915 WRAPPER_NO_CONTRACT;
2917 return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast<TADDR>(ptr))));
2920 inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c)
2922 LIMITED_METHOD_DAC_CONTRACT;
2925 lookup3.c, by Bob Jenkins, May 2006, Public Domain.
2927 These are functions for producing 32-bit hashes for hash table lookup.
2928 hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
2929 are externally useful functions. Routines to test the hash are included
2930 if SELF_TEST is defined. You can use this free for any purpose. It's in
2931 the public domain. It has no warranty.
2934 #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
2935 c ^= b; c -= rot32(b,14);
2936 a ^= c; a -= rot32(c,11);
2937 b ^= a; b -= rot32(a,25);
2938 c ^= b; c -= rot32(b,16);
2939 a ^= c; a -= rot32(c,4);
2940 b ^= a; b -= rot32(a,14);
2941 c ^= b; c -= rot32(b,24);
2946 inline ULONG HashBytes(BYTE const *pbData, size_t iSize)
2948 LIMITED_METHOD_CONTRACT;
2951 BYTE const *pbDataEnd = pbData + iSize;
2953 for (/**/ ; pbData < pbDataEnd; pbData++)
2955 hash = ((hash << 5) + hash) ^ *pbData;
2960 // Helper function for hashing a string char by char.
2961 inline ULONG HashStringA(LPCSTR szStr)
2963 LIMITED_METHOD_CONTRACT;
2967 while ((c = *szStr) != 0)
2969 hash = ((hash << 5) + hash) ^ c;
2975 inline ULONG HashString(LPCWSTR szStr)
2977 LIMITED_METHOD_CONTRACT;
2981 while ((c = *szStr) != 0)
2983 hash = ((hash << 5) + hash) ^ c;
2989 inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr)
2991 LIMITED_METHOD_CONTRACT;
2994 // hash the string two characters at a time
2995 ULONG *ptr = (ULONG *)szStr;
2997 // we assume that szStr is null-terminated
2998 _ASSERTE(cchStr <= wcslen(szStr));
2999 SIZE_T cDwordCount = (cchStr + 1) / 2;
3001 for (SIZE_T i = 0; i < cDwordCount; i++)
3003 hash = ((hash << 5) + hash) ^ ptr[i];
3009 // Case-insensitive string hash function.
3010 inline ULONG HashiStringA(LPCSTR szStr)
3012 LIMITED_METHOD_CONTRACT;
3016 hash = ((hash << 5) + hash) ^ toupper(*szStr);
3022 // Case-insensitive string hash function.
3023 inline ULONG HashiString(LPCWSTR szStr)
3025 LIMITED_METHOD_CONTRACT;
3029 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3035 // Case-insensitive string hash function.
3036 inline ULONG HashiStringN(LPCWSTR szStr, DWORD count)
3038 LIMITED_METHOD_CONTRACT;
3040 while (*szStr != 0 && count--)
3042 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3048 // Case-insensitive string hash function when all of the
3049 // characters in the string are known to be below 0x80.
3050 // Knowing this is much more efficient than calling
3052 inline ULONG HashiStringKnownLower80(LPCWSTR szStr) {
3053 LIMITED_METHOD_CONTRACT;
3057 while ((c = *szStr)!=0) {
3058 //If we have a lowercase character, ANDing off 0x20
3059 //(mask) will make it an uppercase character.
3060 if (c>='a' && c<='z') {
3063 hash = ((hash << 5) + hash) ^ c;
3069 inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) {
3070 LIMITED_METHOD_CONTRACT;
3074 while ((c = *szStr) !=0 && count--) {
3075 //If we have a lowercase character, ANDing off 0x20
3076 //(mask) will make it an uppercase character.
3077 if (c>='a' && c<='z') {
3080 hash = ((hash << 5) + hash) ^ c;
3086 //*****************************************************************************
3087 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3088 // The hashtable implementation that should be used instead is code:SHash.
3089 // If code:SHash does not work for you, talk to mailto:clrdeag.
3090 //*****************************************************************************
3091 // This class implements a closed hashing table. Values are hashed to a bucket,
3092 // and if that bucket is full already, then the value is placed in the next
3093 // free bucket starting after the desired target (with wrap around). If the
3094 // table becomes 75% full, it is grown and rehashed to reduce lookups. This
3095 // class is best used in a reltively small lookup table where hashing is
3096 // not going to cause many collisions. By not having the collision chain
3097 // logic, a lot of memory is saved.
3099 // The user of the template is required to supply several methods which decide
3100 // how each element can be marked as free, deleted, or used. It would have
3101 // been possible to write this with more internal logic, but that would require
3102 // either (a) more overhead to add status on top of elements, or (b) hard
3103 // coded types like one for strings, one for ints, etc... This gives you the
3104 // flexibility of adding logic to your type.
3105 //*****************************************************************************
3106 class CClosedHashBase
3108 BYTE *EntryPtr(int iEntry)
3110 LIMITED_METHOD_CONTRACT;
3111 return (m_rgData + (iEntry * m_iEntrySize));
3114 BYTE *EntryPtr(int iEntry, BYTE *rgData)
3116 LIMITED_METHOD_CONTRACT;
3117 return (rgData + (iEntry * m_iEntrySize));
3123 FREE, // Item is not in use right now.
3124 DELETED, // Item is deleted.
3125 USED // Item is in use.
3129 int iBuckets, // How many buckets should we start with.
3130 int iEntrySize, // Size of an entry.
3131 bool bPerfect) : // true if bucket size will hash with no collisions.
3132 m_bPerfect(bPerfect),
3133 m_iBuckets(iBuckets),
3134 m_iEntrySize(iEntrySize),
3139 LIMITED_METHOD_CONTRACT;
3140 m_iSize = iBuckets + 7;
3143 virtual ~CClosedHashBase()
3145 WRAPPER_NO_CONTRACT;
3149 virtual void Clear()
3151 LIMITED_METHOD_CONTRACT;
3158 //*****************************************************************************
3159 // Accessors for getting at the underlying data. Be careful to use Count()
3160 // only when you want the number of buckets actually used.
3161 //*****************************************************************************
3165 LIMITED_METHOD_CONTRACT;
3171 LIMITED_METHOD_CONTRACT;
3172 return (m_iCollisions);
3177 LIMITED_METHOD_CONTRACT;
3178 return (m_iBuckets);
3181 void SetBuckets(int iBuckets, bool bPerfect=false)
3183 LIMITED_METHOD_CONTRACT;
3184 _ASSERTE(m_rgData == 0);
3185 m_iBuckets = iBuckets;
3186 m_iSize = m_iBuckets + 7;
3187 m_bPerfect = bPerfect;
3192 LIMITED_METHOD_CONTRACT;
3196 //*****************************************************************************
3197 // Add a new item to hash table given the key value. If this new entry
3198 // exceeds maximum size, then the table will grow and be re-hashed, which
3199 // may cause a memory error.
3200 //*****************************************************************************
3201 BYTE *Add( // New item to fill out on success.
3202 void *pData) // The value to hash on.
3204 WRAPPER_NO_CONTRACT;
3205 // If we haven't allocated any memory, or it is too small, fix it.
3206 if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect))
3212 return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount));
3215 //*****************************************************************************
3216 // Delete the given value. This will simply mark the entry as deleted (in
3217 // order to keep the collision chain intact). There is an optimization that
3218 // consecutive deleted entries leading up to a free entry are themselves freed
3219 // to reduce collisions later on.
3220 //*****************************************************************************
3222 void *pData); // Key value to delete.
3225 //*****************************************************************************
3226 // Callback function passed to DeleteLoop.
3227 //*****************************************************************************
3228 typedef BOOL (* DELETELOOPFUNC)( // Delete current item?
3229 BYTE *pEntry, // Bucket entry to evaluate
3230 void *pCustomizer); // User-defined value
3232 //*****************************************************************************
3233 // Iterates over all active values, passing each one to pDeleteLoopFunc.
3234 // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer
3235 // and faster than using FindNext() and Delete().
3236 //*****************************************************************************
3238 DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item
3239 void *pCustomizer); // Extra value passed to deletefunc.
3242 //*****************************************************************************
3243 // Lookup a key value and return a pointer to the element if found.
3244 //*****************************************************************************
3245 BYTE *Find( // The item if found, 0 if not.
3246 void *pData); // The key to lookup.
3248 //*****************************************************************************
3249 // Look for an item in the table. If it isn't found, then create a new one and
3251 //*****************************************************************************
3252 BYTE *FindOrAdd( // The item if found, 0 if not.
3253 void *pData, // The key to lookup.
3254 bool &bNew); // true if created.
3256 //*****************************************************************************
3257 // The following functions are used to traverse each used entry. This code
3258 // will skip over deleted and free entries freeing the caller up from such
3260 //*****************************************************************************
3261 BYTE *GetFirst() // The first entry, 0 if none.
3263 WRAPPER_NO_CONTRACT;
3264 int i; // Loop control.
3266 // If we've never allocated the table there can't be any to get.
3270 // Find the first one.
3271 for (i=0; i<m_iSize; i++)
3273 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3274 return (EntryPtr(i));
3279 BYTE *GetNext(BYTE *Prev) // The next entry, 0 if done.
3281 WRAPPER_NO_CONTRACT;
3282 int i; // Loop control.
3284 for (i = (int)(((size_t) Prev - (size_t) &m_rgData[0]) / m_iEntrySize) + 1; i<m_iSize; i++)
3286 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3287 return (EntryPtr(i));
3293 //*****************************************************************************
3294 // Hash is called with a pointer to an element in the table. You must override
3295 // this method and provide a hash algorithm for your element type.
3296 //*****************************************************************************
3297 virtual unsigned int Hash( // The key value.
3298 void const *pData)=0; // Raw data to hash.
3300 //*****************************************************************************
3301 // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
3302 // direction of miscompare. In this system everything is always equal or not.
3303 //*****************************************************************************
3304 virtual unsigned int Compare( // 0, -1, or 1.
3305 void const *pData, // Raw key data on lookup.
3306 BYTE *pElement)=0; // The element to compare data against.
3308 //*****************************************************************************
3309 // Return true if the element is free to be used.
3310 //*****************************************************************************
3311 virtual ELEMENTSTATUS Status( // The status of the entry.
3312 BYTE *pElement)=0; // The element to check.
3314 //*****************************************************************************
3315 // Sets the status of the given element.
3316 //*****************************************************************************
3317 virtual void SetStatus(
3318 BYTE *pElement, // The element to set status for.
3319 ELEMENTSTATUS eStatus)=0; // New status.
3321 //*****************************************************************************
3322 // Returns the internal key value for an element.
3323 //*****************************************************************************
3324 virtual void *GetKey( // The data to hash on.
3325 BYTE *pElement)=0; // The element to return data ptr for.
3327 //*****************************************************************************
3328 // This helper actually does the add for you.
3329 //*****************************************************************************
3330 BYTE *DoAdd(void *pData, BYTE *rgData, int &iBuckets, int iSize,
3331 int &iCollisions, int &iCount);
3333 //*****************************************************************************
3334 // This function is called either to init the table in the first place, or
3335 // to rehash the table if we ran out of room.
3336 //*****************************************************************************
3337 bool ReHash(); // true if successful.
3339 //*****************************************************************************
3340 // Walk each item in the table and mark it free.
3341 //*****************************************************************************
3342 void InitFree(BYTE *ptr, int iSize)
3344 WRAPPER_NO_CONTRACT;
3346 for (i=0; i<iSize; i++, ptr += m_iEntrySize)
3347 SetStatus(ptr, FREE);
3351 bool m_bPerfect; // true if the table size guarantees
3353 int m_iBuckets; // How many buckets do we have.
3354 int m_iEntrySize; // Size of an entry.
3355 int m_iSize; // How many elements can we have.
3356 int m_iCount; // How many items cannot be used (NON free, i.e. USED+DELETED).
3357 int m_iCollisions; // How many have we had.
3358 BYTE *m_rgData; // Data element list.
3361 //*****************************************************************************
3362 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3363 // The hashtable implementation that should be used instead is code:SHash.
3364 // If code:SHash does not work for you, talk to mailto:clrdeag.
3365 //*****************************************************************************
3366 template <class T> class CClosedHash : public CClosedHashBase
3370 int iBuckets, // How many buckets should we start with.
3371 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3372 CClosedHashBase(iBuckets, sizeof(T), bPerfect)
3374 WRAPPER_NO_CONTRACT;
3377 T &operator[](int iIndex)
3379 WRAPPER_NO_CONTRACT;
3380 return ((T &) *(Data() + (iIndex * sizeof(T))));
3384 //*****************************************************************************
3385 // Add a new item to hash table given the key value. If this new entry
3386 // exceeds maximum size, then the table will grow and be re-hashed, which
3387 // may cause a memory error.
3388 //*****************************************************************************
3389 T *Add( // New item to fill out on success.
3390 void *pData) // The value to hash on.
3392 WRAPPER_NO_CONTRACT;
3393 return ((T *) CClosedHashBase::Add(pData));
3396 //*****************************************************************************
3397 // Lookup a key value and return a pointer to the element if found.
3398 //*****************************************************************************
3399 T *Find( // The item if found, 0 if not.
3400 void *pData) // The key to lookup.
3402 WRAPPER_NO_CONTRACT;
3403 return ((T *) CClosedHashBase::Find(pData));
3406 //*****************************************************************************
3407 // Look for an item in the table. If it isn't found, then create a new one and
3409 //*****************************************************************************
3410 T *FindOrAdd( // The item if found, 0 if not.
3411 void *pData, // The key to lookup.
3412 bool &bNew) // true if created.
3414 WRAPPER_NO_CONTRACT;
3415 return ((T *) CClosedHashBase::FindOrAdd(pData, bNew));
3419 //*****************************************************************************
3420 // The following functions are used to traverse each used entry. This code
3421 // will skip over deleted and free entries freeing the caller up from such
3423 //*****************************************************************************
3424 T *GetFirst() // The first entry, 0 if none.
3426 WRAPPER_NO_CONTRACT;
3427 return ((T *) CClosedHashBase::GetFirst());
3430 T *GetNext(T *Prev) // The next entry, 0 if done.
3432 WRAPPER_NO_CONTRACT;
3433 return ((T *) CClosedHashBase::GetNext((BYTE *) Prev));
3438 //*****************************************************************************
3439 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3440 // The hashtable implementation that should be used instead is code:SHash.
3441 // If code:SHash does not work for you, talk to mailto:clrdeag.
3442 //*****************************************************************************
3443 // Closed hash with typed parameters. The derived class is the second
3444 // parameter to the template. The derived class must implement:
3445 // unsigned long Hash(const T *pData);
3446 // unsigned long Compare(const T *p1, T *p2);
3447 // ELEMENTSTATUS Status(T *pEntry);
3448 // void SetStatus(T *pEntry, ELEMENTSTATUS s);
3449 // void* GetKey(T *pEntry);
3450 //*****************************************************************************
3451 template<class T, class H>class CClosedHashEx : public CClosedHash<T>
3455 int iBuckets, // How many buckets should we start with.
3456 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3457 CClosedHash<T> (iBuckets, bPerfect)
3459 WRAPPER_NO_CONTRACT;
3462 unsigned int Hash(const void *pData)
3464 WRAPPER_NO_CONTRACT;
3465 return static_cast<H*>(this)->Hash((const T*)pData);
3468 unsigned int Compare(const void *p1, BYTE *p2)
3470 WRAPPER_NO_CONTRACT;
3471 return static_cast<H*>(this)->Compare((const T*)p1, (T*)p2);
3474 typename CClosedHash<T>::ELEMENTSTATUS Status(BYTE *p)
3476 WRAPPER_NO_CONTRACT;
3477 return static_cast<H*>(this)->Status((T*)p);
3480 void SetStatus(BYTE *p, typename CClosedHash<T>::ELEMENTSTATUS s)
3482 WRAPPER_NO_CONTRACT;
3483 static_cast<H*>(this)->SetStatus((T*)p, s);
3486 void* GetKey(BYTE *p)
3488 WRAPPER_NO_CONTRACT;
3489 return static_cast<H*>(this)->GetKey((T*)p);
3494 //*****************************************************************************
3495 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3496 // The hashtable implementation that should be used instead is code:SHash.
3497 // If code:SHash does not work for you, talk to mailto:clrdeag.
3498 //*****************************************************************************
3499 // This template is another form of a closed hash table. It handles collisions
3500 // through a linked chain. To use it, derive your hashed item from HASHLINK
3501 // and implement the virtual functions required. 1.5 * ibuckets will be
3502 // allocated, with the extra .5 used for collisions. If you add to the point
3503 // where no free nodes are available, the entire table is grown to make room.
3504 // The advantage to this system is that collisions are always directly known,
3505 // there either is one or there isn't.
3506 //*****************************************************************************
3509 ULONG iNext; // Offset for next entry.
3512 template <class T> class CChainedHash
3514 friend class VerifyLayoutsMD;
3516 CChainedHash(int iBuckets=32) :
3518 m_iBuckets(iBuckets),
3523 LIMITED_METHOD_CONTRACT;
3524 m_iSize = iBuckets + (iBuckets / 2);
3529 LIMITED_METHOD_CONTRACT;
3534 void SetBuckets(int iBuckets)
3536 LIMITED_METHOD_CONTRACT;
3537 _ASSERTE(m_rgData == 0);
3538 // if iBuckets==0, then we'll allocate a zero size array and AV on dereference.
3539 _ASSERTE(iBuckets > 0);
3540 m_iBuckets = iBuckets;
3541 m_iSize = iBuckets + (iBuckets / 2);
3544 T *Add(void const *pData)
3546 WRAPPER_NO_CONTRACT;
3551 // Build the list if required.
3552 if (m_rgData == 0 || m_iFree == 0xffffffff)
3558 // Hash the item and pick a bucket.
3559 iHash = Hash(pData);
3560 iBucket = iHash % m_iBuckets;
3562 // Use the bucket if it is free.
3563 if (InUse(&m_rgData[iBucket]) == false)
3565 pItem = &m_rgData[iBucket];
3566 pItem->iNext = 0xffffffff;
3568 // Else take one off of the free list for use.
3573 // Pull an item from the free list.
3575 pItem = &m_rgData[m_iFree];
3576 m_iFree = pItem->iNext;
3578 // Link the new node in after the bucket.
3579 pItem->iNext = m_rgData[iBucket].iNext;
3580 m_rgData[iBucket].iNext = iEntry;
3586 T *Find(void const *pData, bool bAddIfNew=false)
3588 WRAPPER_NO_CONTRACT;
3593 // Check states for lookup.
3596 // If we won't be adding, then we are through.
3597 if (bAddIfNew == false)
3600 // Otherwise, create the table.
3605 // Hash the item and pick a bucket.
3606 iHash = Hash(pData);
3607 iBucket = iHash % m_iBuckets;
3609 // If it isn't in use, then there it wasn't found.
3610 if (!InUse(&m_rgData[iBucket]))
3612 if (bAddIfNew == false)
3616 pItem = &m_rgData[iBucket];
3617 pItem->iNext = 0xffffffff;
3621 // Scan the list for the one we want.
3625 for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem))
3627 if (Cmp(pData, pItem) == 0)
3632 if (!pItem && bAddIfNew)
3636 // Record maximum chain length.
3637 if (iChain > m_iMaxChain)
3638 m_iMaxChain = iChain;
3640 // Now need more room.
3641 if (m_iFree == 0xffffffff)
3647 // Pull an item from the free list.
3649 pItem = &m_rgData[m_iFree];
3650 m_iFree = pItem->iNext;
3652 // Link the new node in after the bucket.
3653 pItem->iNext = m_rgData[iBucket].iNext;
3654 m_rgData[iBucket].iNext = iEntry;
3663 LIMITED_METHOD_CONTRACT;
3669 LIMITED_METHOD_CONTRACT;
3670 return (m_iBuckets);
3673 ULONG MaxChainLength()
3675 LIMITED_METHOD_CONTRACT;
3676 return (m_iMaxChain);
3679 virtual void Clear()
3681 LIMITED_METHOD_CONTRACT;
3682 // Free up the memory.
3695 virtual bool InUse(T *pItem)=0;
3696 virtual void SetFree(T *pItem)=0;
3697 virtual ULONG Hash(void const *pData)=0;
3698 virtual int Cmp(void const *pData, void *pItem)=0;
3700 inline T *GetNext(T *pItem)
3702 LIMITED_METHOD_CONTRACT;
3703 if (pItem->iNext != 0xffffffff)
3704 return ((T *) &m_rgData[pItem->iNext]);
3710 WRAPPER_NO_CONTRACT;
3714 // If this is a first time allocation, then just malloc it.
3717 if ((m_rgData = new (nothrow) T[m_iSize]) == 0)
3721 for (i=0; i<m_iSize; i++)
3722 SetFree(&m_rgData[i]);
3724 m_iFree = m_iBuckets;
3725 for (i=m_iBuckets; i<m_iSize; i++)
3726 ((T *) &m_rgData[i])->iNext = i + 1;
3727 ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff;
3731 // Otherwise we need more room on the free chain, so allocate some.
3732 iNewSize = m_iSize + (m_iSize / 2);
3734 // Allocate/realloc memory.
3735 if ((rgTemp = new (nothrow) T[iNewSize]) == 0)
3738 memcpy (rgTemp,m_rgData,m_iSize*sizeof(T));
3741 // Init new entries, save the new free chain, and reset internals.
3743 for (int i=m_iFree; i<iNewSize; i++)
3745 SetFree(&rgTemp[i]);
3746 ((T *) &rgTemp[i])->iNext = i + 1;
3748 ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff;
3756 T *m_rgData; // Data to store items in.
3757 int m_iBuckets; // How many buckets we want.
3758 int m_iSize; // How many are allocated.
3759 int m_iCount; // How many are we using.
3760 ULONG m_iMaxChain; // Max chain length.
3761 ULONG m_iFree; // Free chain.
3765 //*****************************************************************************
3767 //********** String helper functions.
3769 //*****************************************************************************
3771 //*****************************************************************************
3772 // Checks if string length exceeds the specified limit
3773 //*****************************************************************************
3774 inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N)
3776 LIMITED_METHOD_CONTRACT;
3780 for(i=0; (i < N)&&(pstr[i]); i++);
3786 //*****************************************************************************
3787 // Class to parse a list of simple assembly names and then find a match
3788 //*****************************************************************************
3790 class AssemblyNamesList
3794 LPUTF8 m_assemblyName;
3795 AssemblyName *m_next; // Next name
3798 AssemblyName *m_pNames; // List of names
3802 bool IsInList(LPCUTF8 assemblyName);
3806 LIMITED_METHOD_CONTRACT;
3807 return m_pNames == 0;
3810 AssemblyNamesList(__in LPWSTR list);
3811 ~AssemblyNamesList();
3814 //*****************************************************************************
3815 // Class to parse a list of method names and then find a match
3816 //*****************************************************************************
3818 struct CORINFO_SIG_INFO;
3820 class MethodNamesListBase
3824 LPUTF8 methodName; // NULL means wildcard
3825 LPUTF8 className; // NULL means wildcard
3826 int numArgs; // number of args for the method, -1 is wildcard
3827 MethodName *next; // Next name
3830 MethodName *pNames; // List of names
3832 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs);
3837 LIMITED_METHOD_CONTRACT;
3841 void Init(__in __in_z LPWSTR list)
3843 WRAPPER_NO_CONTRACT;
3850 void Insert(__in __in_z LPWSTR list);
3852 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3853 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3856 LIMITED_METHOD_CONTRACT;
3861 class MethodNamesList : public MethodNamesListBase
3866 WRAPPER_NO_CONTRACT;
3870 MethodNamesList(__in LPWSTR list)
3872 WRAPPER_NO_CONTRACT;
3878 WRAPPER_NO_CONTRACT;
3883 #if !defined(NO_CLRCONFIG)
3885 /**************************************************************************/
3886 /* simple wrappers around the REGUTIL and MethodNameList routines that make
3889 /* to be used as static variable - no constructor/destructor, assumes zero
3890 initialized memory */
3896 // NOTE: The following function is deprecated; use the CLRConfig class instead.
3897 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
3899 inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0)
3901 WRAPPER_NO_CONTRACT;
3902 // make sure that the memory was zero initialized
3903 _ASSERTE(m_inited == 0 || m_inited == 1);
3905 if (!m_inited) init_DontUse_(keyName, defaultVal);
3908 inline DWORD val(const CLRConfig::ConfigDWORDInfo & info)
3910 WRAPPER_NO_CONTRACT;
3911 // make sure that the memory was zero initialized
3912 _ASSERTE(m_inited == 0 || m_inited == 1);
3914 if (!m_inited) init(info);
3919 void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0);
3920 void init(const CLRConfig::ConfigDWORDInfo & info);
3927 /**************************************************************************/
3931 inline LPWSTR val(const CLRConfig::ConfigStringInfo & info)
3933 WRAPPER_NO_CONTRACT;
3934 // make sure that the memory was zero initialized
3935 _ASSERTE(m_inited == 0 || m_inited == 1);
3937 if (!m_inited) init(info);
3941 bool isInitialized()
3943 WRAPPER_NO_CONTRACT;
3945 // make sure that the memory was zero initialized
3946 _ASSERTE(m_inited == 0 || m_inited == 1);
3948 return m_inited == 1;
3952 void init(const CLRConfig::ConfigStringInfo & info);
3959 /**************************************************************************/
3960 class ConfigMethodSet
3965 WRAPPER_NO_CONTRACT;
3966 _ASSERTE(m_inited == 1);
3967 return m_list.IsEmpty();
3970 bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3971 bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3973 inline void ensureInit(const CLRConfig::ConfigStringInfo & info)
3975 WRAPPER_NO_CONTRACT;
3976 // make sure that the memory was zero initialized
3977 _ASSERTE(m_inited == 0 || m_inited == 1);
3979 if (!m_inited) init(info);
3983 void init(const CLRConfig::ConfigStringInfo & info);
3986 MethodNamesListBase m_list;
3991 #endif // !defined(NO_CLRCONFIG)
3993 //*****************************************************************************
3994 // Convert a pointer to a string into a GUID.
3995 //*****************************************************************************
3996 HRESULT LPCSTRToGuid( // Return status.
3997 LPCSTR szGuid, // String to convert.
3998 GUID *psGuid); // Buffer for converted GUID.
4000 //*****************************************************************************
4001 // Convert a GUID into a pointer to a string
4002 //*****************************************************************************
4003 int GuidToLPWSTR( // Return status.
4004 GUID Guid, // [IN] The GUID to convert.
4005 __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored
4006 DWORD cchGuid); // [IN] Size in wide chars of szGuid
4008 //*****************************************************************************
4009 // Parse a Wide char string into a GUID
4010 //*****************************************************************************
4012 GUID * Guid, // [OUT] The GUID to fill in
4013 __in_ecount(cchGuid) LPCWSTR szGuid, // [IN] String to parse
4014 DWORD cchGuid); // [IN] Count in wchars in string
4016 typedef VPTR(class RangeList) PTR_RangeList;
4021 VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList)
4023 #ifndef DACCESS_COMPILE
4029 LIMITED_METHOD_CONTRACT;
4033 // Wrappers to make the virtual calls DAC-safe.
4034 BOOL AddRange(const BYTE *start, const BYTE *end, void *id)
4036 return this->AddRangeWorker(start, end, id);
4039 void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL)
4041 return this->RemoveRangesWorker(id, start, end);
4044 BOOL IsInRange(TADDR address, TADDR *pID = NULL)
4048 return this->IsInRangeWorker(address, pID);
4051 #ifndef DACCESS_COMPILE
4053 // You can overload these two for synchronization (as LockedRangeList does)
4054 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id);
4055 // If both "start" and "end" are NULL, then this method deletes all ranges with
4056 // the given id (i.e. the original behaviour). Otherwise, it ignores the given
4057 // id and deletes all ranges falling in the region [start, end).
4058 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL);
4060 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id)
4064 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { }
4065 #endif // !DACCESS_COMPILE
4067 virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL);
4069 #ifdef DACCESS_COMPILE
4070 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4087 struct RangeListBlock
4089 Range ranges[RANGE_COUNT];
4090 DPTR(RangeListBlock) next;
4092 #ifdef DACCESS_COMPILE
4093 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4098 void InitBlock(RangeListBlock *block);
4100 RangeListBlock m_starterBlock;
4101 DPTR(RangeListBlock) m_firstEmptyBlock;
4102 TADDR m_firstEmptyRange;
4107 // A private function to do the equavilent of a CoCreateInstance in
4108 // cases where we can't make the real call. Use this when, for
4109 // instance, you need to create a symbol reader in the Runtime but
4110 // we're not CoInitialized. Obviously, this is only good for COM
4111 // objects for which CoCreateInstance is just a glorified
4112 // find-and-load-me operation.
4115 HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid,
4119 HMODULE * phmodDll);
4121 // Provided for backward compatibility and for code that doesn't need the HMODULE of the
4122 // DLL that was loaded to create the COM object. See comment at implementation of
4123 // code:FakeCoCreateInstanceEx for more details.
4124 inline HRESULT FakeCoCreateInstance(REFCLSID rclsid,
4134 return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL);
4137 //*****************************************************************************
4138 // Gets the directory based on the location of the module. This routine
4139 // is called at COR setup time. Set is called during EEStartup and by the
4140 // MetaData dispenser.
4141 //*****************************************************************************
4142 HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength);
4143 LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL);
4145 //*****************************************************************************
4146 // This function validates the given Method/Field/Standalone signature. (util.cpp)
4147 //*****************************************************************************
4148 struct IMDInternalImport;
4149 HRESULT validateTokenSig(
4150 mdToken tk, // [IN] Token whose signature needs to be validated.
4151 PCCOR_SIGNATURE pbSig, // [IN] Signature.
4152 ULONG cbSig, // [IN] Size in bytes of the signature.
4153 DWORD dwFlags, // [IN] Method flags.
4154 IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr
4156 //*****************************************************************************
4157 // Determine the version number of the runtime that was used to build the
4158 // specified image. The pMetadata pointer passed in is the pointer to the
4159 // metadata contained in the image.
4160 //*****************************************************************************
4161 HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString);
4163 //*****************************************************************************
4164 // The registry keys and values that contain the information regarding
4165 // the default registered unmanaged debugger.
4166 //*****************************************************************************
4167 SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4168 SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4170 SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
4171 SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger");
4172 SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto");
4173 SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList");
4175 BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key.
4176 LPCWSTR szKey, // Key name to look at.
4177 LPCWSTR szName, // Name of value to get.
4178 long *pValue, // Put value here, if found.
4179 BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64
4181 HRESULT GetCurrentModuleFileName(SString& pBuffer);
4183 //*****************************************************************************
4184 // Retrieve information regarding what registered default debugger
4185 //*****************************************************************************
4186 void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto);
4187 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto);
4189 void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch);
4192 //*****************************************************************************
4193 // Convert a UTF8 string to Unicode, into a CQuickArray<WCHAR>.
4194 //*****************************************************************************
4196 LPCUTF8 pStr, // The string to convert.
4197 CQuickArray<WCHAR> &rStr, // The QuickArray<WCHAR> to convert it into.
4198 int iCurLen = 0); // Initial characters in the array to leave (default 0).
4200 //*****************************************************************************
4201 // Extract the movl 64-bit unsigned immediate from an IA64 bundle
4203 //*****************************************************************************
4204 UINT64 GetIA64Imm64(UINT64 * pBundle);
4205 UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1);
4207 //*****************************************************************************
4208 // Deposit the movl 64-bit unsigned immediate into an IA64 bundle
4210 //*****************************************************************************
4211 void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64);
4213 //*****************************************************************************
4214 // Extract the IP-Relative signed 25-bit immediate from an IA64 bundle
4215 // (Formats B1, B2 or B3)
4216 // Note that due to branch target alignment requirements
4217 // the lowest four bits in the result will always be zero.
4218 //*****************************************************************************
4219 INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot);
4220 INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot);
4222 //*****************************************************************************
4223 // Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle
4224 // (Formats B1, B2 or B3)
4225 // Note that due to branch target alignment requirements
4226 // the lowest four bits are required to be zero.
4227 //*****************************************************************************
4228 void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25);
4230 //*****************************************************************************
4231 // Extract the IP-Relative signed 64-bit immediate from an IA64 bundle
4232 // (Formats X3 or X4)
4233 //*****************************************************************************
4234 INT64 GetIA64Rel64(UINT64 * pBundle);
4235 INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1);
4237 //*****************************************************************************
4238 // Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle
4239 // (Formats X3 or X4)
4240 //*****************************************************************************
4241 void PutIA64Rel64(UINT64 * pBundle, INT64 imm64);
4243 //*****************************************************************************
4244 // Extract the 32-bit immediate from movw/movt Thumb2 sequence
4245 //*****************************************************************************
4246 UINT32 GetThumb2Mov32(UINT16 * p);
4248 //*****************************************************************************
4249 // Deposit the 32-bit immediate into movw/movt Thumb2 sequence
4250 //*****************************************************************************
4251 void PutThumb2Mov32(UINT16 * p, UINT32 imm32);
4253 //*****************************************************************************
4254 // Extract the 24-bit rel offset from bl instruction
4255 //*****************************************************************************
4256 INT32 GetThumb2BlRel24(UINT16 * p);
4258 //*****************************************************************************
4259 // Extract the 24-bit rel offset from bl instruction
4260 //*****************************************************************************
4261 void PutThumb2BlRel24(UINT16 * p, INT32 imm24);
4263 //*****************************************************************************
4264 // Extract the PC-Relative offset from a b or bl instruction
4265 //*****************************************************************************
4266 INT32 GetArm64Rel28(UINT32 * pCode);
4268 //*****************************************************************************
4269 // Extract the PC-Relative page address from an adrp instruction
4270 //*****************************************************************************
4271 INT32 GetArm64Rel21(UINT32 * pCode);
4273 //*****************************************************************************
4274 // Extract the page offset from an add instruction
4275 //*****************************************************************************
4276 INT32 GetArm64Rel12(UINT32 * pCode);
4278 //*****************************************************************************
4279 // Deposit the PC-Relative offset 'imm28' into a b or bl instruction
4280 //*****************************************************************************
4281 void PutArm64Rel28(UINT32 * pCode, INT32 imm28);
4283 //*****************************************************************************
4284 // Deposit the PC-Relative page address 'imm21' into an adrp instruction
4285 //*****************************************************************************
4286 void PutArm64Rel21(UINT32 * pCode, INT32 imm21);
4288 //*****************************************************************************
4289 // Deposit the page offset 'imm12' into an add instruction
4290 //*****************************************************************************
4291 void PutArm64Rel12(UINT32 * pCode, INT32 imm12);
4293 //*****************************************************************************
4294 // Returns whether the offset fits into bl instruction
4295 //*****************************************************************************
4296 inline bool FitsInThumb2BlRel24(INT32 imm24)
4298 return ((imm24 << 7) >> 7) == imm24;
4301 //*****************************************************************************
4302 // Returns whether the offset fits into an Arm64 b or bl instruction
4303 //*****************************************************************************
4304 inline bool FitsInRel28(INT32 val32)
4306 return (val32 >= -0x08000000) && (val32 < 0x08000000);
4309 //*****************************************************************************
4310 // Returns whether the offset fits into an Arm64 adrp instruction
4311 //*****************************************************************************
4312 inline bool FitsInRel21(INT32 val32)
4314 return (val32 >= 0) && (val32 <= 0x001FFFFF);
4317 //*****************************************************************************
4318 // Returns whether the offset fits into an Arm64 add instruction
4319 //*****************************************************************************
4320 inline bool FitsInRel12(INT32 val32)
4322 return (val32 >= 0) && (val32 <= 0x00000FFF);
4325 //*****************************************************************************
4326 // Returns whether the offset fits into an Arm64 b or bl instruction
4327 //*****************************************************************************
4328 inline bool FitsInRel28(INT64 val64)
4330 return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
4333 //*****************************************************************************
4334 // Splits a command line into argc/argv lists, using the VC7 parsing rules.
4335 // This functions interface mimics the CommandLineToArgvW api.
4336 // If function fails, returns NULL.
4337 // If function suceeds, call delete [] on return pointer when done.
4338 //*****************************************************************************
4339 LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs);
4342 // TEB access can be dangerous when using fibers because a fiber may
4343 // run on multiple threads. If the TEB pointer is retrieved and saved
4344 // and then a fiber is moved to a different thread, when it accesses
4345 // the saved TEB pointer, it will be looking at the TEB state for a
4348 // These accessors serve the purpose of retrieving information from the
4349 // TEB in a manner that ensures that the current fiber will not switch
4350 // threads while the access is occuring.
4355 #if defined(FEATURE_PAL)
4357 // returns pointer that uniquely identifies the fiber
4358 static void* GetFiberPtrId()
4360 LIMITED_METHOD_CONTRACT;
4361 // not fiber for FEATURE_PAL - use the regular thread ID
4362 return (void *)(size_t)GetCurrentThreadId();
4365 static void* InvalidFiberPtrId()
4370 static void* GetStackBase()
4372 return PAL_GetStackBase();
4375 static void* GetStackLimit()
4377 return PAL_GetStackLimit();
4380 #else // !FEATURE_PAL
4382 // returns pointer that uniquely identifies the fiber
4383 static void* GetFiberPtrId()
4385 LIMITED_METHOD_CONTRACT;
4386 // stackbase is the unique fiber identifier
4387 return NtCurrentTeb()->NtTib.StackBase;
4390 static void* GetStackBase()
4392 LIMITED_METHOD_CONTRACT;
4393 return NtCurrentTeb()->NtTib.StackBase;
4396 static void* GetStackLimit()
4398 LIMITED_METHOD_CONTRACT;
4399 return NtCurrentTeb()->NtTib.StackLimit;
4402 // Please don't start to use this method unless you absolutely have to.
4403 // The reason why this is added is for WIN64 to support LEGACY PE-style TLS
4404 // variables. On X86 it is supported by the JIT compilers themselves. On
4405 // WIN64 we build more logic into the JIT helper for accessing fields.
4406 static void* GetLegacyThreadLocalStoragePointer()
4408 LIMITED_METHOD_CONTRACT;
4409 return NtCurrentTeb()->ThreadLocalStoragePointer;
4412 static void* GetOleReservedPtr()
4414 LIMITED_METHOD_CONTRACT;
4415 return NtCurrentTeb()->ReservedForOle;
4418 static void* GetProcessEnvironmentBlock()
4420 LIMITED_METHOD_CONTRACT;
4421 return NtCurrentTeb()->ProcessEnvironmentBlock;
4425 static void* InvalidFiberPtrId()
4429 #endif // !FEATURE_PAL
4432 #if !defined(DACCESS_COMPILE)
4434 // check if current thread is a GC thread (concurrent or server)
4435 inline BOOL IsGCSpecialThread ()
4437 STATIC_CONTRACT_NOTHROW;
4438 STATIC_CONTRACT_GC_NOTRIGGER;
4439 STATIC_CONTRACT_MODE_ANY;
4440 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4442 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC);
4445 // check if current thread is a Gate thread
4446 inline BOOL IsGateSpecialThread ()
4448 STATIC_CONTRACT_NOTHROW;
4449 STATIC_CONTRACT_GC_NOTRIGGER;
4450 STATIC_CONTRACT_MODE_ANY;
4452 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate);
4455 // check if current thread is a Timer thread
4456 inline BOOL IsTimerSpecialThread ()
4458 STATIC_CONTRACT_NOTHROW;
4459 STATIC_CONTRACT_GC_NOTRIGGER;
4460 STATIC_CONTRACT_MODE_ANY;
4462 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer);
4465 // check if current thread is a debugger helper thread
4466 inline BOOL IsDbgHelperSpecialThread ()
4468 STATIC_CONTRACT_NOTHROW;
4469 STATIC_CONTRACT_GC_NOTRIGGER;
4470 STATIC_CONTRACT_MODE_ANY;
4472 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper);
4475 // check if current thread is a debugger helper thread
4476 inline BOOL IsETWRundownSpecialThread ()
4478 STATIC_CONTRACT_NOTHROW;
4479 STATIC_CONTRACT_GC_NOTRIGGER;
4480 STATIC_CONTRACT_MODE_ANY;
4482 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread);
4485 // check if current thread is a generic instantiation lookup compare thread
4486 inline BOOL IsGenericInstantiationLookupCompareThread ()
4488 STATIC_CONTRACT_NOTHROW;
4489 STATIC_CONTRACT_GC_NOTRIGGER;
4490 STATIC_CONTRACT_MODE_ANY;
4492 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare);
4495 // check if current thread is a thread which is performing shutdown
4496 inline BOOL IsShutdownSpecialThread ()
4498 STATIC_CONTRACT_NOTHROW;
4499 STATIC_CONTRACT_GC_NOTRIGGER;
4500 STATIC_CONTRACT_MODE_ANY;
4502 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown);
4505 inline BOOL IsThreadPoolIOCompletionSpecialThread ()
4507 STATIC_CONTRACT_NOTHROW;
4508 STATIC_CONTRACT_GC_NOTRIGGER;
4509 STATIC_CONTRACT_MODE_ANY;
4511 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion);
4514 inline BOOL IsThreadPoolWorkerSpecialThread ()
4516 STATIC_CONTRACT_NOTHROW;
4517 STATIC_CONTRACT_GC_NOTRIGGER;
4518 STATIC_CONTRACT_MODE_ANY;
4520 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker);
4523 inline BOOL IsWaitSpecialThread ()
4525 STATIC_CONTRACT_NOTHROW;
4526 STATIC_CONTRACT_GC_NOTRIGGER;
4527 STATIC_CONTRACT_MODE_ANY;
4529 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait);
4532 // check if current thread is a thread which is performing shutdown
4533 inline BOOL IsSuspendEEThread ()
4535 STATIC_CONTRACT_NOTHROW;
4536 STATIC_CONTRACT_GC_NOTRIGGER;
4537 STATIC_CONTRACT_MODE_ANY;
4539 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE);
4542 inline BOOL IsFinalizerThread ()
4544 STATIC_CONTRACT_NOTHROW;
4545 STATIC_CONTRACT_GC_NOTRIGGER;
4546 STATIC_CONTRACT_MODE_ANY;
4548 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
4551 inline BOOL IsShutdownHelperThread ()
4553 STATIC_CONTRACT_NOTHROW;
4554 STATIC_CONTRACT_GC_NOTRIGGER;
4555 STATIC_CONTRACT_MODE_ANY;
4557 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper);
4560 inline BOOL IsProfilerAttachThread ()
4562 STATIC_CONTRACT_NOTHROW;
4563 STATIC_CONTRACT_GC_NOTRIGGER;
4564 STATIC_CONTRACT_MODE_ANY;
4566 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach);
4569 // set specical type for current thread
4570 inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag)
4572 STATIC_CONTRACT_NOTHROW;
4573 STATIC_CONTRACT_GC_NOTRIGGER;
4574 STATIC_CONTRACT_MODE_ANY;
4576 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag));
4579 // clear specical type for current thread
4580 inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
4582 STATIC_CONTRACT_NOTHROW;
4583 STATIC_CONTRACT_GC_NOTRIGGER;
4584 STATIC_CONTRACT_MODE_ANY;
4586 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag));
4589 #endif //!DACCESS_COMPILE
4591 #ifdef DACCESS_COMPILE
4592 #define SET_THREAD_TYPE_STACKWALKER(pThread)
4593 #define CLEAR_THREAD_TYPE_STACKWALKER()
4594 #else // DACCESS_COMPILE
4595 #define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread)
4596 #define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
4597 #endif // DACCESS_COMPILE
4599 HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription);
4601 inline BOOL IsStackWalkerThread()
4603 STATIC_CONTRACT_NOTHROW;
4604 STATIC_CONTRACT_GC_NOTRIGGER;
4605 STATIC_CONTRACT_MODE_ANY;
4606 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4608 #if defined(DACCESS_COMPILE)
4611 return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL;
4615 inline BOOL IsGCThread ()
4617 STATIC_CONTRACT_NOTHROW;
4618 STATIC_CONTRACT_GC_NOTRIGGER;
4619 STATIC_CONTRACT_MODE_ANY;
4620 STATIC_CONTRACT_SUPPORTS_DAC;
4622 #if !defined(DACCESS_COMPILE)
4623 return IsGCSpecialThread () || IsSuspendEEThread ();
4629 class ClrFlsThreadTypeSwitch
4632 ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag)
4634 STATIC_CONTRACT_NOTHROW;
4635 STATIC_CONTRACT_GC_NOTRIGGER;
4636 STATIC_CONTRACT_MODE_ANY;
4638 #ifndef DACCESS_COMPILE
4640 m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag);
4642 // In debug builds, remember the full group of flags that were set at the time
4643 // the constructor was called. This will be used in ASSERTs in the destructor
4644 INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType));
4646 if (!m_fPreviouslySet)
4648 ClrFlsSetThreadType(flag);
4650 #endif // DACCESS_COMPILE
4653 ~ClrFlsThreadTypeSwitch ()
4655 STATIC_CONTRACT_NOTHROW;
4656 STATIC_CONTRACT_GC_NOTRIGGER;
4657 STATIC_CONTRACT_MODE_ANY;
4659 #ifndef DACCESS_COMPILE
4660 // This holder should only be used to set (and thus restore) ONE thread type flag
4661 // at a time. If more than that one flag was modified since this holder was
4662 // instantiated, then this holder still restores only the flag it knows about. To
4663 // prevent confusion, assert if some other flag was modified, so the user doesn't
4664 // expect the holder to restore the entire original set of flags.
4666 // The expression below says that the only difference between the previous flag
4667 // group and the current flag group should be m_flag (or no difference at all, if
4668 // m_flag's state didn't actually change).
4669 _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag);
4671 if (m_fPreviouslySet)
4673 ClrFlsSetThreadType(m_flag);
4677 ClrFlsClearThreadType(m_flag);
4679 #endif // DACCESS_COMPILE
4683 TlsThreadTypeFlag m_flag;
4684 BOOL m_fPreviouslySet;
4685 INDEBUG(size_t m_nPreviousFlagGroup);
4688 class ClrFlsValueSwitch
4691 ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value)
4693 STATIC_CONTRACT_NOTHROW;
4694 STATIC_CONTRACT_GC_NOTRIGGER;
4695 STATIC_CONTRACT_MODE_ANY;
4697 #ifndef DACCESS_COMPILE
4699 m_PreviousValue = ClrFlsGetValue(slot);
4700 ClrFlsSetValue(slot, value);
4701 #endif // DACCESS_COMPILE
4704 ~ClrFlsValueSwitch ()
4706 STATIC_CONTRACT_NOTHROW;
4707 STATIC_CONTRACT_GC_NOTRIGGER;
4708 STATIC_CONTRACT_MODE_ANY;
4710 #ifndef DACCESS_COMPILE
4711 ClrFlsSetValue(m_slot, m_PreviousValue);
4712 #endif // DACCESS_COMPILE
4716 PVOID m_PreviousValue;
4717 PredefinedTlsSlots m_slot;
4720 //*********************************************************************************
4722 // When we're hosted, operations called by the host (such as Thread::YieldTask)
4723 // may not cause calls back into the host, as the host needs not be reentrant.
4724 // Use the following holder for code in which calls into the host are forbidden.
4725 // (If a call into the host is attempted nevertheless, an assert will fire.)
4727 class ForbidCallsIntoHostOnThisThread
4730 static Volatile<PVOID> s_pvOwningFiber;
4732 FORCEINLINE static BOOL Enter(BOOL)
4734 WRAPPER_NO_CONTRACT;
4735 return InterlockedCompareExchangePointer(
4736 &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL;
4739 FORCEINLINE static void Leave(BOOL)
4741 LIMITED_METHOD_CONTRACT;
4742 s_pvOwningFiber = NULL;
4746 typedef ConditionalStateHolder<BOOL, ForbidCallsIntoHostOnThisThread::Enter, ForbidCallsIntoHostOnThisThread::Leave> Holder;
4748 FORCEINLINE static BOOL CanThisThreadCallIntoHost()
4750 WRAPPER_NO_CONTRACT;
4751 return s_pvOwningFiber != ClrTeb::GetFiberPtrId();
4755 typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder;
4757 FORCEINLINE BOOL CanThisThreadCallIntoHost()
4759 WRAPPER_NO_CONTRACT;
4760 return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost();
4763 //*********************************************************************************
4765 #include "contract.inl"
4772 template < typename T >
4775 bool operator()( T const & first, T const & second ) const
4777 return first < second;
4781 template < typename T >
4784 bool operator()( T const & first, T const & second ) const
4786 return first > second;
4794 template< typename Iter, typename Pred >
4795 void sort( Iter begin, Iter end, Pred pred );
4797 template< typename T, typename Pred >
4798 void sort( T * begin, T * end, Pred pred )
4800 struct sort_helper : CQuickSort< T >
4802 sort_helper( T * begin, T * end, Pred pred )
4803 : CQuickSort< T >( begin, end - begin )
4807 virtual int Compare( T * first, T * second )
4809 return m_pred( *first, *second ) ? -1
4810 : ( m_pred( *second, *first ) ? 1 : 0 );
4816 sort_helper sort_obj( begin, end, pred );
4821 template < typename Iter >
4822 void sort( Iter begin, Iter end );
4824 template < typename T >
4825 void sort( T * begin, T * end )
4827 util::sort( begin, end, util::less< T >() );
4831 // binary search adapters
4834 template < typename Iter, typename T, typename Pred >
4835 Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred );
4837 template < typename T, typename Pred >
4838 T * lower_bound( T * begin, T * end, T const & val, Pred pred )
4840 for (; begin != end; )
4842 T * mid = begin + ( end - begin ) / 2;
4843 if ( pred( *mid, val ) )
4853 template < typename Iter, typename T >
4854 Iter lower_bound( Iter begin, Iter end, T const & val );
4856 template < typename T >
4857 T * lower_bound( T * begin, T * end, T const & val )
4859 return util::lower_bound( begin, end, val, util::less< T >() );
4864 /* ------------------------------------------------------------------------ *
4865 * Overloaded operators for the executable heap
4866 * ------------------------------------------------------------------------ */
4870 struct CExecutable { int x; };
4871 extern const CExecutable executable;
4873 void * __cdecl operator new(size_t n, const CExecutable&);
4874 void * __cdecl operator new[](size_t n, const CExecutable&);
4875 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&);
4876 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&);
4880 // Executable heap delete to match the executable heap new above.
4882 template<class T> void DeleteExecutable(T *p)
4888 ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p);
4892 #endif // FEATURE_PAL
4894 INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
4896 BOOL NoGuiOnAssert();
4898 VOID TerminateOnAssert();
4901 class HighCharHelper {
4903 static inline BOOL IsHighChar(int c) {
4904 return (BOOL)HighCharTable[c];
4908 static const BYTE HighCharTable[];
4912 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
4914 FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
4916 typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
4918 // HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical
4919 // to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address,
4920 // and so is represented by TADDR.
4922 #ifdef DACCESS_COMPILE
4923 typedef TADDR HMODULE_TGT;
4925 typedef HMODULE HMODULE_TGT;
4928 BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
4930 //----------------------------------------------------------------------------------------
4931 // The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical
4932 // callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call
4933 // InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime
4934 // calls a special initialization routine exposed by the loaded module with the callbacks,
4935 // which in turn calls InitUtilcode.
4937 // This structure collects all of the critical callback info passed in InitUtilcode().
4938 // Note that one of them is GetCLRFunction() which is itself a gofer for many other
4939 // callbacks. If a callback fetch be safely deferred until we have TLS and stack probe
4940 // functionality running, it should be added to that function rather than this structure.
4941 // Things like IEE are here because that callback has to be set up before GetCLRFunction()
4942 // can be safely called.
4943 //----------------------------------------------------------------------------------------
4944 struct CoreClrCallbacks
4946 typedef IExecutionEngine* (* pfnIEE_t)();
4947 typedef HRESULT (* pfnGetCORSystemDirectory_t)(SString& pbuffer);
4948 typedef void* (* pfnGetCLRFunction_t)(LPCSTR functionName);
4950 HINSTANCE m_hmodCoreCLR;
4952 pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory;
4953 pfnGetCLRFunction_t m_pfnGetCLRFunction;
4957 // For DAC, we include this functionality only when EH SxS is enabled.
4959 //----------------------------------------------------------------------------------------
4960 // CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback
4961 // pointers it needs.
4962 //----------------------------------------------------------------------------------------
4963 VOID InitUtilcode(const CoreClrCallbacks &cccallbacks);
4964 CoreClrCallbacks const & GetClrCallbacks();
4966 //----------------------------------------------------------------------------------------
4967 // Stuff below is for utilcode.lib eyes only.
4968 //----------------------------------------------------------------------------------------
4970 // Stores callback pointers provided by InitUtilcode().
4971 extern CoreClrCallbacks g_CoreClrCallbacks;
4973 // Throws up a helpful dialog if InitUtilcode() wasn't called.
4975 void OnUninitializedCoreClrCallbacks();
4976 #define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks()
4978 #define VALIDATECORECLRCALLBACKS()
4982 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
4984 // Corrupting Exception limited support for outside the VM folder
4985 BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
4987 #endif // FEATURE_CORRUPTING_EXCEPTIONS
4991 // These are type-safe versions of Interlocked[Compare]Exchange
4992 // They avoid invoking struct cast operations via reinterpreting
4993 // the struct's address as a LONG* or LONGLONG* and dereferencing it.
4995 // If we had a global ::operator & (unary), we would love to use that
4996 // to ensure we were not also accidentally getting a structs's provided
4997 // operator &. TODO: probe with a static_assert?
4999 template <typename T, int SIZE = sizeof(T)>
5000 struct InterlockedCompareExchangeHelper;
5002 template <typename T>
5003 struct InterlockedCompareExchangeHelper<T, sizeof(LONG)>
5005 static inline T InterlockedExchange(
5006 T volatile * target,
5009 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5010 LONG res = ::InterlockedExchange(
5011 reinterpret_cast<LONG volatile *>(target),
5012 *reinterpret_cast<LONG *>(/*::operator*/&(value)));
5013 return *reinterpret_cast<T*>(&res);
5016 static inline T InterlockedCompareExchange(
5017 T volatile * destination,
5021 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5022 LONG res = ::InterlockedCompareExchange(
5023 reinterpret_cast<LONG volatile *>(destination),
5024 *reinterpret_cast<LONG*>(/*::operator*/&(exchange)),
5025 *reinterpret_cast<LONG*>(/*::operator*/&(comparand)));
5026 return *reinterpret_cast<T*>(&res);
5030 template <typename T>
5031 struct InterlockedCompareExchangeHelper<T, sizeof(LONGLONG)>
5033 static inline T InterlockedExchange(
5034 T volatile * target,
5037 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5038 LONGLONG res = ::InterlockedExchange64(
5039 reinterpret_cast<LONGLONG volatile *>(target),
5040 *reinterpret_cast<LONGLONG *>(/*::operator*/&(value)));
5041 return *reinterpret_cast<T*>(&res);
5044 static inline T InterlockedCompareExchange(
5045 T volatile * destination,
5049 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5050 LONGLONG res = ::InterlockedCompareExchange64(
5051 reinterpret_cast<LONGLONG volatile *>(destination),
5052 *reinterpret_cast<LONGLONG*>(/*::operator*/&(exchange)),
5053 *reinterpret_cast<LONGLONG*>(/*::operator*/&(comparand)));
5054 return *reinterpret_cast<T*>(&res);
5059 template <typename T>
5060 inline T InterlockedExchangeT(
5061 T volatile * target,
5064 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedExchange(
5068 template <typename T>
5069 inline T InterlockedCompareExchangeT(
5070 T volatile * destination,
5074 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedCompareExchange(
5075 destination, exchange, comparand);
5078 // Pointer variants for Interlocked[Compare]ExchangePointer
5079 // If the underlying type is a const type, we have to remove its constness
5080 // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments.
5081 template <typename T>
5082 inline T* InterlockedExchangeT(
5083 T* volatile * target,
5086 //STATIC_ASSERT(value == 0);
5087 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5088 return reinterpret_cast<T*>(InterlockedExchangePointer(
5089 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(target)),
5090 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(value))));
5093 template <typename T>
5094 inline T* InterlockedCompareExchangeT(
5095 T* volatile * destination,
5099 //STATIC_ASSERT(exchange == 0);
5100 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5101 return reinterpret_cast<T*>(InterlockedCompareExchangePointer(
5102 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(destination)),
5103 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(exchange)),
5104 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(comparand))));
5107 // NULL pointer variants of the above to avoid having to cast NULL
5108 // to the appropriate pointer type.
5109 template <typename T>
5110 inline T* InterlockedExchangeT(
5111 T* volatile * target,
5112 int value) // When NULL is provided as argument.
5114 //STATIC_ASSERT(value == 0);
5115 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5118 template <typename T>
5119 inline T* InterlockedCompareExchangeT(
5120 T* volatile * destination,
5121 int exchange, // When NULL is provided as argument.
5124 //STATIC_ASSERT(exchange == 0);
5125 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5128 template <typename T>
5129 inline T* InterlockedCompareExchangeT(
5130 T* volatile * destination,
5132 int comparand) // When NULL is provided as argument.
5134 //STATIC_ASSERT(comparand == 0);
5135 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5138 // NULL pointer variants of the above to avoid having to cast NULL
5139 // to the appropriate pointer type.
5140 template <typename T>
5141 inline T* InterlockedExchangeT(
5142 T* volatile * target,
5143 std::nullptr_t value) // When nullptr is provided as argument.
5145 //STATIC_ASSERT(value == 0);
5146 return InterlockedExchangeT(target, static_cast<T*>(value));
5149 template <typename T>
5150 inline T* InterlockedCompareExchangeT(
5151 T* volatile * destination,
5152 std::nullptr_t exchange, // When nullptr is provided as argument.
5155 //STATIC_ASSERT(exchange == 0);
5156 return InterlockedCompareExchangeT(destination, static_cast<T*>(exchange), comparand);
5159 template <typename T>
5160 inline T* InterlockedCompareExchangeT(
5161 T* volatile * destination,
5163 std::nullptr_t comparand) // When nullptr is provided as argument.
5165 //STATIC_ASSERT(comparand == 0);
5166 return InterlockedCompareExchangeT(destination, exchange, static_cast<T*>(comparand));
5169 #undef InterlockedExchangePointer
5170 #define InterlockedExchangePointer Use_InterlockedExchangeT
5171 #undef InterlockedCompareExchangePointer
5172 #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT
5174 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
5175 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
5176 HRESULT GetHModuleDirectory(HMODULE hMod, SString& wszPath);
5177 HRESULT CopySystemDirectory(const SString& pPathString, SString& pbuffer);
5179 HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true);
5180 // This is a slight variation that can be used for anything else
5181 typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR);
5182 void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL);
5186 // Helper to support termination due to heap corruption
5187 // It's not supported on Win2K, so we have to manually delay load it
5188 void EnableTerminationOnHeapCorruption();
5192 namespace Clr { namespace Util
5194 // This api returns a pointer to a null-terminated string that contains the local appdata directory
5195 // or it returns NULL in the case that the directory could not be found. The return value from this function
5196 // is not actually checked for existence.
5197 HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory);
5198 HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory);
5202 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
5203 __success(return == S_OK)
5204 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
5207 #ifdef FEATURE_COMINTEROP
5210 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name);
5212 #endif // FEATURE_COMINTEROP
5216 static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\");
5217 static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\";
5219 void GetModuleFileName(
5221 SString & ssFileName,
5222 bool fAllowLongFileNames = false);
5224 __success(return == S_OK)
5225 HRESULT GetModuleFileName(
5227 __deref_out_z LPWSTR * pwszFileName,
5228 bool fAllowLongFileNames = false);
5230 void GetFullPathName(
5231 SString const & ssFileName,
5232 SString & ssPathName,
5233 DWORD * pdwFilePartIdx,
5234 bool fAllowLongFileNames = false);
5239 #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE)
5240 // Forward declaration of AppX::IsAppXProcess
5241 namespace AppX { bool IsAppXProcess(); }
5243 // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes.
5244 inline DWORD GetLoadWithAlteredSearchPathFlag()
5246 WRAPPER_NO_CONTRACT;
5247 return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
5249 #else // FEATURE_APPX && !DACCESS_COMPILE
5250 // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally.
5251 inline DWORD GetLoadWithAlteredSearchPathFlag()
5253 LIMITED_METHOD_CONTRACT;
5254 #ifdef LOAD_WITH_ALTERED_SEARCH_PATH
5255 return LOAD_WITH_ALTERED_SEARCH_PATH;
5260 #endif // FEATURE_APPX && !DACCESS_COMPILE
5262 // clr::SafeAddRef and clr::SafeRelease helpers.
5265 //=================================================================================================================
5266 template <typename ItfT>
5268 typename std::enable_if< std::is_pointer<ItfT>::value, ItfT >::type
5269 SafeAddRef(ItfT pItf)
5271 STATIC_CONTRACT_LIMITED_METHOD;
5272 if (pItf != nullptr)
5279 //=================================================================================================================
5280 template <typename ItfT>
5281 typename std::enable_if< std::is_pointer<ItfT>::value && std::is_reference<ItfT>::value, ULONG >::type
5282 SafeRelease(ItfT pItf)
5284 STATIC_CONTRACT_LIMITED_METHOD;
5286 if (pItf != nullptr)
5288 res = pItf->Release();
5294 //=================================================================================================================
5295 template <typename ItfT>
5296 typename std::enable_if< std::is_pointer<ItfT>::value && !std::is_reference<ItfT>::value, ULONG >::type
5297 SafeRelease(ItfT pItf)
5299 STATIC_CONTRACT_LIMITED_METHOD;
5301 if (pItf != nullptr)
5303 res = pItf->Release();
5312 //=================================================================================================================
5313 template <typename PtrT>
5315 typename std::enable_if< std::is_pointer<PtrT>::value, PtrT >::type
5316 SafeDelete(PtrT & ptr)
5318 STATIC_CONTRACT_LIMITED_METHOD;
5327 // ======================================================================================
5328 // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp)
5330 struct SpinConstants
5332 DWORD dwInitialDuration;
5333 DWORD dwMaximumDuration;
5334 DWORD dwBackoffFactor;
5335 DWORD dwRepetitions;
5336 DWORD dwMonitorSpinCount;
5339 extern SpinConstants g_SpinConstants;
5341 // ======================================================================================
5343 void* GetCLRFunction(LPCSTR FunctionName);
5345 #endif // __UtilCode_h__