2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 //*****************************************************************************
8 // Utility functions implemented in UtilCode.lib.
10 //*****************************************************************************
12 #ifndef __UtilCode_h__
13 #define __UtilCode_h__
28 #include "debugmacros.h"
29 #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 // Windows CoreSystem has a different naming scheme for some dlls, which we must take account of when doing
52 // LoadLibrary and the like.
53 #if defined(FEATURE_CORESYSTEM)
54 #define WINDOWS_KERNEL32_DLLNAME_A "kernelbase"
55 #define WINDOWS_KERNEL32_DLLNAME_W W("kernelbase")
56 #elif !defined(FEATURE_CORESYSTEM) || defined(CROSS_COMPILE)
57 #define WINDOWS_KERNEL32_DLLNAME_A "kernel32"
58 #define WINDOWS_KERNEL32_DLLNAME_W W("kernel32")
61 class StringArrayList;
63 #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
69 // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct
70 // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this
71 // is handled automatically for us by the compiler. When generating and working with code generated
72 // dynamically we have to be careful to set or mask-out this bit as appropriate.
77 // Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff).
78 inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit)
80 _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit));
81 return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1);
84 // Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the
86 inline bool Is32BitInstruction(WORD opcode)
88 return BitExtract(opcode, 15, 11) >= 0x1d;
91 template <typename ResultType, typename SourceType>
92 inline ResultType DataPointerToThumbCode(SourceType pCode)
94 return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE);
97 template <typename ResultType, typename SourceType>
98 inline ResultType ThumbCodeToDataPointer(SourceType pCode)
100 return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE);
103 #endif // _TARGET_ARM_
105 // Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function;
106 // on ARM, this will mask off the THUMB bit.
107 inline TADDR PCODEToPINSTR(PCODE pc)
110 return ThumbCodeToDataPointer<TADDR,PCODE>(pc);
112 return dac_cast<PCODE>(pc);
116 typedef LPCSTR LPCUTF8;
117 typedef LPSTR LPUTF8;
119 #include "nsutilpriv.h"
121 #include "stdmacros.h"
134 //********** Macros. **********************************************************
137 #define FORCEINLINE inline
139 #define FORCEINLINE __forceinline
143 #ifndef DEBUG_NOINLINE
145 #define DEBUG_NOINLINE __declspec(noinline)
147 #define DEBUG_NOINLINE
151 #ifndef DBG_NOINLINE_X86__RET_INLINE
152 #if defined(_DEBUG) && defined(_TARGET_X86_)
153 // this exists to make scan work on x86.
154 #define DBG_NOINLINE_X86__RET_INLINE __declspec(noinline)
156 #define DBG_NOINLINE_X86__RET_INLINE FORCEINLINE
160 #include <stddef.h> // for offsetof
163 // Number of elements in a fixed-size array
164 #define NumItems(s) (sizeof(s) / sizeof(s[0]))
168 // Number of characters in a string literal. Excludes terminating NULL.
169 #define StrLen(str) (NumItems(str) - 1)
173 #define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9')))
174 #define DIGIT_TO_INT(ch) (ch - W('0'))
175 #define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i))
177 #define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \
178 ((ch >= W('A')) && (ch <= W('F'))))
179 #define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10)
180 #define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10)))
183 // Helper will 4 byte align a value, rounding up.
184 #define ALIGN4BYTE(val) (((val) + 3) & ~0x3)
187 #define DEBUGARG(x) , x
193 // Returns the size of a class or struct member.
194 #define sizeofmember(c,m) (sizeof(((c*)0)->m))
197 #if defined(_MSC_VER) && _MSC_VER < 1900
200 #define NOEXCEPT noexcept
203 //=--------------------------------------------------------------------------=
207 #include "safemath.h"
210 //=--------------------------------------------------------------------------=
214 // given and ANSI String, copy it into a wide buffer.
215 // be careful about scoping when using this macro!
217 // how to use the below two macros:
221 // pszA = MyGetAnsiStringRoutine();
222 // MAKE_WIDEPTR_FROMANSI(pwsz, pszA);
223 // MyUseWideStringRoutine(pwsz);
226 // similarily for MAKE_ANSIPTR_FROMWIDE. note that the first param does not
227 // have to be declared, and no clean up must be done.
230 // We'll define an upper limit that allows multiplication by 4 (the max
231 // bytes/char in UTF-8) but still remains positive, and allows some room for pad.
232 // Under normal circumstances, we should never get anywhere near this limit.
233 #define MAKE_MAX_LENGTH 0x1fffff00
235 #ifndef MAKE_TOOLONGACTION
236 #define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW)
239 #ifndef MAKE_TRANSLATIONFAILED
240 #define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION)
243 // This version throws on conversion errors (ie, no best fit character
244 // mapping to characters that look similar, and no use of the default char
245 // ('?') when printing out unrepresentable characters. Use this method for
246 // most development in the EE, especially anything like metadata or class
247 // names. See the BESTFIT version if you're printing out info to the console.
248 #define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \
249 int __l##ptrname = (int)wcslen(widestr); \
250 if (__l##ptrname > MAKE_MAX_LENGTH) \
251 MAKE_TOOLONGACTION; \
252 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
253 CQuickBytes __CQuickBytes##ptrname; \
254 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
256 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \
257 if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \
258 MAKE_TRANSLATIONFAILED; \
260 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
262 // This version does best fit character mapping and also allows the use
263 // of the default char ('?') for any Unicode character that isn't
264 // representable. This is reasonable for writing to the console, but
265 // shouldn't be used for most string conversions.
266 #define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \
267 int __l##ptrname = (int)wcslen(widestr); \
268 if (__l##ptrname > MAKE_MAX_LENGTH) \
269 MAKE_TOOLONGACTION; \
270 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
271 CQuickBytes __CQuickBytes##ptrname; \
272 __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
273 DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \
274 if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \
275 MAKE_TRANSLATIONFAILED; \
277 LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
279 // Use for anything critical other than output to console, where weird
280 // character mappings are unacceptable.
281 #define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP)
283 // Use for output to the console.
284 #define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP)
286 #define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \
287 CQuickBytes __qb##ptrname; \
289 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
290 if (__l##ptrname > MAKE_MAX_LENGTH) \
291 MAKE_TOOLONGACTION; \
292 LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
293 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \
294 MAKE_TRANSLATIONFAILED; \
297 #define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \
298 CQuickBytes __qb##ptrname; \
299 LPWSTR ptrname = 0; \
301 __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
302 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
303 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
305 if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \
306 ptrname[__l##ptrname] = 0; \
313 #define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr();
315 #define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \
316 CQuickBytes __qb##ptrname; \
317 int __l##ptrname = (int)wcslen(widestr); \
318 LPUTF8 ptrname = 0; \
319 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
320 __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
321 ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \
324 INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \
325 DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \
326 if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \
327 if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \
328 INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \
329 ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \
331 if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \
332 ptrname[__l##ptrname] = 0; \
344 #define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \
345 CQuickBytes __qb##ptrname; \
347 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
348 if (__l##ptrname > MAKE_MAX_LENGTH) \
349 MAKE_TOOLONGACTION; \
350 LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
351 if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \
352 MAKE_TRANSLATIONFAILED; \
354 ptrname[__l##ptrname] = 0;
357 #define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname; _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr();
360 #define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \
361 CQuickBytes __qb##ptrname; \
363 LPWSTR ptrname = 0; \
364 __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
365 if (__l##ptrname <= MAKE_MAX_LENGTH) { \
366 ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \
368 if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \
369 ptrname[__l##ptrname] = 0; \
376 #define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str) MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1)
378 // This method takes the number of characters
379 #define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage) \
380 CQuickBytes __qb##ptrname; \
382 __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL); \
383 if (__l##ptrname > MAKE_MAX_LENGTH) \
384 MAKE_TOOLONGACTION; \
385 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
387 DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname); \
388 if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \
389 MAKE_TRANSLATIONFAILED; \
391 ptrname[__l##ptrname] = 0;
393 #define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage) \
394 CQuickBytes __qb##ptrname; \
396 __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL); \
397 if (__l##ptrname > MAKE_MAX_LENGTH) \
398 MAKE_TOOLONGACTION; \
399 ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
400 DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL); \
401 if (_pCnt == 0 && _nCharacters > 0) { \
402 MAKE_TRANSLATIONFAILED; \
404 ptrname[__l##ptrname] = 0;
406 #define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt) \
407 MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP)
411 LPWSTR DuplicateString(
415 STATIC_CONTRACT_NOTHROW;
417 LPWSTR wszDup = NULL;
418 if (wszString != NULL)
420 wszDup = new (nothrow) WCHAR[cchString + 1];
423 wcscpy_s(wszDup, cchString + 1, wszString);
430 LPWSTR DuplicateString(
433 STATIC_CONTRACT_NOTHROW;
435 if (wszString != NULL)
437 return DuplicateString(wszString, wcslen(wszString));
445 void DECLSPEC_NORETURN ThrowOutOfMemory();
448 LPWSTR DuplicateStringThrowing(
452 STATIC_CONTRACT_THROWS;
454 if (wszString == NULL)
457 LPWSTR wszDup = DuplicateString(wszString, cchString);
465 LPWSTR DuplicateStringThrowing(
468 STATIC_CONTRACT_THROWS;
470 if (wszString == NULL)
473 LPWSTR wszDup = DuplicateString(wszString);
481 //*****************************************************************************
482 // Placement new is used to new and object at an exact location. The pointer
483 // is simply returned to the caller without actually using the heap. The
484 // advantage here is that you cause the ctor() code for the object to be run.
485 // This is ideal for heaps of C++ objects that need to get init'd multiple times.
487 // void *pMem = GetMemFromSomePlace();
488 // Foo *p = new (pMem) Foo;
491 //*****************************************************************************
492 #ifndef __PLACEMENT_NEW_INLINE
493 #define __PLACEMENT_NEW_INLINE
494 inline void *__cdecl operator new(size_t, void *_P)
496 LIMITED_METHOD_DAC_CONTRACT;
500 #endif // __PLACEMENT_NEW_INLINE
503 /********************************************************************************/
504 /* portability helpers */
506 #define IN_WIN64(x) x
510 #define IN_WIN32(x) x
514 operator new(size_t n);
516 _Ret_bytecap_(_Size) void * __cdecl
517 operator new[](size_t n);
520 operator delete(void *p) NOEXCEPT;
523 operator delete[](void *p) NOEXCEPT;
526 HRESULT _OutOfMemory(LPCSTR szFile, int iLine);
527 #define OutOfMemory() _OutOfMemory(__FILE__, __LINE__)
529 inline HRESULT OutOfMemory()
531 LIMITED_METHOD_CONTRACT;
532 return (E_OUTOFMEMORY);
536 //*****************************************************************************
537 // Handle accessing localizable resource strings
538 //*****************************************************************************
539 // NOTE: Should use locale names as much as possible. LCIDs don't support
540 // custom cultures on Vista+.
541 // TODO: This should always use the names
542 #ifdef FEATURE_USE_LCID
543 typedef LCID LocaleID;
544 typedef LCID LocaleIDValue;
546 typedef LPCWSTR LocaleID;
547 typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH];
550 // Notes about the culture callbacks:
551 // - The language we're operating in can change at *runtime*!
552 // - A process may operate in *multiple* languages.
553 // (ex: Each thread may have it's own language)
554 // - If we don't care what language we're in (or have no way of knowing),
555 // then return a 0-length name and UICULTUREID_DONTCARE for the culture ID.
556 // - GetCultureName() and the GetCultureId() must be in sync (refer to the
558 // - We have two functions separate functions for better performance.
559 // - The name is used to resolve a directory for MsCorRC.dll.
560 // - The id is used as a key to map to a dll hinstance.
562 // Callback to obtain both the culture name and the culture's parent culture name
563 typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames);
564 #ifdef FEATURE_USE_LCID
565 // Callback to return the culture ID.
566 const LCID UICULTUREID_DONTCARE = (LCID)-1;
568 const LPCWSTR UICULTUREID_DONTCARE = NULL;
571 typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*);
573 HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName);
575 HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
577 BOOL CLRFreeLibrary(HMODULE hModule);
579 // Prevent people from using LoadStringRC & LoadStringRCEx from inside the product since it
580 // causes issues with having the wrong version picked up inside the shim.
581 #define LoadStringRC __error("From inside the CLR, use UtilLoadStringRC; LoadStringRC is only meant to be exported.")
582 #define LoadStringRCEx __error("From inside the CLR, use UtilLoadStringRCEx; LoadStringRC is only meant to be exported.")
584 // Load a string using the resources for the current module.
585 STDAPI UtilLoadStringRC(UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE);
587 #if ENABLE_DOWNLEVEL_FOR_NLS
588 STDAPI UtilLoadStringRCEx(LCID lcid, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed);
591 // Specify callbacks so that UtilLoadStringRC can find out which language we're in.
592 // If no callbacks specified (or both parameters are NULL), we default to the
593 // resource dll in the root (which is probably english).
594 void SetResourceCultureCallbacks(
595 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
596 FPGETTHREADUICULTUREID fpGetThreadUICultureId
599 void GetResourceCultureCallbacks(
600 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
601 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
604 #if !defined(DACCESS_COMPILE)
605 // Get the MUI ID, on downlevel platforms where MUI is not supported it
606 // returns the default system ID.
607 extern int GetMUILanguageID(LocaleIDValue* pResult);
608 extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames);
610 #endif // !defined(DACCESS_COMPILE)
612 //*****************************************************************************
613 // Use this class by privately deriving from noncopyable to disallow copying of
615 //*****************************************************************************
625 noncopyable(const noncopyable&);
626 const noncopyable& operator=(const noncopyable&);
629 //*****************************************************************************
630 // Must associate each handle to an instance of a resource dll with the int
631 // that it represents
632 //*****************************************************************************
633 typedef HINSTANCE HRESOURCEDLL;
636 class CCulturedHInstance
638 LocaleIDValue m_LangId;
639 HRESOURCEDLL m_hInst;
645 LIMITED_METHOD_CONTRACT;
650 BOOL HasID(LocaleID id)
652 _ASSERTE(m_hInst != NULL || m_fMissing);
653 if (id == UICULTUREID_DONTCARE)
656 #ifdef FEATURE_USE_LCID
657 return id == m_LangId;
659 return wcscmp(id, m_LangId) == 0;
663 HRESOURCEDLL GetLibraryHandle()
670 return m_hInst != NULL;
678 void SetMissing(LocaleID id)
680 _ASSERTE(m_hInst == NULL);
685 void Set(LocaleID id, HRESOURCEDLL hInst)
687 _ASSERTE(m_hInst == NULL);
688 _ASSERTE(m_fMissing == FALSE);
693 void SetId(LocaleID id)
695 #ifdef FEATURE_USE_LCID
698 if (id != UICULTUREID_DONTCARE)
700 wcsncpy_s(m_LangId, NumItems(m_LangId), id, NumItems(m_LangId));
701 m_LangId[NumItems(m_LangId)-1] = W('\0');
705 m_LangId[0] = W('\0');
711 #ifndef DACCESS_COMPILE
712 void AddThreadPreferredUILanguages(StringArrayList* pArray);
714 //*****************************************************************************
715 // CCompRC manages string Resource access for COM+. This includes loading
716 // the MsCorRC.dll for resources as well allowing each thread to use a
717 // a different localized version.
718 //*****************************************************************************
723 enum ResourceCategory
728 // present in Desktop CLR and Core CLR + debug pack, an error
729 // If missing, get a generic error message instead
732 // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing)
733 // if missing, get a generic "resource not found" message instead
736 // present in Desktop CLR, optional for CoreCLR
739 // might not be present, non essential
745 // This constructor will be fired up on startup. Make sure it doesn't
746 // do anything besides zero-out out values.
747 m_bUseFallback = FALSE;
749 m_fpGetThreadUICultureId = NULL;
750 m_fpGetThreadUICultureNames = NULL;
756 m_pResourceFile = NULL;
758 m_pResourceDomain = NULL;
759 #endif // FEATURE_PAL
763 HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE);
766 BOOL ShouldUseFallback()
768 LIMITED_METHOD_CONTRACT;
769 return m_bUseFallback;
772 static void SetIsMscoree() {s_bIsMscoree = TRUE;}
774 HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL);
775 HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed);
777 void SetResourceCultureCallbacks(
778 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
779 FPGETTHREADUICULTUREID fpGetThreadUICultureId
782 void GetResourceCultureCallbacks(
783 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
784 FPGETTHREADUICULTUREID* fpGetThreadUICultureId
787 HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst);
789 // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR)
790 static CCompRC* GetDefaultResourceDll();
791 #ifdef FEATURE_CORECLR
792 // Get the generic messages dll (Silverlight only, mscorrc.dll)
793 static CCompRC* GetFallbackResourceDll();
795 static void ShutdownDefaultResourceDll();
796 static void GetDefaultCallbacks(
797 FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
798 FPGETTHREADUICULTUREID* fpGetThreadUICultureId)
801 m_DefaultResourceDll.GetResourceCultureCallbacks(
802 fpGetThreadUICultureNames,
803 fpGetThreadUICultureId);
806 static void SetDefaultCallbacks(
807 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
808 FPGETTHREADUICULTUREID fpGetThreadUICultureId)
811 // Either both are NULL or neither are NULL
812 _ASSERTE((fpGetThreadUICultureNames != NULL) ==
813 (fpGetThreadUICultureId != NULL));
815 m_DefaultResourceDll.SetResourceCultureCallbacks(
816 fpGetThreadUICultureNames,
817 fpGetThreadUICultureId);
819 #ifdef FEATURE_CORECLR
820 m_FallbackResourceDll.SetResourceCultureCallbacks(
821 fpGetThreadUICultureNames,
822 fpGetThreadUICultureId);
827 #ifdef USE_FORMATMESSAGE_WRAPPER
835 IN DWORD dwMessageId,
836 IN DWORD dwLanguageId,
839 IN va_list *Arguments);
840 #endif // USE_FORMATMESSAGE_WRAPPER
844 HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst);
845 #ifndef DACCESS_COMPILE
846 HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst,
847 __out_ecount(rcPathSize) WCHAR *rcPath, const DWORD rcPathSize);
848 HRESULT LoadLibrary(HRESOURCEDLL * pHInst);
849 HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName);
852 // We do not have global constructors any more
853 static LONG m_dwDefaultInitialized;
854 static CCompRC m_DefaultResourceDll;
855 static LPCWSTR m_pDefaultResource;
857 #ifdef FEATURE_CORECLR
858 // fallback resources if debug pack is not installed
859 static LONG m_dwFallbackInitialized;
860 static CCompRC m_FallbackResourceDll;
861 static LPCWSTR m_pFallbackResource;
864 // We must map between a thread's int and a dll instance.
865 // Since we only expect 1 language almost all of the time, we'll special case
866 // that and then use a variable size map for everything else.
867 CCulturedHInstance m_Primary;
868 CCulturedHInstance * m_pHash;
871 CRITSEC_COOKIE m_csMap;
873 LPCWSTR m_pResourceFile;
875 // Resource domain is an ANSI string identifying a native resources file
876 static LPCSTR m_pDefaultResourceDomain;
877 static LPCSTR m_pFallbackResourceDomain;
878 LPCSTR m_pResourceDomain;
879 #endif // FEATURE_PAL
881 // Main accessors for hash
882 HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing);
883 HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE);
885 FPGETTHREADUICULTUREID m_fpGetThreadUICultureId;
886 FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames;
889 static BOOL s_bIsMscoree;
892 HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax);
896 HWND hWnd, // Handle to Owner Window
897 UINT uText, // Resource Identifier for Text message
898 UINT uCaption, // Resource Identifier for Caption
899 UINT uType, // Style of MessageBox
900 BOOL displayForNonInteractive, // Display even if the process is running non interactive
901 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
902 ...); // Additional Arguments
904 int UtilMessageBoxNonLocalized(
905 HWND hWnd, // Handle to Owner Window
906 LPCWSTR lpText, // Resource Identifier for Text message
907 LPCWSTR lpTitle, // Resource Identifier for Caption
908 UINT uType, // Style of MessageBox
909 BOOL displayForNonInteractive, // Display even if the process is running non interactive
910 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
911 ...); // Additional Arguments
913 int UtilMessageBoxVA(
914 HWND hWnd, // Handle to Owner Window
915 UINT uText, // Resource Identifier for Text message
916 UINT uCaption, // Resource Identifier for Caption
917 UINT uType, // Style of MessageBox
918 BOOL displayForNonInteractive, // Display even if the process is running non interactive
919 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
920 va_list args); // Additional Arguments
922 int UtilMessageBoxNonLocalizedVA(
923 HWND hWnd, // Handle to Owner Window
924 LPCWSTR lpText, // Text message
925 LPCWSTR lpCaption, // Caption
926 UINT uType, // Style of MessageBox
927 BOOL displayForNonInteractive, // Display even if the process is running non interactive
928 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
929 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
930 va_list args); // Additional Arguments
932 int UtilMessageBoxNonLocalizedVA(
933 HWND hWnd, // Handle to Owner Window
934 LPCWSTR lpText, // Text message
935 LPCWSTR lpCaption, // Caption
936 LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher).
937 UINT uType, // Style of MessageBox
938 BOOL displayForNonInteractive, // Display even if the process is running non interactive
939 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
940 BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort.
941 va_list args); // Additional Arguments
943 int UtilMessageBoxCatastrophic(
944 UINT uText, // Text for MessageBox
945 UINT uTitle, // Title for MessageBox
946 UINT uType, // Style of MessageBox
947 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
950 int UtilMessageBoxCatastrophicNonLocalized(
951 LPCWSTR lpText, // Text for MessageBox
952 LPCWSTR lpTitle, // Title for MessageBox
953 UINT uType, // Style of MessageBox
954 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
957 int UtilMessageBoxCatastrophicVA(
958 UINT uText, // Text for MessageBox
959 UINT uTitle, // Title for MessageBox
960 UINT uType, // Style of MessageBox
961 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
962 va_list args); // Additional Arguments
964 int UtilMessageBoxCatastrophicNonLocalizedVA(
965 LPCWSTR lpText, // Text for MessageBox
966 LPCWSTR lpTitle, // Title for MessageBox
967 UINT uType, // Style of MessageBox
968 BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
969 va_list args); // Additional Arguments
972 // The HRESULT_FROM_WIN32 macro evaluates its arguments three times.
973 // <TODO>TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to
974 // this helper function avoid code bloat</TODO>
975 inline HRESULT HRESULT_FROM_GetLastError()
978 DWORD dw = GetLastError();
979 // Make sure we return a failure
980 if (dw == ERROR_SUCCESS)
982 _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!");
986 return HRESULT_FROM_WIN32(dw);
989 inline HRESULT HRESULT_FROM_GetLastErrorNA()
992 DWORD dw = GetLastError();
993 // Make sure we return a failure
994 if (dw == ERROR_SUCCESS)
997 return HRESULT_FROM_WIN32(dw);
1000 inline HRESULT BadError(HRESULT hr)
1002 LIMITED_METHOD_CONTRACT;
1003 _ASSERTE(!"Serious Error");
1007 #define TESTANDRETURN(test, hrVal) \
1009 int ___test = (int)(test); \
1014 #define TESTANDRETURNPOINTER(pointer) \
1015 TESTANDRETURN(pointer!=NULL, E_POINTER)
1017 #define TESTANDRETURNMEMORY(pointer) \
1018 TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY)
1020 #define TESTANDRETURNHR(hr) \
1021 TESTANDRETURN(SUCCEEDED(hr), hr)
1023 #define TESTANDRETURNARG(argtest) \
1024 TESTANDRETURN(argtest, E_INVALIDARG)
1026 // Quick validity check for HANDLEs that are returned by Win32 APIs that
1027 // use INVALID_HANDLE_VALUE instead of NULL to indicate an error
1028 inline BOOL IsValidHandle(HANDLE h)
1030 LIMITED_METHOD_CONTRACT;
1031 return ((h != NULL) && (h != INVALID_HANDLE_VALUE));
1034 // Count the bits in a value in order iBits time.
1035 inline int CountBits(int iNum)
1037 LIMITED_METHOD_CONTRACT;
1039 for (iBits=0; iNum; iBits++)
1040 iNum = iNum & (iNum - 1);
1044 //------------------------------------------------------------------------
1045 // BitPosition: Return the position of the single bit that is set in 'value'.
1048 // The position (0 is LSB) of bit that is set in 'value'
1051 // 'value' must have exactly one bit set.
1052 // The algorithm is as follows:
1053 // - PRIME is a prime bigger than sizeof(unsigned int), which is not of the
1055 // - Taking the modulo of 'value' with this will produce a unique hash for all
1056 // powers of 2 (which is what "value" is).
1057 // - Entries in hashTable[] which are -1 should never be used. There
1058 // should be PRIME-8*sizeof(value) entries which are -1 .
1061 unsigned BitPosition(unsigned value)
1063 _ASSERTE((value != 0) && ((value & (value-1)) == 0));
1064 #ifndef _TARGET_AMD64_
1065 const unsigned PRIME = 37;
1067 static const char hashTable[PRIME] =
1069 -1, 0, 1, 26, 2, 23, 27, -1, 3, 16,
1070 24, 30, 28, 11, -1, 13, 4, 7, 17, -1,
1071 25, 22, 31, 15, 29, 10, 12, 6, -1, 21,
1072 14, 9, 5, 20, 8, 19, 18
1075 _ASSERTE(PRIME >= 8*sizeof(value));
1076 _ASSERTE(sizeof(hashTable) == PRIME);
1079 unsigned hash = value % PRIME;
1080 unsigned index = hashTable[hash];
1081 _ASSERTE(index != (unsigned char)-1);
1083 // not enabled for x86 because BSF is extremely slow on Atom
1084 // (15 clock cycles vs 1-3 on any other Intel CPU post-P4)
1086 BitScanForward(&index, value);
1092 // Used to remove trailing zeros from Decimal types.
1093 // NOTE: Assumes hi32 bits are empty (used for conversions from Cy->Dec)
1094 inline HRESULT DecimalCanonicalize(DECIMAL* dec)
1096 WRAPPER_NO_CONTRACT;
1098 // Clear the VARENUM field
1099 (*(USHORT*)dec) = 0;
1101 // Remove trailing zeros:
1104 temp = templast = *dec;
1106 // Ensure the hi 32 bits are empty (should be if we came from a currency)
1107 if ((DECIMAL_HI32(temp) != 0) || (DECIMAL_SCALE(temp) > 4))
1108 return DISP_E_OVERFLOW;
1110 // Return immediately if dec represents a zero.
1111 if (DECIMAL_LO32(temp) == 0 && DECIMAL_MID32(temp) == 0)
1114 // Compare to the original to see if we've
1115 // lost non-zero digits (and make sure we don't overflow the scale BYTE)
1118 #pragma warning(push)
1119 #pragma warning(disable:6219) // "Suppress PREFast warning about Implicit cast between semantically different integer types"
1121 while ((DECIMAL_SCALE(temp) <= 4) && (VARCMP_EQ == VarDecCmp(dec, &temp)))
1125 #pragma warning(pop)
1129 // Remove the last digit and normalize. Ignore temp.Hi32
1130 // as Currency values will have a max of 64 bits of data.
1131 DECIMAL_SCALE(temp)--;
1132 UINT64 temp64 = (((UINT64) DECIMAL_MID32(temp)) << 32) + DECIMAL_LO32(temp);
1135 DECIMAL_MID32(temp) = (ULONG)(temp64 >> 32);
1136 DECIMAL_LO32(temp) = (ULONG)temp64;
1143 //*****************************************************************************
1145 // Paths functions. Use these instead of the CRT.
1147 //*****************************************************************************
1148 // secure version! Specify the size of the each buffer in count of elements
1149 void SplitPath(register const WCHAR *path,
1150 __inout_z __inout_ecount_opt(driveSizeInWords) WCHAR *drive, int driveSizeInWords,
1151 __inout_z __inout_ecount_opt(dirSizeInWords) WCHAR *dir, int dirSizeInWords,
1152 __inout_z __inout_ecount_opt(fnameSizeInWords) WCHAR *fname, size_t fnameSizeInWords,
1153 __inout_z __inout_ecount_opt(extSizeInWords) WCHAR *ext, size_t extSizeInWords);
1155 //*******************************************************************************
1156 // A much more sensible version that just points to each section of the string.
1157 //*******************************************************************************
1158 void SplitPathInterior(
1159 __in LPCWSTR wszPath,
1160 __out_opt LPCWSTR *pwszDrive, __out_opt size_t *pcchDrive,
1161 __out_opt LPCWSTR *pwszDir, __out_opt size_t *pcchDir,
1162 __out_opt LPCWSTR *pwszFileName, __out_opt size_t *pcchFileName,
1163 __out_opt LPCWSTR *pwszExt, __out_opt size_t *pcchExt);
1165 void MakePath(__out_ecount (MAX_LONGPATH) register WCHAR *path,
1171 WCHAR * FullPath(__out_ecount (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen);
1173 //*****************************************************************************
1175 // SString version of the path functions.
1177 //*****************************************************************************
1178 void SplitPath(__in SString const &path,
1179 __inout_opt SString *drive,
1180 __inout_opt SString *dir,
1181 __inout_opt SString *fname,
1182 __inout_opt SString *ext);
1184 //*****************************************************************************
1186 // **** REGUTIL - Static helper functions for reading/writing to Windows registry.
1188 //*****************************************************************************
1194 //*****************************************************************************
1198 COR_CONFIG_ENV = 0x01,
1199 COR_CONFIG_USER = 0x02,
1200 COR_CONFIG_MACHINE = 0x04,
1201 COR_CONFIG_FUSION = 0x08,
1203 COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION),
1204 COR_CONFIG_ALL = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE),
1208 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1209 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1211 static DWORD GetConfigDWORD_DontUse_(
1214 CORConfigLevel level = COR_CONFIG_ALL,
1215 BOOL fPrependCOMPLUS = TRUE);
1218 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1219 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1221 static HRESULT GetConfigDWORD_DontUse_(
1224 __out DWORD * result,
1225 CORConfigLevel level = COR_CONFIG_ALL,
1226 BOOL fPrependCOMPLUS = TRUE);
1228 static ULONGLONG GetConfigULONGLONG_DontUse_(
1231 CORConfigLevel level = COR_CONFIG_ALL,
1232 BOOL fPrependCOMPLUS = TRUE);
1235 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1236 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1238 static DWORD GetConfigFlag_DontUse_(
1241 BOOL defValue = FALSE);
1244 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1245 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1247 static LPWSTR GetConfigString_DontUse_(
1249 BOOL fPrependCOMPLUS = TRUE,
1250 CORConfigLevel level = COR_CONFIG_ALL,
1251 BOOL fUsePerfCache = TRUE);
1253 static void FreeConfigString(__in __in_z LPWSTR name);
1255 #ifdef FEATURE_CORECLR
1257 #endif //FEATURE_CORECLR
1258 static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS);
1259 #ifdef FEATURE_CORECLR
1261 #endif //FEATURE_CORECLR
1263 static BOOL UseRegistry();
1266 //*****************************************************************************
1267 // Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that
1268 // you can safely cast to a DWORD if fGetDWORD is TRUE.
1269 //*****************************************************************************
1270 static HRESULT GetConfigInteger(
1273 __out ULONGLONG * result,
1274 BOOL fGetDWORD = TRUE,
1275 CORConfigLevel level = COR_CONFIG_ALL,
1276 BOOL fPrependCOMPLUS = TRUE);
1279 #ifndef FEATURE_CORECLR
1280 static void AllowRegistryUse(BOOL fAllowUse);
1283 //*****************************************************************************
1284 // Open's the given key and returns the value desired. If the key or value is
1285 // not found, then the default is returned.
1286 //*****************************************************************************
1287 static long GetLong( // Return value from registry or default.
1288 LPCTSTR szName, // Name of value to get.
1289 long iDefault, // Default value to return if not found.
1290 LPCTSTR szKey=NULL, // Name of key, NULL==default.
1291 HKEY hKey=HKEY_LOCAL_MACHINE);// What key to work on.
1293 //*****************************************************************************
1294 // Open's the given key and returns the value desired. If the key or value is
1295 // not found, then the default is returned.
1296 //*****************************************************************************
1297 static long SetLong( // Return value from registry or default.
1298 LPCTSTR szName, // Name of value to get.
1299 long iValue, // Value to set.
1300 LPCTSTR szKey=NULL, // Name of key, NULL==default.
1301 HKEY hKey=HKEY_LOCAL_MACHINE);// What key to work on.
1303 //*****************************************************************************
1304 // Open's the given key and returns the value desired. If the key or value is
1305 // not found, then it's created
1306 //*****************************************************************************
1307 static long SetOrCreateLong( // Return value from registry or default.
1308 LPCTSTR szName, // Name of value to get.
1309 long iValue, // Value to set.
1310 LPCTSTR szKey=NULL, // Name of key, NULL==default.
1311 HKEY hKey=HKEY_LOCAL_MACHINE);// What key to work on.
1315 //*****************************************************************************
1316 // Set an entry in the registry of the form:
1317 // HKEY_CLASSES_ROOT\szKey\szSubkey = szValue. If szSubkey or szValue are
1318 // NULL, omit them from the above expression.
1319 //*****************************************************************************
1320 static BOOL SetKeyAndValue( // TRUE or FALSE.
1321 LPCTSTR szKey, // Name of the reg key to set.
1322 LPCTSTR szSubkey, // Optional subkey of szKey.
1323 LPCTSTR szValue); // Optional value for szKey\szSubkey.
1325 //*****************************************************************************
1326 // Delete an entry in the registry of the form:
1327 // HKEY_CLASSES_ROOT\szKey\szSubkey.
1328 //*****************************************************************************
1329 static LONG DeleteKey( // TRUE or FALSE.
1330 LPCTSTR szKey, // Name of the reg key to set.
1331 LPCTSTR szSubkey); // Subkey of szKey.
1333 //*****************************************************************************
1334 // Open the key, create a new keyword and value pair under it.
1335 //*****************************************************************************
1336 static BOOL SetRegValue( // Return status.
1337 LPCTSTR szKeyName, // Name of full key.
1338 LPCTSTR szKeyword, // Name of keyword.
1339 LPCTSTR szValue); // Value of keyword.
1341 //*****************************************************************************
1342 // Does standard registration of a CoClass with a progid.
1343 //*****************************************************************************
1344 static HRESULT RegisterCOMClass( // Return code.
1345 REFCLSID rclsid, // Class ID.
1346 LPCTSTR szDesc, // Description of the class.
1347 LPCTSTR szProgIDPrefix, // Prefix for progid.
1348 int iVersion, // Version # for progid.
1349 LPCTSTR szClassProgID, // Class progid.
1350 LPCTSTR szThreadingModel, // What threading model to use.
1351 LPCTSTR szModule, // Path to class.
1352 HINSTANCE hInst, // Handle to module being registered
1353 LPCTSTR szAssemblyName, // Optional assembly name
1354 LPCTSTR szVersion, // Optional Runtime Version (directry containing runtime)
1355 BOOL fExternal, // flag - External to mscoree.
1356 BOOL fRelativePath); // flag - Relative path in szModule
1358 //*****************************************************************************
1359 // Unregister the basic information in the system registry for a given object
1361 //*****************************************************************************
1362 static HRESULT UnregisterCOMClass( // Return code.
1363 REFCLSID rclsid, // Class ID we are registering.
1364 LPCTSTR szProgIDPrefix, // Prefix for progid.
1365 int iVersion, // Version # for progid.
1366 LPCTSTR szClassProgID, // Class progid.
1367 BOOL fExternal); // flag - External to mscoree.
1369 //*****************************************************************************
1370 // Does standard registration of a CoClass with a progid.
1371 // NOTE: This is the non-side-by-side execution version.
1372 //*****************************************************************************
1373 static HRESULT RegisterCOMClass( // Return code.
1374 REFCLSID rclsid, // Class ID.
1375 LPCTSTR szDesc, // Description of the class.
1376 LPCTSTR szProgIDPrefix, // Prefix for progid.
1377 int iVersion, // Version # for progid.
1378 LPCTSTR szClassProgID, // Class progid.
1379 LPCTSTR szThreadingModel, // What threading model to use.
1380 LPCTSTR szModule, // Path to class.
1381 BOOL bInprocServer = true); // Whether we register the server as inproc or local
1383 //*****************************************************************************
1384 // Unregister the basic information in the system registry for a given object
1386 // NOTE: This is the non-side-by-side execution version.
1387 //*****************************************************************************
1388 static HRESULT UnregisterCOMClass( // Return code.
1389 REFCLSID rclsid, // Class ID we are registering.
1390 LPCTSTR szProgIDPrefix, // Prefix for progid.
1391 int iVersion, // Version # for progid.
1392 LPCTSTR szClassProgID); // Class progid.
1394 //*****************************************************************************
1395 // Register a type library.
1396 //*****************************************************************************
1397 static HRESULT RegisterTypeLib( // Return code.
1398 REFGUID rtlbid, // TypeLib ID we are registering.
1399 int iVersion, // Typelib version.
1400 LPCTSTR szDesc, // TypeLib description.
1401 LPCTSTR szModule); // Path to the typelib.
1403 //*****************************************************************************
1404 // Remove the registry keys for a type library.
1405 //*****************************************************************************
1406 static HRESULT UnregisterTypeLib( // Return code.
1407 REFGUID rtlbid, // TypeLib ID we are registering.
1408 int iVersion); // Typelib version.
1410 #endif //#ifndef FEATURE_CORECLR
1412 //*****************************************************************************
1413 // (Optional) Initialize the config registry cache
1414 // (see ConfigCacheValueNameSeenPerhaps, below.)
1415 //*****************************************************************************
1416 static void InitOptionalConfigCache();
1420 #ifndef FEATURE_CORECLR
1422 //*****************************************************************************
1423 // Register the basics for a in proc server.
1424 //*****************************************************************************
1425 static HRESULT RegisterClassBase( // Return code.
1426 REFCLSID rclsid, // Class ID we are registering.
1427 LPCTSTR szDesc, // Class description.
1428 LPCTSTR szProgID, // Class prog ID.
1429 LPCTSTR szIndepProgID, // Class version independant prog ID.
1430 __out_ecount (cchOutCLSID) LPTSTR szOutCLSID, // CLSID formatted in character form.
1431 DWORD cchOutCLSID); // Out CLS ID buffer size in characters
1434 //*****************************************************************************
1435 // Delete the basic settings for an inproc server.
1436 //*****************************************************************************
1437 static HRESULT UnregisterClassBase( // Return code.
1438 REFCLSID rclsid, // Class ID we are registering.
1439 LPCTSTR szProgID, // Class prog ID.
1440 LPCTSTR szIndepProgID, // Class version independant prog ID.
1441 __out_ecount (cchOutCLSID) LPTSTR szOutCLSID, // Return formatted class ID here.
1442 DWORD cchOutCLSID); // Out CLS ID buffer size in characters
1444 #endif //#ifndef FEATURE_CORECLR
1446 //*****************************************************************************
1447 // Return TRUE if the registry value name might have been seen in the registry
1449 // return FALSE if the value was definitely not seen at startup.
1451 // Perf Optimization for VSWhidbey:113373.
1452 //*****************************************************************************
1453 static BOOL RegCacheValueNameSeenPerhaps(
1455 //*****************************************************************************
1456 // Return TRUE if the environment variable name might have been seen at startup;
1457 // return FALSE if the value was definitely not seen at startup.
1458 //*****************************************************************************
1459 static BOOL EnvCacheValueNameSeenPerhaps(
1462 static BOOL s_fUseRegCache; // Enable registry cache; if FALSE, CCVNSP
1463 // always returns TRUE.
1464 static BOOL s_fUseEnvCache; // Enable env cache.
1466 static BOOL s_fUseRegistry; // Allow lookups in the registry
1468 // Open the .NetFramework keys once and cache the handles
1469 static HKEY s_hMachineFrameworkKey;
1470 static HKEY s_hUserFrameworkKey;
1473 // need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig
1474 #include "clrconfig.h"
1476 //-----------------------------------------------------------------------------
1477 // Wrapper for configuration strings.
1478 // This serves as a holder to call FreeConfigString.
1479 class ConfigStringHolder
1482 ConfigStringHolder() { m_wszString = NULL; }
1483 ~ConfigStringHolder()
1489 // NOTE: The following function is deprecated; use the CLRConfig class instead.
1490 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1492 void Init_DontUse_(LPCWSTR wszName)
1495 m_wszString = REGUTIL::GetConfigString_DontUse_(wszName);
1501 if (m_wszString != NULL)
1503 REGUTIL::FreeConfigString(m_wszString);
1508 // Get the string value. NULL if not set.
1520 #define CLRGetTickCount64() GetTickCount64()
1523 // Use this function to initialize the s_CodeAllocHint
1524 // during startup. base is runtime .dll base address,
1525 // size is runtime .dll virtual size.
1527 void InitCodeAllocHint(SIZE_T base, SIZE_T size, int randomPageOffset);
1531 // Use this function to reset the s_CodeAllocHint
1532 // after unloading an AppDomain
1534 void ResetCodeAllocHint();
1537 // Returns TRUE if p is located in near clr.dll that allows us
1538 // to use rel32 IP-relative addressing modes.
1540 BOOL IsPreferredExecutableRange(void * p);
1543 // Allocate free memory that will be used for executable code
1544 // Handles the special requirements that we have on 64-bit platforms
1545 // where we want the executable memory to be located near mscorwks
1547 BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize,
1548 DWORD flAllocationType,
1552 // Allocate free memory within the range [pMinAddr..pMaxAddr] using
1553 // ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it.
1555 BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
1556 const BYTE *pMaxAddr,
1558 DWORD flAllocationType,
1562 // Allocate free memory with specific alignment
1564 LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment);
1566 //******************************************************************************
1567 // Returns the number of processors that a process has been configured to run on
1568 //******************************************************************************
1572 static BOOL m_enableGCNumaAware;
1573 static BOOL InitNumaNodeInfoAPI();
1576 static BOOL CanEnableGCNumaAware();
1577 static void InitNumaNodeInfo();
1579 #if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
1580 private: // apis types
1581 #if !defined(FEATURE_CORESYSTEM)
1582 //GetNumaProcessorNode()
1584 (WINAPI *PGNPN)(UCHAR, PUCHAR);
1587 //GetNumaHighestNodeNumber()
1589 (WINAPI *PGNHNN)(PULONG);
1590 //VirtualAllocExNuma()
1592 (WINAPI *PVAExN)(HANDLE,LPVOID,SIZE_T,DWORD,DWORD,DWORD);
1594 // api pfns and members
1595 #if !defined(FEATURE_CORESYSTEM)
1596 static PGNPN m_pGetNumaProcessorNode;
1598 static PGNHNN m_pGetNumaHighestNodeNumber;
1599 static PVAExN m_pVirtualAllocExNuma;
1601 public: // functions
1602 #if !defined(FEATURE_CORESYSTEM)
1603 static BOOL GetNumaProcessorNode(UCHAR proc_no, PUCHAR node_no);
1606 static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size,
1607 DWORD allocType, DWORD prot, DWORD node);
1609 #if !defined(FEATURE_CORECLR) || defined(FEATURE_CORESYSTEM)
1611 //GetNumaProcessorNodeEx()
1613 (WINAPI *PGNPNEx)(PPROCESSOR_NUMBER, PUSHORT);
1614 static PGNPNEx m_pGetNumaProcessorNodeEx;
1617 static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no);
1622 struct CPU_Group_Info
1624 WORD nr_active; // at most 64
1628 DWORD_PTR active_mask;
1630 DWORD activeThreadWeight;
1636 static LONG m_initialization;
1637 static WORD m_nGroups;
1638 static WORD m_nProcessors;
1639 static BOOL m_enableGCCPUGroups;
1640 static BOOL m_threadUseAllCpuGroups;
1641 static WORD m_initialGroup;
1642 static CPU_Group_Info *m_CPUGroupInfoArray;
1644 static BOOL InitCPUGroupInfoAPI();
1645 static BOOL InitCPUGroupInfoArray();
1646 static BOOL InitCPUGroupInfoRange();
1647 static void InitCPUGroupInfo();
1648 static BOOL IsInitialized();
1651 static void EnsureInitialized();
1652 static BOOL CanEnableGCCPUGroups();
1653 static BOOL CanEnableThreadUseAllCpuGroups();
1654 static WORD GetNumActiveProcessors();
1655 static void GetGroupForProcessor(WORD processor_number,
1656 WORD *group_number, WORD *group_processor_number);
1657 static DWORD CalculateCurrentProcessorNumber();
1658 //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
1660 #if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
1662 //GetLogicalProcessorInforomationEx()
1664 (WINAPI *PGLPIEx)(DWORD, SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *, PDWORD);
1665 //SetThreadGroupAffinity()
1667 (WINAPI *PSTGA)(HANDLE, GROUP_AFFINITY *, GROUP_AFFINITY *);
1668 //GetThreadGroupAffinity()
1670 (WINAPI *PGTGA)(HANDLE, GROUP_AFFINITY *);
1671 #if !defined(FEATURE_CORESYSTEM) && !defined(FEATURE_CORECLR)
1672 //GetCurrentProcessorNumberEx()
1674 (WINAPI *PGCPNEx)(PROCESSOR_NUMBER *);
1677 (WINAPI *PGST)(FILETIME *, FILETIME *, FILETIME *);
1678 //NtQuerySystemInformationEx()
1680 //(WINAPI *PNTQSIEx)(SYSTEM_INFORMATION_CLASS, PULONG, ULONG, PVOID, ULONG, PULONG);
1683 static PGLPIEx m_pGetLogicalProcessorInformationEx;
1684 static PSTGA m_pSetThreadGroupAffinity;
1685 static PGTGA m_pGetThreadGroupAffinity;
1686 #if !defined(FEATURE_CORESYSTEM) && !defined(FEATURE_CORECLR)
1687 static PGCPNEx m_pGetCurrentProcessorNumberEx;
1688 static PGST m_pGetSystemTimes;
1689 //static PNTQSIEx m_pNtQuerySystemInformationEx;
1693 static BOOL GetLogicalProcessorInformationEx(DWORD relationship,
1694 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count);
1695 static BOOL SetThreadGroupAffinity(HANDLE h,
1696 GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity);
1697 static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity);
1698 #if !defined(FEATURE_CORESYSTEM) && !defined(FEATURE_CORECLR)
1699 static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime);
1700 static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf);
1701 static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf);
1706 int GetCurrentProcessCpuCount();
1707 DWORD_PTR GetCurrentProcessCpuMask();
1709 //*****************************************************************************
1710 // Return != 0 if the bit at the specified index in the array is on and 0 if
1712 //*****************************************************************************
1713 inline int GetBit(PTR_BYTE pcBits,int iBit)
1715 LIMITED_METHOD_CONTRACT;
1716 return (pcBits[iBit>>3] & (1 << (iBit & 0x7)));
1719 #ifdef DACCESS_COMPILE
1720 inline int GetBit(BYTE const * pcBits,int iBit)
1722 WRAPPER_NO_CONTRACT;
1723 return GetBit(dac_cast<PTR_BYTE>(pcBits), iBit);
1727 //*****************************************************************************
1728 // Set the state of the bit at the specified index based on the value of bOn.
1729 //*****************************************************************************
1730 inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn)
1732 LIMITED_METHOD_CONTRACT;
1734 pcBits[iBit>>3] |= (1 << (iBit & 0x7));
1736 pcBits[iBit>>3] &= ~(1 << (iBit & 0x7));
1739 #ifdef DACCESS_COMPILE
1740 inline void SetBit(BYTE * pcBits,int iBit,int bOn)
1742 WRAPPER_NO_CONTRACT;
1743 SetBit(dac_cast<PTR_BYTE>(pcBits), iBit, bOn);
1747 template<typename T>
1748 class SimpleListNode
1751 SimpleListNode<T>(const T& _t)
1758 SimpleListNode<T>* next;
1761 template<typename T>
1765 typedef SimpleListNode<T> NodeType;
1772 void LinkHead(NodeType* pNode)
1778 NodeType* UnlinkHead()
1780 NodeType* ret = head;
1800 template < typename T, typename U >
1804 typedef Pair< T, U > this_type;
1805 typedef T first_type;
1806 typedef U second_type;
1811 Pair( T const & t, U const & u )
1816 Pair( this_type const & obj )
1817 : m_first( obj.m_first )
1818 , m_second( obj.m_second )
1821 this_type & operator=( this_type const & obj )
1823 m_first = obj.m_first;
1824 m_second = obj.m_second;
1833 T const & First() const
1843 U const & Second() const
1848 bool operator==(const Pair& rhs) const
1850 return ((this->First() == rhs.First()) &&
1851 (this->Second() == rhs.Second()));
1854 bool operator!=(const Pair& rhs) const
1856 return !(*this == rhs);
1861 second_type m_second;
1865 template < typename T, typename U >
1866 Pair< T, U > MakePair( T const & t, U const & u )
1869 return Pair< T, U >( t, u );
1873 //*****************************************************************************
1874 // This class implements a dynamic array of structures for which the order of
1875 // the elements is unimportant. This means that any item placed in the list
1876 // may be swapped to any other location in the list at any time. If the order
1877 // of the items you place in the array is important, then use the CStructArray
1879 //*****************************************************************************
1884 class CUnorderedArrayWithAllocator
1886 int m_iCount; // # of elements used in the list.
1887 int m_iSize; // # of elements allocated in the list.
1889 #ifndef DACCESS_COMPILE
1890 T *m_pTable; // Pointer to the list of elements.
1892 TADDR m_pTable; // Pointer to the list of elements.
1897 #ifndef DACCESS_COMPILE
1899 CUnorderedArrayWithAllocator() :
1904 LIMITED_METHOD_CONTRACT;
1906 ~CUnorderedArrayWithAllocator()
1908 LIMITED_METHOD_CONTRACT;
1909 // Free the chunk of memory.
1910 if (m_pTable != NULL)
1911 ALLOCATOR::Free(this, m_pTable);
1916 WRAPPER_NO_CONTRACT;
1918 if (m_iSize > iGrowInc)
1920 T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc);
1922 ALLOCATOR::Free(this, m_pTable);
1929 void Clear(int iFirst, int iCount)
1931 WRAPPER_NO_CONTRACT;
1934 if (iFirst + iCount < m_iCount)
1935 memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount)));
1939 iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0);
1940 if (m_iSize > iGrowInc && iSize < m_iSize)
1942 T *tmp = ALLOCATOR::AllocNoThrow(this, iSize);
1944 memcpy (tmp, m_pTable, iSize * sizeof(T));
1950 _ASSERTE(m_iCount <= m_iSize);
1955 LIMITED_METHOD_CONTRACT;
1965 // The array should grow, if we can't fit one more element into the array.
1966 if (m_iSize <= m_iCount && GrowNoThrow() == NULL)
1968 return (&m_pTable[m_iCount++]);
1977 // The array should grow, if we can't fit one more element into the array.
1978 if (m_iSize <= m_iCount)
1980 return (&m_pTable[m_iCount++]);
1983 void Delete(const T &Entry)
1985 LIMITED_METHOD_CONTRACT;
1987 for (int i=0; i <= m_iCount; ++i)
1988 if (m_pTable[i] == Entry)
1990 m_pTable[i] = m_pTable[m_iCount];
1994 // Just in case we didn't find it.
1998 void DeleteByIndex(int i)
2000 LIMITED_METHOD_CONTRACT;
2002 m_pTable[i] = m_pTable[m_iCount];
2005 void Swap(int i,int j)
2007 LIMITED_METHOD_CONTRACT;
2013 m_pTable[i] = m_pTable[j];
2021 LIMITED_METHOD_CONTRACT;
2026 void EnumMemoryRegions(void)
2029 DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T));
2032 #endif // #ifndef DACCESS_COMPILE
2036 LIMITED_METHOD_CONTRACT;
2038 _ASSERTE(FitsIn<USHORT>(m_iCount));
2039 return static_cast<USHORT>(m_iCount);
2048 #ifndef DACCESS_COMPILE
2050 //*****************************************************************************
2051 // Increase the size of the array.
2052 //*****************************************************************************
2056 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::GrowNoThrow() // NULL if can't grow.
2058 WRAPPER_NO_CONTRACT;
2061 // try to allocate memory for reallocation.
2062 if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL)
2064 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
2065 ALLOCATOR::Free(this, m_pTable);
2067 m_iSize += iGrowInc;
2068 _ASSERTE(m_iSize > 0);
2075 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::Grow() // exception if can't grow.
2077 WRAPPER_NO_CONTRACT;
2080 // try to allocate memory for reallocation.
2081 pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc);
2082 memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
2083 ALLOCATOR::Free(this, m_pTable);
2085 m_iSize += iGrowInc;
2086 _ASSERTE(m_iSize > 0);
2090 #endif // #ifndef DACCESS_COMPILE
2094 class CUnorderedArray__Allocator
2098 static T *AllocThrowing (void*, int nElements)
2100 return new T[nElements];
2103 static T *AllocNoThrow (void*, int nElements)
2105 return new (nothrow) T[nElements];
2108 static void Free (void*, T *pTable)
2115 template <class T,int iGrowInc>
2116 class CUnorderedArray : public CUnorderedArrayWithAllocator<T, iGrowInc, CUnorderedArray__Allocator<T> >
2122 LIMITED_METHOD_CONTRACT;
2127 //Used by the debugger. Included here in hopes somebody else might, too
2128 typedef CUnorderedArray<SIZE_T, 17> SIZE_T_UNORDERED_ARRAY;
2131 //*****************************************************************************
2132 // This class implements a dynamic array of structures for which the insert
2133 // order is important. Inserts will slide all elements after the location
2134 // down, deletes slide all values over the deleted item. If the order of the
2135 // items in the array is unimportant to you, then CUnorderedArray may provide
2136 // the same feature set at lower cost.
2137 //*****************************************************************************
2140 BYTE *m_pList; // Pointer to the list of elements.
2141 int m_iCount; // # of elements used in the list.
2142 int m_iSize; // # of elements allocated in the list.
2143 int m_iGrowInc; // Growth increment.
2144 short m_iElemSize; // Size of an array element.
2145 bool m_bFree; // true if data is automatically maintained.
2148 CStructArray(short iElemSize, short iGrowInc = 1) :
2152 m_iGrowInc(iGrowInc),
2153 m_iElemSize(iElemSize),
2156 LIMITED_METHOD_CONTRACT;
2160 WRAPPER_NO_CONTRACT;
2164 void *Insert(int iIndex);
2165 void *InsertThrowing(int iIndex);
2167 void *AppendThrowing();
2168 int AllocateBlock(int iCount);
2169 void AllocateBlockThrowing(int iCount);
2170 void Delete(int iIndex);
2173 LIMITED_METHOD_CONTRACT;
2176 void *Get(int iIndex)
2178 WRAPPER_NO_CONTRACT;
2179 _ASSERTE(iIndex < m_iCount);
2180 return ((void *) ((size_t) Ptr() + (iIndex * m_iElemSize)));
2184 LIMITED_METHOD_CONTRACT;
2185 return (m_iCount * m_iElemSize);
2189 LIMITED_METHOD_CONTRACT;
2195 LIMITED_METHOD_CONTRACT;
2199 void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1)
2201 LIMITED_METHOD_CONTRACT;
2202 m_iElemSize = iElemSize;
2203 m_iGrowInc = (short) iGrowInc;
2204 m_pList = (BYTE*)pList;
2211 void Grow(int iCount);
2215 //*****************************************************************************
2216 // This template simplifies access to a CStructArray by removing void * and
2217 // adding some operator overloads.
2218 //*****************************************************************************
2220 class CDynArray : public CStructArray
2223 CDynArray(short iGrowInc=16) :
2224 CStructArray(sizeof(T), iGrowInc)
2226 LIMITED_METHOD_CONTRACT;
2229 T *Insert(int iIndex)
2231 WRAPPER_NO_CONTRACT;
2232 return ((T *)CStructArray::Insert((int)iIndex));
2235 T *InsertThrowing(int iIndex)
2237 WRAPPER_NO_CONTRACT;
2238 return ((T *)CStructArray::InsertThrowing((int)iIndex));
2243 WRAPPER_NO_CONTRACT;
2244 return ((T *)CStructArray::Append());
2249 WRAPPER_NO_CONTRACT;
2250 return ((T *)CStructArray::AppendThrowing());
2255 WRAPPER_NO_CONTRACT;
2256 return ((T *)CStructArray::Ptr());
2261 WRAPPER_NO_CONTRACT;
2262 return (Ptr() + iIndex);
2264 T &operator[](int iIndex)
2266 WRAPPER_NO_CONTRACT;
2267 return (*(Ptr() + iIndex));
2271 WRAPPER_NO_CONTRACT;
2272 return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T));
2274 void Move(int iFrom, int iTo)
2276 WRAPPER_NO_CONTRACT;
2279 _ASSERTE(iFrom >= 0 && iFrom < Count() &&
2280 iTo >= 0 && iTo < Count());
2282 tmp = *(Ptr() + iFrom);
2284 memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T));
2286 memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T));
2287 *(Ptr() + iTo) = tmp;
2291 // Some common arrays.
2292 typedef CDynArray<int> INTARRAY;
2293 typedef CDynArray<short> SHORTARRAY;
2294 typedef CDynArray<int> LONGARRAY;
2295 typedef CDynArray<USHORT> USHORTARRAY;
2296 typedef CDynArray<ULONG> ULONGARRAY;
2297 typedef CDynArray<BYTE> BYTEARRAY;
2298 typedef CDynArray<mdToken> TOKENARRAY;
2300 template <class T> class CStackArray : public CStructArray
2303 CStackArray(short iGrowInc=4) :
2304 CStructArray(sizeof(T), iGrowInc),
2307 LIMITED_METHOD_CONTRACT;
2312 WRAPPER_NO_CONTRACT;
2313 // We should only inc m_curPos after we grow the array.
2314 T *pT = (T *)CStructArray::InsertThrowing(m_curPos);
2321 WRAPPER_NO_CONTRACT;
2324 _ASSERTE(m_curPos > 0);
2326 retPtr = (T *)CStructArray::Get(m_curPos-1);
2327 CStructArray::Delete(m_curPos--);
2334 LIMITED_METHOD_CONTRACT;
2343 //*****************************************************************************
2344 // This template manages a list of free entries by their 0 based offset. By
2345 // making it a template, you can use whatever size free chain will match your
2346 // maximum count of items. -1 is reserved.
2347 //*****************************************************************************
2348 template <class T> class TFreeList
2355 LIMITED_METHOD_CONTRACT;
2363 for (i=0; i<iCount - 1; i++)
2364 m_rgList[i] = i + 1;
2365 m_rgList[i] = (T) -1;
2368 T GetFreeEntry() // Index of free item, or -1.
2370 LIMITED_METHOD_CONTRACT;
2373 if (m_iNext == (T) -1)
2377 m_iNext = m_rgList[m_iNext];
2381 void DelFreeEntry(T iEntry)
2383 LIMITED_METHOD_CONTRACT;
2384 _ASSERTE(iEntry < m_iCount);
2385 m_rgList[iEntry] = m_iNext;
2389 // This function can only be used when it is guaranteed that the free
2390 // array is contigous, for example, right after creation to quickly
2391 // get a range of items from the heap.
2392 void ReserveRange(int iCount)
2394 LIMITED_METHOD_CONTRACT;
2395 _ASSERTE(iCount < m_iCount);
2396 _ASSERTE(m_iNext == 0);
2401 T *m_rgList; // List of free info.
2402 int m_iCount; // How many entries to manage.
2403 T m_iNext; // Next item to get.
2407 //*****************************************************************************
2408 //*****************************************************************************
2409 template <class T> class CQuickSort
2412 T *m_pBase; // Base of array to sort.
2414 SSIZE_T m_iCount; // How many items in array.
2415 SSIZE_T m_iElemSize; // Size of one element.
2418 T *pBase, // Address of first element.
2419 SSIZE_T iCount) : // How many there are.
2422 m_iElemSize(sizeof(T))
2424 LIMITED_METHOD_DAC_CONTRACT;
2427 //*****************************************************************************
2428 // Call to sort the array.
2429 //*****************************************************************************
2432 WRAPPER_NO_CONTRACT;
2433 SortRange(0, m_iCount - 1);
2437 //*****************************************************************************
2438 // Override this function to do the comparison.
2439 //*****************************************************************************
2440 virtual FORCEINLINE int Compare( // -1, 0, or 1
2441 T *psFirst, // First item to compare.
2442 T *psSecond) // Second item to compare.
2444 LIMITED_METHOD_DAC_CONTRACT;
2445 return (memcmp(psFirst, psSecond, sizeof(T)));
2446 // return (::Compare(*psFirst, *psSecond));
2449 virtual FORCEINLINE void Swap(
2453 LIMITED_METHOD_DAC_CONTRACT;
2454 if (iFirst == iSecond) return;
2455 T sTemp( m_pBase[iFirst] );
2456 m_pBase[iFirst] = m_pBase[iSecond];
2457 m_pBase[iSecond] = sTemp;
2461 inline void SortRange(
2465 WRAPPER_NO_CONTRACT;
2467 SSIZE_T i; // loop variable.
2471 // if less than two elements you're done.
2472 if (iLeft >= iRight)
2475 // ASSERT that we now have valid indicies. This is statically provable
2476 // since this private function is only called with valid indicies,
2477 // and iLeft and iRight only converge towards eachother. However,
2478 // PreFast can't detect this because it doesn't know about our callers.
2479 COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount);
2480 COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount);
2482 // The mid-element is the pivot, move it to the left.
2483 Swap(iLeft, (iLeft + iRight) / 2);
2486 // move everything that is smaller than the pivot to the left.
2487 for (i = iLeft + 1; i <= iRight; i++)
2489 if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0)
2495 // Put the pivot to the point where it is in between smaller and larger elements.
2498 // Sort each partition.
2499 SSIZE_T iLeftLast = iLast - 1;
2500 SSIZE_T iRightFirst = iLast + 1;
2501 if (iLeftLast - iLeft < iRight - iRightFirst)
2502 { // Left partition is smaller, sort it recursively
2503 SortRange(iLeft, iLeftLast);
2504 // Tail call to sort the right (bigger) partition
2505 iLeft = iRightFirst;
2510 { // Right partition is smaller, sort it recursively
2511 SortRange(iRightFirst, iRight);
2512 // Tail call to sort the left (bigger) partition
2521 //*****************************************************************************
2522 // Faster and simpler version of the binary search below.
2523 //*****************************************************************************
2525 const T * BinarySearch(const T * pBase, int iCount, const T & find)
2527 WRAPPER_NO_CONTRACT;
2530 int iLast = iCount - 1;
2532 // It is faster to use linear search once we get down to a small number of elements.
2533 while (iLast - iFirst > 10)
2535 int iMid = (iLast + iFirst) / 2;
2537 if (find < pBase[iMid])
2543 for (int i = iFirst; i <= iLast; i++)
2545 if (find == pBase[i])
2548 if (find < pBase[i])
2555 //*****************************************************************************
2556 // This template encapsulates a binary search algorithm on the given type
2558 //*****************************************************************************
2559 template <class T> class CBinarySearch
2562 const T *m_pBase; // Base of array to sort.
2563 int m_iCount; // How many items in array.
2567 const T *pBase, // Address of first element.
2568 int iCount) : // Value to find.
2572 LIMITED_METHOD_CONTRACT;
2575 //*****************************************************************************
2576 // Searches for the item passed to ctor.
2577 //*****************************************************************************
2578 const T *Find( // Pointer to found item in array.
2579 const T *psFind, // The key to find.
2580 int *piInsert = NULL) // Index to insert at.
2582 WRAPPER_NO_CONTRACT;
2583 int iMid, iFirst, iLast; // Loop control.
2584 int iCmp; // Comparison.
2587 iLast = m_iCount - 1;
2588 while (iFirst <= iLast)
2590 iMid = (iLast + iFirst) / 2;
2591 iCmp = Compare(psFind, &m_pBase[iMid]);
2594 if (piInsert != NULL)
2596 return (&m_pBase[iMid]);
2603 if (piInsert != NULL)
2608 //*****************************************************************************
2609 // Override this function to do the comparison if a comparison operator is
2610 // not valid for your data type (such as a struct).
2611 //*****************************************************************************
2612 virtual int Compare( // -1, 0, or 1
2613 const T *psFirst, // Key you are looking for.
2614 const T *psSecond) // Item to compare to.
2616 LIMITED_METHOD_CONTRACT;
2617 return (memcmp(psFirst, psSecond, sizeof(T)));
2618 // return (::Compare(*psFirst, *psSecond));
2622 //*****************************************************************************
2623 // The information that the hash table implementation stores at the beginning
2624 // of every record that can be but in the hash table.
2625 //*****************************************************************************
2626 typedef DPTR(struct HASHENTRY) PTR_HASHENTRY;
2629 ULONG iPrev; // Previous bucket in the chain.
2630 ULONG iNext; // Next bucket in the chain.
2633 typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY;
2634 struct FREEHASHENTRY : HASHENTRY
2639 //*****************************************************************************
2640 // Used by the FindFirst/FindNextEntry functions. These api's allow you to
2641 // do a sequential scan of all entries.
2642 //*****************************************************************************
2645 ULONG iBucket; // The next bucket to look in.
2650 //*****************************************************************************
2651 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2652 // The hashtable implementation that should be used instead is code:SHash.
2653 // If code:SHash does not work for you, talk to mailto:clrdeag.
2654 //*****************************************************************************
2655 // This is a class that implements a chain and bucket hash table.
2657 // The data is actually supplied as an array of structures by the user of this class.
2658 // This allows the buckets to use small indices to point to the chain, instead of pointers.
2660 // Each entry in the array contains a HASHENTRY structure immediately
2661 // followed by the key used to hash the structure.
2663 // The HASHENTRY part of every structure is used to implement the chain of
2664 // entries in a single bucket.
2666 // This implementation does not support rehashing the buckets if the table grows
2668 // @TODO: Fix this by adding an abstract function Hash() which must be implemented
2671 //*****************************************************************************
2674 friend class DebuggerRCThread; //RCthread actually needs access to
2675 //fields of derrived class DebuggerPatchTable
2678 TADDR m_pcEntries; // Pointer to the array of structs.
2679 ULONG m_iEntrySize; // Size of the structs.
2681 ULONG m_iBuckets; // # of chains we are hashing into.
2682 PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains.
2684 INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics
2686 HASHENTRY *EntryPtr(ULONG iEntry)
2688 LIMITED_METHOD_DAC_CONTRACT;
2689 return (PTR_HASHENTRY(m_pcEntries + (iEntry * m_iEntrySize)));
2692 ULONG ItemIndex(HASHENTRY *p)
2695 LIMITED_METHOD_CONTRACT;
2696 return (ULONG)((dac_cast<TADDR>(p) - m_pcEntries) / m_iEntrySize);
2703 ULONG iBuckets) : // # of chains we are hashing into.
2704 m_pcEntries((TADDR)NULL),
2705 m_iBuckets(iBuckets)
2707 LIMITED_METHOD_CONTRACT;
2711 INDEBUG(m_maxSearch = 0;)
2714 CHashTable() : // # of chains we are hashing into.
2715 m_pcEntries((TADDR)NULL),
2718 LIMITED_METHOD_CONTRACT;
2722 INDEBUG(m_maxSearch = 0;)
2725 #ifndef DACCESS_COMPILE
2729 LIMITED_METHOD_CONTRACT;
2730 if (m_piBuckets != NULL)
2732 delete [] m_piBuckets;
2737 //*****************************************************************************
2738 // This is the second part of construction where we do all of the work that
2739 // can fail. We also take the array of structs here because the calling class
2740 // presumably needs to allocate it in its NewInit.
2741 //*****************************************************************************
2742 HRESULT NewInit( // Return status.
2743 BYTE *pcEntries, // Array of structs we are managing.
2744 ULONG iEntrySize); // Size of the entries.
2746 //*****************************************************************************
2747 // This can be called to change the pointer to the table that the hash table
2748 // is managing. You might call this if (for example) you realloc the size
2749 // of the table and its pointer is different.
2750 //*****************************************************************************
2752 BYTE *pcEntries) // Array of structs we are managing.
2754 LIMITED_METHOD_CONTRACT;
2755 m_pcEntries = (TADDR)pcEntries;
2758 //*****************************************************************************
2759 // Clear the hash table as if there were nothing in it.
2760 //*****************************************************************************
2763 LIMITED_METHOD_CONTRACT;
2764 _ASSERTE(m_piBuckets != NULL);
2765 memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG));
2768 //*****************************************************************************
2769 // Add the struct at the specified index in m_pcEntries to the hash chains.
2770 //*****************************************************************************
2771 BYTE *Add( // New entry.
2772 ULONG iHash, // Hash value of entry to add.
2773 ULONG iIndex); // Index of struct in m_pcEntries.
2775 //*****************************************************************************
2776 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2777 //*****************************************************************************
2779 ULONG iHash, // Hash value of entry to delete.
2780 ULONG iIndex); // Index of struct in m_pcEntries.
2783 ULONG iHash, // Hash value of entry to delete.
2784 HASHENTRY *psEntry); // The struct to delete.
2786 //*****************************************************************************
2787 // The item at the specified index has been moved, update the previous and
2789 //*****************************************************************************
2791 ULONG iHash, // Hash value for the item.
2792 ULONG iNew); // New location.
2794 #endif // #ifndef DACCESS_COMPILE
2796 //*****************************************************************************
2797 // Return a boolean indicating whether or not this hash table has been inited.
2798 //*****************************************************************************
2801 LIMITED_METHOD_CONTRACT;
2802 return (m_piBuckets != NULL);
2805 //*****************************************************************************
2806 // Search the hash table for an entry with the specified key value.
2807 //*****************************************************************************
2808 BYTE *Find( // Index of struct in m_pcEntries.
2809 ULONG iHash, // Hash value of the item.
2810 SIZE_T key); // The key to match.
2812 //*****************************************************************************
2813 // Search the hash table for the next entry with the specified key value.
2814 //*****************************************************************************
2815 ULONG FindNext( // Index of struct in m_pcEntries.
2816 SIZE_T key, // The key to match.
2817 ULONG iIndex); // Index of previous match.
2819 //*****************************************************************************
2820 // Returns the first entry in the first hash bucket and inits the search
2821 // struct. Use the FindNextEntry function to continue walking the list. The
2822 // return order is not gauranteed.
2823 //*****************************************************************************
2824 BYTE *FindFirstEntry( // First entry found, or 0.
2825 HASHFIND *psSrch) // Search object.
2827 WRAPPER_NO_CONTRACT;
2828 if (m_piBuckets == 0)
2830 psSrch->iBucket = 1;
2831 psSrch->iNext = m_piBuckets[0];
2832 return (FindNextEntry(psSrch));
2835 //*****************************************************************************
2836 // Returns the next entry in the list.
2837 //*****************************************************************************
2838 BYTE *FindNextEntry( // The next entry, or0 for end of list.
2839 HASHFIND *psSrch); // Search object.
2841 #ifdef DACCESS_COMPILE
2842 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
2847 virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0;
2854 static BYTE *Alloc(int iSize, int iMaxSize)
2856 WRAPPER_NO_CONTRACT;
2857 return (new BYTE[iSize]);
2859 static void Free(BYTE *pPtr, int iSize)
2861 LIMITED_METHOD_CONTRACT;
2864 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2866 WRAPPER_NO_CONTRACT;
2868 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2869 //check for overflow
2870 if(newSize.IsOverflow())
2873 p = new (nothrow) BYTE[newSize.Value()];
2874 if (p == 0) return (0);
2875 memcpy (p, pPtr, iCurSize);
2880 static void Clean(BYTE * pData, int iSize)
2883 static int RoundSize(int iSize)
2885 LIMITED_METHOD_CONTRACT;
2888 static int GrowSize(int iCurSize)
2890 LIMITED_METHOD_CONTRACT;
2891 int newSize = (3 * iCurSize) / 2;
2892 return (newSize < 256) ? 256 : newSize;
2896 class CNewDataNoThrow
2899 static BYTE *Alloc(int iSize, int iMaxSize)
2901 WRAPPER_NO_CONTRACT;
2902 return (new (nothrow) BYTE[iSize]);
2904 static void Free(BYTE *pPtr, int iSize)
2906 LIMITED_METHOD_CONTRACT;
2909 static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2911 WRAPPER_NO_CONTRACT;
2913 S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2914 //check for overflow
2915 if(newSize.IsOverflow())
2918 p = new (nothrow) BYTE[newSize.Value()];
2919 if (p == 0) return (0);
2920 memcpy (p, pPtr, iCurSize);
2925 static void Clean(BYTE * pData, int iSize)
2928 static int RoundSize(int iSize)
2930 LIMITED_METHOD_CONTRACT;
2933 static int GrowSize(int iCurSize)
2935 LIMITED_METHOD_CONTRACT;
2936 int newSize = (3 * iCurSize) / 2;
2937 return (newSize < 256) ? 256 : newSize;
2942 //*****************************************************************************
2943 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2944 // The hashtable implementation that should be used instead is code:SHash.
2945 // If code:SHash does not work for you, talk to mailto:clrdeag.
2946 //*****************************************************************************
2947 // CHashTable expects the data to be in a single array - this is provided by
2948 // CHashTableAndData.
2949 // The array is allocated using the MemMgr type. CNewData and
2950 // CNewDataNoThrow can be used for this.
2951 //*****************************************************************************
2952 template <class MemMgr>
2953 class CHashTableAndData : public CHashTable
2956 ULONG m_iFree; // Index into m_pcEntries[] of next available slot
2957 ULONG m_iEntries; // size of m_pcEntries[]
2961 CHashTableAndData() :
2964 LIMITED_METHOD_CONTRACT;
2968 ULONG iBuckets) : // # of chains we are hashing into.
2969 CHashTable(iBuckets)
2971 LIMITED_METHOD_CONTRACT;
2974 #ifndef DACCESS_COMPILE
2976 ~CHashTableAndData()
2978 WRAPPER_NO_CONTRACT;
2979 if (m_pcEntries != NULL)
2980 MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize));
2983 //*****************************************************************************
2984 // This is the second part of construction where we do all of the work that
2985 // can fail. We also take the array of structs here because the calling class
2986 // presumably needs to allocate it in its NewInit.
2987 //*****************************************************************************
2988 HRESULT NewInit( // Return status.
2989 ULONG iEntries, // # of entries.
2990 ULONG iEntrySize, // Size of the entries.
2991 int iMaxSize); // Max size of data.
2993 //*****************************************************************************
2994 // Clear the hash table as if there were nothing in it.
2995 //*****************************************************************************
2998 WRAPPER_NO_CONTRACT;
3000 InitFreeChain(0, m_iEntries);
3001 CHashTable::Clear();
3004 //*****************************************************************************
3005 // Grabs a slot for the new entry to be added.
3006 // The caller should fill in the non-HASHENTRY part of the returned slot
3007 //*****************************************************************************
3009 ULONG iHash) // Hash value of entry to add.
3011 WRAPPER_NO_CONTRACT;
3012 FREEHASHENTRY *psEntry;
3014 // Make the table bigger if necessary.
3015 if (m_iFree == UINT32_MAX && !Grow())
3018 // Add the first entry from the free list to the hash chain.
3019 psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree);
3020 m_iFree = psEntry->iFree;
3022 // If we're recycling memory, give our memory-allocator a chance to re-init it.
3024 // Each entry is prefixed with a header - we don't want to trash that.
3025 SIZE_T cbHeader = sizeof(FREEHASHENTRY);
3026 MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader));
3028 return ((BYTE *) psEntry);
3031 //*****************************************************************************
3032 // Delete the struct at the specified index in m_pcEntries from the hash chains.
3033 //*****************************************************************************
3035 ULONG iHash, // Hash value of entry to delete.
3036 ULONG iIndex) // Index of struct in m_pcEntries.
3038 WRAPPER_NO_CONTRACT;
3039 CHashTable::Delete(iHash, iIndex);
3040 ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree;
3045 ULONG iHash, // Hash value of entry to delete.
3046 HASHENTRY *psEntry) // The struct to delete.
3048 WRAPPER_NO_CONTRACT;
3049 CHashTable::Delete(iHash, psEntry);
3050 ((FREEHASHENTRY *) psEntry)->iFree = m_iFree;
3051 m_iFree = ItemIndex(psEntry);
3054 #endif // #ifndef DACCESS_COMPILE
3056 // This is a sad legacy workaround. The debugger's patch table (implemented as this
3057 // class) is shared across process. We publish the runtime offsets of
3058 // some key fields. Since those fields are private, we have to provide
3059 // accessors here. So if you're not using these functions, don't start.
3060 // We can hopefully remove them.
3061 // Note that we can't just make RCThread a friend of this class (we tried
3062 // originally) because the inheritence chain has a private modifier,
3063 // so DebuggerPatchTable::m_pcEntries is illegal.
3064 static SIZE_T helper_GetOffsetOfEntries()
3066 LIMITED_METHOD_CONTRACT;
3067 return offsetof(CHashTableAndData, m_pcEntries);
3070 static SIZE_T helper_GetOffsetOfCount()
3072 LIMITED_METHOD_CONTRACT;
3073 return offsetof(CHashTableAndData, m_iEntries);
3076 #ifdef DACCESS_COMPILE
3077 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
3080 CHashTable::EnumMemoryRegions(flags, m_iEntries);
3085 void InitFreeChain(ULONG iStart,ULONG iEnd);
3089 #ifndef DACCESS_COMPILE
3091 //*****************************************************************************
3092 // This is the second part of construction where we do all of the work that
3093 // can fail. We also take the array of structs here because the calling class
3094 // presumably needs to allocate it in its NewInit.
3095 //*****************************************************************************
3096 template<class MemMgr>
3097 HRESULT CHashTableAndData<MemMgr>::NewInit(// Return status.
3098 ULONG iEntries, // # of entries.
3099 ULONG iEntrySize, // Size of the entries.
3100 int iMaxSize) // Max size of data.
3102 WRAPPER_NO_CONTRACT;
3107 // note that this function can throw because it depends on the <M>::Alloc
3109 // Allocate the memory for the entries.
3110 if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize),
3111 MemMgr::RoundSize(iMaxSize))) == 0)
3112 return (E_OUTOFMEMORY);
3113 m_iEntries = iEntries;
3115 // Init the base table.
3116 if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize)))
3117 MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize));
3120 // Init the free chain.
3122 InitFreeChain(0, iEntries);
3127 //*****************************************************************************
3128 // Initialize a range of records such that they are linked together to be put
3129 // on the free chain.
3130 //*****************************************************************************
3131 template<class MemMgr>
3132 void CHashTableAndData<MemMgr>::InitFreeChain(
3133 ULONG iStart, // Index to start initializing.
3134 ULONG iEnd) // Index to stop initializing
3136 LIMITED_METHOD_CONTRACT;
3138 _ASSERTE(iEnd > iStart);
3140 pcPtr = (BYTE*)m_pcEntries + iStart * m_iEntrySize;
3141 for (++iStart; iStart < iEnd; ++iStart)
3143 ((FREEHASHENTRY *) pcPtr)->iFree = iStart;
3144 pcPtr += m_iEntrySize;
3146 ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX;
3149 //*****************************************************************************
3150 // Attempt to increase the amount of space available for the record heap.
3151 //*****************************************************************************
3152 template<class MemMgr>
3153 int CHashTableAndData<MemMgr>::Grow() // 1 if successful, 0 if not.
3155 WRAPPER_NO_CONTRACT;
3156 int iCurSize; // Current size in bytes.
3157 int iEntries; // New # of entries.
3159 _ASSERTE(m_pcEntries != NULL);
3160 _ASSERTE(m_iFree == UINT32_MAX);
3162 // Compute the current size and new # of entries.
3163 S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize);
3164 if( iTotEntrySize.IsOverflow() )
3166 _ASSERTE( !"CHashTableAndData overflow!" );
3169 iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() );
3170 iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize;
3172 if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) )
3174 _ASSERTE( !"CHashTableAndData overflow!" );
3178 // Try to expand the array.
3179 if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0)
3182 // Init the newly allocated space.
3183 InitFreeChain(m_iEntries, iEntries);
3184 m_iFree = m_iEntries;
3185 m_iEntries = iEntries;
3189 #endif // #ifndef DACCESS_COMPILE
3191 //*****************************************************************************
3192 //*****************************************************************************
3194 inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data)
3196 LIMITED_METHOD_DAC_CONTRACT;
3197 return ((currentHash << 5) + currentHash) ^ data;
3200 inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr)
3202 WRAPPER_NO_CONTRACT;
3204 return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast<TADDR>(ptr))));
3207 inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c)
3209 LIMITED_METHOD_DAC_CONTRACT;
3211 // Current implementation taken from lookup3.c, by Bob Jenkins, May 2006
3213 #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
3214 c ^= b; c -= rot32(b,14);
3215 a ^= c; a -= rot32(c,11);
3216 b ^= a; b -= rot32(a,25);
3217 c ^= b; c -= rot32(b,16);
3218 a ^= c; a -= rot32(c,4);
3219 b ^= a; b -= rot32(a,14);
3220 c ^= b; c -= rot32(b,24);
3225 inline ULONG HashBytes(BYTE const *pbData, size_t iSize)
3227 LIMITED_METHOD_CONTRACT;
3230 BYTE const *pbDataEnd = pbData + iSize;
3232 for (/**/ ; pbData < pbDataEnd; pbData++)
3234 hash = ((hash << 5) + hash) ^ *pbData;
3239 // Helper function for hashing a string char by char.
3240 inline ULONG HashStringA(LPCSTR szStr)
3242 LIMITED_METHOD_CONTRACT;
3246 while ((c = *szStr) != 0)
3248 hash = ((hash << 5) + hash) ^ c;
3254 inline ULONG HashString(LPCWSTR szStr)
3256 LIMITED_METHOD_CONTRACT;
3260 while ((c = *szStr) != 0)
3262 hash = ((hash << 5) + hash) ^ c;
3268 inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr)
3270 LIMITED_METHOD_CONTRACT;
3273 // hash the string two characters at a time
3274 ULONG *ptr = (ULONG *)szStr;
3276 // we assume that szStr is null-terminated
3277 _ASSERTE(cchStr <= wcslen(szStr));
3278 SIZE_T cDwordCount = (cchStr + 1) / 2;
3280 for (SIZE_T i = 0; i < cDwordCount; i++)
3282 hash = ((hash << 5) + hash) ^ ptr[i];
3288 // Case-insensitive string hash function.
3289 inline ULONG HashiStringA(LPCSTR szStr)
3291 LIMITED_METHOD_CONTRACT;
3295 hash = ((hash << 5) + hash) ^ toupper(*szStr);
3301 // Case-insensitive string hash function.
3302 inline ULONG HashiString(LPCWSTR szStr)
3304 LIMITED_METHOD_CONTRACT;
3308 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3314 // Case-insensitive string hash function.
3315 inline ULONG HashiStringN(LPCWSTR szStr, DWORD count)
3317 LIMITED_METHOD_CONTRACT;
3319 while (*szStr != 0 && count--)
3321 hash = ((hash << 5) + hash) ^ towupper(*szStr);
3327 // Case-insensitive string hash function when all of the
3328 // characters in the string are known to be below 0x80.
3329 // Knowing this is much more efficient than calling
3331 inline ULONG HashiStringKnownLower80(LPCWSTR szStr) {
3332 LIMITED_METHOD_CONTRACT;
3336 while ((c = *szStr)!=0) {
3337 //If we have a lowercase character, ANDing off 0x20
3338 //(mask) will make it an uppercase character.
3339 if (c>='a' && c<='z') {
3342 hash = ((hash << 5) + hash) ^ c;
3348 inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) {
3349 LIMITED_METHOD_CONTRACT;
3353 while ((c = *szStr) !=0 && count--) {
3354 //If we have a lowercase character, ANDing off 0x20
3355 //(mask) will make it an uppercase character.
3356 if (c>='a' && c<='z') {
3359 hash = ((hash << 5) + hash) ^ c;
3366 // // // See $\src\utilcode\Debug.cpp for "Binomial (K, M, N)", which
3367 // // // computes the binomial distribution, with which to compare your
3368 // // // hash-table statistics.
3374 //*****************************************************************************
3375 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3376 // The hashtable implementation that should be used instead is code:SHash.
3377 // If code:SHash does not work for you, talk to mailto:clrdeag.
3378 //*****************************************************************************
3379 // This class implements a closed hashing table. Values are hashed to a bucket,
3380 // and if that bucket is full already, then the value is placed in the next
3381 // free bucket starting after the desired target (with wrap around). If the
3382 // table becomes 75% full, it is grown and rehashed to reduce lookups. This
3383 // class is best used in a reltively small lookup table where hashing is
3384 // not going to cause many collisions. By not having the collision chain
3385 // logic, a lot of memory is saved.
3387 // The user of the template is required to supply several methods which decide
3388 // how each element can be marked as free, deleted, or used. It would have
3389 // been possible to write this with more internal logic, but that would require
3390 // either (a) more overhead to add status on top of elements, or (b) hard
3391 // coded types like one for strings, one for ints, etc... This gives you the
3392 // flexibility of adding logic to your type.
3393 //*****************************************************************************
3394 class CClosedHashBase
3396 BYTE *EntryPtr(int iEntry)
3398 LIMITED_METHOD_CONTRACT;
3399 return (m_rgData + (iEntry * m_iEntrySize));
3402 BYTE *EntryPtr(int iEntry, BYTE *rgData)
3404 LIMITED_METHOD_CONTRACT;
3405 return (rgData + (iEntry * m_iEntrySize));
3411 FREE, // Item is not in use right now.
3412 DELETED, // Item is deleted.
3413 USED // Item is in use.
3417 int iBuckets, // How many buckets should we start with.
3418 int iEntrySize, // Size of an entry.
3419 bool bPerfect) : // true if bucket size will hash with no collisions.
3420 m_bPerfect(bPerfect),
3421 m_iBuckets(iBuckets),
3422 m_iEntrySize(iEntrySize),
3427 LIMITED_METHOD_CONTRACT;
3428 m_iSize = iBuckets + 7;
3433 WRAPPER_NO_CONTRACT;
3437 virtual void Clear()
3439 LIMITED_METHOD_CONTRACT;
3446 //*****************************************************************************
3447 // Accessors for getting at the underlying data. Be careful to use Count()
3448 // only when you want the number of buckets actually used.
3449 //*****************************************************************************
3453 LIMITED_METHOD_CONTRACT;
3459 LIMITED_METHOD_CONTRACT;
3460 return (m_iCollisions);
3465 LIMITED_METHOD_CONTRACT;
3466 return (m_iBuckets);
3469 void SetBuckets(int iBuckets, bool bPerfect=false)
3471 LIMITED_METHOD_CONTRACT;
3472 _ASSERTE(m_rgData == 0);
3473 m_iBuckets = iBuckets;
3474 m_iSize = m_iBuckets + 7;
3475 m_bPerfect = bPerfect;
3480 LIMITED_METHOD_CONTRACT;
3484 //*****************************************************************************
3485 // Add a new item to hash table given the key value. If this new entry
3486 // exceeds maximum size, then the table will grow and be re-hashed, which
3487 // may cause a memory error.
3488 //*****************************************************************************
3489 BYTE *Add( // New item to fill out on success.
3490 void *pData) // The value to hash on.
3492 WRAPPER_NO_CONTRACT;
3493 // If we haven't allocated any memory, or it is too small, fix it.
3494 if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect))
3500 return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount));
3503 //*****************************************************************************
3504 // Delete the given value. This will simply mark the entry as deleted (in
3505 // order to keep the collision chain intact). There is an optimization that
3506 // consecutive deleted entries leading up to a free entry are themselves freed
3507 // to reduce collisions later on.
3508 //*****************************************************************************
3510 void *pData); // Key value to delete.
3513 //*****************************************************************************
3514 // Callback function passed to DeleteLoop.
3515 //*****************************************************************************
3516 typedef BOOL (* DELETELOOPFUNC)( // Delete current item?
3517 BYTE *pEntry, // Bucket entry to evaluate
3518 void *pCustomizer); // User-defined value
3520 //*****************************************************************************
3521 // Iterates over all active values, passing each one to pDeleteLoopFunc.
3522 // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer
3523 // and faster than using FindNext() and Delete().
3524 //*****************************************************************************
3526 DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item
3527 void *pCustomizer); // Extra value passed to deletefunc.
3530 //*****************************************************************************
3531 // Lookup a key value and return a pointer to the element if found.
3532 //*****************************************************************************
3533 BYTE *Find( // The item if found, 0 if not.
3534 void *pData); // The key to lookup.
3536 //*****************************************************************************
3537 // Look for an item in the table. If it isn't found, then create a new one and
3539 //*****************************************************************************
3540 BYTE *FindOrAdd( // The item if found, 0 if not.
3541 void *pData, // The key to lookup.
3542 bool &bNew); // true if created.
3544 //*****************************************************************************
3545 // The following functions are used to traverse each used entry. This code
3546 // will skip over deleted and free entries freeing the caller up from such
3548 //*****************************************************************************
3549 BYTE *GetFirst() // The first entry, 0 if none.
3551 WRAPPER_NO_CONTRACT;
3552 int i; // Loop control.
3554 // If we've never allocated the table there can't be any to get.
3558 // Find the first one.
3559 for (i=0; i<m_iSize; i++)
3561 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3562 return (EntryPtr(i));
3567 BYTE *GetNext(BYTE *Prev) // The next entry, 0 if done.
3569 WRAPPER_NO_CONTRACT;
3570 int i; // Loop control.
3572 for (i = (int)(((size_t) Prev - (size_t) &m_rgData[0]) / m_iEntrySize) + 1; i<m_iSize; i++)
3574 if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3575 return (EntryPtr(i));
3581 //*****************************************************************************
3582 // Hash is called with a pointer to an element in the table. You must override
3583 // this method and provide a hash algorithm for your element type.
3584 //*****************************************************************************
3585 virtual unsigned int Hash( // The key value.
3586 void const *pData)=0; // Raw data to hash.
3588 //*****************************************************************************
3589 // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
3590 // direction of miscompare. In this system everything is always equal or not.
3591 //*****************************************************************************
3592 virtual unsigned int Compare( // 0, -1, or 1.
3593 void const *pData, // Raw key data on lookup.
3594 BYTE *pElement)=0; // The element to compare data against.
3596 //*****************************************************************************
3597 // Return true if the element is free to be used.
3598 //*****************************************************************************
3599 virtual ELEMENTSTATUS Status( // The status of the entry.
3600 BYTE *pElement)=0; // The element to check.
3602 //*****************************************************************************
3603 // Sets the status of the given element.
3604 //*****************************************************************************
3605 virtual void SetStatus(
3606 BYTE *pElement, // The element to set status for.
3607 ELEMENTSTATUS eStatus)=0; // New status.
3609 //*****************************************************************************
3610 // Returns the internal key value for an element.
3611 //*****************************************************************************
3612 virtual void *GetKey( // The data to hash on.
3613 BYTE *pElement)=0; // The element to return data ptr for.
3615 //*****************************************************************************
3616 // This helper actually does the add for you.
3617 //*****************************************************************************
3618 BYTE *DoAdd(void *pData, BYTE *rgData, int &iBuckets, int iSize,
3619 int &iCollisions, int &iCount);
3621 //*****************************************************************************
3622 // This function is called either to init the table in the first place, or
3623 // to rehash the table if we ran out of room.
3624 //*****************************************************************************
3625 bool ReHash(); // true if successful.
3627 //*****************************************************************************
3628 // Walk each item in the table and mark it free.
3629 //*****************************************************************************
3630 void InitFree(BYTE *ptr, int iSize)
3632 WRAPPER_NO_CONTRACT;
3634 for (i=0; i<iSize; i++, ptr += m_iEntrySize)
3635 SetStatus(ptr, FREE);
3639 bool m_bPerfect; // true if the table size guarantees
3641 int m_iBuckets; // How many buckets do we have.
3642 int m_iEntrySize; // Size of an entry.
3643 int m_iSize; // How many elements can we have.
3644 int m_iCount; // How many items cannot be used (NON free, i.e. USED+DELETED).
3645 int m_iCollisions; // How many have we had.
3646 BYTE *m_rgData; // Data element list.
3649 //*****************************************************************************
3650 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3651 // The hashtable implementation that should be used instead is code:SHash.
3652 // If code:SHash does not work for you, talk to mailto:clrdeag.
3653 //*****************************************************************************
3654 template <class T> class CClosedHash : public CClosedHashBase
3658 int iBuckets, // How many buckets should we start with.
3659 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3660 CClosedHashBase(iBuckets, sizeof(T), bPerfect)
3662 WRAPPER_NO_CONTRACT;
3665 T &operator[](int iIndex)
3667 WRAPPER_NO_CONTRACT;
3668 return ((T &) *(Data() + (iIndex * sizeof(T))));
3672 //*****************************************************************************
3673 // Add a new item to hash table given the key value. If this new entry
3674 // exceeds maximum size, then the table will grow and be re-hashed, which
3675 // may cause a memory error.
3676 //*****************************************************************************
3677 T *Add( // New item to fill out on success.
3678 void *pData) // The value to hash on.
3680 WRAPPER_NO_CONTRACT;
3681 return ((T *) CClosedHashBase::Add(pData));
3684 //*****************************************************************************
3685 // Lookup a key value and return a pointer to the element if found.
3686 //*****************************************************************************
3687 T *Find( // The item if found, 0 if not.
3688 void *pData) // The key to lookup.
3690 WRAPPER_NO_CONTRACT;
3691 return ((T *) CClosedHashBase::Find(pData));
3694 //*****************************************************************************
3695 // Look for an item in the table. If it isn't found, then create a new one and
3697 //*****************************************************************************
3698 T *FindOrAdd( // The item if found, 0 if not.
3699 void *pData, // The key to lookup.
3700 bool &bNew) // true if created.
3702 WRAPPER_NO_CONTRACT;
3703 return ((T *) CClosedHashBase::FindOrAdd(pData, bNew));
3707 //*****************************************************************************
3708 // The following functions are used to traverse each used entry. This code
3709 // will skip over deleted and free entries freeing the caller up from such
3711 //*****************************************************************************
3712 T *GetFirst() // The first entry, 0 if none.
3714 WRAPPER_NO_CONTRACT;
3715 return ((T *) CClosedHashBase::GetFirst());
3718 T *GetNext(T *Prev) // The next entry, 0 if done.
3720 WRAPPER_NO_CONTRACT;
3721 return ((T *) CClosedHashBase::GetNext((BYTE *) Prev));
3726 //*****************************************************************************
3727 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3728 // The hashtable implementation that should be used instead is code:SHash.
3729 // If code:SHash does not work for you, talk to mailto:clrdeag.
3730 //*****************************************************************************
3731 // Closed hash with typed parameters. The derived class is the second
3732 // parameter to the template. The derived class must implement:
3733 // unsigned long Hash(const T *pData);
3734 // unsigned long Compare(const T *p1, T *p2);
3735 // ELEMENTSTATUS Status(T *pEntry);
3736 // void SetStatus(T *pEntry, ELEMENTSTATUS s);
3737 // void* GetKey(T *pEntry);
3738 //*****************************************************************************
3739 template<class T, class H>class CClosedHashEx : public CClosedHash<T>
3743 int iBuckets, // How many buckets should we start with.
3744 bool bPerfect=false) : // true if bucket size will hash with no collisions.
3745 CClosedHash<T> (iBuckets, bPerfect)
3747 WRAPPER_NO_CONTRACT;
3750 unsigned int Hash(const void *pData)
3752 WRAPPER_NO_CONTRACT;
3753 return static_cast<H*>(this)->Hash((const T*)pData);
3756 unsigned int Compare(const void *p1, BYTE *p2)
3758 WRAPPER_NO_CONTRACT;
3759 return static_cast<H*>(this)->Compare((const T*)p1, (T*)p2);
3762 typename CClosedHash<T>::ELEMENTSTATUS Status(BYTE *p)
3764 WRAPPER_NO_CONTRACT;
3765 return static_cast<H*>(this)->Status((T*)p);
3768 void SetStatus(BYTE *p, typename CClosedHash<T>::ELEMENTSTATUS s)
3770 WRAPPER_NO_CONTRACT;
3771 static_cast<H*>(this)->SetStatus((T*)p, s);
3774 void* GetKey(BYTE *p)
3776 WRAPPER_NO_CONTRACT;
3777 return static_cast<H*>(this)->GetKey((T*)p);
3782 //*****************************************************************************
3783 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3784 // The hashtable implementation that should be used instead is code:SHash.
3785 // If code:SHash does not work for you, talk to mailto:clrdeag.
3786 //*****************************************************************************
3787 // This template is another form of a closed hash table. It handles collisions
3788 // through a linked chain. To use it, derive your hashed item from HASHLINK
3789 // and implement the virtual functions required. 1.5 * ibuckets will be
3790 // allocated, with the extra .5 used for collisions. If you add to the point
3791 // where no free nodes are available, the entire table is grown to make room.
3792 // The advantage to this system is that collisions are always directly known,
3793 // there either is one or there isn't.
3794 //*****************************************************************************
3797 ULONG iNext; // Offset for next entry.
3800 template <class T> class CChainedHash
3802 friend class VerifyLayoutsMD;
3804 CChainedHash(int iBuckets=32) :
3806 m_iBuckets(iBuckets),
3811 LIMITED_METHOD_CONTRACT;
3812 m_iSize = iBuckets + (iBuckets / 2);
3817 LIMITED_METHOD_CONTRACT;
3822 void SetBuckets(int iBuckets)
3824 LIMITED_METHOD_CONTRACT;
3825 _ASSERTE(m_rgData == 0);
3826 // if iBuckets==0, then we'll allocate a zero size array and AV on dereference.
3827 _ASSERTE(iBuckets > 0);
3828 m_iBuckets = iBuckets;
3829 m_iSize = iBuckets + (iBuckets / 2);
3832 T *Add(void const *pData)
3834 WRAPPER_NO_CONTRACT;
3839 // Build the list if required.
3840 if (m_rgData == 0 || m_iFree == 0xffffffff)
3846 // Hash the item and pick a bucket.
3847 iHash = Hash(pData);
3848 iBucket = iHash % m_iBuckets;
3850 // Use the bucket if it is free.
3851 if (InUse(&m_rgData[iBucket]) == false)
3853 pItem = &m_rgData[iBucket];
3854 pItem->iNext = 0xffffffff;
3856 // Else take one off of the free list for use.
3861 // Pull an item from the free list.
3863 pItem = &m_rgData[m_iFree];
3864 m_iFree = pItem->iNext;
3866 // Link the new node in after the bucket.
3867 pItem->iNext = m_rgData[iBucket].iNext;
3868 m_rgData[iBucket].iNext = iEntry;
3874 T *Find(void const *pData, bool bAddIfNew=false)
3876 WRAPPER_NO_CONTRACT;
3881 // Check states for lookup.
3884 // If we won't be adding, then we are through.
3885 if (bAddIfNew == false)
3888 // Otherwise, create the table.
3893 // Hash the item and pick a bucket.
3894 iHash = Hash(pData);
3895 iBucket = iHash % m_iBuckets;
3897 // If it isn't in use, then there it wasn't found.
3898 if (!InUse(&m_rgData[iBucket]))
3900 if (bAddIfNew == false)
3904 pItem = &m_rgData[iBucket];
3905 pItem->iNext = 0xffffffff;
3909 // Scan the list for the one we want.
3913 for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem))
3915 if (Cmp(pData, pItem) == 0)
3920 if (!pItem && bAddIfNew)
3924 // Record maximum chain length.
3925 if (iChain > m_iMaxChain)
3926 m_iMaxChain = iChain;
3928 // Now need more room.
3929 if (m_iFree == 0xffffffff)
3935 // Pull an item from the free list.
3937 pItem = &m_rgData[m_iFree];
3938 m_iFree = pItem->iNext;
3940 // Link the new node in after the bucket.
3941 pItem->iNext = m_rgData[iBucket].iNext;
3942 m_rgData[iBucket].iNext = iEntry;
3951 LIMITED_METHOD_CONTRACT;
3957 LIMITED_METHOD_CONTRACT;
3958 return (m_iBuckets);
3961 ULONG MaxChainLength()
3963 LIMITED_METHOD_CONTRACT;
3964 return (m_iMaxChain);
3967 virtual void Clear()
3969 LIMITED_METHOD_CONTRACT;
3970 // Free up the memory.
3983 virtual bool InUse(T *pItem)=0;
3984 virtual void SetFree(T *pItem)=0;
3985 virtual ULONG Hash(void const *pData)=0;
3986 virtual int Cmp(void const *pData, void *pItem)=0;
3988 inline T *GetNext(T *pItem)
3990 LIMITED_METHOD_CONTRACT;
3991 if (pItem->iNext != 0xffffffff)
3992 return ((T *) &m_rgData[pItem->iNext]);
3998 WRAPPER_NO_CONTRACT;
4002 // If this is a first time allocation, then just malloc it.
4005 if ((m_rgData = new (nothrow) T[m_iSize]) == 0)
4009 for (i=0; i<m_iSize; i++)
4010 SetFree(&m_rgData[i]);
4012 m_iFree = m_iBuckets;
4013 for (i=m_iBuckets; i<m_iSize; i++)
4014 ((T *) &m_rgData[i])->iNext = i + 1;
4015 ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff;
4019 // Otherwise we need more room on the free chain, so allocate some.
4020 iNewSize = m_iSize + (m_iSize / 2);
4022 // Allocate/realloc memory.
4023 if ((rgTemp = new (nothrow) T[iNewSize]) == 0)
4026 memcpy (rgTemp,m_rgData,m_iSize*sizeof(T));
4029 // Init new entries, save the new free chain, and reset internals.
4031 for (int i=m_iFree; i<iNewSize; i++)
4033 SetFree(&rgTemp[i]);
4034 ((T *) &rgTemp[i])->iNext = i + 1;
4036 ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff;
4044 T *m_rgData; // Data to store items in.
4045 int m_iBuckets; // How many buckets we want.
4046 int m_iSize; // How many are allocated.
4047 int m_iCount; // How many are we using.
4048 ULONG m_iMaxChain; // Max chain length.
4049 ULONG m_iFree; // Free chain.
4053 //*****************************************************************************
4055 //********** String helper functions.
4057 //*****************************************************************************
4059 //*****************************************************************************
4060 // Checks if string length exceeds the specified limit
4061 //*****************************************************************************
4062 inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N)
4064 LIMITED_METHOD_CONTRACT;
4068 for(i=0; (i < N)&&(pstr[i]); i++);
4074 //*****************************************************************************
4075 // Class to parse a list of simple assembly names and then find a match
4076 //*****************************************************************************
4078 class AssemblyNamesList
4082 LPUTF8 m_assemblyName;
4083 AssemblyName *m_next; // Next name
4086 AssemblyName *m_pNames; // List of names
4090 bool IsInList(LPCUTF8 assemblyName);
4094 LIMITED_METHOD_CONTRACT;
4095 return m_pNames == 0;
4098 AssemblyNamesList(__in LPWSTR list);
4099 ~AssemblyNamesList();
4102 //*****************************************************************************
4103 // Class to parse a list of method names and then find a match
4104 //*****************************************************************************
4106 class MethodNamesListBase
4110 LPUTF8 methodName; // NULL means wildcard
4111 LPUTF8 className; // NULL means wildcard
4112 int numArgs; // number of args for the method, -1 is wildcard
4113 MethodName *next; // Next name
4116 MethodName *pNames; // List of names
4121 LIMITED_METHOD_CONTRACT;
4125 void Init(__in __in_z LPWSTR list)
4127 WRAPPER_NO_CONTRACT;
4134 void Insert(__in __in_z LPWSTR list);
4136 bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig);
4139 LIMITED_METHOD_CONTRACT;
4144 class MethodNamesList : public MethodNamesListBase
4149 WRAPPER_NO_CONTRACT;
4153 MethodNamesList(__in LPWSTR list)
4155 WRAPPER_NO_CONTRACT;
4161 WRAPPER_NO_CONTRACT;
4166 /**************************************************************************/
4167 /* simple wrappers around the REGUTIL and MethodNameList routines that make
4170 /* to be used as static variable - no constructor/destructor, assumes zero
4171 initialized memory */
4177 // NOTE: The following function is deprecated; use the CLRConfig class instead.
4178 // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
4180 inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0)
4182 WRAPPER_NO_CONTRACT;
4183 // make sure that the memory was zero initialized
4184 _ASSERTE(m_inited == 0 || m_inited == 1);
4186 if (!m_inited) init_DontUse_(keyName, defaultVal);
4189 inline DWORD val(const CLRConfig::ConfigDWORDInfo & info)
4191 WRAPPER_NO_CONTRACT;
4192 // make sure that the memory was zero initialized
4193 _ASSERTE(m_inited == 0 || m_inited == 1);
4195 if (!m_inited) init(info);
4200 void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0);
4201 void init(const CLRConfig::ConfigDWORDInfo & info);
4208 /**************************************************************************/
4212 inline LPWSTR val(const CLRConfig::ConfigStringInfo & info)
4214 WRAPPER_NO_CONTRACT;
4215 // make sure that the memory was zero initialized
4216 _ASSERTE(m_inited == 0 || m_inited == 1);
4218 if (!m_inited) init(info);
4222 bool isInitialized()
4224 WRAPPER_NO_CONTRACT;
4226 // make sure that the memory was zero initialized
4227 _ASSERTE(m_inited == 0 || m_inited == 1);
4229 return m_inited == 1;
4233 void init(const CLRConfig::ConfigStringInfo & info);
4240 /**************************************************************************/
4241 class ConfigMethodSet
4246 WRAPPER_NO_CONTRACT;
4247 _ASSERTE(m_inited == 1);
4248 return m_list.IsEmpty();
4251 bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig);
4253 inline void ensureInit(const CLRConfig::ConfigStringInfo & info)
4255 WRAPPER_NO_CONTRACT;
4256 // make sure that the memory was zero initialized
4257 _ASSERTE(m_inited == 0 || m_inited == 1);
4259 if (!m_inited) init(info);
4263 void init(const CLRConfig::ConfigStringInfo & info);
4266 MethodNamesListBase m_list;
4271 //*****************************************************************************
4272 // Convert a pointer to a string into a GUID.
4273 //*****************************************************************************
4274 HRESULT LPCSTRToGuid( // Return status.
4275 LPCSTR szGuid, // String to convert.
4276 GUID *psGuid); // Buffer for converted GUID.
4278 //*****************************************************************************
4279 // Convert a GUID into a pointer to a string
4280 //*****************************************************************************
4281 int GuidToLPWSTR( // Return status.
4282 GUID Guid, // [IN] The GUID to convert.
4283 __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored
4284 DWORD cchGuid); // [IN] Size in wide chars of szGuid
4286 //*****************************************************************************
4287 // Parse a Wide char string into a GUID
4288 //*****************************************************************************
4290 GUID * Guid, // [OUT] The GUID to fill in
4291 __in_ecount(cchGuid) LPCWSTR szGuid, // [IN] String to parse
4292 DWORD cchGuid); // [IN] Count in wchars in string
4294 typedef VPTR(class RangeList) PTR_RangeList;
4299 VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList)
4301 #ifndef DACCESS_COMPILE
4307 LIMITED_METHOD_CONTRACT;
4311 // Wrappers to make the virtual calls DAC-safe.
4312 BOOL AddRange(const BYTE *start, const BYTE *end, void *id)
4314 return this->AddRangeWorker(start, end, id);
4317 void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL)
4319 return this->RemoveRangesWorker(id, start, end);
4322 BOOL IsInRange(TADDR address, TADDR *pID = NULL)
4326 return this->IsInRangeWorker(address, pID);
4329 #ifndef DACCESS_COMPILE
4331 // You can overload these two for synchronization (as LockedRangeList does)
4332 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id);
4333 // If both "start" and "end" are NULL, then this method deletes all ranges with
4334 // the given id (i.e. the original behaviour). Otherwise, it ignores the given
4335 // id and deletes all ranges falling in the region [start, end).
4336 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL);
4338 virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id)
4342 virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { }
4343 #endif // !DACCESS_COMPILE
4345 virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL);
4347 #ifdef DACCESS_COMPILE
4348 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4365 struct RangeListBlock
4367 Range ranges[RANGE_COUNT];
4368 DPTR(RangeListBlock) next;
4370 #ifdef DACCESS_COMPILE
4371 void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4376 void InitBlock(RangeListBlock *block);
4378 RangeListBlock m_starterBlock;
4379 DPTR(RangeListBlock) m_firstEmptyBlock;
4380 TADDR m_firstEmptyRange;
4385 // A private function to do the equavilent of a CoCreateInstance in
4386 // cases where we can't make the real call. Use this when, for
4387 // instance, you need to create a symbol reader in the Runtime but
4388 // we're not CoInitialized. Obviously, this is only good for COM
4389 // objects for which CoCreateInstance is just a glorified
4390 // find-and-load-me operation.
4393 HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid,
4397 HMODULE * phmodDll);
4399 // Provided for backward compatibility and for code that doesn't need the HMODULE of the
4400 // DLL that was loaded to create the COM object. See comment at implementation of
4401 // code:FakeCoCreateInstanceEx for more details.
4402 inline HRESULT FakeCoCreateInstance(REFCLSID rclsid,
4412 return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL);
4415 HRESULT FakeCoCallDllGetClassObject(REFCLSID rclsid,
4419 HMODULE * phmodDll);
4421 //*****************************************************************************
4422 // Gets the directory based on the location of the module. This routine
4423 // is called at COR setup time. Set is called during EEStartup and by the
4424 // MetaData dispenser.
4425 //*****************************************************************************
4426 HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength);
4427 LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL);
4429 //*****************************************************************************
4430 // This function validates the given Method/Field/Standalone signature. (util.cpp)
4431 //*****************************************************************************
4432 struct IMDInternalImport;
4433 HRESULT validateTokenSig(
4434 mdToken tk, // [IN] Token whose signature needs to be validated.
4435 PCCOR_SIGNATURE pbSig, // [IN] Signature.
4436 ULONG cbSig, // [IN] Size in bytes of the signature.
4437 DWORD dwFlags, // [IN] Method flags.
4438 IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr
4440 //*****************************************************************************
4441 // Determine the version number of the runtime that was used to build the
4442 // specified image. The pMetadata pointer passed in is the pointer to the
4443 // metadata contained in the image.
4444 //*****************************************************************************
4445 HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString);
4446 void AdjustImageRuntimeVersion (SString* pVersion);
4448 //*****************************************************************************
4449 // The registry keys and values that contain the information regarding
4450 // the default registered unmanaged debugger.
4451 //*****************************************************************************
4452 SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4453 SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4455 SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
4456 SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger");
4457 SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto");
4458 SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList");
4460 BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key.
4461 LPCWSTR szKey, // Key name to look at.
4462 LPCWSTR szName, // Name of value to get.
4463 long *pValue, // Put value here, if found.
4464 BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64
4466 HRESULT GetCurrentModuleFileName(__out_ecount(*pcchBuffer) LPWSTR pBuffer, __inout DWORD *pcchBuffer);
4468 //*****************************************************************************
4469 // Retrieve information regarding what registered default debugger
4470 //*****************************************************************************
4471 void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto);
4472 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto);
4474 void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch);
4477 //*****************************************************************************
4478 // Convert a UTF8 string to Unicode, into a CQuickArray<WCHAR>.
4479 //*****************************************************************************
4481 LPCUTF8 pStr, // The string to convert.
4482 CQuickArray<WCHAR> &rStr, // The QuickArray<WCHAR> to convert it into.
4483 int iCurLen); // Inital characters in the array to leave (default 0).
4485 //*****************************************************************************
4486 // Extract the movl 64-bit unsigned immediate from an IA64 bundle
4488 //*****************************************************************************
4489 UINT64 GetIA64Imm64(UINT64 * pBundle);
4490 UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1);
4492 //*****************************************************************************
4493 // Deposit the movl 64-bit unsigned immediate into an IA64 bundle
4495 //*****************************************************************************
4496 void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64);
4498 //*****************************************************************************
4499 // Extract the IP-Relative signed 25-bit immediate from an IA64 bundle
4500 // (Formats B1, B2 or B3)
4501 // Note that due to branch target alignment requirements
4502 // the lowest four bits in the result will always be zero.
4503 //*****************************************************************************
4504 INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot);
4505 INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot);
4507 //*****************************************************************************
4508 // Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle
4509 // (Formats B1, B2 or B3)
4510 // Note that due to branch target alignment requirements
4511 // the lowest four bits are required to be zero.
4512 //*****************************************************************************
4513 void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25);
4515 //*****************************************************************************
4516 // Extract the IP-Relative signed 64-bit immediate from an IA64 bundle
4517 // (Formats X3 or X4)
4518 //*****************************************************************************
4519 INT64 GetIA64Rel64(UINT64 * pBundle);
4520 INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1);
4522 //*****************************************************************************
4523 // Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle
4524 // (Formats X3 or X4)
4525 //*****************************************************************************
4526 void PutIA64Rel64(UINT64 * pBundle, INT64 imm64);
4528 //*****************************************************************************
4529 // Extract the 32-bit immediate from movw/movt Thumb2 sequence
4530 //*****************************************************************************
4531 UINT32 GetThumb2Mov32(UINT16 * p);
4533 //*****************************************************************************
4534 // Deposit the 32-bit immediate into movw/movt Thumb2 sequence
4535 //*****************************************************************************
4536 void PutThumb2Mov32(UINT16 * p, UINT32 imm32);
4538 //*****************************************************************************
4539 // Extract the 24-bit rel offset from bl instruction
4540 //*****************************************************************************
4541 INT32 GetThumb2BlRel24(UINT16 * p);
4543 //*****************************************************************************
4544 // Extract the 24-bit rel offset from bl instruction
4545 //*****************************************************************************
4546 void PutThumb2BlRel24(UINT16 * p, INT32 imm24);
4548 //*****************************************************************************
4549 // Extract the PC-Relative offset from a b or bl instruction
4550 //*****************************************************************************
4551 INT32 GetArm64Rel28(UINT32 * pCode);
4553 //*****************************************************************************
4554 // Deposit the PC-Relative offset 'imm28' into a b or bl instruction
4555 //*****************************************************************************
4556 void PutArm64Rel28(UINT32 * pCode, INT32 imm28);
4558 //*****************************************************************************
4559 // Returns whether the offset fits into bl instruction
4560 //*****************************************************************************
4561 inline bool FitsInThumb2BlRel24(INT32 imm24)
4563 return ((imm24 << 7) >> 7) == imm24;
4566 //*****************************************************************************
4567 // Returns whether the offset fits into an Arm64 b or bl instruction
4568 //*****************************************************************************
4569 inline bool FitsInRel28(INT32 val32)
4571 return (val32 >= -0x08000000) && (val32 < 0x08000000);
4574 //*****************************************************************************
4575 // Returns whether the offset fits into an Arm64 b or bl instruction
4576 //*****************************************************************************
4577 inline bool FitsInRel28(INT64 val64)
4579 return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
4582 //*****************************************************************************
4583 // Splits a command line into argc/argv lists, using the VC7 parsing rules.
4584 // This functions interface mimics the CommandLineToArgvW api.
4585 // If function fails, returns NULL.
4586 // If function suceeds, call delete [] on return pointer when done.
4587 //*****************************************************************************
4588 LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs);
4591 // TEB access can be dangerous when using fibers because a fiber may
4592 // run on multiple threads. If the TEB pointer is retrieved and saved
4593 // and then a fiber is moved to a different thread, when it accesses
4594 // the saved TEB pointer, it will be looking at the TEB state for a
4597 // These accessors serve the purpose of retrieving information from the
4598 // TEB in a manner that ensures that the current fiber will not switch
4599 // threads while the access is occuring.
4604 #if defined(FEATURE_PAL)
4606 // returns pointer that uniquely identifies the fiber
4607 static void* GetFiberPtrId()
4609 LIMITED_METHOD_CONTRACT;
4610 // not fiber for FEATURE_PAL - use the regular thread ID
4611 return (void *)(size_t)GetCurrentThreadId();
4614 static void* InvalidFiberPtrId()
4619 static void* GetStackBase()
4621 return PAL_GetStackBase();
4624 static void* GetStackLimit()
4626 return PAL_GetStackLimit();
4629 #else // !FEATURE_PAL
4631 // returns pointer that uniquely identifies the fiber
4632 static void* GetFiberPtrId()
4634 LIMITED_METHOD_CONTRACT;
4635 // stackbase is the unique fiber identifier
4636 return NtCurrentTeb()->NtTib.StackBase;
4639 static void* GetStackBase()
4641 LIMITED_METHOD_CONTRACT;
4642 return NtCurrentTeb()->NtTib.StackBase;
4645 static void* GetStackLimit()
4647 LIMITED_METHOD_CONTRACT;
4648 return NtCurrentTeb()->NtTib.StackLimit;
4651 // Please don't start to use this method unless you absolutely have to.
4652 // The reason why this is added is for WIN64 to support LEGACY PE-style TLS
4653 // variables. On X86 it is supported by the JIT compilers themselves. On
4654 // WIN64 we build more logic into the JIT helper for accessing fields.
4655 static void* GetLegacyThreadLocalStoragePointer()
4657 LIMITED_METHOD_CONTRACT;
4658 return NtCurrentTeb()->ThreadLocalStoragePointer;
4661 static void* GetOleReservedPtr()
4663 LIMITED_METHOD_CONTRACT;
4664 return NtCurrentTeb()->ReservedForOle;
4667 static void* GetProcessEnvironmentBlock()
4669 LIMITED_METHOD_CONTRACT;
4670 return NtCurrentTeb()->ProcessEnvironmentBlock;
4673 #ifndef FEATURE_CORECLR
4674 static void* GetFiberDataPtr()
4676 LIMITED_METHOD_CONTRACT;
4677 return ClrTeb::IsCurrentThreadAFiber()? GetCurrentFiber() : NULL;
4680 static BOOL IsCurrentThreadAFiber()
4682 return IsThreadAFiber();
4686 static void* InvalidFiberPtrId()
4690 #endif // !FEATURE_PAL
4693 #if !defined(DACCESS_COMPILE) && !defined(CLR_STANDALONE_BINDER)
4695 // check if current thread is a GC thread (concurrent or server)
4696 inline BOOL IsGCSpecialThread ()
4698 STATIC_CONTRACT_NOTHROW;
4699 STATIC_CONTRACT_GC_NOTRIGGER;
4700 STATIC_CONTRACT_MODE_ANY;
4701 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4703 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC);
4706 // check if current thread is a Gate thread
4707 inline BOOL IsGateSpecialThread ()
4709 STATIC_CONTRACT_NOTHROW;
4710 STATIC_CONTRACT_GC_NOTRIGGER;
4711 STATIC_CONTRACT_MODE_ANY;
4713 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate);
4716 // check if current thread is a Timer thread
4717 inline BOOL IsTimerSpecialThread ()
4719 STATIC_CONTRACT_NOTHROW;
4720 STATIC_CONTRACT_GC_NOTRIGGER;
4721 STATIC_CONTRACT_MODE_ANY;
4723 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer);
4726 // check if current thread is a debugger helper thread
4727 inline BOOL IsDbgHelperSpecialThread ()
4729 STATIC_CONTRACT_NOTHROW;
4730 STATIC_CONTRACT_GC_NOTRIGGER;
4731 STATIC_CONTRACT_MODE_ANY;
4733 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper);
4736 // check if current thread is a debugger helper thread
4737 inline BOOL IsETWRundownSpecialThread ()
4739 STATIC_CONTRACT_NOTHROW;
4740 STATIC_CONTRACT_GC_NOTRIGGER;
4741 STATIC_CONTRACT_MODE_ANY;
4743 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread);
4746 // check if current thread is a generic instantiation lookup compare thread
4747 inline BOOL IsGenericInstantiationLookupCompareThread ()
4749 STATIC_CONTRACT_NOTHROW;
4750 STATIC_CONTRACT_GC_NOTRIGGER;
4751 STATIC_CONTRACT_MODE_ANY;
4753 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare);
4756 // check if current thread is a thread which is performing shutdown
4757 inline BOOL IsShutdownSpecialThread ()
4759 STATIC_CONTRACT_NOTHROW;
4760 STATIC_CONTRACT_GC_NOTRIGGER;
4761 STATIC_CONTRACT_MODE_ANY;
4763 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown);
4766 inline BOOL IsThreadPoolIOCompletionSpecialThread ()
4768 STATIC_CONTRACT_NOTHROW;
4769 STATIC_CONTRACT_GC_NOTRIGGER;
4770 STATIC_CONTRACT_MODE_ANY;
4772 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion);
4775 inline BOOL IsThreadPoolWorkerSpecialThread ()
4777 STATIC_CONTRACT_NOTHROW;
4778 STATIC_CONTRACT_GC_NOTRIGGER;
4779 STATIC_CONTRACT_MODE_ANY;
4781 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker);
4784 inline BOOL IsWaitSpecialThread ()
4786 STATIC_CONTRACT_NOTHROW;
4787 STATIC_CONTRACT_GC_NOTRIGGER;
4788 STATIC_CONTRACT_MODE_ANY;
4790 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait);
4793 // check if current thread is a thread which is performing shutdown
4794 inline BOOL IsSuspendEEThread ()
4796 STATIC_CONTRACT_NOTHROW;
4797 STATIC_CONTRACT_GC_NOTRIGGER;
4798 STATIC_CONTRACT_MODE_ANY;
4800 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE);
4803 inline BOOL IsFinalizerThread ()
4805 STATIC_CONTRACT_NOTHROW;
4806 STATIC_CONTRACT_GC_NOTRIGGER;
4807 STATIC_CONTRACT_MODE_ANY;
4809 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
4812 inline BOOL IsADUnloadHelperThread ()
4814 STATIC_CONTRACT_NOTHROW;
4815 STATIC_CONTRACT_GC_NOTRIGGER;
4816 STATIC_CONTRACT_MODE_ANY;
4818 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ADUnloadHelper);
4821 inline BOOL IsShutdownHelperThread ()
4823 STATIC_CONTRACT_NOTHROW;
4824 STATIC_CONTRACT_GC_NOTRIGGER;
4825 STATIC_CONTRACT_MODE_ANY;
4827 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper);
4830 inline BOOL IsProfilerAttachThread ()
4832 STATIC_CONTRACT_NOTHROW;
4833 STATIC_CONTRACT_GC_NOTRIGGER;
4834 STATIC_CONTRACT_MODE_ANY;
4836 return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach);
4839 // set specical type for current thread
4840 inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag)
4842 STATIC_CONTRACT_NOTHROW;
4843 STATIC_CONTRACT_GC_NOTRIGGER;
4844 STATIC_CONTRACT_MODE_ANY;
4845 STATIC_CONTRACT_SO_TOLERANT;
4847 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag));
4850 // clear specical type for current thread
4851 inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
4853 STATIC_CONTRACT_NOTHROW;
4854 STATIC_CONTRACT_GC_NOTRIGGER;
4855 STATIC_CONTRACT_MODE_ANY;
4857 ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag));
4860 #endif //!DACCESS_COMPILE
4862 #ifdef DACCESS_COMPILE
4863 #define SET_THREAD_TYPE_STACKWALKER(pThread)
4864 #define CLEAR_THREAD_TYPE_STACKWALKER()
4865 #else // DACCESS_COMPILE
4866 #define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread)
4867 #define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
4868 #endif // DACCESS_COMPILE
4870 inline BOOL IsStackWalkerThread()
4872 STATIC_CONTRACT_NOTHROW;
4873 STATIC_CONTRACT_GC_NOTRIGGER;
4874 STATIC_CONTRACT_MODE_ANY;
4875 STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4877 #if defined(DACCESS_COMPILE) || defined(CLR_STANDALONE_BINDER)
4880 return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL;
4884 inline BOOL IsGCThread ()
4886 STATIC_CONTRACT_NOTHROW;
4887 STATIC_CONTRACT_GC_NOTRIGGER;
4888 STATIC_CONTRACT_MODE_ANY;
4889 STATIC_CONTRACT_SUPPORTS_DAC;
4890 STATIC_CONTRACT_SO_TOLERANT;
4892 #if !defined(DACCESS_COMPILE) && !defined(CLR_STANDALONE_BINDER)
4893 return IsGCSpecialThread () || IsSuspendEEThread ();
4898 #ifndef CLR_STANDALONE_BINDER
4899 class ClrFlsThreadTypeSwitch
4902 ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag)
4904 STATIC_CONTRACT_NOTHROW;
4905 STATIC_CONTRACT_GC_NOTRIGGER;
4906 STATIC_CONTRACT_MODE_ANY;
4908 #ifndef DACCESS_COMPILE
4910 m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag);
4912 // In debug builds, remember the full group of flags that were set at the time
4913 // the constructor was called. This will be used in ASSERTs in the destructor
4914 INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType));
4916 if (!m_fPreviouslySet)
4918 ClrFlsSetThreadType(flag);
4920 #endif // DACCESS_COMPILE
4923 ~ClrFlsThreadTypeSwitch ()
4925 STATIC_CONTRACT_NOTHROW;
4926 STATIC_CONTRACT_GC_NOTRIGGER;
4927 STATIC_CONTRACT_MODE_ANY;
4929 #ifndef DACCESS_COMPILE
4930 // This holder should only be used to set (and thus restore) ONE thread type flag
4931 // at a time. If more than that one flag was modified since this holder was
4932 // instantiated, then this holder still restores only the flag it knows about. To
4933 // prevent confusion, assert if some other flag was modified, so the user doesn't
4934 // expect the holder to restore the entire original set of flags.
4936 // The expression below says that the only difference between the previous flag
4937 // group and the current flag group should be m_flag (or no difference at all, if
4938 // m_flag's state didn't actually change).
4939 _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag);
4941 if (m_fPreviouslySet)
4943 ClrFlsSetThreadType(m_flag);
4947 ClrFlsClearThreadType(m_flag);
4949 #endif // DACCESS_COMPILE
4953 TlsThreadTypeFlag m_flag;
4954 BOOL m_fPreviouslySet;
4955 INDEBUG(size_t m_nPreviousFlagGroup);
4958 class ClrFlsValueSwitch
4961 ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value)
4963 STATIC_CONTRACT_NOTHROW;
4964 STATIC_CONTRACT_GC_NOTRIGGER;
4965 STATIC_CONTRACT_MODE_ANY;
4967 #ifndef DACCESS_COMPILE
4969 m_PreviousValue = ClrFlsGetValue(slot);
4970 ClrFlsSetValue(slot, value);
4971 #endif // DACCESS_COMPILE
4974 ~ClrFlsValueSwitch ()
4976 STATIC_CONTRACT_NOTHROW;
4977 STATIC_CONTRACT_GC_NOTRIGGER;
4978 STATIC_CONTRACT_MODE_ANY;
4980 #ifndef DACCESS_COMPILE
4981 ClrFlsSetValue(m_slot, m_PreviousValue);
4982 #endif // DACCESS_COMPILE
4986 PVOID m_PreviousValue;
4987 PredefinedTlsSlots m_slot;
4989 #endif // !CLR_STANDALONE_BINDER
4991 //*********************************************************************************
4993 // When we're hosted, operations called by the host (such as Thread::YieldTask)
4994 // may not cause calls back into the host, as the host needs not be reentrant.
4995 // Use the following holder for code in which calls into the host are forbidden.
4996 // (If a call into the host is attempted nevertheless, an assert will fire.)
4998 class ForbidCallsIntoHostOnThisThread
5001 static Volatile<PVOID> s_pvOwningFiber;
5003 FORCEINLINE static BOOL Enter(BOOL)
5005 WRAPPER_NO_CONTRACT;
5006 return InterlockedCompareExchangePointer(
5007 &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL;
5010 FORCEINLINE static void Leave(BOOL)
5012 LIMITED_METHOD_CONTRACT;
5013 s_pvOwningFiber = NULL;
5017 typedef ConditionalStateHolder<BOOL, ForbidCallsIntoHostOnThisThread::Enter, ForbidCallsIntoHostOnThisThread::Leave> Holder;
5019 FORCEINLINE static BOOL CanThisThreadCallIntoHost()
5021 WRAPPER_NO_CONTRACT;
5022 return s_pvOwningFiber != ClrTeb::GetFiberPtrId();
5026 typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder;
5028 FORCEINLINE BOOL CanThisThreadCallIntoHost()
5030 WRAPPER_NO_CONTRACT;
5031 return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost();
5034 //*********************************************************************************
5036 #include "contract.inl"
5043 template < typename T >
5046 bool operator()( T const & first, T const & second ) const
5048 return first < second;
5052 template < typename T >
5055 bool operator()( T const & first, T const & second ) const
5057 return first > second;
5065 template< typename Iter, typename Pred >
5066 void sort( Iter begin, Iter end, Pred pred );
5068 template< typename T, typename Pred >
5069 void sort( T * begin, T * end, Pred pred )
5071 struct sort_helper : CQuickSort< T >
5073 sort_helper( T * begin, T * end, Pred pred )
5074 : CQuickSort< T >( begin, end - begin )
5078 virtual int Compare( T * first, T * second )
5080 return m_pred( *first, *second ) ? -1
5081 : ( m_pred( *second, *first ) ? 1 : 0 );
5087 sort_helper sort_obj( begin, end, pred );
5092 template < typename Iter >
5093 void sort( Iter begin, Iter end );
5095 template < typename T >
5096 void sort( T * begin, T * end )
5098 util::sort( begin, end, util::less< T >() );
5102 // binary search adapters
5105 template < typename Iter, typename T, typename Pred >
5106 Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred );
5108 template < typename T, typename Pred >
5109 T * lower_bound( T * begin, T * end, T const & val, Pred pred )
5111 for (; begin != end; )
5113 T * mid = begin + ( end - begin ) / 2;
5114 if ( pred( *mid, val ) )
5124 template < typename Iter, typename T >
5125 Iter lower_bound( Iter begin, Iter end, T const & val );
5127 template < typename T >
5128 T * lower_bound( T * begin, T * end, T const & val )
5130 return util::lower_bound( begin, end, val, util::less< T >() );
5135 /* ------------------------------------------------------------------------ *
5136 * Overloaded operators for the executable heap
5137 * ------------------------------------------------------------------------ */
5141 struct CExecutable { int x; };
5142 extern const CExecutable executable;
5144 void * __cdecl operator new(size_t n, const CExecutable&);
5145 void * __cdecl operator new[](size_t n, const CExecutable&);
5146 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&);
5147 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&);
5151 // Executable heap delete to match the executable heap new above.
5153 template<class T> void DeleteExecutable(T *p)
5159 ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p);
5163 #endif // FEATURE_PAL
5165 INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
5167 class HighCharHelper {
5169 static inline BOOL IsHighChar(int c) {
5170 return (BOOL)HighCharTable[c];
5174 static const BYTE HighCharTable[];
5178 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
5180 FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
5182 typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
5184 BOOL FileExists(LPCWSTR filename);
5186 #ifndef FEATURE_CORECLR
5187 class FileLockHolder
5193 virtual void Acquire(LPCWSTR lockName, HANDLE hInterrupt = 0, BOOL* pInterrupted = NULL);
5194 HRESULT AcquireNoThrow(LPCWSTR lockName, HANDLE hInterrupt = 0, BOOL* pInterrupted = NULL);
5196 static BOOL IsTaken(LPCWSTR lockName);
5201 #endif // FEATURE_CORECLR
5203 // a class for general x.x version info
5204 class MajorMinorVersionInfo
5211 MajorMinorVersionInfo()
5213 LIMITED_METHOD_CONTRACT;
5214 bInitialized = FALSE;
5215 ZeroMemory(version,sizeof(version));
5218 MajorMinorVersionInfo(WORD wMajor, WORD wMinor)
5220 WRAPPER_NO_CONTRACT;
5221 Init(wMajor,wMinor);
5225 BOOL IsInitialized() const
5227 LIMITED_METHOD_CONTRACT;
5228 return bInitialized;
5233 LIMITED_METHOD_CONTRACT;
5239 LIMITED_METHOD_CONTRACT;
5244 void Init(WORD wMajor, WORD wMinor)
5246 LIMITED_METHOD_CONTRACT;
5253 // CLR runtime version info in Major/Minor form
5254 class RUNTIMEVERSIONINFO : public MajorMinorVersionInfo
5256 static RUNTIMEVERSIONINFO notDefined;
5259 RUNTIMEVERSIONINFO() {};
5261 RUNTIMEVERSIONINFO(WORD wMajor, WORD wMinor) :
5262 MajorMinorVersionInfo(wMajor,wMinor){};
5264 // CLR version specific helpers
5265 BOOL IsPreWhidbey() const
5267 WRAPPER_NO_CONTRACT;
5268 return (Major() == 1) && (Minor() <= 1);
5271 static const RUNTIMEVERSIONINFO& NotApplicable()
5273 LIMITED_METHOD_CONTRACT;
5279 // HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical
5280 // to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address,
5281 // and so is represented by TADDR.
5283 #ifdef DACCESS_COMPILE
5284 typedef TADDR HMODULE_TGT;
5286 typedef HMODULE HMODULE_TGT;
5289 BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
5291 //----------------------------------------------------------------------------------------
5292 // The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical
5293 // callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call
5294 // InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime
5295 // calls a special initialization routine exposed by the loaded module with the callbacks,
5296 // which in turn calls InitUtilcode.
5298 // This structure collects all of the critical callback info passed in InitUtilcode().
5299 // Note that one of them is GetCLRFunction() which is itself a gofer for many other
5300 // callbacks. If a callback fetch be safely deferred until we have TLS and stack probe
5301 // functionality running, it should be added to that function rather than this structure.
5302 // Things like IEE are here because that callback has to be set up before GetCLRFunction()
5303 // can be safely called.
5304 //----------------------------------------------------------------------------------------
5305 struct CoreClrCallbacks
5307 typedef IExecutionEngine* (__stdcall * pfnIEE_t)();
5308 typedef HRESULT (__stdcall * pfnGetCORSystemDirectory_t)(LPWSTR pbuffer, DWORD cchBuffer, DWORD* pdwlength);
5309 typedef void* (__stdcall * pfnGetCLRFunction_t)(LPCSTR functionName);
5311 HINSTANCE m_hmodCoreCLR;
5313 pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory;
5314 pfnGetCLRFunction_t m_pfnGetCLRFunction;
5317 #if defined(FEATURE_CORECLR) || !defined(SELF_NO_HOST) || defined(DACCESS_COMPILE)
5319 // For DAC, we include this functionality only when EH SxS is enabled.
5321 //----------------------------------------------------------------------------------------
5322 // CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback
5323 // pointers it needs.
5324 //----------------------------------------------------------------------------------------
5325 VOID InitUtilcode(const CoreClrCallbacks &cccallbacks);
5326 CoreClrCallbacks const & GetClrCallbacks();
5328 //----------------------------------------------------------------------------------------
5329 // Stuff below is for utilcode.lib eyes only.
5330 //----------------------------------------------------------------------------------------
5332 // Stores callback pointers provided by InitUtilcode().
5333 extern CoreClrCallbacks g_CoreClrCallbacks;
5335 // Throws up a helpful dialog if InitUtilcode() wasn't called.
5337 void OnUninitializedCoreClrCallbacks();
5338 #define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks()
5340 #define VALIDATECORECLRCALLBACKS()
5343 #endif // defined(FEATURE_CORECLR) || !defined(SELF_NO_HOST) || defined(DACCESS_COMPILE)
5345 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
5347 // Corrupting Exception limited support for outside the VM folder
5348 BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
5350 #endif // FEATURE_CORRUPTING_EXCEPTIONS
5353 BOOL IsV2RuntimeLoaded(void);
5357 // These are type-safe versions of Interlocked[Compare]Exchange
5358 // They avoid invoking struct cast operations via reinterpreting
5359 // the struct's address as a LONG* or LONGLONG* and dereferencing it.
5361 // If we had a global ::operator & (unary), we would love to use that
5362 // to ensure we were not also accidentally getting a structs's provided
5363 // operator &. TODO: probe with a static_assert?
5365 template <typename T, int SIZE = sizeof(T)>
5366 struct InterlockedCompareExchangeHelper;
5368 template <typename T>
5369 struct InterlockedCompareExchangeHelper<T, sizeof(LONG)>
5371 static inline T InterlockedExchange(
5372 T volatile * target,
5375 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5376 LONG res = ::InterlockedExchange(
5377 reinterpret_cast<LONG volatile *>(target),
5378 *reinterpret_cast<LONG *>(/*::operator*/&(value)));
5379 return *reinterpret_cast<T*>(&res);
5382 static inline T InterlockedCompareExchange(
5383 T volatile * destination,
5387 static_assert_no_msg(sizeof(T) == sizeof(LONG));
5388 LONG res = ::InterlockedCompareExchange(
5389 reinterpret_cast<LONG volatile *>(destination),
5390 *reinterpret_cast<LONG*>(/*::operator*/&(exchange)),
5391 *reinterpret_cast<LONG*>(/*::operator*/&(comparand)));
5392 return *reinterpret_cast<T*>(&res);
5396 template <typename T>
5397 struct InterlockedCompareExchangeHelper<T, sizeof(LONGLONG)>
5399 static inline T InterlockedExchange(
5400 T volatile * target,
5403 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5404 LONGLONG res = ::InterlockedExchange64(
5405 reinterpret_cast<LONGLONG volatile *>(target),
5406 *reinterpret_cast<LONGLONG *>(/*::operator*/&(value)));
5407 return *reinterpret_cast<T*>(&res);
5410 static inline T InterlockedCompareExchange(
5411 T volatile * destination,
5415 static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5416 LONGLONG res = ::InterlockedCompareExchange64(
5417 reinterpret_cast<LONGLONG volatile *>(destination),
5418 *reinterpret_cast<LONGLONG*>(/*::operator*/&(exchange)),
5419 *reinterpret_cast<LONGLONG*>(/*::operator*/&(comparand)));
5420 return *reinterpret_cast<T*>(&res);
5425 template <typename T>
5426 inline T InterlockedExchangeT(
5427 T volatile * target,
5430 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedExchange(
5434 template <typename T>
5435 inline T InterlockedCompareExchangeT(
5436 T volatile * destination,
5440 return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedCompareExchange(
5441 destination, exchange, comparand);
5444 // Pointer variants for Interlocked[Compare]ExchangePointer
5445 // If the underlying type is a const type, we have to remove its constness
5446 // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments.
5447 template <typename T>
5448 inline T* InterlockedExchangeT(
5449 T* volatile * target,
5452 //STATIC_ASSERT(value == 0);
5453 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5454 return reinterpret_cast<T*>(InterlockedExchangePointer(
5455 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(target)),
5456 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(value))));
5459 template <typename T>
5460 inline T* InterlockedCompareExchangeT(
5461 T* volatile * destination,
5465 //STATIC_ASSERT(exchange == 0);
5466 typedef typename std::remove_const<T>::type * non_const_ptr_t;
5467 return reinterpret_cast<T*>(InterlockedCompareExchangePointer(
5468 reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(destination)),
5469 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(exchange)),
5470 reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(comparand))));
5473 // NULL pointer variants of the above to avoid having to cast NULL
5474 // to the appropriate pointer type.
5475 template <typename T>
5476 inline T* InterlockedExchangeT(
5477 T* volatile * target,
5478 int value) // When NULL is provided as argument.
5480 //STATIC_ASSERT(value == 0);
5481 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5484 template <typename T>
5485 inline T* InterlockedCompareExchangeT(
5486 T* volatile * destination,
5487 int exchange, // When NULL is provided as argument.
5490 //STATIC_ASSERT(exchange == 0);
5491 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5494 template <typename T>
5495 inline T* InterlockedCompareExchangeT(
5496 T* volatile * destination,
5498 int comparand) // When NULL is provided as argument.
5500 //STATIC_ASSERT(comparand == 0);
5501 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5504 // NULL pointer variants of the above to avoid having to cast NULL
5505 // to the appropriate pointer type.
5506 template <typename T>
5507 inline T* InterlockedExchangeT(
5508 T* volatile * target,
5509 std::nullptr_t value) // When nullptr is provided as argument.
5511 //STATIC_ASSERT(value == 0);
5512 return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5515 template <typename T>
5516 inline T* InterlockedCompareExchangeT(
5517 T* volatile * destination,
5518 std::nullptr_t exchange, // When nullptr is provided as argument.
5521 //STATIC_ASSERT(exchange == 0);
5522 return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5525 template <typename T>
5526 inline T* InterlockedCompareExchangeT(
5527 T* volatile * destination,
5529 std::nullptr_t comparand) // When nullptr is provided as argument.
5531 //STATIC_ASSERT(comparand == 0);
5532 return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5535 #undef InterlockedExchangePointer
5536 #define InterlockedExchangePointer Use_InterlockedExchangeT
5537 #undef InterlockedCompareExchangePointer
5538 #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT
5540 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
5541 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
5542 HRESULT GetHModuleDirectory(HMODULE hMod, __out_z __out_ecount(cchPath) LPWSTR wszPath, size_t cchPath);
5543 SString & GetHModuleDirectory(HMODULE hMod, SString &ssDir);
5545 HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true);
5546 // This is a slight variation that can be used for anything else
5547 typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR);
5548 void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL);
5550 BOOL IsClrHostedLegacyComObject(REFCLSID rclsid);
5553 #if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE)
5555 // No utilcode code should use the global LoadLibraryShim anymore. UtilCode::LoadLibraryShim will do
5556 // the right thing based on whether the hosted or non-hosted utilcode is linked to. Using the global
5557 // LoadLibraryShim will result in a deprecated use warning.
5560 #define LEGACY_ACTIVATION_SHIM_LOAD_LIBRARY WszLoadLibrary
5561 #include "legacyactivationshim.h"
5562 #include "mscoreepriv.h"
5566 inline HRESULT LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll)
5568 return LegacyActivationShim::LoadLibraryShim(szDllName, szVersion, pvReserved, phModDll);
5571 #else // SELF_NO_HOST
5574 // Hosted environment
5575 HRESULT LoadLibraryShim(LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE *phModDll);
5577 #endif // SELF_NO_HOST
5579 #endif // !FEATURE_CORECLR && !CROSSGEN_COMPILE
5582 // Helper to support termination due to heap corruption
5583 // It's not supported on Win2K, so we have to manually delay load it
5584 void EnableTerminationOnHeapCorruption();
5587 #if !defined(FEATURE_CORECLR)
5588 // On success, sets pwszProcessExePath (required) to full path to process EXE.
5589 HRESULT GetProcessExePath(LPCWSTR *pwszProcessExePath);
5592 namespace Clr { namespace Util
5594 // This api returns a pointer to a null-terminated string that contains the local appdata directory
5595 // or it returns NULL in the case that the directory could not be found. The return value from this function
5596 // is not actually checked for existence.
5597 HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory);
5598 HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory);
5602 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
5603 __success(return == S_OK)
5604 HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
5607 #ifdef FEATURE_COMINTEROP
5610 HRESULT FindServerUsingCLSID(REFCLSID rclsid, SString & ssServerName);
5611 HRESULT FindServerUsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszServerName);
5612 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name);
5613 HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszInprocServer32Name);
5614 BOOL IsMscoreeInprocServer32(const SString & ssInprocServer32Name);
5615 BOOL CLSIDHasMscoreeAsInprocServer32(REFCLSID rclsid);
5617 #endif // FEATURE_COMINTEROP
5621 static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\");
5622 static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\";
5624 void GetModuleFileName(
5626 SString & ssFileName,
5627 bool fAllowLongFileNames = false);
5629 __success(return == S_OK)
5630 HRESULT GetModuleFileName(
5632 __deref_out_z LPWSTR * pwszFileName,
5633 bool fAllowLongFileNames = false);
5635 void GetFullPathName(
5636 SString const & ssFileName,
5637 SString & ssPathName,
5638 DWORD * pdwFilePartIdx,
5639 bool fAllowLongFileNames = false);
5644 #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE)
5645 // Forward declaration of AppX::IsAppXProcess
5646 namespace AppX { bool IsAppXProcess(); }
5648 // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes.
5649 inline DWORD GetLoadWithAlteredSearchPathFlag()
5651 WRAPPER_NO_CONTRACT;
5652 return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
5654 #else // FEATURE_APPX && !DACCESS_COMPILE
5655 // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally.
5656 inline DWORD GetLoadWithAlteredSearchPathFlag()
5658 LIMITED_METHOD_CONTRACT;
5659 #ifdef LOAD_WITH_ALTERED_SEARCH_PATH
5660 return LOAD_WITH_ALTERED_SEARCH_PATH;
5665 #endif // FEATURE_APPX && !DACCESS_COMPILE
5667 // clr::SafeAddRef and clr::SafeRelease helpers.
5670 //=================================================================================================================
5671 template <typename ItfT>
5673 typename std::enable_if< std::is_pointer<ItfT>::value, ItfT >::type
5674 SafeAddRef(ItfT pItf)
5676 STATIC_CONTRACT_LIMITED_METHOD;
5677 if (pItf != nullptr)
5684 //=================================================================================================================
5685 template <typename ItfT>
5686 typename std::enable_if< std::is_pointer<ItfT>::value && std::is_reference<ItfT>::value, ULONG >::type
5687 SafeRelease(ItfT pItf)
5689 STATIC_CONTRACT_LIMITED_METHOD;
5691 if (pItf != nullptr)
5693 res = pItf->Release();
5699 //=================================================================================================================
5700 template <typename ItfT>
5701 typename std::enable_if< std::is_pointer<ItfT>::value && !std::is_reference<ItfT>::value, ULONG >::type
5702 SafeRelease(ItfT pItf)
5704 STATIC_CONTRACT_LIMITED_METHOD;
5706 if (pItf != nullptr)
5708 res = pItf->Release();
5717 //=================================================================================================================
5718 template <typename PtrT>
5720 typename std::enable_if< std::is_pointer<PtrT>::value, PtrT >::type
5721 SafeDelete(PtrT & ptr)
5723 STATIC_CONTRACT_LIMITED_METHOD;
5732 // ======================================================================================
5733 // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp)
5735 struct SpinConstants
5737 DWORD dwInitialDuration;
5738 DWORD dwMaximumDuration;
5739 DWORD dwBackoffFactor;
5740 DWORD dwRepetitions;
5743 extern SpinConstants g_SpinConstants;
5745 // ======================================================================================
5747 #endif // __UtilCode_h__