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"
45 // Values for the names of Watson
46 const WCHAR kWatsonName1[] = W("drwatson");
47 const WCHAR kWatsonName2[] = W("drwtsn32");
51 #define WINDOWS_KERNEL32_DLLNAME_A "kernel32"
52 #define WINDOWS_KERNEL32_DLLNAME_W W("kernel32")
54 #define CoreLibName_W W("System.Private.CoreLib")
55 #define CoreLibName_IL_W W("System.Private.CoreLib.dll")
56 #define CoreLibName_NI_W W("System.Private.CoreLib.ni.dll")
57 #define CoreLibName_TLB_W W("System.Private.CoreLib.tlb")
58 #define CoreLibName_A "System.Private.CoreLib"
59 #define CoreLibName_IL_A "System.Private.CoreLib.dll"
60 #define CoreLibName_NI_A "System.Private.CoreLib.ni.dll"
61 #define CoreLibName_TLB_A "System.Private.CoreLib.tlb"
62 #define CoreLibNameLen 22
63 #define CoreLibSatelliteName_A "System.Private.CoreLib.resources"
64 #define CoreLibSatelliteNameLen 32
65 #define LegacyCoreLibName_A "mscorlib"
67 class StringArrayList;
69 #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
75 // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct
76 // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this
77 // is handled automatically for us by the compiler. When generating and working with code generated
78 // dynamically we have to be careful to set or mask-out this bit as appropriate.
83 // Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff).
84 inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit)
86 _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit));
87 return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1);
90 // Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the
92 inline bool Is32BitInstruction(WORD opcode)
94 return BitExtract(opcode, 15, 11) >= 0x1d;
97 template <typename ResultType, typename SourceType>
98 inline ResultType DataPointerToThumbCode(SourceType pCode)
100 return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE);
103 template <typename ResultType, typename SourceType>
104 inline ResultType ThumbCodeToDataPointer(SourceType pCode)
106 return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE);
109 #endif // _TARGET_ARM_
111 // Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function;
112 // on ARM, this will mask off the THUMB bit.
113 inline TADDR PCODEToPINSTR(PCODE pc)
116 return ThumbCodeToDataPointer<TADDR,PCODE>(pc);
118 return dac_cast<PCODE>(pc);
122 // Convert from a PINSTR to the corresponding PCODE. On many architectures this will be the identity function;
123 // on ARM, this will raise the THUMB bit.
124 inline PCODE PINSTRToPCODE(TADDR addr)
127 return DataPointerToThumbCode<PCODE,TADDR>(addr);
129 return dac_cast<PCODE>(addr);
133 typedef LPCSTR LPCUTF8;
134 typedef LPSTR LPUTF8;
136 #include "nsutilpriv.h"
138 #include "stdmacros.h"
151 //********** Macros. **********************************************************
154 #define FORCEINLINE inline
156 #define FORCEINLINE __forceinline
160 #ifndef DEBUG_NOINLINE
162 #define DEBUG_NOINLINE __declspec(noinline)
164 #define DEBUG_NOINLINE
168 #ifndef DBG_NOINLINE_X86__RET_INLINE
169 #if defined(_DEBUG) && defined(_TARGET_X86_)
170 // this exists to make scan work on x86.
171 #define DBG_NOINLINE_X86__RET_INLINE __declspec(noinline)
173 #define DBG_NOINLINE_X86__RET_INLINE FORCEINLINE
177 #include <stddef.h> // for offsetof
180 // Number of elements in a fixed-size array
181 #define NumItems(s) (sizeof(s) / sizeof(s[0]))
185 // Number of characters in a string literal. Excludes terminating NULL.
186 #define StrLen(str) (NumItems(str) - 1)
190 #define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9')))
191 #define DIGIT_TO_INT(ch) (ch - W('0'))
192 #define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i))
194 #define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \
195 ((ch >= W('A')) && (ch <= W('F'))))
196 #define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10)
197 #define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10)))
200 // Helper will 4 byte align a value, rounding up.
201 #define ALIGN4BYTE(val) (((val) + 3) & ~0x3)
204 #define DEBUGARG(x) , x
210 // Returns the size of a class or struct member.
211 #define sizeofmember(c,m) (sizeof(((c*)0)->m))
214 //=--------------------------------------------------------------------------=
218 #include "safemath.h"
221 //=--------------------------------------------------------------------------=
225 // given and ANSI String, copy it into a wide buffer.
226 // be careful about scoping when using this macro!
228 // how to use the below two macros:
232 // pszA = MyGetAnsiStringRoutine();
233 // MAKE_WIDEPTR_FROMANSI(pwsz, pszA);
234 // MyUseWideStringRoutine(pwsz);
237 // similarily for MAKE_ANSIPTR_FROMWIDE. note that the first param does not
238 // have to be declared, and no clean up must be done.
241 // We'll define an upper limit that allows multiplication by 4 (the max
242 // bytes/char in UTF-8) but still remains positive, and allows some room for pad.
243 // Under normal circumstances, we should never get anywhere near this limit.
244 #define MAKE_MAX_LENGTH 0x1fffff00
246 #ifndef MAKE_TOOLONGACTION
247 #define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW)
250 #ifndef MAKE_TRANSLATIONFAILED
251 #define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION)
254 // This version throws on conversion errors (ie, no best fit character
255 // mapping to characters that look similar, and no use of the default char
256 // ('?') when printing out unrepresentable characters. Use this method for
257 // most development in the EE, especially anything like metadata or class
258 // names. See the BESTFIT version if you're printing out info to the console.
259 #define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \
260 int __l##ptrname = (int)wcslen(widestr); \
261 if (__l##ptrname > MAKE_MAX_LENGTH) \
262 MAKE_TOOLONGACTION; \
263 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
264 CQuickBytes __CQuickBytes##ptrname; \
265 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
267 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \
268 if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \
269 MAKE_TRANSLATIONFAILED; \
271 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
273 // This version does best fit character mapping and also allows the use
274 // of the default char ('?') for any Unicode character that isn't
275 // representable. This is reasonable for writing to the console, but
276 // shouldn't be used for most string conversions.
277 #define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \
278 int __l##ptrname = (int)wcslen(widestr); \
279 if (__l##ptrname > MAKE_MAX_LENGTH) \
280 MAKE_TOOLONGACTION; \
281 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
282 CQuickBytes __CQuickBytes##ptrname; \
283 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
284 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \
285 if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \
286 MAKE_TRANSLATIONFAILED; \
288 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
290 // Use for anything critical other than output to console, where weird
291 // character mappings are unacceptable.
292 #define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP)
294 // Use for output to the console.
295 #define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP)
297 #define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \
298 CQuickBytes __qb##ptrname; \
300 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
301 if (__l##ptrname > MAKE_MAX_LENGTH) \
302 MAKE_TOOLONGACTION; \
303 LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
304 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \
305 MAKE_TRANSLATIONFAILED; \
308 #define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \
309 CQuickBytes __qb##ptrname; \
310 LPWSTR ptrname = 0; \
312 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
313 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
314 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
316 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \
317 ptrname[__l##ptrname] = 0; \
324 #define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr();
326 #define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \
327 CQuickBytes __qb##ptrname; \
328 int __l##ptrname = (int)wcslen(widestr); \
329 LPUTF8 ptrname = 0; \
330 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
331 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
332 ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \
335 INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \
336 DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \
337 if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \
338 if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \
339 INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \
340 ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \
342 if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \
343 ptrname[__l##ptrname] = 0; \
355 #define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \
356 CQuickBytes __qb##ptrname; \
358 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
359 if (__l##ptrname > MAKE_MAX_LENGTH) \
360 MAKE_TOOLONGACTION; \
361 LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
362 if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \
363 MAKE_TRANSLATIONFAILED; \
365 ptrname[__l##ptrname] = 0;
368 #define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname; _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr();
371 #define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \
372 CQuickBytes __qb##ptrname; \
374 LPWSTR ptrname = 0; \
375 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
376 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
377 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
379 if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \
380 ptrname[__l##ptrname] = 0; \
387 #define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str) MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1)
389 // This method takes the number of characters
390 #define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage) \
391 CQuickBytes __qb##ptrname; \
393 __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL); \
394 if (__l##ptrname > MAKE_MAX_LENGTH) \
395 MAKE_TOOLONGACTION; \
396 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
398 DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname); \
399 if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \
400 MAKE_TRANSLATIONFAILED; \
402 ptrname[__l##ptrname] = 0;
404 #define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage) \
405 CQuickBytes __qb##ptrname; \
407 __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL); \
408 if (__l##ptrname > MAKE_MAX_LENGTH) \
409 MAKE_TOOLONGACTION; \
410 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
411 DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL); \
412 if (_pCnt == 0 && _nCharacters > 0) { \
413 MAKE_TRANSLATIONFAILED; \
415 ptrname[__l##ptrname] = 0;
417 #define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt) \
418 MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP)
422 LPWSTR DuplicateString(
426 STATIC_CONTRACT_NOTHROW;
428 LPWSTR wszDup = NULL;
429 if (wszString != NULL)
431 wszDup = new (nothrow) WCHAR[cchString + 1];
434 wcscpy_s(wszDup, cchString + 1, wszString);
441 LPWSTR DuplicateString(
444 STATIC_CONTRACT_NOTHROW;
446 if (wszString != NULL)
448 return DuplicateString(wszString, wcslen(wszString));
456 void DECLSPEC_NORETURN ThrowOutOfMemory();
459 LPWSTR DuplicateStringThrowing(
463 STATIC_CONTRACT_THROWS;
465 if (wszString == NULL)
468 LPWSTR wszDup = DuplicateString(wszString, cchString);
476 LPWSTR DuplicateStringThrowing(
479 STATIC_CONTRACT_THROWS;
481 if (wszString == NULL)
484 LPWSTR wszDup = DuplicateString(wszString);
492 //*****************************************************************************
493 // Placement new is used to new and object at an exact location. The pointer
494 // is simply returned to the caller without actually using the heap. The
495 // advantage here is that you cause the ctor() code for the object to be run.
496 // This is ideal for heaps of C++ objects that need to get init'd multiple times.
498 // void *pMem = GetMemFromSomePlace();
499 // Foo *p = new (pMem) Foo;
502 //*****************************************************************************
503 #ifndef __PLACEMENT_NEW_INLINE
504 #define __PLACEMENT_NEW_INLINE
505 inline void *__cdecl operator new(size_t, void *_P)
507 LIMITED_METHOD_DAC_CONTRACT;
511 #endif // __PLACEMENT_NEW_INLINE
514 /********************************************************************************/
515 /* portability helpers */
517 #define IN_WIN64(x) x
521 #define IN_WIN32(x) x
525 operator new(size_t n);
527 _Ret_bytecap_(n) void * __cdecl
528 operator new[](size_t n);
531 operator delete(void *p) NOEXCEPT;
534 operator delete[](void *p) NOEXCEPT;
537 HRESULT _OutOfMemory(LPCSTR szFile, int iLine);
538 #define OutOfMemory() _OutOfMemory(__FILE__, __LINE__)
540 inline HRESULT OutOfMemory()
542 LIMITED_METHOD_CONTRACT;
543 return (E_OUTOFMEMORY);
547 //*****************************************************************************
548 // Handle accessing localizable resource strings
549 //*****************************************************************************
550 // NOTE: Should use locale names as much as possible. LCIDs don't support
551 // custom cultures on Vista+.
552 // TODO: This should always use the names
553 #ifdef FEATURE_USE_LCID
554 typedef LCID LocaleID;
555 typedef LCID LocaleIDValue;
557 typedef LPCWSTR LocaleID;
558 typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH];
561 // Notes about the culture callbacks:
562 // - The language we're operating in can change at *runtime*!
563 // - A process may operate in *multiple* languages.
564 // (ex: Each thread may have it's own language)
565 // - If we don't care what language we're in (or have no way of knowing),
566 // then return a 0-length name and UICULTUREID_DONTCARE for the culture ID.
567 // - GetCultureName() and the GetCultureId() must be in sync (refer to the
569 // - We have two functions separate functions for better performance.
570 // - The name is used to resolve a directory for MsCorRC.dll.
571 // - The id is used as a key to map to a dll hinstance.
573 // Callback to obtain both the culture name and the culture's parent culture name
574 typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames);
575 #ifdef FEATURE_USE_LCID
576 // Callback to return the culture ID.
577 const LCID UICULTUREID_DONTCARE = (LCID)-1;
579 const LPCWSTR UICULTUREID_DONTCARE = NULL;
582 typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*);
584 HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName);
586 HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
588 BOOL CLRFreeLibrary(HMODULE hModule);
590 // Prevent people from using LoadStringRC & LoadStringRCEx from inside the product since it
591 // causes issues with having the wrong version picked up inside the shim.
592 #define LoadStringRC __error("From inside the CLR, use UtilLoadStringRC; LoadStringRC is only meant to be exported.")
593 #define LoadStringRCEx __error("From inside the CLR, use UtilLoadStringRCEx; LoadStringRC is only meant to be exported.")
595 // Load a string using the resources for the current module.
596 STDAPI UtilLoadStringRC(UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE);
598 #if defined(ENABLE_DOWNLEVEL_FOR_NLS) || defined(FEATURE_USE_LCID)
599 STDAPI UtilLoadStringRCEx(LCID lcid, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed);
602 // Specify callbacks so that UtilLoadStringRC can find out which language we're in.
603 // If no callbacks specified (or both parameters are NULL), we default to the
604 // resource dll in the root (which is probably english).
605 void SetResourceCultureCallbacks(
606 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
607 FPGETTHREADUICULTUREID fpGetThreadUICultureId
610 void GetResourceCultureCallbacks(
611 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
612 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
615 #if !defined(DACCESS_COMPILE)
616 // Get the MUI ID, on downlevel platforms where MUI is not supported it
617 // returns the default system ID.
618 extern int GetMUILanguageID(LocaleIDValue* pResult);
619 extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames);
621 #endif // !defined(DACCESS_COMPILE)
623 //*****************************************************************************
624 // Use this class by privately deriving from noncopyable to disallow copying of
626 //*****************************************************************************
636 noncopyable(const noncopyable&);
637 const noncopyable& operator=(const noncopyable&);
640 //*****************************************************************************
641 // Must associate each handle to an instance of a resource dll with the int
642 // that it represents
643 //*****************************************************************************
644 typedef HINSTANCE HRESOURCEDLL;
647 class CCulturedHInstance
649 LocaleIDValue m_LangId;
650 HRESOURCEDLL m_hInst;
656 LIMITED_METHOD_CONTRACT;
661 BOOL HasID(LocaleID id)
663 _ASSERTE(m_hInst != NULL || m_fMissing);
664 if (id == UICULTUREID_DONTCARE)
667 #ifdef FEATURE_USE_LCID
668 return id == m_LangId;
670 return wcscmp(id, m_LangId) == 0;
674 HRESOURCEDLL GetLibraryHandle()
681 return m_hInst != NULL;
689 void SetMissing(LocaleID id)
691 _ASSERTE(m_hInst == NULL);
696 void Set(LocaleID id, HRESOURCEDLL hInst)
698 _ASSERTE(m_hInst == NULL);
699 _ASSERTE(m_fMissing == FALSE);
704 void SetId(LocaleID id)
706 #ifdef FEATURE_USE_LCID
709 if (id != UICULTUREID_DONTCARE)
711 wcsncpy_s(m_LangId, NumItems(m_LangId), id, NumItems(m_LangId));
712 m_LangId[NumItems(m_LangId)-1] = W('\0');
716 m_LangId[0] = W('\0');
722 #ifndef DACCESS_COMPILE
723 void AddThreadPreferredUILanguages(StringArrayList* pArray);
725 //*****************************************************************************
726 // CCompRC manages string Resource access for COM+. This includes loading
727 // the MsCorRC.dll for resources as well allowing each thread to use a
728 // a different localized version.
729 //*****************************************************************************
734 enum ResourceCategory
739 // present in Desktop CLR and Core CLR + debug pack, an error
740 // If missing, get a generic error message instead
743 // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing)
744 // if missing, get a generic "resource not found" message instead
747 // present in Desktop CLR, optional for CoreCLR
750 // might not be present, non essential
756 // This constructor will be fired up on startup. Make sure it doesn't
757 // do anything besides zero-out out values.
758 m_bUseFallback = FALSE;
760 m_fpGetThreadUICultureId = NULL;
761 m_fpGetThreadUICultureNames = NULL;
767 m_pResourceFile = NULL;
769 m_pResourceDomain = NULL;
770 #endif // FEATURE_PAL
774 HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE);
777 BOOL ShouldUseFallback()
779 LIMITED_METHOD_CONTRACT;
780 return m_bUseFallback;
783 static void SetIsMscoree() {s_bIsMscoree = TRUE;}
785 HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL);
786 HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed);
788 void SetResourceCultureCallbacks(
789 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
790 FPGETTHREADUICULTUREID fpGetThreadUICultureId
793 void GetResourceCultureCallbacks(
794 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
795 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
798 HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst);
800 // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR)
801 static CCompRC* GetDefaultResourceDll();
802 // Get the generic messages dll (Silverlight only, mscorrc.dll)
803 static CCompRC* GetFallbackResourceDll();
804 static void ShutdownDefaultResourceDll();
805 static void GetDefaultCallbacks(
806 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
807 FPGETTHREADUICULTUREID* fpGetThreadUICultureId)
810 m_DefaultResourceDll.GetResourceCultureCallbacks(
811 fpGetThreadUICultureNames,
812 fpGetThreadUICultureId);
815 static void SetDefaultCallbacks(
816 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
817 FPGETTHREADUICULTUREID fpGetThreadUICultureId)
820 // Either both are NULL or neither are NULL
821 _ASSERTE((fpGetThreadUICultureNames != NULL) ==
822 (fpGetThreadUICultureId != NULL));
824 m_DefaultResourceDll.SetResourceCultureCallbacks(
825 fpGetThreadUICultureNames,
826 fpGetThreadUICultureId);
828 m_FallbackResourceDll.SetResourceCultureCallbacks(
829 fpGetThreadUICultureNames,
830 fpGetThreadUICultureId);
834 #ifdef USE_FORMATMESSAGE_WRAPPER
842 IN DWORD dwMessageId,
843 IN DWORD dwLanguageId,
846 IN va_list *Arguments);
847 #endif // USE_FORMATMESSAGE_WRAPPER
851 HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst);
852 #ifndef DACCESS_COMPILE
853 HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst,
855 HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst);
856 HRESULT LoadLibrary(HRESOURCEDLL * pHInst);
857 HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName);
860 // We do not have global constructors any more
861 static LONG m_dwDefaultInitialized;
862 static CCompRC m_DefaultResourceDll;
863 static LPCWSTR m_pDefaultResource;
865 // fallback resources if debug pack is not installed
866 static LONG m_dwFallbackInitialized;
867 static CCompRC m_FallbackResourceDll;
868 static LPCWSTR m_pFallbackResource;
870 // We must map between a thread's int and a dll instance.
871 // Since we only expect 1 language almost all of the time, we'll special case
872 // that and then use a variable size map for everything else.
873 CCulturedHInstance m_Primary;
874 CCulturedHInstance * m_pHash;
877 CRITSEC_COOKIE m_csMap;
879 LPCWSTR m_pResourceFile;
881 // Resource domain is an ANSI string identifying a native resources file
882 static LPCSTR m_pDefaultResourceDomain;
883 static LPCSTR m_pFallbackResourceDomain;
884 LPCSTR m_pResourceDomain;
885 #endif // FEATURE_PAL
887 // Main accessors for hash
888 HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing);
889 HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE);
891 FPGETTHREADUICULTUREID m_fpGetThreadUICultureId;
892 FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames;
895 static BOOL s_bIsMscoree;
898 HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax);
902 HWND hWnd, // Handle to Owner Window
903 UINT uText, // Resource Identifier for Text message
904 UINT uCaption, // Resource Identifier for Caption
905 UINT uType, // Style of MessageBox
906 BOOL displayForNonInteractive, // Display even if the process is running non interactive
907 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
908 ...); // Additional Arguments
910 int UtilMessageBoxNonLocalized(
911 HWND hWnd, // Handle to Owner Window
912 LPCWSTR lpText, // Resource Identifier for Text message
913 LPCWSTR lpTitle, // Resource Identifier for Caption
914 UINT uType, // Style of MessageBox
915 BOOL displayForNonInteractive, // Display even if the process is running non interactive
916 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
917 ...); // Additional Arguments
919 int UtilMessageBoxVA(
920 HWND hWnd, // Handle to Owner Window
921 UINT uText, // Resource Identifier for Text message
922 UINT uCaption, // Resource Identifier for Caption
923 UINT uType, // Style of MessageBox
924 BOOL displayForNonInteractive, // Display even if the process is running non interactive
925 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
926 va_list args); // Additional Arguments
928 int UtilMessageBoxNonLocalizedVA(
929 HWND hWnd, // Handle to Owner Window
930 LPCWSTR lpText, // Text message
931 LPCWSTR lpCaption, // Caption
932 UINT uType, // Style of MessageBox
933 BOOL displayForNonInteractive, // Display even if the process is running non interactive
934 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
935 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
936 va_list args); // Additional Arguments
938 int UtilMessageBoxNonLocalizedVA(
939 HWND hWnd, // Handle to Owner Window
940 LPCWSTR lpText, // Text message
941 LPCWSTR lpCaption, // Caption
942 LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher).
943 UINT uType, // Style of MessageBox
944 BOOL displayForNonInteractive, // Display even if the process is running non interactive
945 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
946 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
947 va_list args); // Additional Arguments
949 int UtilMessageBoxCatastrophic(
950 UINT uText, // Text for MessageBox
951 UINT uTitle, // Title for MessageBox
952 UINT uType, // Style of MessageBox
953 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
956 int UtilMessageBoxCatastrophicNonLocalized(
957 LPCWSTR lpText, // Text for MessageBox
958 LPCWSTR lpTitle, // Title for MessageBox
959 UINT uType, // Style of MessageBox
960 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
963 int UtilMessageBoxCatastrophicVA(
964 UINT uText, // Text for MessageBox
965 UINT uTitle, // Title for MessageBox
966 UINT uType, // Style of MessageBox
967 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
968 va_list args); // Additional Arguments
970 int UtilMessageBoxCatastrophicNonLocalizedVA(
971 LPCWSTR lpText, // Text for MessageBox
972 LPCWSTR lpTitle, // Title for MessageBox
973 UINT uType, // Style of MessageBox
974 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
975 va_list args); // Additional Arguments
978 // The HRESULT_FROM_WIN32 macro evaluates its arguments three times.
979 // <TODO>TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to
980 // this helper function avoid code bloat</TODO>
981 inline HRESULT HRESULT_FROM_GetLastError()
984 DWORD dw = GetLastError();
985 // Make sure we return a failure
986 if (dw == ERROR_SUCCESS)
988 _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!");
992 return HRESULT_FROM_WIN32(dw);
995 inline HRESULT HRESULT_FROM_GetLastErrorNA()
998 DWORD dw = GetLastError();
999 // Make sure we return a failure
1000 if (dw == ERROR_SUCCESS)
1003 return HRESULT_FROM_WIN32(dw);
1006 inline HRESULT BadError(HRESULT hr)
1008 LIMITED_METHOD_CONTRACT;
1009 _ASSERTE(!"Serious Error");
1013 #define TESTANDRETURN(test, hrVal) \
1015 int ___test = (int)(test); \
1020 #define TESTANDRETURNPOINTER(pointer) \
1021 TESTANDRETURN(pointer!=NULL, E_POINTER)
1023 #define TESTANDRETURNMEMORY(pointer) \
1024 TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY)
1026 #define TESTANDRETURNHR(hr) \
1027 TESTANDRETURN(SUCCEEDED(hr), hr)
1029 #define TESTANDRETURNARG(argtest) \
1030 TESTANDRETURN(argtest, E_INVALIDARG)
1032 // Quick validity check for HANDLEs that are returned by Win32 APIs that
1033 // use INVALID_HANDLE_VALUE instead of NULL to indicate an error
1034 inline BOOL IsValidHandle(HANDLE h)
1036 LIMITED_METHOD_CONTRACT;
1037 return ((h != NULL) && (h != INVALID_HANDLE_VALUE));
1040 // Count the bits in a value in order iBits time.
1041 inline int CountBits(int iNum)
1043 LIMITED_METHOD_CONTRACT;
1045 for (iBits=0; iNum; iBits++)
1046 iNum = iNum & (iNum - 1);
1050 #include "bitposition.h"
1052 // Used to remove trailing zeros from Decimal types.
1053 // NOTE: Assumes hi32 bits are empty (used for conversions from Cy->Dec)
1054 inline HRESULT DecimalCanonicalize(DECIMAL* dec)
1056 WRAPPER_NO_CONTRACT;
1058 // Clear the VARENUM field
1059 (*(USHORT*)dec) = 0;
1061 // Remove trailing zeros:
1064 temp = templast = *dec;
1066 // Ensure the hi 32 bits are empty (should be if we came from a currency)
1067 if ((DECIMAL_HI32(temp) != 0) || (DECIMAL_SCALE(temp) > 4))
1068 return DISP_E_OVERFLOW;
1070 // Return immediately if dec represents a zero.
1071 if (DECIMAL_LO32(temp) == 0 && DECIMAL_MID32(temp) == 0)
1074 // Compare to the original to see if we've
1075 // lost non-zero digits (and make sure we don't overflow the scale BYTE)
1078 #pragma warning(push)
1079 #pragma warning(disable:6219) // "Suppress PREFast warning about Implicit cast between semantically different integer types"
1081 while ((DECIMAL_SCALE(temp) <= 4) && (VARCMP_EQ == VarDecCmp(dec, &temp)))
1085 #pragma warning(pop)
1089 // Remove the last digit and normalize. Ignore temp.Hi32
1090 // as Currency values will have a max of 64 bits of data.
1091 DECIMAL_SCALE(temp)--;
1092 UINT64 temp64 = (((UINT64) DECIMAL_MID32(temp)) << 32) + DECIMAL_LO32(temp);
1095 DECIMAL_MID32(temp) = (ULONG)(temp64 >> 32);
1096 DECIMAL_LO32(temp) = (ULONG)temp64;
1103 //*****************************************************************************
1105 // Paths functions. Use these instead of the CRT.
1107 //*****************************************************************************
1108 // secure version! Specify the size of the each buffer in count of elements
1109 void SplitPath(register const WCHAR *path,
1110 __inout_z __inout_ecount_opt(driveSizeInWords) WCHAR *drive, int driveSizeInWords,
1111 __inout_z __inout_ecount_opt(dirSizeInWords) WCHAR *dir, int dirSizeInWords,
1112 __inout_z __inout_ecount_opt(fnameSizeInWords) WCHAR *fname, size_t fnameSizeInWords,
1113 __inout_z __inout_ecount_opt(extSizeInWords) WCHAR *ext, size_t extSizeInWords);
1115 //*******************************************************************************
1116 // A much more sensible version that just points to each section of the string.
1117 //*******************************************************************************
1118 void SplitPathInterior(
1119 __in LPCWSTR wszPath,
1120 __out_opt LPCWSTR *pwszDrive, __out_opt size_t *pcchDrive,
1121 __out_opt LPCWSTR *pwszDir, __out_opt size_t *pcchDir,
1122 __out_opt LPCWSTR *pwszFileName, __out_opt size_t *pcchFileName,
1123 __out_opt LPCWSTR *pwszExt, __out_opt size_t *pcchExt);
1126 void MakePath(__out CQuickWSTR &path,
1132 WCHAR * FullPath(__out_ecount (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen);
1134 //*****************************************************************************
1136 // SString version of the path functions.
1138 //*****************************************************************************
1139 void SplitPath(__in SString const &path,
1140 __inout_opt SString *drive,
1141 __inout_opt SString *dir,
1142 __inout_opt SString *fname,
1143 __inout_opt SString *ext);
1145 #if !defined(NO_CLRCONFIG)
1147 //*****************************************************************************
1149 // **** REGUTIL - Static helper functions for reading/writing to Windows registry.
1151 //*****************************************************************************
1157 //*****************************************************************************
1161 COR_CONFIG_ENV = 0x01,
1162 COR_CONFIG_USER = 0x02,
1163 COR_CONFIG_MACHINE = 0x04,
1164 COR_CONFIG_FUSION = 0x08,
1166 COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION),
1167 COR_CONFIG_ALL = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE),
1171 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1172 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1174 static DWORD GetConfigDWORD_DontUse_(
1177 CORConfigLevel level = COR_CONFIG_ALL,
1178 BOOL fPrependCOMPLUS = TRUE);
1181 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1182 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1184 static HRESULT GetConfigDWORD_DontUse_(
1187 __out DWORD * result,
1188 CORConfigLevel level = COR_CONFIG_ALL,
1189 BOOL fPrependCOMPLUS = TRUE);
1191 static ULONGLONG GetConfigULONGLONG_DontUse_(
1194 CORConfigLevel level = COR_CONFIG_ALL,
1195 BOOL fPrependCOMPLUS = TRUE);
1198 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1199 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1201 static DWORD GetConfigFlag_DontUse_(
1204 BOOL defValue = FALSE);
1207 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1208 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1210 static LPWSTR GetConfigString_DontUse_(
1212 BOOL fPrependCOMPLUS = TRUE,
1213 CORConfigLevel level = COR_CONFIG_ALL,
1214 BOOL fUsePerfCache = TRUE);
1216 static void FreeConfigString(__in __in_z LPWSTR name);
1219 static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS);
1222 static BOOL UseRegistry();
1225 //*****************************************************************************
1226 // Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that
1227 // you can safely cast to a DWORD if fGetDWORD is TRUE.
1228 //*****************************************************************************
1229 static HRESULT GetConfigInteger(
1232 __out ULONGLONG * result,
1233 BOOL fGetDWORD = TRUE,
1234 CORConfigLevel level = COR_CONFIG_ALL,
1235 BOOL fPrependCOMPLUS = TRUE);
1239 //*****************************************************************************
1240 // (Optional) Initialize the config registry cache
1241 // (see ConfigCacheValueNameSeenPerhaps, below.)
1242 //*****************************************************************************
1243 static void InitOptionalConfigCache();
1248 //*****************************************************************************
1249 // Return TRUE if the registry value name might have been seen in the registry
1251 // return FALSE if the value was definitely not seen at startup.
1253 // Perf Optimization for VSWhidbey:113373.
1254 //*****************************************************************************
1255 static BOOL RegCacheValueNameSeenPerhaps(
1257 //*****************************************************************************
1258 // Return TRUE if the environment variable name might have been seen at startup;
1259 // return FALSE if the value was definitely not seen at startup.
1260 //*****************************************************************************
1261 static BOOL EnvCacheValueNameSeenPerhaps(
1264 static BOOL s_fUseRegCache; // Enable registry cache; if FALSE, CCVNSP
1265 // always returns TRUE.
1266 static BOOL s_fUseEnvCache; // Enable env cache.
1268 static BOOL s_fUseRegistry; // Allow lookups in the registry
1270 // Open the .NetFramework keys once and cache the handles
1271 static HKEY s_hMachineFrameworkKey;
1272 static HKEY s_hUserFrameworkKey;
1275 // need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig
1276 #include "clrconfig.h"
1278 //-----------------------------------------------------------------------------
1279 // Wrapper for configuration strings.
1280 // This serves as a holder to call FreeConfigString.
1281 class ConfigStringHolder
1284 ConfigStringHolder() { m_wszString = NULL; }
1285 ~ConfigStringHolder()
1291 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1292 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1294 void Init_DontUse_(LPCWSTR wszName)
1297 m_wszString = REGUTIL::GetConfigString_DontUse_(wszName);
1303 if (m_wszString != NULL)
1305 REGUTIL::FreeConfigString(m_wszString);
1310 // Get the string value. NULL if not set.
1320 #endif // defined(NO_CLRCONFIG)
1324 #define CLRGetTickCount64() GetTickCount64()
1327 // Use this function to initialize the s_CodeAllocHint
1328 // during startup. base is runtime .dll base address,
1329 // size is runtime .dll virtual size.
1331 void InitCodeAllocHint(SIZE_T base, SIZE_T size, int randomPageOffset);
1335 // Use this function to reset the s_CodeAllocHint
1336 // after unloading an AppDomain
1338 void ResetCodeAllocHint();
1341 // Returns TRUE if p is located in near clr.dll that allows us
1342 // to use rel32 IP-relative addressing modes.
1344 BOOL IsPreferredExecutableRange(void * p);
1347 // Allocate free memory that will be used for executable code
1348 // Handles the special requirements that we have on 64-bit platforms
1349 // where we want the executable memory to be located near mscorwks
1351 BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize,
1352 DWORD flAllocationType,
1356 // Allocate free memory within the range [pMinAddr..pMaxAddr] using
1357 // ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it.
1359 BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
1360 const BYTE *pMaxAddr,
1362 DWORD flAllocationType,
1366 // Allocate free memory with specific alignment
1368 LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment);
1370 //******************************************************************************
1371 // Returns the number of processors that a process has been configured to run on
1372 //******************************************************************************
1376 static BOOL m_enableGCNumaAware;
1377 static BOOL InitNumaNodeInfoAPI();
1380 static BOOL CanEnableGCNumaAware();
1381 static void InitNumaNodeInfo();
1383 #if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
1384 private: // apis types
1386 //GetNumaHighestNodeNumber()
1388 (WINAPI *PGNHNN)(PULONG);
1389 //VirtualAllocExNuma()
1391 (WINAPI *PVAExN)(HANDLE,LPVOID,SIZE_T,DWORD,DWORD,DWORD);
1393 // api pfns and members
1394 static PGNHNN m_pGetNumaHighestNodeNumber;
1395 static PVAExN m_pVirtualAllocExNuma;
1397 public: // functions
1399 static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size,
1400 DWORD allocType, DWORD prot, DWORD node);
1403 //GetNumaProcessorNodeEx()
1405 (WINAPI *PGNPNEx)(PPROCESSOR_NUMBER, PUSHORT);
1406 static PGNPNEx m_pGetNumaProcessorNodeEx;
1409 static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no);
1413 struct CPU_Group_Info
1415 WORD nr_active; // at most 64
1419 DWORD_PTR active_mask;
1421 DWORD activeThreadWeight;
1427 static LONG m_initialization;
1428 static WORD m_nGroups;
1429 static WORD m_nProcessors;
1430 static BOOL m_enableGCCPUGroups;
1431 static BOOL m_threadUseAllCpuGroups;
1432 static WORD m_initialGroup;
1433 static CPU_Group_Info *m_CPUGroupInfoArray;
1435 static BOOL InitCPUGroupInfoAPI();
1436 static BOOL InitCPUGroupInfoArray();
1437 static BOOL InitCPUGroupInfoRange();
1438 static void InitCPUGroupInfo();
1439 static BOOL IsInitialized();
1442 static void EnsureInitialized();
1443 static BOOL CanEnableGCCPUGroups();
1444 static BOOL CanEnableThreadUseAllCpuGroups();
1445 static WORD GetNumActiveProcessors();
1446 static void GetGroupForProcessor(WORD processor_number,
1447 WORD *group_number, WORD *group_processor_number);
1448 static DWORD CalculateCurrentProcessorNumber();
1449 //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
1451 #if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
1453 //GetLogicalProcessorInforomationEx()
1455 (WINAPI *PGLPIEx)(DWORD, SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *, PDWORD);
1456 //SetThreadGroupAffinity()
1458 (WINAPI *PSTGA)(HANDLE, GROUP_AFFINITY *, GROUP_AFFINITY *);
1459 //GetThreadGroupAffinity()
1461 (WINAPI *PGTGA)(HANDLE, GROUP_AFFINITY *);
1462 //GetCurrentProcessorNumberEx()
1464 (WINAPI *PGCPNEx)(PROCESSOR_NUMBER *);
1467 (WINAPI *PGST)(FILETIME *, FILETIME *, FILETIME *);
1468 //NtQuerySystemInformationEx()
1470 //(WINAPI *PNTQSIEx)(SYSTEM_INFORMATION_CLASS, PULONG, ULONG, PVOID, ULONG, PULONG);
1471 static PGLPIEx m_pGetLogicalProcessorInformationEx;
1472 static PSTGA m_pSetThreadGroupAffinity;
1473 static PGTGA m_pGetThreadGroupAffinity;
1474 static PGCPNEx m_pGetCurrentProcessorNumberEx;
1475 static PGST m_pGetSystemTimes;
1476 //static PNTQSIEx m_pNtQuerySystemInformationEx;
1479 static BOOL GetLogicalProcessorInformationEx(DWORD relationship,
1480 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count);
1481 static BOOL SetThreadGroupAffinity(HANDLE h,
1482 GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity);
1483 static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity);
1484 static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime);
1485 static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf);
1486 static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf);
1490 int GetCurrentProcessCpuCount();
1491 DWORD_PTR GetCurrentProcessCpuMask();
1493 //*****************************************************************************
1494 // Return != 0 if the bit at the specified index in the array is on and 0 if
1496 //*****************************************************************************
1497 inline int GetBit(PTR_BYTE pcBits,int iBit)
1499 LIMITED_METHOD_CONTRACT;
1500 return (pcBits[iBit>>3] & (1 << (iBit & 0x7)));
1503 #ifdef DACCESS_COMPILE
1504 inline int GetBit(BYTE const * pcBits,int iBit)
1506 WRAPPER_NO_CONTRACT;
1507 return GetBit(dac_cast<PTR_BYTE>(pcBits), iBit);
1511 //*****************************************************************************
1512 // Set the state of the bit at the specified index based on the value of bOn.
1513 //*****************************************************************************
1514 inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn)
1516 LIMITED_METHOD_CONTRACT;
1518 pcBits[iBit>>3] |= (1 << (iBit & 0x7));
1520 pcBits[iBit>>3] &= ~(1 << (iBit & 0x7));
1523 #ifdef DACCESS_COMPILE
1524 inline void SetBit(BYTE * pcBits,int iBit,int bOn)
1526 WRAPPER_NO_CONTRACT;
1527 SetBit(dac_cast<PTR_BYTE>(pcBits), iBit, bOn);
1531 template<typename T>
1532 class SimpleListNode
1535 SimpleListNode<T>(const T& _t)
1542 SimpleListNode<T>* next;
1545 template<typename T>
1549 typedef SimpleListNode<T> NodeType;
1556 void LinkHead(NodeType* pNode)
1562 NodeType* UnlinkHead()
1564 NodeType* ret = head;
1584 template < typename T, typename U >
1588 typedef Pair< T, U > this_type;
1589 typedef T first_type;
1590 typedef U second_type;
1595 Pair( T const & t, U const & u )
1600 Pair( this_type const & obj )
1601 : m_first( obj.m_first )
1602 , m_second( obj.m_second )
1605 this_type & operator=( this_type const & obj )
1607 m_first = obj.m_first;
1608 m_second = obj.m_second;
1617 T const & First() const
1627 U const & Second() const
1632 bool operator==(const Pair& rhs) const
1634 return ((this->First() == rhs.First()) &&
1635 (this->Second() == rhs.Second()));
1638 bool operator!=(const Pair& rhs) const
1640 return !(*this == rhs);
1645 second_type m_second;
1649 template < typename T, typename U >
1650 Pair< T, U > MakePair( T const & t, U const & u )
1653 return Pair< T, U >( t, u );
1657 //*****************************************************************************
1658 // This class implements a dynamic array of structures for which the order of
1659 // the elements is unimportant. This means that any item placed in the list
1660 // may be swapped to any other location in the list at any time. If the order
1661 // of the items you place in the array is important, then use the CStructArray
1663 //*****************************************************************************
1668 class CUnorderedArrayWithAllocator
1670 int m_iCount; // # of elements used in the list.
1671 int m_iSize; // # of elements allocated in the list.
1673 #ifndef DACCESS_COMPILE
1674 T *m_pTable; // Pointer to the list of elements.
1676 TADDR m_pTable; // Pointer to the list of elements.
1681 #ifndef DACCESS_COMPILE
1683 CUnorderedArrayWithAllocator() :
1688 LIMITED_METHOD_CONTRACT;
1690 ~CUnorderedArrayWithAllocator()
1692 LIMITED_METHOD_CONTRACT;
1693 // Free the chunk of memory.
1694 if (m_pTable != NULL)
1695 ALLOCATOR::Free(this, m_pTable);
1700 WRAPPER_NO_CONTRACT;
1702 if (m_iSize > iGrowInc)
1704 T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc);
1706 ALLOCATOR::Free(this, m_pTable);
1713 void Clear(int iFirst, int iCount)
1715 WRAPPER_NO_CONTRACT;
1718 if (iFirst + iCount < m_iCount)
1719 memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount)));
1723 iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0);
1724 if (m_iSize > iGrowInc && iSize < m_iSize)
1726 T *tmp = ALLOCATOR::AllocNoThrow(this, iSize);
1728 memcpy (tmp, m_pTable, iSize * sizeof(T));
1734 _ASSERTE(m_iCount <= m_iSize);
1739 LIMITED_METHOD_CONTRACT;
1749 // The array should grow, if we can't fit one more element into the array.
1750 if (m_iSize <= m_iCount && GrowNoThrow() == NULL)
1752 return (&m_pTable[m_iCount++]);
1761 // The array should grow, if we can't fit one more element into the array.
1762 if (m_iSize <= m_iCount)
1764 return (&m_pTable[m_iCount++]);
1767 void Delete(const T &Entry)
1769 LIMITED_METHOD_CONTRACT;
1771 for (int i=0; i <= m_iCount; ++i)
1772 if (m_pTable[i] == Entry)
1774 m_pTable[i] = m_pTable[m_iCount];
1778 // Just in case we didn't find it.
1782 void DeleteByIndex(int i)
1784 LIMITED_METHOD_CONTRACT;
1786 m_pTable[i] = m_pTable[m_iCount];
1789 void Swap(int i,int j)
1791 LIMITED_METHOD_CONTRACT;
1797 m_pTable[i] = m_pTable[j];
1805 LIMITED_METHOD_CONTRACT;
1810 void EnumMemoryRegions(void)
1813 DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T));
1816 #endif // #ifndef DACCESS_COMPILE
1820 LIMITED_METHOD_CONTRACT;
1822 _ASSERTE(FitsIn<USHORT>(m_iCount));
1823 return static_cast<USHORT>(m_iCount);
1832 #ifndef DACCESS_COMPILE
1834 //*****************************************************************************
1835 // Increase the size of the array.
1836 //*****************************************************************************
1840 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::GrowNoThrow() // NULL if can't grow.
1842 WRAPPER_NO_CONTRACT;
1845 // try to allocate memory for reallocation.
1846 if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL)
1848 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1849 ALLOCATOR::Free(this, m_pTable);
1851 m_iSize += iGrowInc;
1852 _ASSERTE(m_iSize > 0);
1859 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::Grow() // exception if can't grow.
1861 WRAPPER_NO_CONTRACT;
1864 // try to allocate memory for reallocation.
1865 pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc);
1866 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1867 ALLOCATOR::Free(this, m_pTable);
1869 m_iSize += iGrowInc;
1870 _ASSERTE(m_iSize > 0);
1874 #endif // #ifndef DACCESS_COMPILE
1878 class CUnorderedArray__Allocator
1882 static T *AllocThrowing (void*, int nElements)
1884 return new T[nElements];
1887 static T *AllocNoThrow (void*, int nElements)
1889 return new (nothrow) T[nElements];
1892 static void Free (void*, T *pTable)
1899 template <class T,int iGrowInc>
1900 class CUnorderedArray : public CUnorderedArrayWithAllocator<T, iGrowInc, CUnorderedArray__Allocator<T> >
1906 LIMITED_METHOD_CONTRACT;
1911 //Used by the debugger. Included here in hopes somebody else might, too
1912 typedef CUnorderedArray<SIZE_T, 17> SIZE_T_UNORDERED_ARRAY;
1915 //*****************************************************************************
1916 // This class implements a dynamic array of structures for which the insert
1917 // order is important. Inserts will slide all elements after the location
1918 // down, deletes slide all values over the deleted item. If the order of the
1919 // items in the array is unimportant to you, then CUnorderedArray may provide
1920 // the same feature set at lower cost.
1921 //*****************************************************************************
1924 BYTE *m_pList; // Pointer to the list of elements.
1925 int m_iCount; // # of elements used in the list.
1926 int m_iSize; // # of elements allocated in the list.
1927 int m_iGrowInc; // Growth increment.
1928 short m_iElemSize; // Size of an array element.
1929 bool m_bFree; // true if data is automatically maintained.
1932 CStructArray(short iElemSize, short iGrowInc = 1) :
1936 m_iGrowInc(iGrowInc),
1937 m_iElemSize(iElemSize),
1940 LIMITED_METHOD_CONTRACT;
1944 WRAPPER_NO_CONTRACT;
1948 void *Insert(int iIndex);
1949 void *InsertThrowing(int iIndex);
1951 void *AppendThrowing();
1952 int AllocateBlock(int iCount);
1953 void AllocateBlockThrowing(int iCount);
1954 void Delete(int iIndex);
1957 LIMITED_METHOD_CONTRACT;
1960 void *Get(int iIndex)
1962 WRAPPER_NO_CONTRACT;
1963 _ASSERTE(iIndex < m_iCount);
1964 return ((void *) ((size_t) Ptr() + (iIndex * m_iElemSize)));
1968 LIMITED_METHOD_CONTRACT;
1969 return (m_iCount * m_iElemSize);
1973 LIMITED_METHOD_CONTRACT;
1979 LIMITED_METHOD_CONTRACT;
1983 void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1)
1985 LIMITED_METHOD_CONTRACT;
1986 m_iElemSize = iElemSize;
1987 m_iGrowInc = (short) iGrowInc;
1988 m_pList = (BYTE*)pList;
1995 void Grow(int iCount);
1999 //*****************************************************************************
2000 // This template simplifies access to a CStructArray by removing void * and
2001 // adding some operator overloads.
2002 //*****************************************************************************
2004 class CDynArray : public CStructArray
2007 CDynArray(short iGrowInc=16) :
2008 CStructArray(sizeof(T), iGrowInc)
2010 LIMITED_METHOD_CONTRACT;
2013 T *Insert(int iIndex)
2015 WRAPPER_NO_CONTRACT;
2016 return ((T *)CStructArray::Insert((int)iIndex));
2019 T *InsertThrowing(int iIndex)
2021 WRAPPER_NO_CONTRACT;
2022 return ((T *)CStructArray::InsertThrowing((int)iIndex));
2027 WRAPPER_NO_CONTRACT;
2028 return ((T *)CStructArray::Append());
2033 WRAPPER_NO_CONTRACT;
2034 return ((T *)CStructArray::AppendThrowing());
2039 WRAPPER_NO_CONTRACT;
2040 return ((T *)CStructArray::Ptr());
2045 WRAPPER_NO_CONTRACT;
2046 return (Ptr() + iIndex);
2048 T &operator[](int iIndex)
2050 WRAPPER_NO_CONTRACT;
2051 return (*(Ptr() + iIndex));
2055 WRAPPER_NO_CONTRACT;
2056 return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T));
2058 void Move(int iFrom, int iTo)
2060 WRAPPER_NO_CONTRACT;
2063 _ASSERTE(iFrom >= 0 && iFrom < Count() &&
2064 iTo >= 0 && iTo < Count());
2066 tmp = *(Ptr() + iFrom);
2068 memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T));
2070 memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T));
2071 *(Ptr() + iTo) = tmp;
2075 // Some common arrays.
2076 typedef CDynArray<int> INTARRAY;
2077 typedef CDynArray<short> SHORTARRAY;
2078 typedef CDynArray<int> LONGARRAY;
2079 typedef CDynArray<USHORT> USHORTARRAY;
2080 typedef CDynArray<ULONG> ULONGARRAY;
2081 typedef CDynArray<BYTE> BYTEARRAY;
2082 typedef CDynArray<mdToken> TOKENARRAY;
2084 template <class T> class CStackArray : public CStructArray
2087 CStackArray(short iGrowInc=4) :
2088 CStructArray(sizeof(T), iGrowInc),
2091 LIMITED_METHOD_CONTRACT;
2096 WRAPPER_NO_CONTRACT;
2097 // We should only inc m_curPos after we grow the array.
2098 T *pT = (T *)CStructArray::InsertThrowing(m_curPos);
2105 WRAPPER_NO_CONTRACT;
2108 _ASSERTE(m_curPos > 0);
2110 retPtr = (T *)CStructArray::Get(m_curPos-1);
2111 CStructArray::Delete(m_curPos--);
2118 LIMITED_METHOD_CONTRACT;
2127 //*****************************************************************************
2128 // This template manages a list of free entries by their 0 based offset. By
2129 // making it a template, you can use whatever size free chain will match your
2130 // maximum count of items. -1 is reserved.
2131 //*****************************************************************************
2132 template <class T> class TFreeList
2139 LIMITED_METHOD_CONTRACT;
2147 for (i=0; i<iCount - 1; i++)
2148 m_rgList[i] = i + 1;
2149 m_rgList[i] = (T) -1;
2152 T GetFreeEntry() // Index of free item, or -1.
2154 LIMITED_METHOD_CONTRACT;
2157 if (m_iNext == (T) -1)
2161 m_iNext = m_rgList[m_iNext];
2165 void DelFreeEntry(T iEntry)
2167 LIMITED_METHOD_CONTRACT;
2168 _ASSERTE(iEntry < m_iCount);
2169 m_rgList[iEntry] = m_iNext;
2173 // This function can only be used when it is guaranteed that the free
2174 // array is contigous, for example, right after creation to quickly
2175 // get a range of items from the heap.
2176 void ReserveRange(int iCount)
2178 LIMITED_METHOD_CONTRACT;
2179 _ASSERTE(iCount < m_iCount);
2180 _ASSERTE(m_iNext == 0);
2185 T *m_rgList; // List of free info.
2186 int m_iCount; // How many entries to manage.
2187 T m_iNext; // Next item to get.
2191 //*****************************************************************************
2192 //*****************************************************************************
2193 template <class T> class CQuickSort
2196 T *m_pBase; // Base of array to sort.
2198 SSIZE_T m_iCount; // How many items in array.
2199 SSIZE_T m_iElemSize; // Size of one element.
2202 T *pBase, // Address of first element.
2203 SSIZE_T iCount) : // How many there are.
2206 m_iElemSize(sizeof(T))
2208 LIMITED_METHOD_DAC_CONTRACT;
2211 //*****************************************************************************
2212 // Call to sort the array.
2213 //*****************************************************************************
2216 WRAPPER_NO_CONTRACT;
2217 SortRange(0, m_iCount - 1);
2221 //*****************************************************************************
2222 // Override this function to do the comparison.
2223 //*****************************************************************************
2224 virtual FORCEINLINE int Compare( // -1, 0, or 1
2225 T *psFirst, // First item to compare.
2226 T *psSecond) // Second item to compare.
2228 LIMITED_METHOD_DAC_CONTRACT;
2229 return (memcmp(psFirst, psSecond, sizeof(T)));
2230 // return (::Compare(*psFirst, *psSecond));
2233 virtual FORCEINLINE void Swap(
2237 LIMITED_METHOD_DAC_CONTRACT;
2238 if (iFirst == iSecond) return;
2239 T sTemp( m_pBase[iFirst] );
2240 m_pBase[iFirst] = m_pBase[iSecond];
2241 m_pBase[iSecond] = sTemp;
2245 inline void SortRange(
2249 WRAPPER_NO_CONTRACT;
2251 SSIZE_T i; // loop variable.
2255 // if less than two elements you're done.
2256 if (iLeft >= iRight)
2259 // ASSERT that we now have valid indicies. This is statically provable
2260 // since this private function is only called with valid indicies,
2261 // and iLeft and iRight only converge towards eachother. However,
2262 // PreFast can't detect this because it doesn't know about our callers.
2263 COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount);
2264 COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount);
2266 // The mid-element is the pivot, move it to the left.
2267 Swap(iLeft, (iLeft + iRight) / 2);
2270 // move everything that is smaller than the pivot to the left.
2271 for (i = iLeft + 1; i <= iRight; i++)
2273 if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0)
2279 // Put the pivot to the point where it is in between smaller and larger elements.
2282 // Sort each partition.
2283 SSIZE_T iLeftLast = iLast - 1;
2284 SSIZE_T iRightFirst = iLast + 1;
2285 if (iLeftLast - iLeft < iRight - iRightFirst)
2286 { // Left partition is smaller, sort it recursively
2287 SortRange(iLeft, iLeftLast);
2288 // Tail call to sort the right (bigger) partition
2289 iLeft = iRightFirst;
2294 { // Right partition is smaller, sort it recursively
2295 SortRange(iRightFirst, iRight);
2296 // Tail call to sort the left (bigger) partition
2305 //*****************************************************************************
2306 // Faster and simpler version of the binary search below.
2307 //*****************************************************************************
2309 const T * BinarySearch(const T * pBase, int iCount, const T & find)
2311 WRAPPER_NO_CONTRACT;
2314 int iLast = iCount - 1;
2316 // It is faster to use linear search once we get down to a small number of elements.
2317 while (iLast - iFirst > 10)
2319 int iMid = (iLast + iFirst) / 2;
2321 if (find < pBase[iMid])
2327 for (int i = iFirst; i <= iLast; i++)
2329 if (find == pBase[i])
2332 if (find < pBase[i])
2339 //*****************************************************************************
2340 // This template encapsulates a binary search algorithm on the given type
2342 //*****************************************************************************
2343 template <class T> class CBinarySearch
2346 const T *m_pBase; // Base of array to sort.
2347 int m_iCount; // How many items in array.
2351 const T *pBase, // Address of first element.
2352 int iCount) : // Value to find.
2356 LIMITED_METHOD_CONTRACT;
2359 //*****************************************************************************
2360 // Searches for the item passed to ctor.
2361 //*****************************************************************************
2362 const T *Find( // Pointer to found item in array.
2363 const T *psFind, // The key to find.
2364 int *piInsert = NULL) // Index to insert at.
2366 WRAPPER_NO_CONTRACT;
2367 int iMid, iFirst, iLast; // Loop control.
2368 int iCmp; // Comparison.
2371 iLast = m_iCount - 1;
2372 while (iFirst <= iLast)
2374 iMid = (iLast + iFirst) / 2;
2375 iCmp = Compare(psFind, &m_pBase[iMid]);
2378 if (piInsert != NULL)
2380 return (&m_pBase[iMid]);
2387 if (piInsert != NULL)
2392 //*****************************************************************************
2393 // Override this function to do the comparison if a comparison operator is
2394 // not valid for your data type (such as a struct).
2395 //*****************************************************************************
2396 virtual int Compare( // -1, 0, or 1
2397 const T *psFirst, // Key you are looking for.
2398 const T *psSecond) // Item to compare to.
2400 LIMITED_METHOD_CONTRACT;
2401 return (memcmp(psFirst, psSecond, sizeof(T)));
2402 // return (::Compare(*psFirst, *psSecond));
2406 //*****************************************************************************
2407 // The information that the hash table implementation stores at the beginning
2408 // of every record that can be but in the hash table.
2409 //*****************************************************************************
2410 typedef DPTR(struct HASHENTRY) PTR_HASHENTRY;
2413 ULONG iPrev; // Previous bucket in the chain.
2414 ULONG iNext; // Next bucket in the chain.
2417 typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY;
2418 struct FREEHASHENTRY : HASHENTRY
2423 //*****************************************************************************
2424 // Used by the FindFirst/FindNextEntry functions. These api's allow you to
2425 // do a sequential scan of all entries.
2426 //*****************************************************************************
2429 ULONG iBucket; // The next bucket to look in.
2434 //*****************************************************************************
2435 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2436 // The hashtable implementation that should be used instead is code:SHash.
2437 // If code:SHash does not work for you, talk to mailto:clrdeag.
2438 //*****************************************************************************
2439 // This is a class that implements a chain and bucket hash table.
2441 // The data is actually supplied as an array of structures by the user of this class.
2442 // This allows the buckets to use small indices to point to the chain, instead of pointers.
2444 // Each entry in the array contains a HASHENTRY structure immediately
2445 // followed by the key used to hash the structure.
2447 // The HASHENTRY part of every structure is used to implement the chain of
2448 // entries in a single bucket.
2450 // This implementation does not support rehashing the buckets if the table grows
2452 // @TODO: Fix this by adding an abstract function Hash() which must be implemented
2455 //*****************************************************************************
2458 friend class DebuggerRCThread; //RCthread actually needs access to
2459 //fields of derrived class DebuggerPatchTable
2462 TADDR m_pcEntries; // Pointer to the array of structs.
2463 ULONG m_iEntrySize; // Size of the structs.
2465 ULONG m_iBuckets; // # of chains we are hashing into.
2466 PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains.
2468 INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics
2470 HASHENTRY *EntryPtr(ULONG iEntry)
2472 LIMITED_METHOD_DAC_CONTRACT;
2473 return (PTR_HASHENTRY(m_pcEntries + (iEntry * m_iEntrySize)));
2476 ULONG ItemIndex(HASHENTRY *p)
2479 LIMITED_METHOD_CONTRACT;
2480 return (ULONG)((dac_cast<TADDR>(p) - m_pcEntries) / m_iEntrySize);
2487 ULONG iBuckets) : // # of chains we are hashing into.
2488 m_pcEntries((TADDR)NULL),
2489 m_iBuckets(iBuckets)
2491 LIMITED_METHOD_CONTRACT;
2495 INDEBUG(m_maxSearch = 0;)
2498 CHashTable() : // # of chains we are hashing into.
2499 m_pcEntries((TADDR)NULL),
2502 LIMITED_METHOD_CONTRACT;
2506 INDEBUG(m_maxSearch = 0;)
2509 #ifndef DACCESS_COMPILE
2513 LIMITED_METHOD_CONTRACT;
2514 if (m_piBuckets != NULL)
2516 delete [] m_piBuckets;
2521 //*****************************************************************************
2522 // This is the second part of construction where we do all of the work that
2523 // can fail. We also take the array of structs here because the calling class
2524 // presumably needs to allocate it in its NewInit.
2525 //*****************************************************************************
2526 HRESULT NewInit( // Return status.
2527 BYTE *pcEntries, // Array of structs we are managing.
2528 ULONG iEntrySize); // Size of the entries.
2530 //*****************************************************************************
2531 // This can be called to change the pointer to the table that the hash table
2532 // is managing. You might call this if (for example) you realloc the size
2533 // of the table and its pointer is different.
2534 //*****************************************************************************
2536 BYTE *pcEntries) // Array of structs we are managing.
2538 LIMITED_METHOD_CONTRACT;
2539 m_pcEntries = (TADDR)pcEntries;
2542 //*****************************************************************************
2543 // Clear the hash table as if there were nothing in it.
2544 //*****************************************************************************
2547 LIMITED_METHOD_CONTRACT;
2548 _ASSERTE(m_piBuckets != NULL);
2549 memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG));
2552 //*****************************************************************************
2553 // Add the struct at the specified index in m_pcEntries to the hash chains.
2554 //*****************************************************************************
2555 BYTE *Add( // New entry.
2556 ULONG iHash, // Hash value of entry to add.
2557 ULONG iIndex); // Index of struct in m_pcEntries.
2559 //*****************************************************************************
2560 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2561 //*****************************************************************************
2563 ULONG iHash, // Hash value of entry to delete.
2564 ULONG iIndex); // Index of struct in m_pcEntries.
2567 ULONG iHash, // Hash value of entry to delete.
2568 HASHENTRY *psEntry); // The struct to delete.
2570 //*****************************************************************************
2571 // The item at the specified index has been moved, update the previous and
2573 //*****************************************************************************
2575 ULONG iHash, // Hash value for the item.
2576 ULONG iNew); // New location.
2578 #endif // #ifndef DACCESS_COMPILE
2580 //*****************************************************************************
2581 // Return a boolean indicating whether or not this hash table has been inited.
2582 //*****************************************************************************
2585 LIMITED_METHOD_CONTRACT;
2586 return (m_piBuckets != NULL);
2589 //*****************************************************************************
2590 // Search the hash table for an entry with the specified key value.
2591 //*****************************************************************************
2592 BYTE *Find( // Index of struct in m_pcEntries.
2593 ULONG iHash, // Hash value of the item.
2594 SIZE_T key); // The key to match.
2596 //*****************************************************************************
2597 // Search the hash table for the next entry with the specified key value.
2598 //*****************************************************************************
2599 ULONG FindNext( // Index of struct in m_pcEntries.
2600 SIZE_T key, // The key to match.
2601 ULONG iIndex); // Index of previous match.
2603 //*****************************************************************************
2604 // Returns the first entry in the first hash bucket and inits the search
2605 // struct. Use the FindNextEntry function to continue walking the list. The
2606 // return order is not gauranteed.
2607 //*****************************************************************************
2608 BYTE *FindFirstEntry( // First entry found, or 0.
2609 HASHFIND *psSrch) // Search object.
2611 WRAPPER_NO_CONTRACT;
2612 if (m_piBuckets == 0)
2614 psSrch->iBucket = 1;
2615 psSrch->iNext = m_piBuckets[0];
2616 return (FindNextEntry(psSrch));
2619 //*****************************************************************************
2620 // Returns the next entry in the list.
2621 //*****************************************************************************
2622 BYTE *FindNextEntry( // The next entry, or0 for end of list.
2623 HASHFIND *psSrch); // Search object.
2625 #ifdef DACCESS_COMPILE
2626 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
2631 virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0;
2638 static BYTE *Alloc(int iSize, int iMaxSize)
2640 WRAPPER_NO_CONTRACT;
2641 return (new BYTE[iSize]);
2643 static void Free(BYTE *pPtr, int iSize)
2645 LIMITED_METHOD_CONTRACT;
2648 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2650 WRAPPER_NO_CONTRACT;
2652 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2653 //check for overflow
2654 if(newSize.IsOverflow())
2657 p = new (nothrow) BYTE[newSize.Value()];
2658 if (p == 0) return (0);
2659 memcpy (p, pPtr, iCurSize);
2664 static void Clean(BYTE * pData, int iSize)
2667 static int RoundSize(int iSize)
2669 LIMITED_METHOD_CONTRACT;
2672 static int GrowSize(int iCurSize)
2674 LIMITED_METHOD_CONTRACT;
2675 int newSize = (3 * iCurSize) / 2;
2676 return (newSize < 256) ? 256 : newSize;
2680 class CNewDataNoThrow
2683 static BYTE *Alloc(int iSize, int iMaxSize)
2685 WRAPPER_NO_CONTRACT;
2686 return (new (nothrow) BYTE[iSize]);
2688 static void Free(BYTE *pPtr, int iSize)
2690 LIMITED_METHOD_CONTRACT;
2693 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2695 WRAPPER_NO_CONTRACT;
2697 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2698 //check for overflow
2699 if(newSize.IsOverflow())
2702 p = new (nothrow) BYTE[newSize.Value()];
2703 if (p == 0) return (0);
2704 memcpy (p, pPtr, iCurSize);
2709 static void Clean(BYTE * pData, int iSize)
2712 static int RoundSize(int iSize)
2714 LIMITED_METHOD_CONTRACT;
2717 static int GrowSize(int iCurSize)
2719 LIMITED_METHOD_CONTRACT;
2720 int newSize = (3 * iCurSize) / 2;
2721 return (newSize < 256) ? 256 : newSize;
2726 //*****************************************************************************
2727 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2728 // The hashtable implementation that should be used instead is code:SHash.
2729 // If code:SHash does not work for you, talk to mailto:clrdeag.
2730 //*****************************************************************************
2731 // CHashTable expects the data to be in a single array - this is provided by
2732 // CHashTableAndData.
2733 // The array is allocated using the MemMgr type. CNewData and
2734 // CNewDataNoThrow can be used for this.
2735 //*****************************************************************************
2736 template <class MemMgr>
2737 class CHashTableAndData : public CHashTable
2740 ULONG m_iFree; // Index into m_pcEntries[] of next available slot
2741 ULONG m_iEntries; // size of m_pcEntries[]
2745 CHashTableAndData() :
2748 LIMITED_METHOD_CONTRACT;
2752 ULONG iBuckets) : // # of chains we are hashing into.
2753 CHashTable(iBuckets)
2755 LIMITED_METHOD_CONTRACT;
2758 #ifndef DACCESS_COMPILE
2760 ~CHashTableAndData()
2762 WRAPPER_NO_CONTRACT;
2763 if (m_pcEntries != NULL)
2764 MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize));
2767 //*****************************************************************************
2768 // This is the second part of construction where we do all of the work that
2769 // can fail. We also take the array of structs here because the calling class
2770 // presumably needs to allocate it in its NewInit.
2771 //*****************************************************************************
2772 HRESULT NewInit( // Return status.
2773 ULONG iEntries, // # of entries.
2774 ULONG iEntrySize, // Size of the entries.
2775 int iMaxSize); // Max size of data.
2777 //*****************************************************************************
2778 // Clear the hash table as if there were nothing in it.
2779 //*****************************************************************************
2782 WRAPPER_NO_CONTRACT;
2784 InitFreeChain(0, m_iEntries);
2785 CHashTable::Clear();
2788 //*****************************************************************************
2789 // Grabs a slot for the new entry to be added.
2790 // The caller should fill in the non-HASHENTRY part of the returned slot
2791 //*****************************************************************************
2793 ULONG iHash) // Hash value of entry to add.
2795 WRAPPER_NO_CONTRACT;
2796 FREEHASHENTRY *psEntry;
2798 // Make the table bigger if necessary.
2799 if (m_iFree == UINT32_MAX && !Grow())
2802 // Add the first entry from the free list to the hash chain.
2803 psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree);
2804 m_iFree = psEntry->iFree;
2806 // If we're recycling memory, give our memory-allocator a chance to re-init it.
2808 // Each entry is prefixed with a header - we don't want to trash that.
2809 SIZE_T cbHeader = sizeof(FREEHASHENTRY);
2810 MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader));
2812 return ((BYTE *) psEntry);
2815 //*****************************************************************************
2816 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2817 //*****************************************************************************
2819 ULONG iHash, // Hash value of entry to delete.
2820 ULONG iIndex) // Index of struct in m_pcEntries.
2822 WRAPPER_NO_CONTRACT;
2823 CHashTable::Delete(iHash, iIndex);
2824 ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree;
2829 ULONG iHash, // Hash value of entry to delete.
2830 HASHENTRY *psEntry) // The struct to delete.
2832 WRAPPER_NO_CONTRACT;
2833 CHashTable::Delete(iHash, psEntry);
2834 ((FREEHASHENTRY *) psEntry)->iFree = m_iFree;
2835 m_iFree = ItemIndex(psEntry);
2838 #endif // #ifndef DACCESS_COMPILE
2840 // This is a sad legacy workaround. The debugger's patch table (implemented as this
2841 // class) is shared across process. We publish the runtime offsets of
2842 // some key fields. Since those fields are private, we have to provide
2843 // accessors here. So if you're not using these functions, don't start.
2844 // We can hopefully remove them.
2845 // Note that we can't just make RCThread a friend of this class (we tried
2846 // originally) because the inheritence chain has a private modifier,
2847 // so DebuggerPatchTable::m_pcEntries is illegal.
2848 static SIZE_T helper_GetOffsetOfEntries()
2850 LIMITED_METHOD_CONTRACT;
2851 return offsetof(CHashTableAndData, m_pcEntries);
2854 static SIZE_T helper_GetOffsetOfCount()
2856 LIMITED_METHOD_CONTRACT;
2857 return offsetof(CHashTableAndData, m_iEntries);
2860 #ifdef DACCESS_COMPILE
2861 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2864 CHashTable::EnumMemoryRegions(flags, m_iEntries);
2869 void InitFreeChain(ULONG iStart,ULONG iEnd);
2873 #ifndef DACCESS_COMPILE
2875 //*****************************************************************************
2876 // This is the second part of construction where we do all of the work that
2877 // can fail. We also take the array of structs here because the calling class
2878 // presumably needs to allocate it in its NewInit.
2879 //*****************************************************************************
2880 template<class MemMgr>
2881 HRESULT CHashTableAndData<MemMgr>::NewInit(// Return status.
2882 ULONG iEntries, // # of entries.
2883 ULONG iEntrySize, // Size of the entries.
2884 int iMaxSize) // Max size of data.
2886 WRAPPER_NO_CONTRACT;
2891 // note that this function can throw because it depends on the <M>::Alloc
2893 // Allocate the memory for the entries.
2894 if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize),
2895 MemMgr::RoundSize(iMaxSize))) == 0)
2896 return (E_OUTOFMEMORY);
2897 m_iEntries = iEntries;
2899 // Init the base table.
2900 if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize)))
2901 MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize));
2904 // Init the free chain.
2906 InitFreeChain(0, iEntries);
2911 //*****************************************************************************
2912 // Initialize a range of records such that they are linked together to be put
2913 // on the free chain.
2914 //*****************************************************************************
2915 template<class MemMgr>
2916 void CHashTableAndData<MemMgr>::InitFreeChain(
2917 ULONG iStart, // Index to start initializing.
2918 ULONG iEnd) // Index to stop initializing
2920 LIMITED_METHOD_CONTRACT;
2922 _ASSERTE(iEnd > iStart);
2924 pcPtr = (BYTE*)m_pcEntries + iStart * m_iEntrySize;
2925 for (++iStart; iStart < iEnd; ++iStart)
2927 ((FREEHASHENTRY *) pcPtr)->iFree = iStart;
2928 pcPtr += m_iEntrySize;
2930 ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX;
2933 //*****************************************************************************
2934 // Attempt to increase the amount of space available for the record heap.
2935 //*****************************************************************************
2936 template<class MemMgr>
2937 int CHashTableAndData<MemMgr>::Grow() // 1 if successful, 0 if not.
2939 WRAPPER_NO_CONTRACT;
2940 int iCurSize; // Current size in bytes.
2941 int iEntries; // New # of entries.
2943 _ASSERTE(m_pcEntries != NULL);
2944 _ASSERTE(m_iFree == UINT32_MAX);
2946 // Compute the current size and new # of entries.
2947 S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize);
2948 if( iTotEntrySize.IsOverflow() )
2950 _ASSERTE( !"CHashTableAndData overflow!" );
2953 iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() );
2954 iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize;
2956 if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) )
2958 _ASSERTE( !"CHashTableAndData overflow!" );
2962 // Try to expand the array.
2963 if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0)
2966 // Init the newly allocated space.
2967 InitFreeChain(m_iEntries, iEntries);
2968 m_iFree = m_iEntries;
2969 m_iEntries = iEntries;
2973 #endif // #ifndef DACCESS_COMPILE
2975 //*****************************************************************************
2976 //*****************************************************************************
2978 inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data)
2980 LIMITED_METHOD_DAC_CONTRACT;
2981 return ((currentHash << 5) + currentHash) ^ data;
2984 inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr)
2986 WRAPPER_NO_CONTRACT;
2988 return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast<TADDR>(ptr))));
2991 inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c)
2993 LIMITED_METHOD_DAC_CONTRACT;
2996 lookup3.c, by Bob Jenkins, May 2006, Public Domain.
2998 These are functions for producing 32-bit hashes for hash table lookup.
2999 hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
3000 are externally useful functions. Routines to test the hash are included
3001 if SELF_TEST is defined. You can use this free for any purpose. It's in
3002 the public domain. It has no warranty.
3005 #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
3006 c ^= b; c -= rot32(b,14);
3007 a ^= c; a -= rot32(c,11);
3008 b ^= a; b -= rot32(a,25);
3009 c ^= b; c -= rot32(b,16);
3010 a ^= c; a -= rot32(c,4);
3011 b ^= a; b -= rot32(a,14);
3012 c ^= b; c -= rot32(b,24);
3017 inline ULONG HashBytes(BYTE const *pbData, size_t iSize)
3019 LIMITED_METHOD_CONTRACT;
3022 BYTE const *pbDataEnd = pbData + iSize;
3024 for (/**/ ; pbData < pbDataEnd; pbData++)
3026 hash = ((hash << 5) + hash) ^ *pbData;
3031 // Helper function for hashing a string char by char.
3032 inline ULONG HashStringA(LPCSTR szStr)
3034 LIMITED_METHOD_CONTRACT;
3038 while ((c = *szStr) != 0)
3040 hash = ((hash << 5) + hash) ^ c;
3046 inline ULONG HashString(LPCWSTR szStr)
3048 LIMITED_METHOD_CONTRACT;
3052 while ((c = *szStr) != 0)
3054 hash = ((hash << 5) + hash) ^ c;
3060 inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr)
3062 LIMITED_METHOD_CONTRACT;
3065 // hash the string two characters at a time
3066 ULONG *ptr = (ULONG *)szStr;
3068 // we assume that szStr is null-terminated
3069 _ASSERTE(cchStr <= wcslen(szStr));
3070 SIZE_T cDwordCount = (cchStr + 1) / 2;
3072 for (SIZE_T i = 0; i < cDwordCount; i++)
3074 hash = ((hash << 5) + hash) ^ ptr[i];
3080 // Case-insensitive string hash function.
3081 inline ULONG HashiStringA(LPCSTR szStr)
3083 LIMITED_METHOD_CONTRACT;
3087 hash = ((hash << 5) + hash) ^ toupper(*szStr);
3093 // Case-insensitive string hash function.
3094 inline ULONG HashiString(LPCWSTR szStr)
3096 LIMITED_METHOD_CONTRACT;
3100 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3106 // Case-insensitive string hash function.
3107 inline ULONG HashiStringN(LPCWSTR szStr, DWORD count)
3109 LIMITED_METHOD_CONTRACT;
3111 while (*szStr != 0 && count--)
3113 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3119 // Case-insensitive string hash function when all of the
3120 // characters in the string are known to be below 0x80.
3121 // Knowing this is much more efficient than calling
3123 inline ULONG HashiStringKnownLower80(LPCWSTR szStr) {
3124 LIMITED_METHOD_CONTRACT;
3128 while ((c = *szStr)!=0) {
3129 //If we have a lowercase character, ANDing off 0x20
3130 //(mask) will make it an uppercase character.
3131 if (c>='a' && c<='z') {
3134 hash = ((hash << 5) + hash) ^ c;
3140 inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) {
3141 LIMITED_METHOD_CONTRACT;
3145 while ((c = *szStr) !=0 && count--) {
3146 //If we have a lowercase character, ANDing off 0x20
3147 //(mask) will make it an uppercase character.
3148 if (c>='a' && c<='z') {
3151 hash = ((hash << 5) + hash) ^ c;
3157 //*****************************************************************************
3158 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3159 // The hashtable implementation that should be used instead is code:SHash.
3160 // If code:SHash does not work for you, talk to mailto:clrdeag.
3161 //*****************************************************************************
3162 // This class implements a closed hashing table. Values are hashed to a bucket,
3163 // and if that bucket is full already, then the value is placed in the next
3164 // free bucket starting after the desired target (with wrap around). If the
3165 // table becomes 75% full, it is grown and rehashed to reduce lookups. This
3166 // class is best used in a reltively small lookup table where hashing is
3167 // not going to cause many collisions. By not having the collision chain
3168 // logic, a lot of memory is saved.
3170 // The user of the template is required to supply several methods which decide
3171 // how each element can be marked as free, deleted, or used. It would have
3172 // been possible to write this with more internal logic, but that would require
3173 // either (a) more overhead to add status on top of elements, or (b) hard
3174 // coded types like one for strings, one for ints, etc... This gives you the
3175 // flexibility of adding logic to your type.
3176 //*****************************************************************************
3177 class CClosedHashBase
3179 BYTE *EntryPtr(int iEntry)
3181 LIMITED_METHOD_CONTRACT;
3182 return (m_rgData + (iEntry * m_iEntrySize));
3185 BYTE *EntryPtr(int iEntry, BYTE *rgData)
3187 LIMITED_METHOD_CONTRACT;
3188 return (rgData + (iEntry * m_iEntrySize));
3194 FREE, // Item is not in use right now.
3195 DELETED, // Item is deleted.
3196 USED // Item is in use.
3200 int iBuckets, // How many buckets should we start with.
3201 int iEntrySize, // Size of an entry.
3202 bool bPerfect) : // true if bucket size will hash with no collisions.
3203 m_bPerfect(bPerfect),
3204 m_iBuckets(iBuckets),
3205 m_iEntrySize(iEntrySize),
3210 LIMITED_METHOD_CONTRACT;
3211 m_iSize = iBuckets + 7;
3214 virtual ~CClosedHashBase()
3216 WRAPPER_NO_CONTRACT;
3220 virtual void Clear()
3222 LIMITED_METHOD_CONTRACT;
3229 //*****************************************************************************
3230 // Accessors for getting at the underlying data. Be careful to use Count()
3231 // only when you want the number of buckets actually used.
3232 //*****************************************************************************
3236 LIMITED_METHOD_CONTRACT;
3242 LIMITED_METHOD_CONTRACT;
3243 return (m_iCollisions);
3248 LIMITED_METHOD_CONTRACT;
3249 return (m_iBuckets);
3252 void SetBuckets(int iBuckets, bool bPerfect=false)
3254 LIMITED_METHOD_CONTRACT;
3255 _ASSERTE(m_rgData == 0);
3256 m_iBuckets = iBuckets;
3257 m_iSize = m_iBuckets + 7;
3258 m_bPerfect = bPerfect;
3263 LIMITED_METHOD_CONTRACT;
3267 //*****************************************************************************
3268 // Add a new item to hash table given the key value. If this new entry
3269 // exceeds maximum size, then the table will grow and be re-hashed, which
3270 // may cause a memory error.
3271 //*****************************************************************************
3272 BYTE *Add( // New item to fill out on success.
3273 void *pData) // The value to hash on.
3275 WRAPPER_NO_CONTRACT;
3276 // If we haven't allocated any memory, or it is too small, fix it.
3277 if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect))
3283 return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount));
3286 //*****************************************************************************
3287 // Delete the given value. This will simply mark the entry as deleted (in
3288 // order to keep the collision chain intact). There is an optimization that
3289 // consecutive deleted entries leading up to a free entry are themselves freed
3290 // to reduce collisions later on.
3291 //*****************************************************************************
3293 void *pData); // Key value to delete.
3296 //*****************************************************************************
3297 // Callback function passed to DeleteLoop.
3298 //*****************************************************************************
3299 typedef BOOL (* DELETELOOPFUNC)( // Delete current item?
3300 BYTE *pEntry, // Bucket entry to evaluate
3301 void *pCustomizer); // User-defined value
3303 //*****************************************************************************
3304 // Iterates over all active values, passing each one to pDeleteLoopFunc.
3305 // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer
3306 // and faster than using FindNext() and Delete().
3307 //*****************************************************************************
3309 DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item
3310 void *pCustomizer); // Extra value passed to deletefunc.
3313 //*****************************************************************************
3314 // Lookup a key value and return a pointer to the element if found.
3315 //*****************************************************************************
3316 BYTE *Find( // The item if found, 0 if not.
3317 void *pData); // The key to lookup.
3319 //*****************************************************************************
3320 // Look for an item in the table. If it isn't found, then create a new one and
3322 //*****************************************************************************
3323 BYTE *FindOrAdd( // The item if found, 0 if not.
3324 void *pData, // The key to lookup.
3325 bool &bNew); // true if created.
3327 //*****************************************************************************
3328 // The following functions are used to traverse each used entry. This code
3329 // will skip over deleted and free entries freeing the caller up from such
3331 //*****************************************************************************
3332 BYTE *GetFirst() // The first entry, 0 if none.
3334 WRAPPER_NO_CONTRACT;
3335 int i; // Loop control.
3337 // If we've never allocated the table there can't be any to get.
3341 // Find the first one.
3342 for (i=0; i<m_iSize; i++)
3344 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3345 return (EntryPtr(i));
3350 BYTE *GetNext(BYTE *Prev) // The next entry, 0 if done.
3352 WRAPPER_NO_CONTRACT;
3353 int i; // Loop control.
3355 for (i = (int)(((size_t) Prev - (size_t) &m_rgData[0]) / m_iEntrySize) + 1; i<m_iSize; i++)
3357 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3358 return (EntryPtr(i));
3364 //*****************************************************************************
3365 // Hash is called with a pointer to an element in the table. You must override
3366 // this method and provide a hash algorithm for your element type.
3367 //*****************************************************************************
3368 virtual unsigned int Hash( // The key value.
3369 void const *pData)=0; // Raw data to hash.
3371 //*****************************************************************************
3372 // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
3373 // direction of miscompare. In this system everything is always equal or not.
3374 //*****************************************************************************
3375 virtual unsigned int Compare( // 0, -1, or 1.
3376 void const *pData, // Raw key data on lookup.
3377 BYTE *pElement)=0; // The element to compare data against.
3379 //*****************************************************************************
3380 // Return true if the element is free to be used.
3381 //*****************************************************************************
3382 virtual ELEMENTSTATUS Status( // The status of the entry.
3383 BYTE *pElement)=0; // The element to check.
3385 //*****************************************************************************
3386 // Sets the status of the given element.
3387 //*****************************************************************************
3388 virtual void SetStatus(
3389 BYTE *pElement, // The element to set status for.
3390 ELEMENTSTATUS eStatus)=0; // New status.
3392 //*****************************************************************************
3393 // Returns the internal key value for an element.
3394 //*****************************************************************************
3395 virtual void *GetKey( // The data to hash on.
3396 BYTE *pElement)=0; // The element to return data ptr for.
3398 //*****************************************************************************
3399 // This helper actually does the add for you.
3400 //*****************************************************************************
3401 BYTE *DoAdd(void *pData, BYTE *rgData, int &iBuckets, int iSize,
3402 int &iCollisions, int &iCount);
3404 //*****************************************************************************
3405 // This function is called either to init the table in the first place, or
3406 // to rehash the table if we ran out of room.
3407 //*****************************************************************************
3408 bool ReHash(); // true if successful.
3410 //*****************************************************************************
3411 // Walk each item in the table and mark it free.
3412 //*****************************************************************************
3413 void InitFree(BYTE *ptr, int iSize)
3415 WRAPPER_NO_CONTRACT;
3417 for (i=0; i<iSize; i++, ptr += m_iEntrySize)
3418 SetStatus(ptr, FREE);
3422 bool m_bPerfect; // true if the table size guarantees
3424 int m_iBuckets; // How many buckets do we have.
3425 int m_iEntrySize; // Size of an entry.
3426 int m_iSize; // How many elements can we have.
3427 int m_iCount; // How many items cannot be used (NON free, i.e. USED+DELETED).
3428 int m_iCollisions; // How many have we had.
3429 BYTE *m_rgData; // Data element list.
3432 //*****************************************************************************
3433 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3434 // The hashtable implementation that should be used instead is code:SHash.
3435 // If code:SHash does not work for you, talk to mailto:clrdeag.
3436 //*****************************************************************************
3437 template <class T> class CClosedHash : public CClosedHashBase
3441 int iBuckets, // How many buckets should we start with.
3442 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3443 CClosedHashBase(iBuckets, sizeof(T), bPerfect)
3445 WRAPPER_NO_CONTRACT;
3448 T &operator[](int iIndex)
3450 WRAPPER_NO_CONTRACT;
3451 return ((T &) *(Data() + (iIndex * sizeof(T))));
3455 //*****************************************************************************
3456 // Add a new item to hash table given the key value. If this new entry
3457 // exceeds maximum size, then the table will grow and be re-hashed, which
3458 // may cause a memory error.
3459 //*****************************************************************************
3460 T *Add( // New item to fill out on success.
3461 void *pData) // The value to hash on.
3463 WRAPPER_NO_CONTRACT;
3464 return ((T *) CClosedHashBase::Add(pData));
3467 //*****************************************************************************
3468 // Lookup a key value and return a pointer to the element if found.
3469 //*****************************************************************************
3470 T *Find( // The item if found, 0 if not.
3471 void *pData) // The key to lookup.
3473 WRAPPER_NO_CONTRACT;
3474 return ((T *) CClosedHashBase::Find(pData));
3477 //*****************************************************************************
3478 // Look for an item in the table. If it isn't found, then create a new one and
3480 //*****************************************************************************
3481 T *FindOrAdd( // The item if found, 0 if not.
3482 void *pData, // The key to lookup.
3483 bool &bNew) // true if created.
3485 WRAPPER_NO_CONTRACT;
3486 return ((T *) CClosedHashBase::FindOrAdd(pData, bNew));
3490 //*****************************************************************************
3491 // The following functions are used to traverse each used entry. This code
3492 // will skip over deleted and free entries freeing the caller up from such
3494 //*****************************************************************************
3495 T *GetFirst() // The first entry, 0 if none.
3497 WRAPPER_NO_CONTRACT;
3498 return ((T *) CClosedHashBase::GetFirst());
3501 T *GetNext(T *Prev) // The next entry, 0 if done.
3503 WRAPPER_NO_CONTRACT;
3504 return ((T *) CClosedHashBase::GetNext((BYTE *) Prev));
3509 //*****************************************************************************
3510 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3511 // The hashtable implementation that should be used instead is code:SHash.
3512 // If code:SHash does not work for you, talk to mailto:clrdeag.
3513 //*****************************************************************************
3514 // Closed hash with typed parameters. The derived class is the second
3515 // parameter to the template. The derived class must implement:
3516 // unsigned long Hash(const T *pData);
3517 // unsigned long Compare(const T *p1, T *p2);
3518 // ELEMENTSTATUS Status(T *pEntry);
3519 // void SetStatus(T *pEntry, ELEMENTSTATUS s);
3520 // void* GetKey(T *pEntry);
3521 //*****************************************************************************
3522 template<class T, class H>class CClosedHashEx : public CClosedHash<T>
3526 int iBuckets, // How many buckets should we start with.
3527 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3528 CClosedHash<T> (iBuckets, bPerfect)
3530 WRAPPER_NO_CONTRACT;
3533 unsigned int Hash(const void *pData)
3535 WRAPPER_NO_CONTRACT;
3536 return static_cast<H*>(this)->Hash((const T*)pData);
3539 unsigned int Compare(const void *p1, BYTE *p2)
3541 WRAPPER_NO_CONTRACT;
3542 return static_cast<H*>(this)->Compare((const T*)p1, (T*)p2);
3545 typename CClosedHash<T>::ELEMENTSTATUS Status(BYTE *p)
3547 WRAPPER_NO_CONTRACT;
3548 return static_cast<H*>(this)->Status((T*)p);
3551 void SetStatus(BYTE *p, typename CClosedHash<T>::ELEMENTSTATUS s)
3553 WRAPPER_NO_CONTRACT;
3554 static_cast<H*>(this)->SetStatus((T*)p, s);
3557 void* GetKey(BYTE *p)
3559 WRAPPER_NO_CONTRACT;
3560 return static_cast<H*>(this)->GetKey((T*)p);
3565 //*****************************************************************************
3566 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3567 // The hashtable implementation that should be used instead is code:SHash.
3568 // If code:SHash does not work for you, talk to mailto:clrdeag.
3569 //*****************************************************************************
3570 // This template is another form of a closed hash table. It handles collisions
3571 // through a linked chain. To use it, derive your hashed item from HASHLINK
3572 // and implement the virtual functions required. 1.5 * ibuckets will be
3573 // allocated, with the extra .5 used for collisions. If you add to the point
3574 // where no free nodes are available, the entire table is grown to make room.
3575 // The advantage to this system is that collisions are always directly known,
3576 // there either is one or there isn't.
3577 //*****************************************************************************
3580 ULONG iNext; // Offset for next entry.
3583 template <class T> class CChainedHash
3585 friend class VerifyLayoutsMD;
3587 CChainedHash(int iBuckets=32) :
3589 m_iBuckets(iBuckets),
3594 LIMITED_METHOD_CONTRACT;
3595 m_iSize = iBuckets + (iBuckets / 2);
3600 LIMITED_METHOD_CONTRACT;
3605 void SetBuckets(int iBuckets)
3607 LIMITED_METHOD_CONTRACT;
3608 _ASSERTE(m_rgData == 0);
3609 // if iBuckets==0, then we'll allocate a zero size array and AV on dereference.
3610 _ASSERTE(iBuckets > 0);
3611 m_iBuckets = iBuckets;
3612 m_iSize = iBuckets + (iBuckets / 2);
3615 T *Add(void const *pData)
3617 WRAPPER_NO_CONTRACT;
3622 // Build the list if required.
3623 if (m_rgData == 0 || m_iFree == 0xffffffff)
3629 // Hash the item and pick a bucket.
3630 iHash = Hash(pData);
3631 iBucket = iHash % m_iBuckets;
3633 // Use the bucket if it is free.
3634 if (InUse(&m_rgData[iBucket]) == false)
3636 pItem = &m_rgData[iBucket];
3637 pItem->iNext = 0xffffffff;
3639 // Else take one off of the free list for use.
3644 // Pull an item from the free list.
3646 pItem = &m_rgData[m_iFree];
3647 m_iFree = pItem->iNext;
3649 // Link the new node in after the bucket.
3650 pItem->iNext = m_rgData[iBucket].iNext;
3651 m_rgData[iBucket].iNext = iEntry;
3657 T *Find(void const *pData, bool bAddIfNew=false)
3659 WRAPPER_NO_CONTRACT;
3664 // Check states for lookup.
3667 // If we won't be adding, then we are through.
3668 if (bAddIfNew == false)
3671 // Otherwise, create the table.
3676 // Hash the item and pick a bucket.
3677 iHash = Hash(pData);
3678 iBucket = iHash % m_iBuckets;
3680 // If it isn't in use, then there it wasn't found.
3681 if (!InUse(&m_rgData[iBucket]))
3683 if (bAddIfNew == false)
3687 pItem = &m_rgData[iBucket];
3688 pItem->iNext = 0xffffffff;
3692 // Scan the list for the one we want.
3696 for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem))
3698 if (Cmp(pData, pItem) == 0)
3703 if (!pItem && bAddIfNew)
3707 // Record maximum chain length.
3708 if (iChain > m_iMaxChain)
3709 m_iMaxChain = iChain;
3711 // Now need more room.
3712 if (m_iFree == 0xffffffff)
3718 // Pull an item from the free list.
3720 pItem = &m_rgData[m_iFree];
3721 m_iFree = pItem->iNext;
3723 // Link the new node in after the bucket.
3724 pItem->iNext = m_rgData[iBucket].iNext;
3725 m_rgData[iBucket].iNext = iEntry;
3734 LIMITED_METHOD_CONTRACT;
3740 LIMITED_METHOD_CONTRACT;
3741 return (m_iBuckets);
3744 ULONG MaxChainLength()
3746 LIMITED_METHOD_CONTRACT;
3747 return (m_iMaxChain);
3750 virtual void Clear()
3752 LIMITED_METHOD_CONTRACT;
3753 // Free up the memory.
3766 virtual bool InUse(T *pItem)=0;
3767 virtual void SetFree(T *pItem)=0;
3768 virtual ULONG Hash(void const *pData)=0;
3769 virtual int Cmp(void const *pData, void *pItem)=0;
3771 inline T *GetNext(T *pItem)
3773 LIMITED_METHOD_CONTRACT;
3774 if (pItem->iNext != 0xffffffff)
3775 return ((T *) &m_rgData[pItem->iNext]);
3781 WRAPPER_NO_CONTRACT;
3785 // If this is a first time allocation, then just malloc it.
3788 if ((m_rgData = new (nothrow) T[m_iSize]) == 0)
3792 for (i=0; i<m_iSize; i++)
3793 SetFree(&m_rgData[i]);
3795 m_iFree = m_iBuckets;
3796 for (i=m_iBuckets; i<m_iSize; i++)
3797 ((T *) &m_rgData[i])->iNext = i + 1;
3798 ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff;
3802 // Otherwise we need more room on the free chain, so allocate some.
3803 iNewSize = m_iSize + (m_iSize / 2);
3805 // Allocate/realloc memory.
3806 if ((rgTemp = new (nothrow) T[iNewSize]) == 0)
3809 memcpy (rgTemp,m_rgData,m_iSize*sizeof(T));
3812 // Init new entries, save the new free chain, and reset internals.
3814 for (int i=m_iFree; i<iNewSize; i++)
3816 SetFree(&rgTemp[i]);
3817 ((T *) &rgTemp[i])->iNext = i + 1;
3819 ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff;
3827 T *m_rgData; // Data to store items in.
3828 int m_iBuckets; // How many buckets we want.
3829 int m_iSize; // How many are allocated.
3830 int m_iCount; // How many are we using.
3831 ULONG m_iMaxChain; // Max chain length.
3832 ULONG m_iFree; // Free chain.
3836 //*****************************************************************************
3838 //********** String helper functions.
3840 //*****************************************************************************
3842 //*****************************************************************************
3843 // Checks if string length exceeds the specified limit
3844 //*****************************************************************************
3845 inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N)
3847 LIMITED_METHOD_CONTRACT;
3851 for(i=0; (i < N)&&(pstr[i]); i++);
3857 //*****************************************************************************
3858 // Class to parse a list of simple assembly names and then find a match
3859 //*****************************************************************************
3861 class AssemblyNamesList
3865 LPUTF8 m_assemblyName;
3866 AssemblyName *m_next; // Next name
3869 AssemblyName *m_pNames; // List of names
3873 bool IsInList(LPCUTF8 assemblyName);
3877 LIMITED_METHOD_CONTRACT;
3878 return m_pNames == 0;
3881 AssemblyNamesList(__in LPWSTR list);
3882 ~AssemblyNamesList();
3885 //*****************************************************************************
3886 // Class to parse a list of method names and then find a match
3887 //*****************************************************************************
3889 struct CORINFO_SIG_INFO;
3891 class MethodNamesListBase
3895 LPUTF8 methodName; // NULL means wildcard
3896 LPUTF8 className; // NULL means wildcard
3897 int numArgs; // number of args for the method, -1 is wildcard
3898 MethodName *next; // Next name
3901 MethodName *pNames; // List of names
3903 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs);
3908 LIMITED_METHOD_CONTRACT;
3912 void Init(__in __in_z LPWSTR list)
3914 WRAPPER_NO_CONTRACT;
3921 void Insert(__in __in_z LPWSTR list);
3923 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3924 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3927 LIMITED_METHOD_CONTRACT;
3932 class MethodNamesList : public MethodNamesListBase
3937 WRAPPER_NO_CONTRACT;
3941 MethodNamesList(__in LPWSTR list)
3943 WRAPPER_NO_CONTRACT;
3949 WRAPPER_NO_CONTRACT;
3954 #if !defined(NO_CLRCONFIG)
3956 /**************************************************************************/
3957 /* simple wrappers around the REGUTIL and MethodNameList routines that make
3960 /* to be used as static variable - no constructor/destructor, assumes zero
3961 initialized memory */
3967 // NOTE: The following function is deprecated; use the CLRConfig class instead.
3968 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
3970 inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0)
3972 WRAPPER_NO_CONTRACT;
3973 // make sure that the memory was zero initialized
3974 _ASSERTE(m_inited == 0 || m_inited == 1);
3976 if (!m_inited) init_DontUse_(keyName, defaultVal);
3979 inline DWORD val(const CLRConfig::ConfigDWORDInfo & info)
3981 WRAPPER_NO_CONTRACT;
3982 // make sure that the memory was zero initialized
3983 _ASSERTE(m_inited == 0 || m_inited == 1);
3985 if (!m_inited) init(info);
3990 void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0);
3991 void init(const CLRConfig::ConfigDWORDInfo & info);
3998 /**************************************************************************/
4002 inline LPWSTR val(const CLRConfig::ConfigStringInfo & info)
4004 WRAPPER_NO_CONTRACT;
4005 // make sure that the memory was zero initialized
4006 _ASSERTE(m_inited == 0 || m_inited == 1);
4008 if (!m_inited) init(info);
4012 bool isInitialized()
4014 WRAPPER_NO_CONTRACT;
4016 // make sure that the memory was zero initialized
4017 _ASSERTE(m_inited == 0 || m_inited == 1);
4019 return m_inited == 1;
4023 void init(const CLRConfig::ConfigStringInfo & info);
4030 /**************************************************************************/
4031 class ConfigMethodSet
4036 WRAPPER_NO_CONTRACT;
4037 _ASSERTE(m_inited == 1);
4038 return m_list.IsEmpty();
4041 bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
4042 bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
4044 inline void ensureInit(const CLRConfig::ConfigStringInfo & info)
4046 WRAPPER_NO_CONTRACT;
4047 // make sure that the memory was zero initialized
4048 _ASSERTE(m_inited == 0 || m_inited == 1);
4050 if (!m_inited) init(info);
4054 void init(const CLRConfig::ConfigStringInfo & info);
4057 MethodNamesListBase m_list;
4062 #endif // !defined(NO_CLRCONFIG)
4064 //*****************************************************************************
4065 // Convert a pointer to a string into a GUID.
4066 //*****************************************************************************
4067 HRESULT LPCSTRToGuid( // Return status.
4068 LPCSTR szGuid, // String to convert.
4069 GUID *psGuid); // Buffer for converted GUID.
4071 //*****************************************************************************
4072 // Convert a GUID into a pointer to a string
4073 //*****************************************************************************
4074 int GuidToLPWSTR( // Return status.
4075 GUID Guid, // [IN] The GUID to convert.
4076 __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored
4077 DWORD cchGuid); // [IN] Size in wide chars of szGuid
4079 //*****************************************************************************
4080 // Parse a Wide char string into a GUID
4081 //*****************************************************************************
4083 GUID * Guid, // [OUT] The GUID to fill in
4084 __in_ecount(cchGuid) LPCWSTR szGuid, // [IN] String to parse
4085 DWORD cchGuid); // [IN] Count in wchars in string
4087 typedef VPTR(class RangeList) PTR_RangeList;
4092 VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList)
4094 #ifndef DACCESS_COMPILE
4100 LIMITED_METHOD_CONTRACT;
4104 // Wrappers to make the virtual calls DAC-safe.
4105 BOOL AddRange(const BYTE *start, const BYTE *end, void *id)
4107 return this->AddRangeWorker(start, end, id);
4110 void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL)
4112 return this->RemoveRangesWorker(id, start, end);
4115 BOOL IsInRange(TADDR address, TADDR *pID = NULL)
4119 return this->IsInRangeWorker(address, pID);
4122 #ifndef DACCESS_COMPILE
4124 // You can overload these two for synchronization (as LockedRangeList does)
4125 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id);
4126 // If both "start" and "end" are NULL, then this method deletes all ranges with
4127 // the given id (i.e. the original behaviour). Otherwise, it ignores the given
4128 // id and deletes all ranges falling in the region [start, end).
4129 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL);
4131 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id)
4135 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { }
4136 #endif // !DACCESS_COMPILE
4138 virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL);
4140 #ifdef DACCESS_COMPILE
4141 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4158 struct RangeListBlock
4160 Range ranges[RANGE_COUNT];
4161 DPTR(RangeListBlock) next;
4163 #ifdef DACCESS_COMPILE
4164 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4169 void InitBlock(RangeListBlock *block);
4171 RangeListBlock m_starterBlock;
4172 DPTR(RangeListBlock) m_firstEmptyBlock;
4173 TADDR m_firstEmptyRange;
4178 // A private function to do the equavilent of a CoCreateInstance in
4179 // cases where we can't make the real call. Use this when, for
4180 // instance, you need to create a symbol reader in the Runtime but
4181 // we're not CoInitialized. Obviously, this is only good for COM
4182 // objects for which CoCreateInstance is just a glorified
4183 // find-and-load-me operation.
4186 HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid,
4190 HMODULE * phmodDll);
4192 // Provided for backward compatibility and for code that doesn't need the HMODULE of the
4193 // DLL that was loaded to create the COM object. See comment at implementation of
4194 // code:FakeCoCreateInstanceEx for more details.
4195 inline HRESULT FakeCoCreateInstance(REFCLSID rclsid,
4205 return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL);
4208 HRESULT FakeCoCallDllGetClassObject(REFCLSID rclsid,
4212 HMODULE * phmodDll);
4214 //*****************************************************************************
4215 // Gets the directory based on the location of the module. This routine
4216 // is called at COR setup time. Set is called during EEStartup and by the
4217 // MetaData dispenser.
4218 //*****************************************************************************
4219 HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength);
4220 LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL);
4222 //*****************************************************************************
4223 // This function validates the given Method/Field/Standalone signature. (util.cpp)
4224 //*****************************************************************************
4225 struct IMDInternalImport;
4226 HRESULT validateTokenSig(
4227 mdToken tk, // [IN] Token whose signature needs to be validated.
4228 PCCOR_SIGNATURE pbSig, // [IN] Signature.
4229 ULONG cbSig, // [IN] Size in bytes of the signature.
4230 DWORD dwFlags, // [IN] Method flags.
4231 IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr
4233 //*****************************************************************************
4234 // Determine the version number of the runtime that was used to build the
4235 // specified image. The pMetadata pointer passed in is the pointer to the
4236 // metadata contained in the image.
4237 //*****************************************************************************
4238 HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString);
4239 void AdjustImageRuntimeVersion (SString* pVersion);
4241 //*****************************************************************************
4242 // The registry keys and values that contain the information regarding
4243 // the default registered unmanaged debugger.
4244 //*****************************************************************************
4245 SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4246 SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4248 SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
4249 SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger");
4250 SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto");
4251 SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList");
4253 BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key.
4254 LPCWSTR szKey, // Key name to look at.
4255 LPCWSTR szName, // Name of value to get.
4256 long *pValue, // Put value here, if found.
4257 BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64
4259 HRESULT GetCurrentModuleFileName(SString& pBuffer);
4261 //*****************************************************************************
4262 // Retrieve information regarding what registered default debugger
4263 //*****************************************************************************
4264 void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto);
4265 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto);
4267 void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch);
4270 //*****************************************************************************
4271 // Convert a UTF8 string to Unicode, into a CQuickArray<WCHAR>.
4272 //*****************************************************************************
4274 LPCUTF8 pStr, // The string to convert.
4275 CQuickArray<WCHAR> &rStr, // The QuickArray<WCHAR> to convert it into.
4276 int iCurLen); // Inital characters in the array to leave (default 0).
4278 //*****************************************************************************
4279 // Extract the movl 64-bit unsigned immediate from an IA64 bundle
4281 //*****************************************************************************
4282 UINT64 GetIA64Imm64(UINT64 * pBundle);
4283 UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1);
4285 //*****************************************************************************
4286 // Deposit the movl 64-bit unsigned immediate into an IA64 bundle
4288 //*****************************************************************************
4289 void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64);
4291 //*****************************************************************************
4292 // Extract the IP-Relative signed 25-bit immediate from an IA64 bundle
4293 // (Formats B1, B2 or B3)
4294 // Note that due to branch target alignment requirements
4295 // the lowest four bits in the result will always be zero.
4296 //*****************************************************************************
4297 INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot);
4298 INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot);
4300 //*****************************************************************************
4301 // Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle
4302 // (Formats B1, B2 or B3)
4303 // Note that due to branch target alignment requirements
4304 // the lowest four bits are required to be zero.
4305 //*****************************************************************************
4306 void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25);
4308 //*****************************************************************************
4309 // Extract the IP-Relative signed 64-bit immediate from an IA64 bundle
4310 // (Formats X3 or X4)
4311 //*****************************************************************************
4312 INT64 GetIA64Rel64(UINT64 * pBundle);
4313 INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1);
4315 //*****************************************************************************
4316 // Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle
4317 // (Formats X3 or X4)
4318 //*****************************************************************************
4319 void PutIA64Rel64(UINT64 * pBundle, INT64 imm64);
4321 //*****************************************************************************
4322 // Extract the 32-bit immediate from movw/movt Thumb2 sequence
4323 //*****************************************************************************
4324 UINT32 GetThumb2Mov32(UINT16 * p);
4326 //*****************************************************************************
4327 // Deposit the 32-bit immediate into movw/movt Thumb2 sequence
4328 //*****************************************************************************
4329 void PutThumb2Mov32(UINT16 * p, UINT32 imm32);
4331 //*****************************************************************************
4332 // Extract the 24-bit rel offset from bl instruction
4333 //*****************************************************************************
4334 INT32 GetThumb2BlRel24(UINT16 * p);
4336 //*****************************************************************************
4337 // Extract the 24-bit rel offset from bl instruction
4338 //*****************************************************************************
4339 void PutThumb2BlRel24(UINT16 * p, INT32 imm24);
4341 //*****************************************************************************
4342 // Extract the PC-Relative offset from a b or bl instruction
4343 //*****************************************************************************
4344 INT32 GetArm64Rel28(UINT32 * pCode);
4346 //*****************************************************************************
4347 // Extract the PC-Relative page address from an adrp instruction
4348 //*****************************************************************************
4349 INT32 GetArm64Rel21(UINT32 * pCode);
4351 //*****************************************************************************
4352 // Extract the page offset from an add instruction
4353 //*****************************************************************************
4354 INT32 GetArm64Rel12(UINT32 * pCode);
4356 //*****************************************************************************
4357 // Deposit the PC-Relative offset 'imm28' into a b or bl instruction
4358 //*****************************************************************************
4359 void PutArm64Rel28(UINT32 * pCode, INT32 imm28);
4361 //*****************************************************************************
4362 // Deposit the PC-Relative page address 'imm21' into an adrp instruction
4363 //*****************************************************************************
4364 void PutArm64Rel21(UINT32 * pCode, INT32 imm21);
4366 //*****************************************************************************
4367 // Deposit the page offset 'imm12' into an add instruction
4368 //*****************************************************************************
4369 void PutArm64Rel12(UINT32 * pCode, INT32 imm12);
4371 //*****************************************************************************
4372 // Returns whether the offset fits into bl instruction
4373 //*****************************************************************************
4374 inline bool FitsInThumb2BlRel24(INT32 imm24)
4376 return ((imm24 << 7) >> 7) == imm24;
4379 //*****************************************************************************
4380 // Returns whether the offset fits into an Arm64 b or bl instruction
4381 //*****************************************************************************
4382 inline bool FitsInRel28(INT32 val32)
4384 return (val32 >= -0x08000000) && (val32 < 0x08000000);
4387 //*****************************************************************************
4388 // Returns whether the offset fits into an Arm64 adrp instruction
4389 //*****************************************************************************
4390 inline bool FitsInRel21(INT32 val32)
4392 return (val32 >= 0) && (val32 <= 0x001FFFFF);
4395 //*****************************************************************************
4396 // Returns whether the offset fits into an Arm64 add instruction
4397 //*****************************************************************************
4398 inline bool FitsInRel12(INT32 val32)
4400 return (val32 >= 0) && (val32 <= 0x00000FFF);
4403 //*****************************************************************************
4404 // Returns whether the offset fits into an Arm64 b or bl instruction
4405 //*****************************************************************************
4406 inline bool FitsInRel28(INT64 val64)
4408 return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
4411 //*****************************************************************************
4412 // Splits a command line into argc/argv lists, using the VC7 parsing rules.
4413 // This functions interface mimics the CommandLineToArgvW api.
4414 // If function fails, returns NULL.
4415 // If function suceeds, call delete [] on return pointer when done.
4416 //*****************************************************************************
4417 LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs);
4420 // TEB access can be dangerous when using fibers because a fiber may
4421 // run on multiple threads. If the TEB pointer is retrieved and saved
4422 // and then a fiber is moved to a different thread, when it accesses
4423 // the saved TEB pointer, it will be looking at the TEB state for a
4426 // These accessors serve the purpose of retrieving information from the
4427 // TEB in a manner that ensures that the current fiber will not switch
4428 // threads while the access is occuring.
4433 #if defined(FEATURE_PAL)
4435 // returns pointer that uniquely identifies the fiber
4436 static void* GetFiberPtrId()
4438 LIMITED_METHOD_CONTRACT;
4439 // not fiber for FEATURE_PAL - use the regular thread ID
4440 return (void *)(size_t)GetCurrentThreadId();
4443 static void* InvalidFiberPtrId()
4448 static void* GetStackBase()
4450 return PAL_GetStackBase();
4453 static void* GetStackLimit()
4455 return PAL_GetStackLimit();
4458 #else // !FEATURE_PAL
4460 // returns pointer that uniquely identifies the fiber
4461 static void* GetFiberPtrId()
4463 LIMITED_METHOD_CONTRACT;
4464 // stackbase is the unique fiber identifier
4465 return NtCurrentTeb()->NtTib.StackBase;
4468 static void* GetStackBase()
4470 LIMITED_METHOD_CONTRACT;
4471 return NtCurrentTeb()->NtTib.StackBase;
4474 static void* GetStackLimit()
4476 LIMITED_METHOD_CONTRACT;
4477 return NtCurrentTeb()->NtTib.StackLimit;
4480 // Please don't start to use this method unless you absolutely have to.
4481 // The reason why this is added is for WIN64 to support LEGACY PE-style TLS
4482 // variables. On X86 it is supported by the JIT compilers themselves. On
4483 // WIN64 we build more logic into the JIT helper for accessing fields.
4484 static void* GetLegacyThreadLocalStoragePointer()
4486 LIMITED_METHOD_CONTRACT;
4487 return NtCurrentTeb()->ThreadLocalStoragePointer;
4490 static void* GetOleReservedPtr()
4492 LIMITED_METHOD_CONTRACT;
4493 return NtCurrentTeb()->ReservedForOle;
4496 static void* GetProcessEnvironmentBlock()
4498 LIMITED_METHOD_CONTRACT;
4499 return NtCurrentTeb()->ProcessEnvironmentBlock;
4503 static void* InvalidFiberPtrId()
4507 #endif // !FEATURE_PAL
4510 #if !defined(DACCESS_COMPILE)
4512 // check if current thread is a GC thread (concurrent or server)
4513 inline BOOL IsGCSpecialThread ()
4515 STATIC_CONTRACT_NOTHROW;
4516 STATIC_CONTRACT_GC_NOTRIGGER;
4517 STATIC_CONTRACT_MODE_ANY;
4518 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4520 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC);
4523 // check if current thread is a Gate thread
4524 inline BOOL IsGateSpecialThread ()
4526 STATIC_CONTRACT_NOTHROW;
4527 STATIC_CONTRACT_GC_NOTRIGGER;
4528 STATIC_CONTRACT_MODE_ANY;
4530 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate);
4533 // check if current thread is a Timer thread
4534 inline BOOL IsTimerSpecialThread ()
4536 STATIC_CONTRACT_NOTHROW;
4537 STATIC_CONTRACT_GC_NOTRIGGER;
4538 STATIC_CONTRACT_MODE_ANY;
4540 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer);
4543 // check if current thread is a debugger helper thread
4544 inline BOOL IsDbgHelperSpecialThread ()
4546 STATIC_CONTRACT_NOTHROW;
4547 STATIC_CONTRACT_GC_NOTRIGGER;
4548 STATIC_CONTRACT_MODE_ANY;
4550 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper);
4553 // check if current thread is a debugger helper thread
4554 inline BOOL IsETWRundownSpecialThread ()
4556 STATIC_CONTRACT_NOTHROW;
4557 STATIC_CONTRACT_GC_NOTRIGGER;
4558 STATIC_CONTRACT_MODE_ANY;
4560 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread);
4563 // check if current thread is a generic instantiation lookup compare thread
4564 inline BOOL IsGenericInstantiationLookupCompareThread ()
4566 STATIC_CONTRACT_NOTHROW;
4567 STATIC_CONTRACT_GC_NOTRIGGER;
4568 STATIC_CONTRACT_MODE_ANY;
4570 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare);
4573 // check if current thread is a thread which is performing shutdown
4574 inline BOOL IsShutdownSpecialThread ()
4576 STATIC_CONTRACT_NOTHROW;
4577 STATIC_CONTRACT_GC_NOTRIGGER;
4578 STATIC_CONTRACT_MODE_ANY;
4580 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown);
4583 inline BOOL IsThreadPoolIOCompletionSpecialThread ()
4585 STATIC_CONTRACT_NOTHROW;
4586 STATIC_CONTRACT_GC_NOTRIGGER;
4587 STATIC_CONTRACT_MODE_ANY;
4589 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion);
4592 inline BOOL IsThreadPoolWorkerSpecialThread ()
4594 STATIC_CONTRACT_NOTHROW;
4595 STATIC_CONTRACT_GC_NOTRIGGER;
4596 STATIC_CONTRACT_MODE_ANY;
4598 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker);
4601 inline BOOL IsWaitSpecialThread ()
4603 STATIC_CONTRACT_NOTHROW;
4604 STATIC_CONTRACT_GC_NOTRIGGER;
4605 STATIC_CONTRACT_MODE_ANY;
4607 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait);
4610 // check if current thread is a thread which is performing shutdown
4611 inline BOOL IsSuspendEEThread ()
4613 STATIC_CONTRACT_NOTHROW;
4614 STATIC_CONTRACT_GC_NOTRIGGER;
4615 STATIC_CONTRACT_MODE_ANY;
4617 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE);
4620 inline BOOL IsFinalizerThread ()
4622 STATIC_CONTRACT_NOTHROW;
4623 STATIC_CONTRACT_GC_NOTRIGGER;
4624 STATIC_CONTRACT_MODE_ANY;
4626 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
4629 inline BOOL IsADUnloadHelperThread ()
4631 STATIC_CONTRACT_NOTHROW;
4632 STATIC_CONTRACT_GC_NOTRIGGER;
4633 STATIC_CONTRACT_MODE_ANY;
4635 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ADUnloadHelper);
4638 inline BOOL IsShutdownHelperThread ()
4640 STATIC_CONTRACT_NOTHROW;
4641 STATIC_CONTRACT_GC_NOTRIGGER;
4642 STATIC_CONTRACT_MODE_ANY;
4644 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper);
4647 inline BOOL IsProfilerAttachThread ()
4649 STATIC_CONTRACT_NOTHROW;
4650 STATIC_CONTRACT_GC_NOTRIGGER;
4651 STATIC_CONTRACT_MODE_ANY;
4653 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach);
4656 // set specical type for current thread
4657 inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag)
4659 STATIC_CONTRACT_NOTHROW;
4660 STATIC_CONTRACT_GC_NOTRIGGER;
4661 STATIC_CONTRACT_MODE_ANY;
4662 STATIC_CONTRACT_SO_TOLERANT;
4664 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag));
4667 // clear specical type for current thread
4668 inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
4670 STATIC_CONTRACT_NOTHROW;
4671 STATIC_CONTRACT_GC_NOTRIGGER;
4672 STATIC_CONTRACT_MODE_ANY;
4674 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag));
4677 #endif //!DACCESS_COMPILE
4679 #ifdef DACCESS_COMPILE
4680 #define SET_THREAD_TYPE_STACKWALKER(pThread)
4681 #define CLEAR_THREAD_TYPE_STACKWALKER()
4682 #else // DACCESS_COMPILE
4683 #define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread)
4684 #define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
4685 #endif // DACCESS_COMPILE
4687 inline BOOL IsStackWalkerThread()
4689 STATIC_CONTRACT_NOTHROW;
4690 STATIC_CONTRACT_GC_NOTRIGGER;
4691 STATIC_CONTRACT_MODE_ANY;
4692 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4694 #if defined(DACCESS_COMPILE)
4697 return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL;
4701 inline BOOL IsGCThread ()
4703 STATIC_CONTRACT_NOTHROW;
4704 STATIC_CONTRACT_GC_NOTRIGGER;
4705 STATIC_CONTRACT_MODE_ANY;
4706 STATIC_CONTRACT_SUPPORTS_DAC;
4707 STATIC_CONTRACT_SO_TOLERANT;
4709 #if !defined(DACCESS_COMPILE)
4710 return IsGCSpecialThread () || IsSuspendEEThread ();
4716 class ClrFlsThreadTypeSwitch
4719 ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag)
4721 STATIC_CONTRACT_NOTHROW;
4722 STATIC_CONTRACT_GC_NOTRIGGER;
4723 STATIC_CONTRACT_MODE_ANY;
4725 #ifndef DACCESS_COMPILE
4727 m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag);
4729 // In debug builds, remember the full group of flags that were set at the time
4730 // the constructor was called. This will be used in ASSERTs in the destructor
4731 INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType));
4733 if (!m_fPreviouslySet)
4735 ClrFlsSetThreadType(flag);
4737 #endif // DACCESS_COMPILE
4740 ~ClrFlsThreadTypeSwitch ()
4742 STATIC_CONTRACT_NOTHROW;
4743 STATIC_CONTRACT_GC_NOTRIGGER;
4744 STATIC_CONTRACT_MODE_ANY;
4746 #ifndef DACCESS_COMPILE
4747 // This holder should only be used to set (and thus restore) ONE thread type flag
4748 // at a time. If more than that one flag was modified since this holder was
4749 // instantiated, then this holder still restores only the flag it knows about. To
4750 // prevent confusion, assert if some other flag was modified, so the user doesn't
4751 // expect the holder to restore the entire original set of flags.
4753 // The expression below says that the only difference between the previous flag
4754 // group and the current flag group should be m_flag (or no difference at all, if
4755 // m_flag's state didn't actually change).
4756 _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag);
4758 if (m_fPreviouslySet)
4760 ClrFlsSetThreadType(m_flag);
4764 ClrFlsClearThreadType(m_flag);
4766 #endif // DACCESS_COMPILE
4770 TlsThreadTypeFlag m_flag;
4771 BOOL m_fPreviouslySet;
4772 INDEBUG(size_t m_nPreviousFlagGroup);
4775 class ClrFlsValueSwitch
4778 ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value)
4780 STATIC_CONTRACT_NOTHROW;
4781 STATIC_CONTRACT_GC_NOTRIGGER;
4782 STATIC_CONTRACT_MODE_ANY;
4784 #ifndef DACCESS_COMPILE
4786 m_PreviousValue = ClrFlsGetValue(slot);
4787 ClrFlsSetValue(slot, value);
4788 #endif // DACCESS_COMPILE
4791 ~ClrFlsValueSwitch ()
4793 STATIC_CONTRACT_NOTHROW;
4794 STATIC_CONTRACT_GC_NOTRIGGER;
4795 STATIC_CONTRACT_MODE_ANY;
4797 #ifndef DACCESS_COMPILE
4798 ClrFlsSetValue(m_slot, m_PreviousValue);
4799 #endif // DACCESS_COMPILE
4803 PVOID m_PreviousValue;
4804 PredefinedTlsSlots m_slot;
4807 //*********************************************************************************
4809 // When we're hosted, operations called by the host (such as Thread::YieldTask)
4810 // may not cause calls back into the host, as the host needs not be reentrant.
4811 // Use the following holder for code in which calls into the host are forbidden.
4812 // (If a call into the host is attempted nevertheless, an assert will fire.)
4814 class ForbidCallsIntoHostOnThisThread
4817 static Volatile<PVOID> s_pvOwningFiber;
4819 FORCEINLINE static BOOL Enter(BOOL)
4821 WRAPPER_NO_CONTRACT;
4822 return InterlockedCompareExchangePointer(
4823 &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL;
4826 FORCEINLINE static void Leave(BOOL)
4828 LIMITED_METHOD_CONTRACT;
4829 s_pvOwningFiber = NULL;
4833 typedef ConditionalStateHolder<BOOL, ForbidCallsIntoHostOnThisThread::Enter, ForbidCallsIntoHostOnThisThread::Leave> Holder;
4835 FORCEINLINE static BOOL CanThisThreadCallIntoHost()
4837 WRAPPER_NO_CONTRACT;
4838 return s_pvOwningFiber != ClrTeb::GetFiberPtrId();
4842 typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder;
4844 FORCEINLINE BOOL CanThisThreadCallIntoHost()
4846 WRAPPER_NO_CONTRACT;
4847 return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost();
4850 //*********************************************************************************
4852 #include "contract.inl"
4859 template < typename T >
4862 bool operator()( T const & first, T const & second ) const
4864 return first < second;
4868 template < typename T >
4871 bool operator()( T const & first, T const & second ) const
4873 return first > second;
4881 template< typename Iter, typename Pred >
4882 void sort( Iter begin, Iter end, Pred pred );
4884 template< typename T, typename Pred >
4885 void sort( T * begin, T * end, Pred pred )
4887 struct sort_helper : CQuickSort< T >
4889 sort_helper( T * begin, T * end, Pred pred )
4890 : CQuickSort< T >( begin, end - begin )
4894 virtual int Compare( T * first, T * second )
4896 return m_pred( *first, *second ) ? -1
4897 : ( m_pred( *second, *first ) ? 1 : 0 );
4903 sort_helper sort_obj( begin, end, pred );
4908 template < typename Iter >
4909 void sort( Iter begin, Iter end );
4911 template < typename T >
4912 void sort( T * begin, T * end )
4914 util::sort( begin, end, util::less< T >() );
4918 // binary search adapters
4921 template < typename Iter, typename T, typename Pred >
4922 Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred );
4924 template < typename T, typename Pred >
4925 T * lower_bound( T * begin, T * end, T const & val, Pred pred )
4927 for (; begin != end; )
4929 T * mid = begin + ( end - begin ) / 2;
4930 if ( pred( *mid, val ) )
4940 template < typename Iter, typename T >
4941 Iter lower_bound( Iter begin, Iter end, T const & val );
4943 template < typename T >
4944 T * lower_bound( T * begin, T * end, T const & val )
4946 return util::lower_bound( begin, end, val, util::less< T >() );
4951 /* ------------------------------------------------------------------------ *
4952 * Overloaded operators for the executable heap
4953 * ------------------------------------------------------------------------ */
4957 struct CExecutable { int x; };
4958 extern const CExecutable executable;
4960 void * __cdecl operator new(size_t n, const CExecutable&);
4961 void * __cdecl operator new[](size_t n, const CExecutable&);
4962 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&);
4963 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&);
4967 // Executable heap delete to match the executable heap new above.
4969 template<class T> void DeleteExecutable(T *p)
4975 ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p);
4979 #endif // FEATURE_PAL
4981 INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
4983 BOOL NoGuiOnAssert();
4985 VOID TerminateOnAssert();
4988 class HighCharHelper {
4990 static inline BOOL IsHighChar(int c) {
4991 return (BOOL)HighCharTable[c];
4995 static const BYTE HighCharTable[];
4999 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
5001 FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
5003 typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
5005 BOOL FileExists(LPCWSTR filename);
5008 // a class for general x.x version info
5009 class MajorMinorVersionInfo
5016 MajorMinorVersionInfo()
5018 LIMITED_METHOD_CONTRACT;
5019 bInitialized = FALSE;
5020 ZeroMemory(version,sizeof(version));
5023 MajorMinorVersionInfo(WORD wMajor, WORD wMinor)
5025 WRAPPER_NO_CONTRACT;
5026 Init(wMajor,wMinor);
5030 BOOL IsInitialized() const
5032 LIMITED_METHOD_CONTRACT;
5033 return bInitialized;
5038 LIMITED_METHOD_CONTRACT;
5044 LIMITED_METHOD_CONTRACT;
5049 void Init(WORD wMajor, WORD wMinor)
5051 LIMITED_METHOD_CONTRACT;
5058 // CLR runtime version info in Major/Minor form
5059 class RUNTIMEVERSIONINFO : public MajorMinorVersionInfo
5061 static RUNTIMEVERSIONINFO notDefined;
5064 RUNTIMEVERSIONINFO() {};
5066 RUNTIMEVERSIONINFO(WORD wMajor, WORD wMinor) :
5067 MajorMinorVersionInfo(wMajor,wMinor){};
5069 // CLR version specific helpers
5070 BOOL IsPreWhidbey() const
5072 WRAPPER_NO_CONTRACT;
5073 return (Major() == 1) && (Minor() <= 1);
5076 static const RUNTIMEVERSIONINFO& NotApplicable()
5078 LIMITED_METHOD_CONTRACT;
5084 // HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical
5085 // to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address,
5086 // and so is represented by TADDR.
5088 #ifdef DACCESS_COMPILE
5089 typedef TADDR HMODULE_TGT;
5091 typedef HMODULE HMODULE_TGT;
5094 BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
5096 //----------------------------------------------------------------------------------------
5097 // The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical
5098 // callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call
5099 // InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime
5100 // calls a special initialization routine exposed by the loaded module with the callbacks,
5101 // which in turn calls InitUtilcode.
5103 // This structure collects all of the critical callback info passed in InitUtilcode().
5104 // Note that one of them is GetCLRFunction() which is itself a gofer for many other
5105 // callbacks. If a callback fetch be safely deferred until we have TLS and stack probe
5106 // functionality running, it should be added to that function rather than this structure.
5107 // Things like IEE are here because that callback has to be set up before GetCLRFunction()
5108 // can be safely called.
5109 //----------------------------------------------------------------------------------------
5110 struct CoreClrCallbacks
5112 typedef IExecutionEngine* (__stdcall * pfnIEE_t)();
5113 typedef HRESULT (__stdcall * pfnGetCORSystemDirectory_t)(SString& pbuffer);
5114 typedef void* (__stdcall * pfnGetCLRFunction_t)(LPCSTR functionName);
5116 HINSTANCE m_hmodCoreCLR;
5118 pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory;
5119 pfnGetCLRFunction_t m_pfnGetCLRFunction;
5123 // For DAC, we include this functionality only when EH SxS is enabled.
5125 //----------------------------------------------------------------------------------------
5126 // CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback
5127 // pointers it needs.
5128 //----------------------------------------------------------------------------------------
5129 VOID InitUtilcode(const CoreClrCallbacks &cccallbacks);
5130 CoreClrCallbacks const & GetClrCallbacks();
5132 //----------------------------------------------------------------------------------------
5133 // Stuff below is for utilcode.lib eyes only.
5134 //----------------------------------------------------------------------------------------
5136 // Stores callback pointers provided by InitUtilcode().
5137 extern CoreClrCallbacks g_CoreClrCallbacks;
5139 // Throws up a helpful dialog if InitUtilcode() wasn't called.
5141 void OnUninitializedCoreClrCallbacks();
5142 #define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks()
5144 #define VALIDATECORECLRCALLBACKS()
5148 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
5150 // Corrupting Exception limited support for outside the VM folder
5151 BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
5153 #endif // FEATURE_CORRUPTING_EXCEPTIONS
5156 BOOL IsV2RuntimeLoaded(void);
5160 // These are type-safe versions of Interlocked[Compare]Exchange
5161 // They avoid invoking struct cast operations via reinterpreting
5162 // the struct's address as a LONG* or LONGLONG* and dereferencing it.
5164 // If we had a global ::operator & (unary), we would love to use that
5165 // to ensure we were not also accidentally getting a structs's provided
5166 // operator &. TODO: probe with a static_assert?
5168 template <typename T, int SIZE = sizeof(T)>
5169 struct InterlockedCompareExchangeHelper;
5171 template <typename T>
5172 struct InterlockedCompareExchangeHelper<T, sizeof(LONG)>
5174 static inline T InterlockedExchange(
5175 T volatile * target,
5178 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5179 LONG res = ::InterlockedExchange(
5180 reinterpret_cast<LONG volatile *>(target),
5181 *reinterpret_cast<LONG *>(/*::operator*/&(value)));
5182 return *reinterpret_cast<T*>(&res);
5185 static inline T InterlockedCompareExchange(
5186 T volatile * destination,
5190 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5191 LONG res = ::InterlockedCompareExchange(
5192 reinterpret_cast<LONG volatile *>(destination),
5193 *reinterpret_cast<LONG*>(/*::operator*/&(exchange)),
5194 *reinterpret_cast<LONG*>(/*::operator*/&(comparand)));
5195 return *reinterpret_cast<T*>(&res);
5199 template <typename T>
5200 struct InterlockedCompareExchangeHelper<T, sizeof(LONGLONG)>
5202 static inline T InterlockedExchange(
5203 T volatile * target,
5206 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5207 LONGLONG res = ::InterlockedExchange64(
5208 reinterpret_cast<LONGLONG volatile *>(target),
5209 *reinterpret_cast<LONGLONG *>(/*::operator*/&(value)));
5210 return *reinterpret_cast<T*>(&res);
5213 static inline T InterlockedCompareExchange(
5214 T volatile * destination,
5218 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5219 LONGLONG res = ::InterlockedCompareExchange64(
5220 reinterpret_cast<LONGLONG volatile *>(destination),
5221 *reinterpret_cast<LONGLONG*>(/*::operator*/&(exchange)),
5222 *reinterpret_cast<LONGLONG*>(/*::operator*/&(comparand)));
5223 return *reinterpret_cast<T*>(&res);
5228 template <typename T>
5229 inline T InterlockedExchangeT(
5230 T volatile * target,
5233 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedExchange(
5237 template <typename T>
5238 inline T InterlockedCompareExchangeT(
5239 T volatile * destination,
5243 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedCompareExchange(
5244 destination, exchange, comparand);
5247 // Pointer variants for Interlocked[Compare]ExchangePointer
5248 // If the underlying type is a const type, we have to remove its constness
5249 // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments.
5250 template <typename T>
5251 inline T* InterlockedExchangeT(
5252 T* volatile * target,
5255 //STATIC_ASSERT(value == 0);
5256 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5257 return reinterpret_cast<T*>(InterlockedExchangePointer(
5258 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(target)),
5259 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(value))));
5262 template <typename T>
5263 inline T* InterlockedCompareExchangeT(
5264 T* volatile * destination,
5268 //STATIC_ASSERT(exchange == 0);
5269 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5270 return reinterpret_cast<T*>(InterlockedCompareExchangePointer(
5271 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(destination)),
5272 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(exchange)),
5273 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(comparand))));
5276 // NULL pointer variants of the above to avoid having to cast NULL
5277 // to the appropriate pointer type.
5278 template <typename T>
5279 inline T* InterlockedExchangeT(
5280 T* volatile * target,
5281 int value) // When NULL is provided as argument.
5283 //STATIC_ASSERT(value == 0);
5284 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5287 template <typename T>
5288 inline T* InterlockedCompareExchangeT(
5289 T* volatile * destination,
5290 int exchange, // When NULL is provided as argument.
5293 //STATIC_ASSERT(exchange == 0);
5294 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5297 template <typename T>
5298 inline T* InterlockedCompareExchangeT(
5299 T* volatile * destination,
5301 int comparand) // When NULL is provided as argument.
5303 //STATIC_ASSERT(comparand == 0);
5304 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5307 // NULL pointer variants of the above to avoid having to cast NULL
5308 // to the appropriate pointer type.
5309 template <typename T>
5310 inline T* InterlockedExchangeT(
5311 T* volatile * target,
5312 std::nullptr_t value) // When nullptr is provided as argument.
5314 //STATIC_ASSERT(value == 0);
5315 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5318 template <typename T>
5319 inline T* InterlockedCompareExchangeT(
5320 T* volatile * destination,
5321 std::nullptr_t exchange, // When nullptr is provided as argument.
5324 //STATIC_ASSERT(exchange == 0);
5325 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5328 template <typename T>
5329 inline T* InterlockedCompareExchangeT(
5330 T* volatile * destination,
5332 std::nullptr_t comparand) // When nullptr is provided as argument.
5334 //STATIC_ASSERT(comparand == 0);
5335 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5338 #undef InterlockedExchangePointer
5339 #define InterlockedExchangePointer Use_InterlockedExchangeT
5340 #undef InterlockedCompareExchangePointer
5341 #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT
5343 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
5344 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
5345 HRESULT GetHModuleDirectory(HMODULE hMod, SString& wszPath);
5346 HRESULT CopySystemDirectory(const SString& pPathString, SString& pbuffer);
5348 HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true);
5349 // This is a slight variation that can be used for anything else
5350 typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR);
5351 void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL);
5353 BOOL IsClrHostedLegacyComObject(REFCLSID rclsid);
5358 // Helper to support termination due to heap corruption
5359 // It's not supported on Win2K, so we have to manually delay load it
5360 void EnableTerminationOnHeapCorruption();
5364 namespace Clr { namespace Util
5366 // This api returns a pointer to a null-terminated string that contains the local appdata directory
5367 // or it returns NULL in the case that the directory could not be found. The return value from this function
5368 // is not actually checked for existence.
5369 HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory);
5370 HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory);
5374 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
5375 __success(return == S_OK)
5376 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
5379 #ifdef FEATURE_COMINTEROP
5382 HRESULT FindServerUsingCLSID(REFCLSID rclsid, SString & ssServerName);
5383 HRESULT FindServerUsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszServerName);
5384 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name);
5385 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszInprocServer32Name);
5386 BOOL IsMscoreeInprocServer32(const SString & ssInprocServer32Name);
5387 BOOL CLSIDHasMscoreeAsInprocServer32(REFCLSID rclsid);
5389 #endif // FEATURE_COMINTEROP
5393 static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\");
5394 static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\";
5396 void GetModuleFileName(
5398 SString & ssFileName,
5399 bool fAllowLongFileNames = false);
5401 __success(return == S_OK)
5402 HRESULT GetModuleFileName(
5404 __deref_out_z LPWSTR * pwszFileName,
5405 bool fAllowLongFileNames = false);
5407 void GetFullPathName(
5408 SString const & ssFileName,
5409 SString & ssPathName,
5410 DWORD * pdwFilePartIdx,
5411 bool fAllowLongFileNames = false);
5416 #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE)
5417 // Forward declaration of AppX::IsAppXProcess
5418 namespace AppX { bool IsAppXProcess(); }
5420 // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes.
5421 inline DWORD GetLoadWithAlteredSearchPathFlag()
5423 WRAPPER_NO_CONTRACT;
5424 return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
5426 #else // FEATURE_APPX && !DACCESS_COMPILE
5427 // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally.
5428 inline DWORD GetLoadWithAlteredSearchPathFlag()
5430 LIMITED_METHOD_CONTRACT;
5431 #ifdef LOAD_WITH_ALTERED_SEARCH_PATH
5432 return LOAD_WITH_ALTERED_SEARCH_PATH;
5437 #endif // FEATURE_APPX && !DACCESS_COMPILE
5439 // clr::SafeAddRef and clr::SafeRelease helpers.
5442 //=================================================================================================================
5443 template <typename ItfT>
5445 typename std::enable_if< std::is_pointer<ItfT>::value, ItfT >::type
5446 SafeAddRef(ItfT pItf)
5448 STATIC_CONTRACT_LIMITED_METHOD;
5449 if (pItf != nullptr)
5456 //=================================================================================================================
5457 template <typename ItfT>
5458 typename std::enable_if< std::is_pointer<ItfT>::value && std::is_reference<ItfT>::value, ULONG >::type
5459 SafeRelease(ItfT pItf)
5461 STATIC_CONTRACT_LIMITED_METHOD;
5463 if (pItf != nullptr)
5465 res = pItf->Release();
5471 //=================================================================================================================
5472 template <typename ItfT>
5473 typename std::enable_if< std::is_pointer<ItfT>::value && !std::is_reference<ItfT>::value, ULONG >::type
5474 SafeRelease(ItfT pItf)
5476 STATIC_CONTRACT_LIMITED_METHOD;
5478 if (pItf != nullptr)
5480 res = pItf->Release();
5489 //=================================================================================================================
5490 template <typename PtrT>
5492 typename std::enable_if< std::is_pointer<PtrT>::value, PtrT >::type
5493 SafeDelete(PtrT & ptr)
5495 STATIC_CONTRACT_LIMITED_METHOD;
5504 // ======================================================================================
5505 // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp)
5507 struct SpinConstants
5509 DWORD dwInitialDuration;
5510 DWORD dwMaximumDuration;
5511 DWORD dwBackoffFactor;
5512 DWORD dwRepetitions;
5515 extern SpinConstants g_SpinConstants;
5517 // ======================================================================================
5519 void* __stdcall GetCLRFunction(LPCSTR FunctionName);
5521 #endif // __UtilCode_h__