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);
1408 static bool HadSingleProcessorAtStartup()
1410 LIMITED_METHOD_CONTRACT;
1411 return s_hadSingleProcessorAtStartup;
1415 int GetCurrentProcessCpuCount();
1416 DWORD_PTR GetCurrentProcessCpuMask();
1418 uint32_t GetOsPageSize();
1421 //*****************************************************************************
1422 // Return != 0 if the bit at the specified index in the array is on and 0 if
1424 //*****************************************************************************
1425 inline int GetBit(PTR_BYTE pcBits,int iBit)
1427 LIMITED_METHOD_CONTRACT;
1428 return (pcBits[iBit>>3] & (1 << (iBit & 0x7)));
1431 #ifdef DACCESS_COMPILE
1432 inline int GetBit(BYTE const * pcBits,int iBit)
1434 WRAPPER_NO_CONTRACT;
1435 return GetBit(dac_cast<PTR_BYTE>(pcBits), iBit);
1439 //*****************************************************************************
1440 // Set the state of the bit at the specified index based on the value of bOn.
1441 //*****************************************************************************
1442 inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn)
1444 LIMITED_METHOD_CONTRACT;
1446 pcBits[iBit>>3] |= (1 << (iBit & 0x7));
1448 pcBits[iBit>>3] &= ~(1 << (iBit & 0x7));
1451 #ifdef DACCESS_COMPILE
1452 inline void SetBit(BYTE * pcBits,int iBit,int bOn)
1454 WRAPPER_NO_CONTRACT;
1455 SetBit(dac_cast<PTR_BYTE>(pcBits), iBit, bOn);
1459 template<typename T>
1460 class SimpleListNode
1463 SimpleListNode<T>(const T& _t)
1470 SimpleListNode<T>* next;
1473 template<typename T>
1477 typedef SimpleListNode<T> NodeType;
1484 void LinkHead(NodeType* pNode)
1490 NodeType* UnlinkHead()
1492 NodeType* ret = head;
1512 template < typename T, typename U >
1516 typedef Pair< T, U > this_type;
1517 typedef T first_type;
1518 typedef U second_type;
1523 Pair( T const & t, U const & u )
1528 Pair( this_type const & obj )
1529 : m_first( obj.m_first )
1530 , m_second( obj.m_second )
1533 this_type & operator=( this_type const & obj )
1535 m_first = obj.m_first;
1536 m_second = obj.m_second;
1545 T const & First() const
1555 U const & Second() const
1560 bool operator==(const Pair& rhs) const
1562 return ((this->First() == rhs.First()) &&
1563 (this->Second() == rhs.Second()));
1566 bool operator!=(const Pair& rhs) const
1568 return !(*this == rhs);
1573 second_type m_second;
1577 template < typename T, typename U >
1578 Pair< T, U > MakePair( T const & t, U const & u )
1581 return Pair< T, U >( t, u );
1585 //*****************************************************************************
1586 // This class implements a dynamic array of structures for which the order of
1587 // the elements is unimportant. This means that any item placed in the list
1588 // may be swapped to any other location in the list at any time. If the order
1589 // of the items you place in the array is important, then use the CStructArray
1591 //*****************************************************************************
1596 class CUnorderedArrayWithAllocator
1598 int m_iCount; // # of elements used in the list.
1599 int m_iSize; // # of elements allocated in the list.
1601 #ifndef DACCESS_COMPILE
1602 T *m_pTable; // Pointer to the list of elements.
1604 TADDR m_pTable; // Pointer to the list of elements.
1609 #ifndef DACCESS_COMPILE
1611 CUnorderedArrayWithAllocator() :
1616 LIMITED_METHOD_CONTRACT;
1618 ~CUnorderedArrayWithAllocator()
1620 LIMITED_METHOD_CONTRACT;
1621 // Free the chunk of memory.
1622 if (m_pTable != NULL)
1623 ALLOCATOR::Free(this, m_pTable);
1628 WRAPPER_NO_CONTRACT;
1630 if (m_iSize > iGrowInc)
1632 T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc);
1634 ALLOCATOR::Free(this, m_pTable);
1641 void Clear(int iFirst, int iCount)
1643 WRAPPER_NO_CONTRACT;
1646 if (iFirst + iCount < m_iCount)
1647 memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount)));
1651 iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0);
1652 if (m_iSize > iGrowInc && iSize < m_iSize)
1654 T *tmp = ALLOCATOR::AllocNoThrow(this, iSize);
1656 memcpy (tmp, m_pTable, iSize * sizeof(T));
1662 _ASSERTE(m_iCount <= m_iSize);
1667 LIMITED_METHOD_CONTRACT;
1677 // The array should grow, if we can't fit one more element into the array.
1678 if (m_iSize <= m_iCount && GrowNoThrow() == NULL)
1680 return (&m_pTable[m_iCount++]);
1689 // The array should grow, if we can't fit one more element into the array.
1690 if (m_iSize <= m_iCount)
1692 return (&m_pTable[m_iCount++]);
1695 void Delete(const T &Entry)
1697 LIMITED_METHOD_CONTRACT;
1699 for (int i=0; i <= m_iCount; ++i)
1700 if (m_pTable[i] == Entry)
1702 m_pTable[i] = m_pTable[m_iCount];
1706 // Just in case we didn't find it.
1710 void DeleteByIndex(int i)
1712 LIMITED_METHOD_CONTRACT;
1714 m_pTable[i] = m_pTable[m_iCount];
1717 void Swap(int i,int j)
1719 LIMITED_METHOD_CONTRACT;
1725 m_pTable[i] = m_pTable[j];
1733 LIMITED_METHOD_CONTRACT;
1738 void EnumMemoryRegions(void)
1741 DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T));
1744 #endif // #ifndef DACCESS_COMPILE
1748 LIMITED_METHOD_CONTRACT;
1750 _ASSERTE(FitsIn<USHORT>(m_iCount));
1751 return static_cast<USHORT>(m_iCount);
1760 #ifndef DACCESS_COMPILE
1762 //*****************************************************************************
1763 // Increase the size of the array.
1764 //*****************************************************************************
1768 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::GrowNoThrow() // NULL if can't grow.
1770 WRAPPER_NO_CONTRACT;
1773 // try to allocate memory for reallocation.
1774 if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL)
1776 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1777 ALLOCATOR::Free(this, m_pTable);
1779 m_iSize += iGrowInc;
1780 _ASSERTE(m_iSize > 0);
1787 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::Grow() // exception if can't grow.
1789 WRAPPER_NO_CONTRACT;
1792 // try to allocate memory for reallocation.
1793 pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc);
1794 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1795 ALLOCATOR::Free(this, m_pTable);
1797 m_iSize += iGrowInc;
1798 _ASSERTE(m_iSize > 0);
1802 #endif // #ifndef DACCESS_COMPILE
1806 class CUnorderedArray__Allocator
1810 static T *AllocThrowing (void*, int nElements)
1812 return new T[nElements];
1815 static T *AllocNoThrow (void*, int nElements)
1817 return new (nothrow) T[nElements];
1820 static void Free (void*, T *pTable)
1827 template <class T,int iGrowInc>
1828 class CUnorderedArray : public CUnorderedArrayWithAllocator<T, iGrowInc, CUnorderedArray__Allocator<T> >
1834 LIMITED_METHOD_CONTRACT;
1839 //Used by the debugger. Included here in hopes somebody else might, too
1840 typedef CUnorderedArray<SIZE_T, 17> SIZE_T_UNORDERED_ARRAY;
1843 //*****************************************************************************
1844 // This class implements a dynamic array of structures for which the insert
1845 // order is important. Inserts will slide all elements after the location
1846 // down, deletes slide all values over the deleted item. If the order of the
1847 // items in the array is unimportant to you, then CUnorderedArray may provide
1848 // the same feature set at lower cost.
1849 //*****************************************************************************
1852 BYTE *m_pList; // Pointer to the list of elements.
1853 int m_iCount; // # of elements used in the list.
1854 int m_iSize; // # of elements allocated in the list.
1855 int m_iGrowInc; // Growth increment.
1856 short m_iElemSize; // Size of an array element.
1857 bool m_bFree; // true if data is automatically maintained.
1860 CStructArray(short iElemSize, short iGrowInc = 1) :
1864 m_iGrowInc(iGrowInc),
1865 m_iElemSize(iElemSize),
1868 LIMITED_METHOD_CONTRACT;
1872 WRAPPER_NO_CONTRACT;
1876 void *Insert(int iIndex);
1877 void *InsertThrowing(int iIndex);
1879 void *AppendThrowing();
1880 int AllocateBlock(int iCount);
1881 void AllocateBlockThrowing(int iCount);
1882 void Delete(int iIndex);
1885 LIMITED_METHOD_CONTRACT;
1888 void *Get(int iIndex)
1890 WRAPPER_NO_CONTRACT;
1891 _ASSERTE(iIndex < m_iCount);
1892 return ((void *) ((size_t) Ptr() + (iIndex * m_iElemSize)));
1896 LIMITED_METHOD_CONTRACT;
1897 return (m_iCount * m_iElemSize);
1901 LIMITED_METHOD_CONTRACT;
1907 LIMITED_METHOD_CONTRACT;
1911 void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1)
1913 LIMITED_METHOD_CONTRACT;
1914 m_iElemSize = iElemSize;
1915 m_iGrowInc = (short) iGrowInc;
1916 m_pList = (BYTE*)pList;
1923 void Grow(int iCount);
1927 //*****************************************************************************
1928 // This template simplifies access to a CStructArray by removing void * and
1929 // adding some operator overloads.
1930 //*****************************************************************************
1932 class CDynArray : public CStructArray
1935 CDynArray(short iGrowInc=16) :
1936 CStructArray(sizeof(T), iGrowInc)
1938 LIMITED_METHOD_CONTRACT;
1941 T *Insert(int iIndex)
1943 WRAPPER_NO_CONTRACT;
1944 return ((T *)CStructArray::Insert((int)iIndex));
1947 T *InsertThrowing(int iIndex)
1949 WRAPPER_NO_CONTRACT;
1950 return ((T *)CStructArray::InsertThrowing((int)iIndex));
1955 WRAPPER_NO_CONTRACT;
1956 return ((T *)CStructArray::Append());
1961 WRAPPER_NO_CONTRACT;
1962 return ((T *)CStructArray::AppendThrowing());
1967 WRAPPER_NO_CONTRACT;
1968 return ((T *)CStructArray::Ptr());
1973 WRAPPER_NO_CONTRACT;
1974 return (Ptr() + iIndex);
1976 T &operator[](int iIndex)
1978 WRAPPER_NO_CONTRACT;
1979 return (*(Ptr() + iIndex));
1983 WRAPPER_NO_CONTRACT;
1984 return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T));
1986 void Move(int iFrom, int iTo)
1988 WRAPPER_NO_CONTRACT;
1991 _ASSERTE(iFrom >= 0 && iFrom < Count() &&
1992 iTo >= 0 && iTo < Count());
1994 tmp = *(Ptr() + iFrom);
1996 memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T));
1998 memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T));
1999 *(Ptr() + iTo) = tmp;
2003 // Some common arrays.
2004 typedef CDynArray<int> INTARRAY;
2005 typedef CDynArray<short> SHORTARRAY;
2006 typedef CDynArray<int> LONGARRAY;
2007 typedef CDynArray<USHORT> USHORTARRAY;
2008 typedef CDynArray<ULONG> ULONGARRAY;
2009 typedef CDynArray<BYTE> BYTEARRAY;
2010 typedef CDynArray<mdToken> TOKENARRAY;
2012 template <class T> class CStackArray : public CStructArray
2015 CStackArray(short iGrowInc=4) :
2016 CStructArray(sizeof(T), iGrowInc),
2019 LIMITED_METHOD_CONTRACT;
2024 WRAPPER_NO_CONTRACT;
2025 // We should only inc m_curPos after we grow the array.
2026 T *pT = (T *)CStructArray::InsertThrowing(m_curPos);
2033 WRAPPER_NO_CONTRACT;
2036 _ASSERTE(m_curPos > 0);
2038 retPtr = (T *)CStructArray::Get(m_curPos-1);
2039 CStructArray::Delete(m_curPos--);
2046 LIMITED_METHOD_CONTRACT;
2055 //*****************************************************************************
2056 // This template manages a list of free entries by their 0 based offset. By
2057 // making it a template, you can use whatever size free chain will match your
2058 // maximum count of items. -1 is reserved.
2059 //*****************************************************************************
2060 template <class T> class TFreeList
2067 LIMITED_METHOD_CONTRACT;
2075 for (i=0; i<iCount - 1; i++)
2076 m_rgList[i] = i + 1;
2077 m_rgList[i] = (T) -1;
2080 T GetFreeEntry() // Index of free item, or -1.
2082 LIMITED_METHOD_CONTRACT;
2085 if (m_iNext == (T) -1)
2089 m_iNext = m_rgList[m_iNext];
2093 void DelFreeEntry(T iEntry)
2095 LIMITED_METHOD_CONTRACT;
2096 _ASSERTE(iEntry < m_iCount);
2097 m_rgList[iEntry] = m_iNext;
2101 // This function can only be used when it is guaranteed that the free
2102 // array is contigous, for example, right after creation to quickly
2103 // get a range of items from the heap.
2104 void ReserveRange(int iCount)
2106 LIMITED_METHOD_CONTRACT;
2107 _ASSERTE(iCount < m_iCount);
2108 _ASSERTE(m_iNext == 0);
2113 T *m_rgList; // List of free info.
2114 int m_iCount; // How many entries to manage.
2115 T m_iNext; // Next item to get.
2119 //*****************************************************************************
2120 //*****************************************************************************
2121 template <class T> class CQuickSort
2124 T *m_pBase; // Base of array to sort.
2126 SSIZE_T m_iCount; // How many items in array.
2127 SSIZE_T m_iElemSize; // Size of one element.
2130 T *pBase, // Address of first element.
2131 SSIZE_T iCount) : // How many there are.
2134 m_iElemSize(sizeof(T))
2136 LIMITED_METHOD_DAC_CONTRACT;
2139 //*****************************************************************************
2140 // Call to sort the array.
2141 //*****************************************************************************
2144 WRAPPER_NO_CONTRACT;
2145 SortRange(0, m_iCount - 1);
2149 //*****************************************************************************
2150 // Override this function to do the comparison.
2151 //*****************************************************************************
2152 virtual FORCEINLINE int Compare( // -1, 0, or 1
2153 T *psFirst, // First item to compare.
2154 T *psSecond) // Second item to compare.
2156 LIMITED_METHOD_DAC_CONTRACT;
2157 return (memcmp(psFirst, psSecond, sizeof(T)));
2158 // return (::Compare(*psFirst, *psSecond));
2161 virtual FORCEINLINE void Swap(
2165 LIMITED_METHOD_DAC_CONTRACT;
2166 if (iFirst == iSecond) return;
2167 T sTemp( m_pBase[iFirst] );
2168 m_pBase[iFirst] = m_pBase[iSecond];
2169 m_pBase[iSecond] = sTemp;
2173 inline void SortRange(
2177 WRAPPER_NO_CONTRACT;
2179 SSIZE_T i; // loop variable.
2183 // if less than two elements you're done.
2184 if (iLeft >= iRight)
2187 // ASSERT that we now have valid indicies. This is statically provable
2188 // since this private function is only called with valid indicies,
2189 // and iLeft and iRight only converge towards eachother. However,
2190 // PreFast can't detect this because it doesn't know about our callers.
2191 COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount);
2192 COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount);
2194 // The mid-element is the pivot, move it to the left.
2195 Swap(iLeft, (iLeft + iRight) / 2);
2198 // move everything that is smaller than the pivot to the left.
2199 for (i = iLeft + 1; i <= iRight; i++)
2201 if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0)
2207 // Put the pivot to the point where it is in between smaller and larger elements.
2210 // Sort each partition.
2211 SSIZE_T iLeftLast = iLast - 1;
2212 SSIZE_T iRightFirst = iLast + 1;
2213 if (iLeftLast - iLeft < iRight - iRightFirst)
2214 { // Left partition is smaller, sort it recursively
2215 SortRange(iLeft, iLeftLast);
2216 // Tail call to sort the right (bigger) partition
2217 iLeft = iRightFirst;
2222 { // Right partition is smaller, sort it recursively
2223 SortRange(iRightFirst, iRight);
2224 // Tail call to sort the left (bigger) partition
2233 //*****************************************************************************
2234 // Faster and simpler version of the binary search below.
2235 //*****************************************************************************
2237 const T * BinarySearch(const T * pBase, int iCount, const T & find)
2239 WRAPPER_NO_CONTRACT;
2242 int iLast = iCount - 1;
2244 // It is faster to use linear search once we get down to a small number of elements.
2245 while (iLast - iFirst > 10)
2247 int iMid = (iLast + iFirst) / 2;
2249 if (find < pBase[iMid])
2255 for (int i = iFirst; i <= iLast; i++)
2257 if (find == pBase[i])
2260 if (find < pBase[i])
2267 //*****************************************************************************
2268 // This template encapsulates a binary search algorithm on the given type
2270 //*****************************************************************************
2271 template <class T> class CBinarySearch
2274 const T *m_pBase; // Base of array to sort.
2275 int m_iCount; // How many items in array.
2279 const T *pBase, // Address of first element.
2280 int iCount) : // Value to find.
2284 LIMITED_METHOD_CONTRACT;
2287 //*****************************************************************************
2288 // Searches for the item passed to ctor.
2289 //*****************************************************************************
2290 const T *Find( // Pointer to found item in array.
2291 const T *psFind, // The key to find.
2292 int *piInsert = NULL) // Index to insert at.
2294 WRAPPER_NO_CONTRACT;
2295 int iMid, iFirst, iLast; // Loop control.
2296 int iCmp; // Comparison.
2299 iLast = m_iCount - 1;
2300 while (iFirst <= iLast)
2302 iMid = (iLast + iFirst) / 2;
2303 iCmp = Compare(psFind, &m_pBase[iMid]);
2306 if (piInsert != NULL)
2308 return (&m_pBase[iMid]);
2315 if (piInsert != NULL)
2320 //*****************************************************************************
2321 // Override this function to do the comparison if a comparison operator is
2322 // not valid for your data type (such as a struct).
2323 //*****************************************************************************
2324 virtual int Compare( // -1, 0, or 1
2325 const T *psFirst, // Key you are looking for.
2326 const T *psSecond) // Item to compare to.
2328 LIMITED_METHOD_CONTRACT;
2329 return (memcmp(psFirst, psSecond, sizeof(T)));
2330 // return (::Compare(*psFirst, *psSecond));
2334 //*****************************************************************************
2335 // The information that the hash table implementation stores at the beginning
2336 // of every record that can be but in the hash table.
2337 //*****************************************************************************
2338 typedef DPTR(struct HASHENTRY) PTR_HASHENTRY;
2341 ULONG iPrev; // Previous bucket in the chain.
2342 ULONG iNext; // Next bucket in the chain.
2345 typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY;
2346 struct FREEHASHENTRY : HASHENTRY
2351 //*****************************************************************************
2352 // Used by the FindFirst/FindNextEntry functions. These api's allow you to
2353 // do a sequential scan of all entries.
2354 //*****************************************************************************
2357 ULONG iBucket; // The next bucket to look in.
2362 //*****************************************************************************
2363 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2364 // The hashtable implementation that should be used instead is code:SHash.
2365 // If code:SHash does not work for you, talk to mailto:clrdeag.
2366 //*****************************************************************************
2367 // This is a class that implements a chain and bucket hash table.
2369 // The data is actually supplied as an array of structures by the user of this class.
2370 // This allows the buckets to use small indices to point to the chain, instead of pointers.
2372 // Each entry in the array contains a HASHENTRY structure immediately
2373 // followed by the key used to hash the structure.
2375 // The HASHENTRY part of every structure is used to implement the chain of
2376 // entries in a single bucket.
2378 // This implementation does not support rehashing the buckets if the table grows
2380 // @TODO: Fix this by adding an abstract function Hash() which must be implemented
2383 //*****************************************************************************
2386 friend class DebuggerRCThread; //RCthread actually needs access to
2387 //fields of derrived class DebuggerPatchTable
2390 TADDR m_pcEntries; // Pointer to the array of structs.
2391 ULONG m_iEntrySize; // Size of the structs.
2393 ULONG m_iBuckets; // # of chains we are hashing into.
2394 PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains.
2396 INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics
2398 HASHENTRY *EntryPtr(ULONG iEntry)
2400 LIMITED_METHOD_DAC_CONTRACT;
2401 return (PTR_HASHENTRY(m_pcEntries + (iEntry * m_iEntrySize)));
2404 ULONG ItemIndex(HASHENTRY *p)
2407 LIMITED_METHOD_CONTRACT;
2408 return (ULONG)((dac_cast<TADDR>(p) - m_pcEntries) / m_iEntrySize);
2415 ULONG iBuckets) : // # of chains we are hashing into.
2416 m_pcEntries((TADDR)NULL),
2417 m_iBuckets(iBuckets)
2419 LIMITED_METHOD_CONTRACT;
2423 INDEBUG(m_maxSearch = 0;)
2426 CHashTable() : // # of chains we are hashing into.
2427 m_pcEntries((TADDR)NULL),
2430 LIMITED_METHOD_CONTRACT;
2434 INDEBUG(m_maxSearch = 0;)
2437 #ifndef DACCESS_COMPILE
2441 LIMITED_METHOD_CONTRACT;
2442 if (m_piBuckets != NULL)
2444 delete [] m_piBuckets;
2449 //*****************************************************************************
2450 // This is the second part of construction where we do all of the work that
2451 // can fail. We also take the array of structs here because the calling class
2452 // presumably needs to allocate it in its NewInit.
2453 //*****************************************************************************
2454 HRESULT NewInit( // Return status.
2455 BYTE *pcEntries, // Array of structs we are managing.
2456 ULONG iEntrySize); // Size of the entries.
2458 //*****************************************************************************
2459 // This can be called to change the pointer to the table that the hash table
2460 // is managing. You might call this if (for example) you realloc the size
2461 // of the table and its pointer is different.
2462 //*****************************************************************************
2464 BYTE *pcEntries) // Array of structs we are managing.
2466 LIMITED_METHOD_CONTRACT;
2467 m_pcEntries = (TADDR)pcEntries;
2470 //*****************************************************************************
2471 // Clear the hash table as if there were nothing in it.
2472 //*****************************************************************************
2475 LIMITED_METHOD_CONTRACT;
2476 _ASSERTE(m_piBuckets != NULL);
2477 memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG));
2480 //*****************************************************************************
2481 // Add the struct at the specified index in m_pcEntries to the hash chains.
2482 //*****************************************************************************
2483 BYTE *Add( // New entry.
2484 ULONG iHash, // Hash value of entry to add.
2485 ULONG iIndex); // Index of struct in m_pcEntries.
2487 //*****************************************************************************
2488 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2489 //*****************************************************************************
2491 ULONG iHash, // Hash value of entry to delete.
2492 ULONG iIndex); // Index of struct in m_pcEntries.
2495 ULONG iHash, // Hash value of entry to delete.
2496 HASHENTRY *psEntry); // The struct to delete.
2498 //*****************************************************************************
2499 // The item at the specified index has been moved, update the previous and
2501 //*****************************************************************************
2503 ULONG iHash, // Hash value for the item.
2504 ULONG iNew); // New location.
2506 #endif // #ifndef DACCESS_COMPILE
2508 //*****************************************************************************
2509 // Return a boolean indicating whether or not this hash table has been inited.
2510 //*****************************************************************************
2513 LIMITED_METHOD_CONTRACT;
2514 return (m_piBuckets != NULL);
2517 //*****************************************************************************
2518 // Search the hash table for an entry with the specified key value.
2519 //*****************************************************************************
2520 BYTE *Find( // Index of struct in m_pcEntries.
2521 ULONG iHash, // Hash value of the item.
2522 SIZE_T key); // The key to match.
2524 //*****************************************************************************
2525 // Search the hash table for the next entry with the specified key value.
2526 //*****************************************************************************
2527 ULONG FindNext( // Index of struct in m_pcEntries.
2528 SIZE_T key, // The key to match.
2529 ULONG iIndex); // Index of previous match.
2531 //*****************************************************************************
2532 // Returns the first entry in the first hash bucket and inits the search
2533 // struct. Use the FindNextEntry function to continue walking the list. The
2534 // return order is not gauranteed.
2535 //*****************************************************************************
2536 BYTE *FindFirstEntry( // First entry found, or 0.
2537 HASHFIND *psSrch) // Search object.
2539 WRAPPER_NO_CONTRACT;
2540 if (m_piBuckets == 0)
2542 psSrch->iBucket = 1;
2543 psSrch->iNext = m_piBuckets[0];
2544 return (FindNextEntry(psSrch));
2547 //*****************************************************************************
2548 // Returns the next entry in the list.
2549 //*****************************************************************************
2550 BYTE *FindNextEntry( // The next entry, or0 for end of list.
2551 HASHFIND *psSrch); // Search object.
2553 #ifdef DACCESS_COMPILE
2554 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
2559 virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0;
2566 static BYTE *Alloc(int iSize, int iMaxSize)
2568 WRAPPER_NO_CONTRACT;
2569 return (new BYTE[iSize]);
2571 static void Free(BYTE *pPtr, int iSize)
2573 LIMITED_METHOD_CONTRACT;
2576 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2578 WRAPPER_NO_CONTRACT;
2580 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2581 //check for overflow
2582 if(newSize.IsOverflow())
2585 p = new (nothrow) BYTE[newSize.Value()];
2586 if (p == 0) return (0);
2587 memcpy (p, pPtr, iCurSize);
2592 static void Clean(BYTE * pData, int iSize)
2595 static int RoundSize(int iSize)
2597 LIMITED_METHOD_CONTRACT;
2600 static int GrowSize(int iCurSize)
2602 LIMITED_METHOD_CONTRACT;
2603 int newSize = (3 * iCurSize) / 2;
2604 return (newSize < 256) ? 256 : newSize;
2608 class CNewDataNoThrow
2611 static BYTE *Alloc(int iSize, int iMaxSize)
2613 WRAPPER_NO_CONTRACT;
2614 return (new (nothrow) BYTE[iSize]);
2616 static void Free(BYTE *pPtr, int iSize)
2618 LIMITED_METHOD_CONTRACT;
2621 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2623 WRAPPER_NO_CONTRACT;
2625 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2626 //check for overflow
2627 if(newSize.IsOverflow())
2630 p = new (nothrow) BYTE[newSize.Value()];
2631 if (p == 0) return (0);
2632 memcpy (p, pPtr, iCurSize);
2637 static void Clean(BYTE * pData, int iSize)
2640 static int RoundSize(int iSize)
2642 LIMITED_METHOD_CONTRACT;
2645 static int GrowSize(int iCurSize)
2647 LIMITED_METHOD_CONTRACT;
2648 int newSize = (3 * iCurSize) / 2;
2649 return (newSize < 256) ? 256 : newSize;
2654 //*****************************************************************************
2655 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2656 // The hashtable implementation that should be used instead is code:SHash.
2657 // If code:SHash does not work for you, talk to mailto:clrdeag.
2658 //*****************************************************************************
2659 // CHashTable expects the data to be in a single array - this is provided by
2660 // CHashTableAndData.
2661 // The array is allocated using the MemMgr type. CNewData and
2662 // CNewDataNoThrow can be used for this.
2663 //*****************************************************************************
2664 template <class MemMgr>
2665 class CHashTableAndData : public CHashTable
2668 ULONG m_iFree; // Index into m_pcEntries[] of next available slot
2669 ULONG m_iEntries; // size of m_pcEntries[]
2673 CHashTableAndData() :
2676 LIMITED_METHOD_CONTRACT;
2680 ULONG iBuckets) : // # of chains we are hashing into.
2681 CHashTable(iBuckets)
2683 LIMITED_METHOD_CONTRACT;
2686 #ifndef DACCESS_COMPILE
2688 ~CHashTableAndData()
2690 WRAPPER_NO_CONTRACT;
2691 if (m_pcEntries != NULL)
2692 MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize));
2695 //*****************************************************************************
2696 // This is the second part of construction where we do all of the work that
2697 // can fail. We also take the array of structs here because the calling class
2698 // presumably needs to allocate it in its NewInit.
2699 //*****************************************************************************
2700 HRESULT NewInit( // Return status.
2701 ULONG iEntries, // # of entries.
2702 ULONG iEntrySize, // Size of the entries.
2703 int iMaxSize); // Max size of data.
2705 //*****************************************************************************
2706 // Clear the hash table as if there were nothing in it.
2707 //*****************************************************************************
2710 WRAPPER_NO_CONTRACT;
2712 InitFreeChain(0, m_iEntries);
2713 CHashTable::Clear();
2716 //*****************************************************************************
2717 // Grabs a slot for the new entry to be added.
2718 // The caller should fill in the non-HASHENTRY part of the returned slot
2719 //*****************************************************************************
2721 ULONG iHash) // Hash value of entry to add.
2723 WRAPPER_NO_CONTRACT;
2724 FREEHASHENTRY *psEntry;
2726 // Make the table bigger if necessary.
2727 if (m_iFree == UINT32_MAX && !Grow())
2730 // Add the first entry from the free list to the hash chain.
2731 psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree);
2732 m_iFree = psEntry->iFree;
2734 // If we're recycling memory, give our memory-allocator a chance to re-init it.
2736 // Each entry is prefixed with a header - we don't want to trash that.
2737 SIZE_T cbHeader = sizeof(FREEHASHENTRY);
2738 MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader));
2740 return ((BYTE *) psEntry);
2743 //*****************************************************************************
2744 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2745 //*****************************************************************************
2747 ULONG iHash, // Hash value of entry to delete.
2748 ULONG iIndex) // Index of struct in m_pcEntries.
2750 WRAPPER_NO_CONTRACT;
2751 CHashTable::Delete(iHash, iIndex);
2752 ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree;
2757 ULONG iHash, // Hash value of entry to delete.
2758 HASHENTRY *psEntry) // The struct to delete.
2760 WRAPPER_NO_CONTRACT;
2761 CHashTable::Delete(iHash, psEntry);
2762 ((FREEHASHENTRY *) psEntry)->iFree = m_iFree;
2763 m_iFree = ItemIndex(psEntry);
2766 #endif // #ifndef DACCESS_COMPILE
2768 // This is a sad legacy workaround. The debugger's patch table (implemented as this
2769 // class) is shared across process. We publish the runtime offsets of
2770 // some key fields. Since those fields are private, we have to provide
2771 // accessors here. So if you're not using these functions, don't start.
2772 // We can hopefully remove them.
2773 // Note that we can't just make RCThread a friend of this class (we tried
2774 // originally) because the inheritence chain has a private modifier,
2775 // so DebuggerPatchTable::m_pcEntries is illegal.
2776 static SIZE_T helper_GetOffsetOfEntries()
2778 LIMITED_METHOD_CONTRACT;
2779 return offsetof(CHashTableAndData, m_pcEntries);
2782 static SIZE_T helper_GetOffsetOfCount()
2784 LIMITED_METHOD_CONTRACT;
2785 return offsetof(CHashTableAndData, m_iEntries);
2788 #ifdef DACCESS_COMPILE
2789 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2792 CHashTable::EnumMemoryRegions(flags, m_iEntries);
2797 void InitFreeChain(ULONG iStart,ULONG iEnd);
2801 #ifndef DACCESS_COMPILE
2803 //*****************************************************************************
2804 // This is the second part of construction where we do all of the work that
2805 // can fail. We also take the array of structs here because the calling class
2806 // presumably needs to allocate it in its NewInit.
2807 //*****************************************************************************
2808 template<class MemMgr>
2809 HRESULT CHashTableAndData<MemMgr>::NewInit(// Return status.
2810 ULONG iEntries, // # of entries.
2811 ULONG iEntrySize, // Size of the entries.
2812 int iMaxSize) // Max size of data.
2814 WRAPPER_NO_CONTRACT;
2819 // note that this function can throw because it depends on the <M>::Alloc
2821 // Allocate the memory for the entries.
2822 if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize),
2823 MemMgr::RoundSize(iMaxSize))) == 0)
2824 return (E_OUTOFMEMORY);
2825 m_iEntries = iEntries;
2827 // Init the base table.
2828 if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize)))
2829 MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize));
2832 // Init the free chain.
2834 InitFreeChain(0, iEntries);
2839 //*****************************************************************************
2840 // Initialize a range of records such that they are linked together to be put
2841 // on the free chain.
2842 //*****************************************************************************
2843 template<class MemMgr>
2844 void CHashTableAndData<MemMgr>::InitFreeChain(
2845 ULONG iStart, // Index to start initializing.
2846 ULONG iEnd) // Index to stop initializing
2848 LIMITED_METHOD_CONTRACT;
2850 _ASSERTE(iEnd > iStart);
2852 pcPtr = (BYTE*)m_pcEntries + iStart * m_iEntrySize;
2853 for (++iStart; iStart < iEnd; ++iStart)
2855 ((FREEHASHENTRY *) pcPtr)->iFree = iStart;
2856 pcPtr += m_iEntrySize;
2858 ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX;
2861 //*****************************************************************************
2862 // Attempt to increase the amount of space available for the record heap.
2863 //*****************************************************************************
2864 template<class MemMgr>
2865 int CHashTableAndData<MemMgr>::Grow() // 1 if successful, 0 if not.
2867 WRAPPER_NO_CONTRACT;
2868 int iCurSize; // Current size in bytes.
2869 int iEntries; // New # of entries.
2871 _ASSERTE(m_pcEntries != NULL);
2872 _ASSERTE(m_iFree == UINT32_MAX);
2874 // Compute the current size and new # of entries.
2875 S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize);
2876 if( iTotEntrySize.IsOverflow() )
2878 _ASSERTE( !"CHashTableAndData overflow!" );
2881 iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() );
2882 iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize;
2884 if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) )
2886 _ASSERTE( !"CHashTableAndData overflow!" );
2890 // Try to expand the array.
2891 if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0)
2894 // Init the newly allocated space.
2895 InitFreeChain(m_iEntries, iEntries);
2896 m_iFree = m_iEntries;
2897 m_iEntries = iEntries;
2901 #endif // #ifndef DACCESS_COMPILE
2903 //*****************************************************************************
2904 //*****************************************************************************
2906 inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data)
2908 LIMITED_METHOD_DAC_CONTRACT;
2909 return ((currentHash << 5) + currentHash) ^ data;
2912 inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr)
2914 WRAPPER_NO_CONTRACT;
2916 return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast<TADDR>(ptr))));
2919 inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c)
2921 LIMITED_METHOD_DAC_CONTRACT;
2924 lookup3.c, by Bob Jenkins, May 2006, Public Domain.
2926 These are functions for producing 32-bit hashes for hash table lookup.
2927 hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
2928 are externally useful functions. Routines to test the hash are included
2929 if SELF_TEST is defined. You can use this free for any purpose. It's in
2930 the public domain. It has no warranty.
2933 #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
2934 c ^= b; c -= rot32(b,14);
2935 a ^= c; a -= rot32(c,11);
2936 b ^= a; b -= rot32(a,25);
2937 c ^= b; c -= rot32(b,16);
2938 a ^= c; a -= rot32(c,4);
2939 b ^= a; b -= rot32(a,14);
2940 c ^= b; c -= rot32(b,24);
2945 inline ULONG HashBytes(BYTE const *pbData, size_t iSize)
2947 LIMITED_METHOD_CONTRACT;
2950 BYTE const *pbDataEnd = pbData + iSize;
2952 for (/**/ ; pbData < pbDataEnd; pbData++)
2954 hash = ((hash << 5) + hash) ^ *pbData;
2959 // Helper function for hashing a string char by char.
2960 inline ULONG HashStringA(LPCSTR szStr)
2962 LIMITED_METHOD_CONTRACT;
2966 while ((c = *szStr) != 0)
2968 hash = ((hash << 5) + hash) ^ c;
2974 inline ULONG HashString(LPCWSTR szStr)
2976 LIMITED_METHOD_CONTRACT;
2980 while ((c = *szStr) != 0)
2982 hash = ((hash << 5) + hash) ^ c;
2988 inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr)
2990 LIMITED_METHOD_CONTRACT;
2993 // hash the string two characters at a time
2994 ULONG *ptr = (ULONG *)szStr;
2996 // we assume that szStr is null-terminated
2997 _ASSERTE(cchStr <= wcslen(szStr));
2998 SIZE_T cDwordCount = (cchStr + 1) / 2;
3000 for (SIZE_T i = 0; i < cDwordCount; i++)
3002 hash = ((hash << 5) + hash) ^ ptr[i];
3008 // Case-insensitive string hash function.
3009 inline ULONG HashiStringA(LPCSTR szStr)
3011 LIMITED_METHOD_CONTRACT;
3015 hash = ((hash << 5) + hash) ^ toupper(*szStr);
3021 // Case-insensitive string hash function.
3022 inline ULONG HashiString(LPCWSTR szStr)
3024 LIMITED_METHOD_CONTRACT;
3028 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3034 // Case-insensitive string hash function.
3035 inline ULONG HashiStringN(LPCWSTR szStr, DWORD count)
3037 LIMITED_METHOD_CONTRACT;
3039 while (*szStr != 0 && count--)
3041 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3047 // Case-insensitive string hash function when all of the
3048 // characters in the string are known to be below 0x80.
3049 // Knowing this is much more efficient than calling
3051 inline ULONG HashiStringKnownLower80(LPCWSTR szStr) {
3052 LIMITED_METHOD_CONTRACT;
3056 while ((c = *szStr)!=0) {
3057 //If we have a lowercase character, ANDing off 0x20
3058 //(mask) will make it an uppercase character.
3059 if (c>='a' && c<='z') {
3062 hash = ((hash << 5) + hash) ^ c;
3068 inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) {
3069 LIMITED_METHOD_CONTRACT;
3073 while ((c = *szStr) !=0 && count--) {
3074 //If we have a lowercase character, ANDing off 0x20
3075 //(mask) will make it an uppercase character.
3076 if (c>='a' && c<='z') {
3079 hash = ((hash << 5) + hash) ^ c;
3085 //*****************************************************************************
3086 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3087 // The hashtable implementation that should be used instead is code:SHash.
3088 // If code:SHash does not work for you, talk to mailto:clrdeag.
3089 //*****************************************************************************
3090 // This class implements a closed hashing table. Values are hashed to a bucket,
3091 // and if that bucket is full already, then the value is placed in the next
3092 // free bucket starting after the desired target (with wrap around). If the
3093 // table becomes 75% full, it is grown and rehashed to reduce lookups. This
3094 // class is best used in a reltively small lookup table where hashing is
3095 // not going to cause many collisions. By not having the collision chain
3096 // logic, a lot of memory is saved.
3098 // The user of the template is required to supply several methods which decide
3099 // how each element can be marked as free, deleted, or used. It would have
3100 // been possible to write this with more internal logic, but that would require
3101 // either (a) more overhead to add status on top of elements, or (b) hard
3102 // coded types like one for strings, one for ints, etc... This gives you the
3103 // flexibility of adding logic to your type.
3104 //*****************************************************************************
3105 class CClosedHashBase
3107 BYTE *EntryPtr(int iEntry)
3109 LIMITED_METHOD_CONTRACT;
3110 return (m_rgData + (iEntry * m_iEntrySize));
3113 BYTE *EntryPtr(int iEntry, BYTE *rgData)
3115 LIMITED_METHOD_CONTRACT;
3116 return (rgData + (iEntry * m_iEntrySize));
3122 FREE, // Item is not in use right now.
3123 DELETED, // Item is deleted.
3124 USED // Item is in use.
3128 int iBuckets, // How many buckets should we start with.
3129 int iEntrySize, // Size of an entry.
3130 bool bPerfect) : // true if bucket size will hash with no collisions.
3131 m_bPerfect(bPerfect),
3132 m_iBuckets(iBuckets),
3133 m_iEntrySize(iEntrySize),
3138 LIMITED_METHOD_CONTRACT;
3139 m_iSize = iBuckets + 7;
3142 virtual ~CClosedHashBase()
3144 WRAPPER_NO_CONTRACT;
3148 virtual void Clear()
3150 LIMITED_METHOD_CONTRACT;
3157 //*****************************************************************************
3158 // Accessors for getting at the underlying data. Be careful to use Count()
3159 // only when you want the number of buckets actually used.
3160 //*****************************************************************************
3164 LIMITED_METHOD_CONTRACT;
3170 LIMITED_METHOD_CONTRACT;
3171 return (m_iCollisions);
3176 LIMITED_METHOD_CONTRACT;
3177 return (m_iBuckets);
3180 void SetBuckets(int iBuckets, bool bPerfect=false)
3182 LIMITED_METHOD_CONTRACT;
3183 _ASSERTE(m_rgData == 0);
3184 m_iBuckets = iBuckets;
3185 m_iSize = m_iBuckets + 7;
3186 m_bPerfect = bPerfect;
3191 LIMITED_METHOD_CONTRACT;
3195 //*****************************************************************************
3196 // Add a new item to hash table given the key value. If this new entry
3197 // exceeds maximum size, then the table will grow and be re-hashed, which
3198 // may cause a memory error.
3199 //*****************************************************************************
3200 BYTE *Add( // New item to fill out on success.
3201 void *pData) // The value to hash on.
3203 WRAPPER_NO_CONTRACT;
3204 // If we haven't allocated any memory, or it is too small, fix it.
3205 if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect))
3211 return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount));
3214 //*****************************************************************************
3215 // Delete the given value. This will simply mark the entry as deleted (in
3216 // order to keep the collision chain intact). There is an optimization that
3217 // consecutive deleted entries leading up to a free entry are themselves freed
3218 // to reduce collisions later on.
3219 //*****************************************************************************
3221 void *pData); // Key value to delete.
3224 //*****************************************************************************
3225 // Callback function passed to DeleteLoop.
3226 //*****************************************************************************
3227 typedef BOOL (* DELETELOOPFUNC)( // Delete current item?
3228 BYTE *pEntry, // Bucket entry to evaluate
3229 void *pCustomizer); // User-defined value
3231 //*****************************************************************************
3232 // Iterates over all active values, passing each one to pDeleteLoopFunc.
3233 // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer
3234 // and faster than using FindNext() and Delete().
3235 //*****************************************************************************
3237 DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item
3238 void *pCustomizer); // Extra value passed to deletefunc.
3241 //*****************************************************************************
3242 // Lookup a key value and return a pointer to the element if found.
3243 //*****************************************************************************
3244 BYTE *Find( // The item if found, 0 if not.
3245 void *pData); // The key to lookup.
3247 //*****************************************************************************
3248 // Look for an item in the table. If it isn't found, then create a new one and
3250 //*****************************************************************************
3251 BYTE *FindOrAdd( // The item if found, 0 if not.
3252 void *pData, // The key to lookup.
3253 bool &bNew); // true if created.
3255 //*****************************************************************************
3256 // The following functions are used to traverse each used entry. This code
3257 // will skip over deleted and free entries freeing the caller up from such
3259 //*****************************************************************************
3260 BYTE *GetFirst() // The first entry, 0 if none.
3262 WRAPPER_NO_CONTRACT;
3263 int i; // Loop control.
3265 // If we've never allocated the table there can't be any to get.
3269 // Find the first one.
3270 for (i=0; i<m_iSize; i++)
3272 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3273 return (EntryPtr(i));
3278 BYTE *GetNext(BYTE *Prev) // The next entry, 0 if done.
3280 WRAPPER_NO_CONTRACT;
3281 int i; // Loop control.
3283 for (i = (int)(((size_t) Prev - (size_t) &m_rgData[0]) / m_iEntrySize) + 1; i<m_iSize; i++)
3285 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3286 return (EntryPtr(i));
3292 //*****************************************************************************
3293 // Hash is called with a pointer to an element in the table. You must override
3294 // this method and provide a hash algorithm for your element type.
3295 //*****************************************************************************
3296 virtual unsigned int Hash( // The key value.
3297 void const *pData)=0; // Raw data to hash.
3299 //*****************************************************************************
3300 // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
3301 // direction of miscompare. In this system everything is always equal or not.
3302 //*****************************************************************************
3303 virtual unsigned int Compare( // 0, -1, or 1.
3304 void const *pData, // Raw key data on lookup.
3305 BYTE *pElement)=0; // The element to compare data against.
3307 //*****************************************************************************
3308 // Return true if the element is free to be used.
3309 //*****************************************************************************
3310 virtual ELEMENTSTATUS Status( // The status of the entry.
3311 BYTE *pElement)=0; // The element to check.
3313 //*****************************************************************************
3314 // Sets the status of the given element.
3315 //*****************************************************************************
3316 virtual void SetStatus(
3317 BYTE *pElement, // The element to set status for.
3318 ELEMENTSTATUS eStatus)=0; // New status.
3320 //*****************************************************************************
3321 // Returns the internal key value for an element.
3322 //*****************************************************************************
3323 virtual void *GetKey( // The data to hash on.
3324 BYTE *pElement)=0; // The element to return data ptr for.
3326 //*****************************************************************************
3327 // This helper actually does the add for you.
3328 //*****************************************************************************
3329 BYTE *DoAdd(void *pData, BYTE *rgData, int &iBuckets, int iSize,
3330 int &iCollisions, int &iCount);
3332 //*****************************************************************************
3333 // This function is called either to init the table in the first place, or
3334 // to rehash the table if we ran out of room.
3335 //*****************************************************************************
3336 bool ReHash(); // true if successful.
3338 //*****************************************************************************
3339 // Walk each item in the table and mark it free.
3340 //*****************************************************************************
3341 void InitFree(BYTE *ptr, int iSize)
3343 WRAPPER_NO_CONTRACT;
3345 for (i=0; i<iSize; i++, ptr += m_iEntrySize)
3346 SetStatus(ptr, FREE);
3350 bool m_bPerfect; // true if the table size guarantees
3352 int m_iBuckets; // How many buckets do we have.
3353 int m_iEntrySize; // Size of an entry.
3354 int m_iSize; // How many elements can we have.
3355 int m_iCount; // How many items cannot be used (NON free, i.e. USED+DELETED).
3356 int m_iCollisions; // How many have we had.
3357 BYTE *m_rgData; // Data element list.
3360 //*****************************************************************************
3361 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3362 // The hashtable implementation that should be used instead is code:SHash.
3363 // If code:SHash does not work for you, talk to mailto:clrdeag.
3364 //*****************************************************************************
3365 template <class T> class CClosedHash : public CClosedHashBase
3369 int iBuckets, // How many buckets should we start with.
3370 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3371 CClosedHashBase(iBuckets, sizeof(T), bPerfect)
3373 WRAPPER_NO_CONTRACT;
3376 T &operator[](int iIndex)
3378 WRAPPER_NO_CONTRACT;
3379 return ((T &) *(Data() + (iIndex * sizeof(T))));
3383 //*****************************************************************************
3384 // Add a new item to hash table given the key value. If this new entry
3385 // exceeds maximum size, then the table will grow and be re-hashed, which
3386 // may cause a memory error.
3387 //*****************************************************************************
3388 T *Add( // New item to fill out on success.
3389 void *pData) // The value to hash on.
3391 WRAPPER_NO_CONTRACT;
3392 return ((T *) CClosedHashBase::Add(pData));
3395 //*****************************************************************************
3396 // Lookup a key value and return a pointer to the element if found.
3397 //*****************************************************************************
3398 T *Find( // The item if found, 0 if not.
3399 void *pData) // The key to lookup.
3401 WRAPPER_NO_CONTRACT;
3402 return ((T *) CClosedHashBase::Find(pData));
3405 //*****************************************************************************
3406 // Look for an item in the table. If it isn't found, then create a new one and
3408 //*****************************************************************************
3409 T *FindOrAdd( // The item if found, 0 if not.
3410 void *pData, // The key to lookup.
3411 bool &bNew) // true if created.
3413 WRAPPER_NO_CONTRACT;
3414 return ((T *) CClosedHashBase::FindOrAdd(pData, bNew));
3418 //*****************************************************************************
3419 // The following functions are used to traverse each used entry. This code
3420 // will skip over deleted and free entries freeing the caller up from such
3422 //*****************************************************************************
3423 T *GetFirst() // The first entry, 0 if none.
3425 WRAPPER_NO_CONTRACT;
3426 return ((T *) CClosedHashBase::GetFirst());
3429 T *GetNext(T *Prev) // The next entry, 0 if done.
3431 WRAPPER_NO_CONTRACT;
3432 return ((T *) CClosedHashBase::GetNext((BYTE *) Prev));
3437 //*****************************************************************************
3438 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3439 // The hashtable implementation that should be used instead is code:SHash.
3440 // If code:SHash does not work for you, talk to mailto:clrdeag.
3441 //*****************************************************************************
3442 // Closed hash with typed parameters. The derived class is the second
3443 // parameter to the template. The derived class must implement:
3444 // unsigned long Hash(const T *pData);
3445 // unsigned long Compare(const T *p1, T *p2);
3446 // ELEMENTSTATUS Status(T *pEntry);
3447 // void SetStatus(T *pEntry, ELEMENTSTATUS s);
3448 // void* GetKey(T *pEntry);
3449 //*****************************************************************************
3450 template<class T, class H>class CClosedHashEx : public CClosedHash<T>
3454 int iBuckets, // How many buckets should we start with.
3455 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3456 CClosedHash<T> (iBuckets, bPerfect)
3458 WRAPPER_NO_CONTRACT;
3461 unsigned int Hash(const void *pData)
3463 WRAPPER_NO_CONTRACT;
3464 return static_cast<H*>(this)->Hash((const T*)pData);
3467 unsigned int Compare(const void *p1, BYTE *p2)
3469 WRAPPER_NO_CONTRACT;
3470 return static_cast<H*>(this)->Compare((const T*)p1, (T*)p2);
3473 typename CClosedHash<T>::ELEMENTSTATUS Status(BYTE *p)
3475 WRAPPER_NO_CONTRACT;
3476 return static_cast<H*>(this)->Status((T*)p);
3479 void SetStatus(BYTE *p, typename CClosedHash<T>::ELEMENTSTATUS s)
3481 WRAPPER_NO_CONTRACT;
3482 static_cast<H*>(this)->SetStatus((T*)p, s);
3485 void* GetKey(BYTE *p)
3487 WRAPPER_NO_CONTRACT;
3488 return static_cast<H*>(this)->GetKey((T*)p);
3493 //*****************************************************************************
3494 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3495 // The hashtable implementation that should be used instead is code:SHash.
3496 // If code:SHash does not work for you, talk to mailto:clrdeag.
3497 //*****************************************************************************
3498 // This template is another form of a closed hash table. It handles collisions
3499 // through a linked chain. To use it, derive your hashed item from HASHLINK
3500 // and implement the virtual functions required. 1.5 * ibuckets will be
3501 // allocated, with the extra .5 used for collisions. If you add to the point
3502 // where no free nodes are available, the entire table is grown to make room.
3503 // The advantage to this system is that collisions are always directly known,
3504 // there either is one or there isn't.
3505 //*****************************************************************************
3508 ULONG iNext; // Offset for next entry.
3511 template <class T> class CChainedHash
3513 friend class VerifyLayoutsMD;
3515 CChainedHash(int iBuckets=32) :
3517 m_iBuckets(iBuckets),
3522 LIMITED_METHOD_CONTRACT;
3523 m_iSize = iBuckets + (iBuckets / 2);
3528 LIMITED_METHOD_CONTRACT;
3533 void SetBuckets(int iBuckets)
3535 LIMITED_METHOD_CONTRACT;
3536 _ASSERTE(m_rgData == 0);
3537 // if iBuckets==0, then we'll allocate a zero size array and AV on dereference.
3538 _ASSERTE(iBuckets > 0);
3539 m_iBuckets = iBuckets;
3540 m_iSize = iBuckets + (iBuckets / 2);
3543 T *Add(void const *pData)
3545 WRAPPER_NO_CONTRACT;
3550 // Build the list if required.
3551 if (m_rgData == 0 || m_iFree == 0xffffffff)
3557 // Hash the item and pick a bucket.
3558 iHash = Hash(pData);
3559 iBucket = iHash % m_iBuckets;
3561 // Use the bucket if it is free.
3562 if (InUse(&m_rgData[iBucket]) == false)
3564 pItem = &m_rgData[iBucket];
3565 pItem->iNext = 0xffffffff;
3567 // Else take one off of the free list for use.
3572 // Pull an item from the free list.
3574 pItem = &m_rgData[m_iFree];
3575 m_iFree = pItem->iNext;
3577 // Link the new node in after the bucket.
3578 pItem->iNext = m_rgData[iBucket].iNext;
3579 m_rgData[iBucket].iNext = iEntry;
3585 T *Find(void const *pData, bool bAddIfNew=false)
3587 WRAPPER_NO_CONTRACT;
3592 // Check states for lookup.
3595 // If we won't be adding, then we are through.
3596 if (bAddIfNew == false)
3599 // Otherwise, create the table.
3604 // Hash the item and pick a bucket.
3605 iHash = Hash(pData);
3606 iBucket = iHash % m_iBuckets;
3608 // If it isn't in use, then there it wasn't found.
3609 if (!InUse(&m_rgData[iBucket]))
3611 if (bAddIfNew == false)
3615 pItem = &m_rgData[iBucket];
3616 pItem->iNext = 0xffffffff;
3620 // Scan the list for the one we want.
3624 for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem))
3626 if (Cmp(pData, pItem) == 0)
3631 if (!pItem && bAddIfNew)
3635 // Record maximum chain length.
3636 if (iChain > m_iMaxChain)
3637 m_iMaxChain = iChain;
3639 // Now need more room.
3640 if (m_iFree == 0xffffffff)
3646 // Pull an item from the free list.
3648 pItem = &m_rgData[m_iFree];
3649 m_iFree = pItem->iNext;
3651 // Link the new node in after the bucket.
3652 pItem->iNext = m_rgData[iBucket].iNext;
3653 m_rgData[iBucket].iNext = iEntry;
3662 LIMITED_METHOD_CONTRACT;
3668 LIMITED_METHOD_CONTRACT;
3669 return (m_iBuckets);
3672 ULONG MaxChainLength()
3674 LIMITED_METHOD_CONTRACT;
3675 return (m_iMaxChain);
3678 virtual void Clear()
3680 LIMITED_METHOD_CONTRACT;
3681 // Free up the memory.
3694 virtual bool InUse(T *pItem)=0;
3695 virtual void SetFree(T *pItem)=0;
3696 virtual ULONG Hash(void const *pData)=0;
3697 virtual int Cmp(void const *pData, void *pItem)=0;
3699 inline T *GetNext(T *pItem)
3701 LIMITED_METHOD_CONTRACT;
3702 if (pItem->iNext != 0xffffffff)
3703 return ((T *) &m_rgData[pItem->iNext]);
3709 WRAPPER_NO_CONTRACT;
3713 // If this is a first time allocation, then just malloc it.
3716 if ((m_rgData = new (nothrow) T[m_iSize]) == 0)
3720 for (i=0; i<m_iSize; i++)
3721 SetFree(&m_rgData[i]);
3723 m_iFree = m_iBuckets;
3724 for (i=m_iBuckets; i<m_iSize; i++)
3725 ((T *) &m_rgData[i])->iNext = i + 1;
3726 ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff;
3730 // Otherwise we need more room on the free chain, so allocate some.
3731 iNewSize = m_iSize + (m_iSize / 2);
3733 // Allocate/realloc memory.
3734 if ((rgTemp = new (nothrow) T[iNewSize]) == 0)
3737 memcpy (rgTemp,m_rgData,m_iSize*sizeof(T));
3740 // Init new entries, save the new free chain, and reset internals.
3742 for (int i=m_iFree; i<iNewSize; i++)
3744 SetFree(&rgTemp[i]);
3745 ((T *) &rgTemp[i])->iNext = i + 1;
3747 ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff;
3755 T *m_rgData; // Data to store items in.
3756 int m_iBuckets; // How many buckets we want.
3757 int m_iSize; // How many are allocated.
3758 int m_iCount; // How many are we using.
3759 ULONG m_iMaxChain; // Max chain length.
3760 ULONG m_iFree; // Free chain.
3764 //*****************************************************************************
3766 //********** String helper functions.
3768 //*****************************************************************************
3770 //*****************************************************************************
3771 // Checks if string length exceeds the specified limit
3772 //*****************************************************************************
3773 inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N)
3775 LIMITED_METHOD_CONTRACT;
3779 for(i=0; (i < N)&&(pstr[i]); i++);
3785 //*****************************************************************************
3786 // Class to parse a list of simple assembly names and then find a match
3787 //*****************************************************************************
3789 class AssemblyNamesList
3793 LPUTF8 m_assemblyName;
3794 AssemblyName *m_next; // Next name
3797 AssemblyName *m_pNames; // List of names
3801 bool IsInList(LPCUTF8 assemblyName);
3805 LIMITED_METHOD_CONTRACT;
3806 return m_pNames == 0;
3809 AssemblyNamesList(__in LPWSTR list);
3810 ~AssemblyNamesList();
3813 //*****************************************************************************
3814 // Class to parse a list of method names and then find a match
3815 //*****************************************************************************
3817 struct CORINFO_SIG_INFO;
3819 class MethodNamesListBase
3823 LPUTF8 methodName; // NULL means wildcard
3824 LPUTF8 className; // NULL means wildcard
3825 int numArgs; // number of args for the method, -1 is wildcard
3826 MethodName *next; // Next name
3829 MethodName *pNames; // List of names
3831 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs);
3836 LIMITED_METHOD_CONTRACT;
3840 void Init(__in __in_z LPWSTR list)
3842 WRAPPER_NO_CONTRACT;
3849 void Insert(__in __in_z LPWSTR list);
3851 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3852 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3855 LIMITED_METHOD_CONTRACT;
3860 class MethodNamesList : public MethodNamesListBase
3865 WRAPPER_NO_CONTRACT;
3869 MethodNamesList(__in LPWSTR list)
3871 WRAPPER_NO_CONTRACT;
3877 WRAPPER_NO_CONTRACT;
3882 #if !defined(NO_CLRCONFIG)
3884 /**************************************************************************/
3885 /* simple wrappers around the REGUTIL and MethodNameList routines that make
3888 /* to be used as static variable - no constructor/destructor, assumes zero
3889 initialized memory */
3895 // NOTE: The following function is deprecated; use the CLRConfig class instead.
3896 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
3898 inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0)
3900 WRAPPER_NO_CONTRACT;
3901 // make sure that the memory was zero initialized
3902 _ASSERTE(m_inited == 0 || m_inited == 1);
3904 if (!m_inited) init_DontUse_(keyName, defaultVal);
3907 inline DWORD val(const CLRConfig::ConfigDWORDInfo & info)
3909 WRAPPER_NO_CONTRACT;
3910 // make sure that the memory was zero initialized
3911 _ASSERTE(m_inited == 0 || m_inited == 1);
3913 if (!m_inited) init(info);
3918 void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0);
3919 void init(const CLRConfig::ConfigDWORDInfo & info);
3926 /**************************************************************************/
3930 inline LPWSTR val(const CLRConfig::ConfigStringInfo & info)
3932 WRAPPER_NO_CONTRACT;
3933 // make sure that the memory was zero initialized
3934 _ASSERTE(m_inited == 0 || m_inited == 1);
3936 if (!m_inited) init(info);
3940 bool isInitialized()
3942 WRAPPER_NO_CONTRACT;
3944 // make sure that the memory was zero initialized
3945 _ASSERTE(m_inited == 0 || m_inited == 1);
3947 return m_inited == 1;
3951 void init(const CLRConfig::ConfigStringInfo & info);
3958 /**************************************************************************/
3959 class ConfigMethodSet
3964 WRAPPER_NO_CONTRACT;
3965 _ASSERTE(m_inited == 1);
3966 return m_list.IsEmpty();
3969 bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3970 bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3972 inline void ensureInit(const CLRConfig::ConfigStringInfo & info)
3974 WRAPPER_NO_CONTRACT;
3975 // make sure that the memory was zero initialized
3976 _ASSERTE(m_inited == 0 || m_inited == 1);
3978 if (!m_inited) init(info);
3982 void init(const CLRConfig::ConfigStringInfo & info);
3985 MethodNamesListBase m_list;
3990 #endif // !defined(NO_CLRCONFIG)
3992 //*****************************************************************************
3993 // Convert a pointer to a string into a GUID.
3994 //*****************************************************************************
3995 HRESULT LPCSTRToGuid( // Return status.
3996 LPCSTR szGuid, // String to convert.
3997 GUID *psGuid); // Buffer for converted GUID.
3999 //*****************************************************************************
4000 // Convert a GUID into a pointer to a string
4001 //*****************************************************************************
4002 int GuidToLPWSTR( // Return status.
4003 GUID Guid, // [IN] The GUID to convert.
4004 __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored
4005 DWORD cchGuid); // [IN] Size in wide chars of szGuid
4007 //*****************************************************************************
4008 // Parse a Wide char string into a GUID
4009 //*****************************************************************************
4011 GUID * Guid, // [OUT] The GUID to fill in
4012 __in_ecount(cchGuid) LPCWSTR szGuid, // [IN] String to parse
4013 DWORD cchGuid); // [IN] Count in wchars in string
4015 typedef VPTR(class RangeList) PTR_RangeList;
4020 VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList)
4022 #ifndef DACCESS_COMPILE
4028 LIMITED_METHOD_CONTRACT;
4032 // Wrappers to make the virtual calls DAC-safe.
4033 BOOL AddRange(const BYTE *start, const BYTE *end, void *id)
4035 return this->AddRangeWorker(start, end, id);
4038 void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL)
4040 return this->RemoveRangesWorker(id, start, end);
4043 BOOL IsInRange(TADDR address, TADDR *pID = NULL)
4047 return this->IsInRangeWorker(address, pID);
4050 #ifndef DACCESS_COMPILE
4052 // You can overload these two for synchronization (as LockedRangeList does)
4053 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id);
4054 // If both "start" and "end" are NULL, then this method deletes all ranges with
4055 // the given id (i.e. the original behaviour). Otherwise, it ignores the given
4056 // id and deletes all ranges falling in the region [start, end).
4057 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL);
4059 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id)
4063 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { }
4064 #endif // !DACCESS_COMPILE
4066 virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL);
4068 #ifdef DACCESS_COMPILE
4069 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4086 struct RangeListBlock
4088 Range ranges[RANGE_COUNT];
4089 DPTR(RangeListBlock) next;
4091 #ifdef DACCESS_COMPILE
4092 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4097 void InitBlock(RangeListBlock *block);
4099 RangeListBlock m_starterBlock;
4100 DPTR(RangeListBlock) m_firstEmptyBlock;
4101 TADDR m_firstEmptyRange;
4106 // A private function to do the equavilent of a CoCreateInstance in
4107 // cases where we can't make the real call. Use this when, for
4108 // instance, you need to create a symbol reader in the Runtime but
4109 // we're not CoInitialized. Obviously, this is only good for COM
4110 // objects for which CoCreateInstance is just a glorified
4111 // find-and-load-me operation.
4114 HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid,
4118 HMODULE * phmodDll);
4120 // Provided for backward compatibility and for code that doesn't need the HMODULE of the
4121 // DLL that was loaded to create the COM object. See comment at implementation of
4122 // code:FakeCoCreateInstanceEx for more details.
4123 inline HRESULT FakeCoCreateInstance(REFCLSID rclsid,
4133 return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL);
4136 //*****************************************************************************
4137 // Gets the directory based on the location of the module. This routine
4138 // is called at COR setup time. Set is called during EEStartup and by the
4139 // MetaData dispenser.
4140 //*****************************************************************************
4141 HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength);
4142 LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL);
4144 //*****************************************************************************
4145 // This function validates the given Method/Field/Standalone signature. (util.cpp)
4146 //*****************************************************************************
4147 struct IMDInternalImport;
4148 HRESULT validateTokenSig(
4149 mdToken tk, // [IN] Token whose signature needs to be validated.
4150 PCCOR_SIGNATURE pbSig, // [IN] Signature.
4151 ULONG cbSig, // [IN] Size in bytes of the signature.
4152 DWORD dwFlags, // [IN] Method flags.
4153 IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr
4155 //*****************************************************************************
4156 // Determine the version number of the runtime that was used to build the
4157 // specified image. The pMetadata pointer passed in is the pointer to the
4158 // metadata contained in the image.
4159 //*****************************************************************************
4160 HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString);
4162 //*****************************************************************************
4163 // The registry keys and values that contain the information regarding
4164 // the default registered unmanaged debugger.
4165 //*****************************************************************************
4166 SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4167 SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4169 SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
4170 SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger");
4171 SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto");
4172 SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList");
4174 BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key.
4175 LPCWSTR szKey, // Key name to look at.
4176 LPCWSTR szName, // Name of value to get.
4177 long *pValue, // Put value here, if found.
4178 BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64
4180 HRESULT GetCurrentModuleFileName(SString& pBuffer);
4182 //*****************************************************************************
4183 // Retrieve information regarding what registered default debugger
4184 //*****************************************************************************
4185 void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto);
4186 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto);
4188 void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch);
4191 //*****************************************************************************
4192 // Convert a UTF8 string to Unicode, into a CQuickArray<WCHAR>.
4193 //*****************************************************************************
4195 LPCUTF8 pStr, // The string to convert.
4196 CQuickArray<WCHAR> &rStr, // The QuickArray<WCHAR> to convert it into.
4197 int iCurLen = 0); // Initial characters in the array to leave (default 0).
4199 //*****************************************************************************
4200 // Extract the movl 64-bit unsigned immediate from an IA64 bundle
4202 //*****************************************************************************
4203 UINT64 GetIA64Imm64(UINT64 * pBundle);
4204 UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1);
4206 //*****************************************************************************
4207 // Deposit the movl 64-bit unsigned immediate into an IA64 bundle
4209 //*****************************************************************************
4210 void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64);
4212 //*****************************************************************************
4213 // Extract the IP-Relative signed 25-bit immediate from an IA64 bundle
4214 // (Formats B1, B2 or B3)
4215 // Note that due to branch target alignment requirements
4216 // the lowest four bits in the result will always be zero.
4217 //*****************************************************************************
4218 INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot);
4219 INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot);
4221 //*****************************************************************************
4222 // Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle
4223 // (Formats B1, B2 or B3)
4224 // Note that due to branch target alignment requirements
4225 // the lowest four bits are required to be zero.
4226 //*****************************************************************************
4227 void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25);
4229 //*****************************************************************************
4230 // Extract the IP-Relative signed 64-bit immediate from an IA64 bundle
4231 // (Formats X3 or X4)
4232 //*****************************************************************************
4233 INT64 GetIA64Rel64(UINT64 * pBundle);
4234 INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1);
4236 //*****************************************************************************
4237 // Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle
4238 // (Formats X3 or X4)
4239 //*****************************************************************************
4240 void PutIA64Rel64(UINT64 * pBundle, INT64 imm64);
4242 //*****************************************************************************
4243 // Extract the 32-bit immediate from movw/movt Thumb2 sequence
4244 //*****************************************************************************
4245 UINT32 GetThumb2Mov32(UINT16 * p);
4247 //*****************************************************************************
4248 // Deposit the 32-bit immediate into movw/movt Thumb2 sequence
4249 //*****************************************************************************
4250 void PutThumb2Mov32(UINT16 * p, UINT32 imm32);
4252 //*****************************************************************************
4253 // Extract the 24-bit rel offset from bl instruction
4254 //*****************************************************************************
4255 INT32 GetThumb2BlRel24(UINT16 * p);
4257 //*****************************************************************************
4258 // Extract the 24-bit rel offset from bl instruction
4259 //*****************************************************************************
4260 void PutThumb2BlRel24(UINT16 * p, INT32 imm24);
4262 //*****************************************************************************
4263 // Extract the PC-Relative offset from a b or bl instruction
4264 //*****************************************************************************
4265 INT32 GetArm64Rel28(UINT32 * pCode);
4267 //*****************************************************************************
4268 // Extract the PC-Relative page address from an adrp instruction
4269 //*****************************************************************************
4270 INT32 GetArm64Rel21(UINT32 * pCode);
4272 //*****************************************************************************
4273 // Extract the page offset from an add instruction
4274 //*****************************************************************************
4275 INT32 GetArm64Rel12(UINT32 * pCode);
4277 //*****************************************************************************
4278 // Deposit the PC-Relative offset 'imm28' into a b or bl instruction
4279 //*****************************************************************************
4280 void PutArm64Rel28(UINT32 * pCode, INT32 imm28);
4282 //*****************************************************************************
4283 // Deposit the PC-Relative page address 'imm21' into an adrp instruction
4284 //*****************************************************************************
4285 void PutArm64Rel21(UINT32 * pCode, INT32 imm21);
4287 //*****************************************************************************
4288 // Deposit the page offset 'imm12' into an add instruction
4289 //*****************************************************************************
4290 void PutArm64Rel12(UINT32 * pCode, INT32 imm12);
4292 //*****************************************************************************
4293 // Returns whether the offset fits into bl instruction
4294 //*****************************************************************************
4295 inline bool FitsInThumb2BlRel24(INT32 imm24)
4297 return ((imm24 << 7) >> 7) == imm24;
4300 //*****************************************************************************
4301 // Returns whether the offset fits into an Arm64 b or bl instruction
4302 //*****************************************************************************
4303 inline bool FitsInRel28(INT32 val32)
4305 return (val32 >= -0x08000000) && (val32 < 0x08000000);
4308 //*****************************************************************************
4309 // Returns whether the offset fits into an Arm64 adrp instruction
4310 //*****************************************************************************
4311 inline bool FitsInRel21(INT32 val32)
4313 return (val32 >= 0) && (val32 <= 0x001FFFFF);
4316 //*****************************************************************************
4317 // Returns whether the offset fits into an Arm64 add instruction
4318 //*****************************************************************************
4319 inline bool FitsInRel12(INT32 val32)
4321 return (val32 >= 0) && (val32 <= 0x00000FFF);
4324 //*****************************************************************************
4325 // Returns whether the offset fits into an Arm64 b or bl instruction
4326 //*****************************************************************************
4327 inline bool FitsInRel28(INT64 val64)
4329 return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
4332 //*****************************************************************************
4333 // Splits a command line into argc/argv lists, using the VC7 parsing rules.
4334 // This functions interface mimics the CommandLineToArgvW api.
4335 // If function fails, returns NULL.
4336 // If function suceeds, call delete [] on return pointer when done.
4337 //*****************************************************************************
4338 LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs);
4341 // TEB access can be dangerous when using fibers because a fiber may
4342 // run on multiple threads. If the TEB pointer is retrieved and saved
4343 // and then a fiber is moved to a different thread, when it accesses
4344 // the saved TEB pointer, it will be looking at the TEB state for a
4347 // These accessors serve the purpose of retrieving information from the
4348 // TEB in a manner that ensures that the current fiber will not switch
4349 // threads while the access is occuring.
4354 #if defined(FEATURE_PAL)
4356 // returns pointer that uniquely identifies the fiber
4357 static void* GetFiberPtrId()
4359 LIMITED_METHOD_CONTRACT;
4360 // not fiber for FEATURE_PAL - use the regular thread ID
4361 return (void *)(size_t)GetCurrentThreadId();
4364 static void* InvalidFiberPtrId()
4369 static void* GetStackBase()
4371 return PAL_GetStackBase();
4374 static void* GetStackLimit()
4376 return PAL_GetStackLimit();
4379 #else // !FEATURE_PAL
4381 // returns pointer that uniquely identifies the fiber
4382 static void* GetFiberPtrId()
4384 LIMITED_METHOD_CONTRACT;
4385 // stackbase is the unique fiber identifier
4386 return NtCurrentTeb()->NtTib.StackBase;
4389 static void* GetStackBase()
4391 LIMITED_METHOD_CONTRACT;
4392 return NtCurrentTeb()->NtTib.StackBase;
4395 static void* GetStackLimit()
4397 LIMITED_METHOD_CONTRACT;
4398 return NtCurrentTeb()->NtTib.StackLimit;
4401 // Please don't start to use this method unless you absolutely have to.
4402 // The reason why this is added is for WIN64 to support LEGACY PE-style TLS
4403 // variables. On X86 it is supported by the JIT compilers themselves. On
4404 // WIN64 we build more logic into the JIT helper for accessing fields.
4405 static void* GetLegacyThreadLocalStoragePointer()
4407 LIMITED_METHOD_CONTRACT;
4408 return NtCurrentTeb()->ThreadLocalStoragePointer;
4411 static void* GetOleReservedPtr()
4413 LIMITED_METHOD_CONTRACT;
4414 return NtCurrentTeb()->ReservedForOle;
4417 static void* GetProcessEnvironmentBlock()
4419 LIMITED_METHOD_CONTRACT;
4420 return NtCurrentTeb()->ProcessEnvironmentBlock;
4424 static void* InvalidFiberPtrId()
4428 #endif // !FEATURE_PAL
4431 #if !defined(DACCESS_COMPILE)
4433 // check if current thread is a GC thread (concurrent or server)
4434 inline BOOL IsGCSpecialThread ()
4436 STATIC_CONTRACT_NOTHROW;
4437 STATIC_CONTRACT_GC_NOTRIGGER;
4438 STATIC_CONTRACT_MODE_ANY;
4439 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4441 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC);
4444 // check if current thread is a Gate thread
4445 inline BOOL IsGateSpecialThread ()
4447 STATIC_CONTRACT_NOTHROW;
4448 STATIC_CONTRACT_GC_NOTRIGGER;
4449 STATIC_CONTRACT_MODE_ANY;
4451 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate);
4454 // check if current thread is a Timer thread
4455 inline BOOL IsTimerSpecialThread ()
4457 STATIC_CONTRACT_NOTHROW;
4458 STATIC_CONTRACT_GC_NOTRIGGER;
4459 STATIC_CONTRACT_MODE_ANY;
4461 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer);
4464 // check if current thread is a debugger helper thread
4465 inline BOOL IsDbgHelperSpecialThread ()
4467 STATIC_CONTRACT_NOTHROW;
4468 STATIC_CONTRACT_GC_NOTRIGGER;
4469 STATIC_CONTRACT_MODE_ANY;
4471 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper);
4474 // check if current thread is a debugger helper thread
4475 inline BOOL IsETWRundownSpecialThread ()
4477 STATIC_CONTRACT_NOTHROW;
4478 STATIC_CONTRACT_GC_NOTRIGGER;
4479 STATIC_CONTRACT_MODE_ANY;
4481 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread);
4484 // check if current thread is a generic instantiation lookup compare thread
4485 inline BOOL IsGenericInstantiationLookupCompareThread ()
4487 STATIC_CONTRACT_NOTHROW;
4488 STATIC_CONTRACT_GC_NOTRIGGER;
4489 STATIC_CONTRACT_MODE_ANY;
4491 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare);
4494 // check if current thread is a thread which is performing shutdown
4495 inline BOOL IsShutdownSpecialThread ()
4497 STATIC_CONTRACT_NOTHROW;
4498 STATIC_CONTRACT_GC_NOTRIGGER;
4499 STATIC_CONTRACT_MODE_ANY;
4501 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown);
4504 inline BOOL IsThreadPoolIOCompletionSpecialThread ()
4506 STATIC_CONTRACT_NOTHROW;
4507 STATIC_CONTRACT_GC_NOTRIGGER;
4508 STATIC_CONTRACT_MODE_ANY;
4510 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion);
4513 inline BOOL IsThreadPoolWorkerSpecialThread ()
4515 STATIC_CONTRACT_NOTHROW;
4516 STATIC_CONTRACT_GC_NOTRIGGER;
4517 STATIC_CONTRACT_MODE_ANY;
4519 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker);
4522 inline BOOL IsWaitSpecialThread ()
4524 STATIC_CONTRACT_NOTHROW;
4525 STATIC_CONTRACT_GC_NOTRIGGER;
4526 STATIC_CONTRACT_MODE_ANY;
4528 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait);
4531 // check if current thread is a thread which is performing shutdown
4532 inline BOOL IsSuspendEEThread ()
4534 STATIC_CONTRACT_NOTHROW;
4535 STATIC_CONTRACT_GC_NOTRIGGER;
4536 STATIC_CONTRACT_MODE_ANY;
4538 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE);
4541 inline BOOL IsFinalizerThread ()
4543 STATIC_CONTRACT_NOTHROW;
4544 STATIC_CONTRACT_GC_NOTRIGGER;
4545 STATIC_CONTRACT_MODE_ANY;
4547 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
4550 inline BOOL IsShutdownHelperThread ()
4552 STATIC_CONTRACT_NOTHROW;
4553 STATIC_CONTRACT_GC_NOTRIGGER;
4554 STATIC_CONTRACT_MODE_ANY;
4556 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper);
4559 inline BOOL IsProfilerAttachThread ()
4561 STATIC_CONTRACT_NOTHROW;
4562 STATIC_CONTRACT_GC_NOTRIGGER;
4563 STATIC_CONTRACT_MODE_ANY;
4565 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach);
4568 // set specical type for current thread
4569 inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag)
4571 STATIC_CONTRACT_NOTHROW;
4572 STATIC_CONTRACT_GC_NOTRIGGER;
4573 STATIC_CONTRACT_MODE_ANY;
4575 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag));
4578 // clear specical type for current thread
4579 inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
4581 STATIC_CONTRACT_NOTHROW;
4582 STATIC_CONTRACT_GC_NOTRIGGER;
4583 STATIC_CONTRACT_MODE_ANY;
4585 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag));
4588 #endif //!DACCESS_COMPILE
4590 #ifdef DACCESS_COMPILE
4591 #define SET_THREAD_TYPE_STACKWALKER(pThread)
4592 #define CLEAR_THREAD_TYPE_STACKWALKER()
4593 #else // DACCESS_COMPILE
4594 #define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread)
4595 #define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
4596 #endif // DACCESS_COMPILE
4598 HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription);
4600 inline BOOL IsStackWalkerThread()
4602 STATIC_CONTRACT_NOTHROW;
4603 STATIC_CONTRACT_GC_NOTRIGGER;
4604 STATIC_CONTRACT_MODE_ANY;
4605 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4607 #if defined(DACCESS_COMPILE)
4610 return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL;
4614 inline BOOL IsGCThread ()
4616 STATIC_CONTRACT_NOTHROW;
4617 STATIC_CONTRACT_GC_NOTRIGGER;
4618 STATIC_CONTRACT_MODE_ANY;
4619 STATIC_CONTRACT_SUPPORTS_DAC;
4621 #if !defined(DACCESS_COMPILE)
4622 return IsGCSpecialThread () || IsSuspendEEThread ();
4628 class ClrFlsThreadTypeSwitch
4631 ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag)
4633 STATIC_CONTRACT_NOTHROW;
4634 STATIC_CONTRACT_GC_NOTRIGGER;
4635 STATIC_CONTRACT_MODE_ANY;
4637 #ifndef DACCESS_COMPILE
4639 m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag);
4641 // In debug builds, remember the full group of flags that were set at the time
4642 // the constructor was called. This will be used in ASSERTs in the destructor
4643 INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType));
4645 if (!m_fPreviouslySet)
4647 ClrFlsSetThreadType(flag);
4649 #endif // DACCESS_COMPILE
4652 ~ClrFlsThreadTypeSwitch ()
4654 STATIC_CONTRACT_NOTHROW;
4655 STATIC_CONTRACT_GC_NOTRIGGER;
4656 STATIC_CONTRACT_MODE_ANY;
4658 #ifndef DACCESS_COMPILE
4659 // This holder should only be used to set (and thus restore) ONE thread type flag
4660 // at a time. If more than that one flag was modified since this holder was
4661 // instantiated, then this holder still restores only the flag it knows about. To
4662 // prevent confusion, assert if some other flag was modified, so the user doesn't
4663 // expect the holder to restore the entire original set of flags.
4665 // The expression below says that the only difference between the previous flag
4666 // group and the current flag group should be m_flag (or no difference at all, if
4667 // m_flag's state didn't actually change).
4668 _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag);
4670 if (m_fPreviouslySet)
4672 ClrFlsSetThreadType(m_flag);
4676 ClrFlsClearThreadType(m_flag);
4678 #endif // DACCESS_COMPILE
4682 TlsThreadTypeFlag m_flag;
4683 BOOL m_fPreviouslySet;
4684 INDEBUG(size_t m_nPreviousFlagGroup);
4687 class ClrFlsValueSwitch
4690 ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value)
4692 STATIC_CONTRACT_NOTHROW;
4693 STATIC_CONTRACT_GC_NOTRIGGER;
4694 STATIC_CONTRACT_MODE_ANY;
4696 #ifndef DACCESS_COMPILE
4698 m_PreviousValue = ClrFlsGetValue(slot);
4699 ClrFlsSetValue(slot, value);
4700 #endif // DACCESS_COMPILE
4703 ~ClrFlsValueSwitch ()
4705 STATIC_CONTRACT_NOTHROW;
4706 STATIC_CONTRACT_GC_NOTRIGGER;
4707 STATIC_CONTRACT_MODE_ANY;
4709 #ifndef DACCESS_COMPILE
4710 ClrFlsSetValue(m_slot, m_PreviousValue);
4711 #endif // DACCESS_COMPILE
4715 PVOID m_PreviousValue;
4716 PredefinedTlsSlots m_slot;
4719 //*********************************************************************************
4721 // When we're hosted, operations called by the host (such as Thread::YieldTask)
4722 // may not cause calls back into the host, as the host needs not be reentrant.
4723 // Use the following holder for code in which calls into the host are forbidden.
4724 // (If a call into the host is attempted nevertheless, an assert will fire.)
4726 class ForbidCallsIntoHostOnThisThread
4729 static Volatile<PVOID> s_pvOwningFiber;
4731 FORCEINLINE static BOOL Enter(BOOL)
4733 WRAPPER_NO_CONTRACT;
4734 return InterlockedCompareExchangePointer(
4735 &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL;
4738 FORCEINLINE static void Leave(BOOL)
4740 LIMITED_METHOD_CONTRACT;
4741 s_pvOwningFiber = NULL;
4745 typedef ConditionalStateHolder<BOOL, ForbidCallsIntoHostOnThisThread::Enter, ForbidCallsIntoHostOnThisThread::Leave> Holder;
4747 FORCEINLINE static BOOL CanThisThreadCallIntoHost()
4749 WRAPPER_NO_CONTRACT;
4750 return s_pvOwningFiber != ClrTeb::GetFiberPtrId();
4754 typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder;
4756 FORCEINLINE BOOL CanThisThreadCallIntoHost()
4758 WRAPPER_NO_CONTRACT;
4759 return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost();
4762 //*********************************************************************************
4764 #include "contract.inl"
4771 template < typename T >
4774 bool operator()( T const & first, T const & second ) const
4776 return first < second;
4780 template < typename T >
4783 bool operator()( T const & first, T const & second ) const
4785 return first > second;
4793 template< typename Iter, typename Pred >
4794 void sort( Iter begin, Iter end, Pred pred );
4796 template< typename T, typename Pred >
4797 void sort( T * begin, T * end, Pred pred )
4799 struct sort_helper : CQuickSort< T >
4801 sort_helper( T * begin, T * end, Pred pred )
4802 : CQuickSort< T >( begin, end - begin )
4806 virtual int Compare( T * first, T * second )
4808 return m_pred( *first, *second ) ? -1
4809 : ( m_pred( *second, *first ) ? 1 : 0 );
4815 sort_helper sort_obj( begin, end, pred );
4820 template < typename Iter >
4821 void sort( Iter begin, Iter end );
4823 template < typename T >
4824 void sort( T * begin, T * end )
4826 util::sort( begin, end, util::less< T >() );
4830 // binary search adapters
4833 template < typename Iter, typename T, typename Pred >
4834 Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred );
4836 template < typename T, typename Pred >
4837 T * lower_bound( T * begin, T * end, T const & val, Pred pred )
4839 for (; begin != end; )
4841 T * mid = begin + ( end - begin ) / 2;
4842 if ( pred( *mid, val ) )
4852 template < typename Iter, typename T >
4853 Iter lower_bound( Iter begin, Iter end, T const & val );
4855 template < typename T >
4856 T * lower_bound( T * begin, T * end, T const & val )
4858 return util::lower_bound( begin, end, val, util::less< T >() );
4863 /* ------------------------------------------------------------------------ *
4864 * Overloaded operators for the executable heap
4865 * ------------------------------------------------------------------------ */
4869 struct CExecutable { int x; };
4870 extern const CExecutable executable;
4872 void * __cdecl operator new(size_t n, const CExecutable&);
4873 void * __cdecl operator new[](size_t n, const CExecutable&);
4874 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&);
4875 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&);
4879 // Executable heap delete to match the executable heap new above.
4881 template<class T> void DeleteExecutable(T *p)
4887 ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p);
4891 #endif // FEATURE_PAL
4893 INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
4895 BOOL NoGuiOnAssert();
4897 VOID TerminateOnAssert();
4900 class HighCharHelper {
4902 static inline BOOL IsHighChar(int c) {
4903 return (BOOL)HighCharTable[c];
4907 static const BYTE HighCharTable[];
4911 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
4913 FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
4915 typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
4917 // HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical
4918 // to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address,
4919 // and so is represented by TADDR.
4921 #ifdef DACCESS_COMPILE
4922 typedef TADDR HMODULE_TGT;
4924 typedef HMODULE HMODULE_TGT;
4927 BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
4929 //----------------------------------------------------------------------------------------
4930 // The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical
4931 // callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call
4932 // InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime
4933 // calls a special initialization routine exposed by the loaded module with the callbacks,
4934 // which in turn calls InitUtilcode.
4936 // This structure collects all of the critical callback info passed in InitUtilcode().
4937 // Note that one of them is GetCLRFunction() which is itself a gofer for many other
4938 // callbacks. If a callback fetch be safely deferred until we have TLS and stack probe
4939 // functionality running, it should be added to that function rather than this structure.
4940 // Things like IEE are here because that callback has to be set up before GetCLRFunction()
4941 // can be safely called.
4942 //----------------------------------------------------------------------------------------
4943 struct CoreClrCallbacks
4945 typedef IExecutionEngine* (* pfnIEE_t)();
4946 typedef HRESULT (* pfnGetCORSystemDirectory_t)(SString& pbuffer);
4947 typedef void* (* pfnGetCLRFunction_t)(LPCSTR functionName);
4949 HINSTANCE m_hmodCoreCLR;
4951 pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory;
4952 pfnGetCLRFunction_t m_pfnGetCLRFunction;
4956 // For DAC, we include this functionality only when EH SxS is enabled.
4958 //----------------------------------------------------------------------------------------
4959 // CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback
4960 // pointers it needs.
4961 //----------------------------------------------------------------------------------------
4962 VOID InitUtilcode(const CoreClrCallbacks &cccallbacks);
4963 CoreClrCallbacks const & GetClrCallbacks();
4965 //----------------------------------------------------------------------------------------
4966 // Stuff below is for utilcode.lib eyes only.
4967 //----------------------------------------------------------------------------------------
4969 // Stores callback pointers provided by InitUtilcode().
4970 extern CoreClrCallbacks g_CoreClrCallbacks;
4972 // Throws up a helpful dialog if InitUtilcode() wasn't called.
4974 void OnUninitializedCoreClrCallbacks();
4975 #define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks()
4977 #define VALIDATECORECLRCALLBACKS()
4981 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
4983 // Corrupting Exception limited support for outside the VM folder
4984 BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
4986 #endif // FEATURE_CORRUPTING_EXCEPTIONS
4990 // These are type-safe versions of Interlocked[Compare]Exchange
4991 // They avoid invoking struct cast operations via reinterpreting
4992 // the struct's address as a LONG* or LONGLONG* and dereferencing it.
4994 // If we had a global ::operator & (unary), we would love to use that
4995 // to ensure we were not also accidentally getting a structs's provided
4996 // operator &. TODO: probe with a static_assert?
4998 template <typename T, int SIZE = sizeof(T)>
4999 struct InterlockedCompareExchangeHelper;
5001 template <typename T>
5002 struct InterlockedCompareExchangeHelper<T, sizeof(LONG)>
5004 static inline T InterlockedExchange(
5005 T volatile * target,
5008 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5009 LONG res = ::InterlockedExchange(
5010 reinterpret_cast<LONG volatile *>(target),
5011 *reinterpret_cast<LONG *>(/*::operator*/&(value)));
5012 return *reinterpret_cast<T*>(&res);
5015 static inline T InterlockedCompareExchange(
5016 T volatile * destination,
5020 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5021 LONG res = ::InterlockedCompareExchange(
5022 reinterpret_cast<LONG volatile *>(destination),
5023 *reinterpret_cast<LONG*>(/*::operator*/&(exchange)),
5024 *reinterpret_cast<LONG*>(/*::operator*/&(comparand)));
5025 return *reinterpret_cast<T*>(&res);
5029 template <typename T>
5030 struct InterlockedCompareExchangeHelper<T, sizeof(LONGLONG)>
5032 static inline T InterlockedExchange(
5033 T volatile * target,
5036 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5037 LONGLONG res = ::InterlockedExchange64(
5038 reinterpret_cast<LONGLONG volatile *>(target),
5039 *reinterpret_cast<LONGLONG *>(/*::operator*/&(value)));
5040 return *reinterpret_cast<T*>(&res);
5043 static inline T InterlockedCompareExchange(
5044 T volatile * destination,
5048 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5049 LONGLONG res = ::InterlockedCompareExchange64(
5050 reinterpret_cast<LONGLONG volatile *>(destination),
5051 *reinterpret_cast<LONGLONG*>(/*::operator*/&(exchange)),
5052 *reinterpret_cast<LONGLONG*>(/*::operator*/&(comparand)));
5053 return *reinterpret_cast<T*>(&res);
5058 template <typename T>
5059 inline T InterlockedExchangeT(
5060 T volatile * target,
5063 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedExchange(
5067 template <typename T>
5068 inline T InterlockedCompareExchangeT(
5069 T volatile * destination,
5073 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedCompareExchange(
5074 destination, exchange, comparand);
5077 // Pointer variants for Interlocked[Compare]ExchangePointer
5078 // If the underlying type is a const type, we have to remove its constness
5079 // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments.
5080 template <typename T>
5081 inline T* InterlockedExchangeT(
5082 T* volatile * target,
5085 //STATIC_ASSERT(value == 0);
5086 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5087 return reinterpret_cast<T*>(InterlockedExchangePointer(
5088 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(target)),
5089 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(value))));
5092 template <typename T>
5093 inline T* InterlockedCompareExchangeT(
5094 T* volatile * destination,
5098 //STATIC_ASSERT(exchange == 0);
5099 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5100 return reinterpret_cast<T*>(InterlockedCompareExchangePointer(
5101 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(destination)),
5102 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(exchange)),
5103 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(comparand))));
5106 // NULL pointer variants of the above to avoid having to cast NULL
5107 // to the appropriate pointer type.
5108 template <typename T>
5109 inline T* InterlockedExchangeT(
5110 T* volatile * target,
5111 int value) // When NULL is provided as argument.
5113 //STATIC_ASSERT(value == 0);
5114 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5117 template <typename T>
5118 inline T* InterlockedCompareExchangeT(
5119 T* volatile * destination,
5120 int exchange, // When NULL is provided as argument.
5123 //STATIC_ASSERT(exchange == 0);
5124 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5127 template <typename T>
5128 inline T* InterlockedCompareExchangeT(
5129 T* volatile * destination,
5131 int comparand) // When NULL is provided as argument.
5133 //STATIC_ASSERT(comparand == 0);
5134 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5137 // NULL pointer variants of the above to avoid having to cast NULL
5138 // to the appropriate pointer type.
5139 template <typename T>
5140 inline T* InterlockedExchangeT(
5141 T* volatile * target,
5142 std::nullptr_t value) // When nullptr is provided as argument.
5144 //STATIC_ASSERT(value == 0);
5145 return InterlockedExchangeT(target, static_cast<T*>(value));
5148 template <typename T>
5149 inline T* InterlockedCompareExchangeT(
5150 T* volatile * destination,
5151 std::nullptr_t exchange, // When nullptr is provided as argument.
5154 //STATIC_ASSERT(exchange == 0);
5155 return InterlockedCompareExchangeT(destination, static_cast<T*>(exchange), comparand);
5158 template <typename T>
5159 inline T* InterlockedCompareExchangeT(
5160 T* volatile * destination,
5162 std::nullptr_t comparand) // When nullptr is provided as argument.
5164 //STATIC_ASSERT(comparand == 0);
5165 return InterlockedCompareExchangeT(destination, exchange, static_cast<T*>(comparand));
5168 #undef InterlockedExchangePointer
5169 #define InterlockedExchangePointer Use_InterlockedExchangeT
5170 #undef InterlockedCompareExchangePointer
5171 #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT
5173 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
5174 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
5175 HRESULT GetHModuleDirectory(HMODULE hMod, SString& wszPath);
5176 HRESULT CopySystemDirectory(const SString& pPathString, SString& pbuffer);
5178 HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true);
5179 // This is a slight variation that can be used for anything else
5180 typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR);
5181 void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL);
5185 // Helper to support termination due to heap corruption
5186 // It's not supported on Win2K, so we have to manually delay load it
5187 void EnableTerminationOnHeapCorruption();
5191 namespace Clr { namespace Util
5193 // This api returns a pointer to a null-terminated string that contains the local appdata directory
5194 // or it returns NULL in the case that the directory could not be found. The return value from this function
5195 // is not actually checked for existence.
5196 HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory);
5197 HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory);
5201 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
5202 __success(return == S_OK)
5203 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
5206 #ifdef FEATURE_COMINTEROP
5209 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name);
5211 #endif // FEATURE_COMINTEROP
5215 static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\");
5216 static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\";
5218 void GetModuleFileName(
5220 SString & ssFileName,
5221 bool fAllowLongFileNames = false);
5223 __success(return == S_OK)
5224 HRESULT GetModuleFileName(
5226 __deref_out_z LPWSTR * pwszFileName,
5227 bool fAllowLongFileNames = false);
5229 void GetFullPathName(
5230 SString const & ssFileName,
5231 SString & ssPathName,
5232 DWORD * pdwFilePartIdx,
5233 bool fAllowLongFileNames = false);
5238 #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE)
5239 // Forward declaration of AppX::IsAppXProcess
5240 namespace AppX { bool IsAppXProcess(); }
5242 // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes.
5243 inline DWORD GetLoadWithAlteredSearchPathFlag()
5245 WRAPPER_NO_CONTRACT;
5246 return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
5248 #else // FEATURE_APPX && !DACCESS_COMPILE
5249 // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally.
5250 inline DWORD GetLoadWithAlteredSearchPathFlag()
5252 LIMITED_METHOD_CONTRACT;
5253 #ifdef LOAD_WITH_ALTERED_SEARCH_PATH
5254 return LOAD_WITH_ALTERED_SEARCH_PATH;
5259 #endif // FEATURE_APPX && !DACCESS_COMPILE
5261 // clr::SafeAddRef and clr::SafeRelease helpers.
5264 //=================================================================================================================
5265 template <typename ItfT>
5267 typename std::enable_if< std::is_pointer<ItfT>::value, ItfT >::type
5268 SafeAddRef(ItfT pItf)
5270 STATIC_CONTRACT_LIMITED_METHOD;
5271 if (pItf != nullptr)
5278 //=================================================================================================================
5279 template <typename ItfT>
5280 typename std::enable_if< std::is_pointer<ItfT>::value && std::is_reference<ItfT>::value, ULONG >::type
5281 SafeRelease(ItfT pItf)
5283 STATIC_CONTRACT_LIMITED_METHOD;
5285 if (pItf != nullptr)
5287 res = pItf->Release();
5293 //=================================================================================================================
5294 template <typename ItfT>
5295 typename std::enable_if< std::is_pointer<ItfT>::value && !std::is_reference<ItfT>::value, ULONG >::type
5296 SafeRelease(ItfT pItf)
5298 STATIC_CONTRACT_LIMITED_METHOD;
5300 if (pItf != nullptr)
5302 res = pItf->Release();
5311 //=================================================================================================================
5312 template <typename PtrT>
5314 typename std::enable_if< std::is_pointer<PtrT>::value, PtrT >::type
5315 SafeDelete(PtrT & ptr)
5317 STATIC_CONTRACT_LIMITED_METHOD;
5326 // ======================================================================================
5327 // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp)
5329 struct SpinConstants
5331 DWORD dwInitialDuration;
5332 DWORD dwMaximumDuration;
5333 DWORD dwBackoffFactor;
5334 DWORD dwRepetitions;
5335 DWORD dwMonitorSpinCount;
5338 extern SpinConstants g_SpinConstants;
5340 // ======================================================================================
5342 void* GetCLRFunction(LPCSTR FunctionName);
5344 #endif // __UtilCode_h__