Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / inc / utilcode.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
5 // UtilCode.h
6 //
7 // Utility functions implemented in UtilCode.lib.
8 //
9 //*****************************************************************************
10
11 #ifndef __UtilCode_h__
12 #define __UtilCode_h__
13
14 #include "crtwrap.h"
15 #include "winwrap.h"
16 #include <wchar.h>
17 #include <stdio.h>
18 #include <malloc.h>
19 #include <ole2.h>
20 #include <oleauto.h>
21 #include <limits.h>
22 #include "clrtypes.h"
23 #include "safewrap.h"
24 #include "volatile.h"
25 #include <daccess.h>
26 #include "clrhost.h"
27 #include "debugmacros.h"
28 #include "corhlprpriv.h"
29 #include "winnls.h"
30 #include "check.h"
31 #include "safemath.h"
32 #include "new.hpp"
33
34 #ifdef PAL_STDCPP_COMPAT
35 #include <type_traits>
36 #else
37 #include "clr_std/type_traits"
38 #endif
39
40 #include "contract.h"
41 #include "entrypoints.h"
42
43 #include "clrnt.h"
44
45 // Values for the names of Watson
46 const WCHAR kWatsonName1[] = W("drwatson");
47 const WCHAR kWatsonName2[] = W("drwtsn32");
48
49 #include "random.h"
50
51 #define WINDOWS_KERNEL32_DLLNAME_A "kernel32"
52 #define WINDOWS_KERNEL32_DLLNAME_W W("kernel32")
53
54 #define CoreLibName_W W("System.Private.CoreLib")
55 #define CoreLibName_IL_W W("System.Private.CoreLib.dll")
56 #define CoreLibName_NI_W W("System.Private.CoreLib.ni.dll")
57 #define CoreLibName_TLB_W W("System.Private.CoreLib.tlb")
58 #define CoreLibName_A "System.Private.CoreLib"
59 #define CoreLibName_IL_A "System.Private.CoreLib.dll"
60 #define CoreLibName_NI_A "System.Private.CoreLib.ni.dll"
61 #define CoreLibName_TLB_A "System.Private.CoreLib.tlb"
62 #define CoreLibNameLen 22
63 #define CoreLibSatelliteName_A "System.Private.CoreLib.resources"
64 #define CoreLibSatelliteNameLen 32
65 #define LegacyCoreLibName_A "mscorlib"
66
67 class StringArrayList;
68
69 #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE)
70 #define _DEBUG_IMPL 1
71 #endif
72
73 #ifdef _TARGET_ARM_
74
75 // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct
76 // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this
77 // is handled automatically for us by the compiler. When generating and working with code generated
78 // dynamically we have to be careful to set or mask-out this bit as appropriate.
79 #ifndef THUMB_CODE
80 #define THUMB_CODE 1
81 #endif
82
83 // Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff).
84 inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit)
85 {
86     _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit));
87     return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1);
88 }
89
90 // Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the
91 // instruction.
92 inline bool Is32BitInstruction(WORD opcode)
93 {
94     return BitExtract(opcode, 15, 11) >= 0x1d;
95 }
96
97 template <typename ResultType, typename SourceType>
98 inline ResultType DataPointerToThumbCode(SourceType pCode)
99 {
100     return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE);
101 }
102
103 template <typename ResultType, typename SourceType>
104 inline ResultType ThumbCodeToDataPointer(SourceType pCode)
105 {
106     return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE);
107 }
108
109 #endif // _TARGET_ARM_
110
111 // Convert from a PCODE to the corresponding PINSTR.  On many architectures this will be the identity function;
112 // on ARM, this will mask off the THUMB bit.
113 inline TADDR PCODEToPINSTR(PCODE pc)
114 {
115 #ifdef _TARGET_ARM_
116     return ThumbCodeToDataPointer<TADDR,PCODE>(pc);
117 #else
118     return dac_cast<PCODE>(pc);
119 #endif
120 }
121
122 // Convert from a PINSTR to the corresponding PCODE.  On many architectures this will be the identity function;
123 // on ARM, this will raise the THUMB bit.
124 inline PCODE PINSTRToPCODE(TADDR addr)
125 {
126 #ifdef _TARGET_ARM_
127     return DataPointerToThumbCode<PCODE,TADDR>(addr);
128 #else
129     return dac_cast<PCODE>(addr);
130 #endif
131 }
132
133 typedef LPCSTR  LPCUTF8;
134 typedef LPSTR   LPUTF8;
135
136 #include "nsutilpriv.h"
137
138 #include "stdmacros.h"
139
140 /*
141 // This is for WinCE
142 #ifdef VERIFY
143 #undef VERIFY
144 #endif
145
146 #ifdef _ASSERTE
147 #undef _ASSERTE
148 #endif
149 */
150
151 //********** Macros. **********************************************************
152 #ifndef FORCEINLINE
153  #if _MSC_VER < 1200
154    #define FORCEINLINE inline
155  #else
156    #define FORCEINLINE __forceinline
157  #endif
158 #endif
159
160 #ifndef DEBUG_NOINLINE
161 #if defined(_DEBUG)
162 #define DEBUG_NOINLINE __declspec(noinline)
163 #else
164 #define DEBUG_NOINLINE
165 #endif
166 #endif
167
168 #ifndef DBG_NOINLINE_X86__RET_INLINE
169 #if defined(_DEBUG) && defined(_TARGET_X86_)
170 // this exists to make scan work on x86. 
171 #define DBG_NOINLINE_X86__RET_INLINE __declspec(noinline)
172 #else
173 #define DBG_NOINLINE_X86__RET_INLINE FORCEINLINE
174 #endif
175 #endif
176
177 #include <stddef.h> // for offsetof
178
179 #ifndef NumItems
180 // Number of elements in a fixed-size array
181 #define NumItems(s) (sizeof(s) / sizeof(s[0]))
182 #endif
183
184 #ifndef StrLen
185 // Number of characters in a string literal. Excludes terminating NULL.
186 #define StrLen(str) (NumItems(str) - 1)
187 #endif
188
189
190 #define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9')))
191 #define DIGIT_TO_INT(ch) (ch - W('0'))
192 #define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i))
193
194 #define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \
195                          ((ch >= W('A')) && (ch <= W('F'))))
196 #define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10)
197 #define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10)))
198
199
200 // Helper will 4 byte align a value, rounding up.
201 #define ALIGN4BYTE(val) (((val) + 3) & ~0x3)
202
203 #ifdef  _DEBUG
204 #define DEBUGARG(x)         , x
205 #else
206 #define DEBUGARG(x)
207 #endif
208
209 #ifndef sizeofmember
210 // Returns the size of a class or struct member.
211 #define sizeofmember(c,m) (sizeof(((c*)0)->m))
212 #endif
213
214 //=--------------------------------------------------------------------------=
215 // Prefast helpers.
216 //
217
218 #include "safemath.h"
219
220
221 //=--------------------------------------------------------------------------=
222 // string helpers.
223
224 //
225 // given and ANSI String, copy it into a wide buffer.
226 // be careful about scoping when using this macro!
227 //
228 // how to use the below two macros:
229 //
230 //  ...
231 //  LPSTR pszA;
232 //  pszA = MyGetAnsiStringRoutine();
233 //  MAKE_WIDEPTR_FROMANSI(pwsz, pszA);
234 //  MyUseWideStringRoutine(pwsz);
235 //  ...
236 //
237 // similarily for MAKE_ANSIPTR_FROMWIDE.  note that the first param does not
238 // have to be declared, and no clean up must be done.
239 //
240
241 // We'll define an upper limit that allows multiplication by 4 (the max
242 // bytes/char in UTF-8) but still remains positive, and allows some room for pad.
243 // Under normal circumstances, we should never get anywhere near this limit.
244 #define MAKE_MAX_LENGTH 0x1fffff00
245
246 #ifndef MAKE_TOOLONGACTION
247 #define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW)
248 #endif
249
250 #ifndef MAKE_TRANSLATIONFAILED
251 #define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION)
252 #endif
253
254 // This version throws on conversion errors (ie, no best fit character
255 // mapping to characters that look similar, and no use of the default char
256 // ('?') when printing out unrepresentable characters.  Use this method for
257 // most development in the EE, especially anything like metadata or class
258 // names.  See the BESTFIT version if you're printing out info to the console.
259 #define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \
260     int __l##ptrname = (int)wcslen(widestr);        \
261     if (__l##ptrname > MAKE_MAX_LENGTH)         \
262         MAKE_TOOLONGACTION;                     \
263     __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
264     CQuickBytes __CQuickBytes##ptrname; \
265     __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
266     BOOL __b##ptrname; \
267     DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \
268     if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \
269         MAKE_TRANSLATIONFAILED; \
270     } \
271     LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
272
273 // This version does best fit character mapping and also allows the use
274 // of the default char ('?') for any Unicode character that isn't
275 // representable.  This is reasonable for writing to the console, but
276 // shouldn't be used for most string conversions.
277 #define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \
278     int __l##ptrname = (int)wcslen(widestr);        \
279     if (__l##ptrname > MAKE_MAX_LENGTH)         \
280         MAKE_TOOLONGACTION;                     \
281     __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
282     CQuickBytes __CQuickBytes##ptrname; \
283     __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \
284     DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \
285     if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \
286         MAKE_TRANSLATIONFAILED; \
287     } \
288     LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr()
289
290 // Use for anything critical other than output to console, where weird
291 // character mappings are unacceptable.
292 #define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP)
293
294 // Use for output to the console.
295 #define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP)
296
297 #define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \
298     CQuickBytes __qb##ptrname; \
299     int __l##ptrname; \
300     __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
301     if (__l##ptrname > MAKE_MAX_LENGTH) \
302         MAKE_TOOLONGACTION; \
303     LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR));  \
304     if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \
305         MAKE_TRANSLATIONFAILED; \
306     }
307
308 #define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \
309     CQuickBytes __qb##ptrname; \
310     LPWSTR ptrname = 0; \
311     int __l##ptrname; \
312     __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \
313     if (__l##ptrname <= MAKE_MAX_LENGTH) { \
314         ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR));  \
315         if (ptrname) { \
316             if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \
317                 ptrname[__l##ptrname] = 0; \
318             } else { \
319                 ptrname = 0; \
320             } \
321         } \
322     }
323
324 #define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr();
325
326 #define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \
327     CQuickBytes __qb##ptrname; \
328     int __l##ptrname = (int)wcslen(widestr); \
329     LPUTF8 ptrname = 0; \
330     if (__l##ptrname <= MAKE_MAX_LENGTH) { \
331         __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \
332         ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \
333     } \
334     if (ptrname) { \
335         INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \
336         DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \
337         if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \
338             if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \
339                 INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \
340                 ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \
341                 if (ptrname) { \
342                     if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \
343                         ptrname[__l##ptrname] = 0; \
344                     } else { \
345                         ptrname = 0; \
346                     } \
347                 } \
348             } \
349             else { \
350                 ptrname = 0; \
351             } \
352         } \
353     } \
354
355 #define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \
356     CQuickBytes __qb##ptrname; \
357     int __l##ptrname; \
358     __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
359     if (__l##ptrname > MAKE_MAX_LENGTH) \
360         MAKE_TOOLONGACTION; \
361     LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \
362     if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \
363         MAKE_TRANSLATIONFAILED; \
364     } \
365     ptrname[__l##ptrname] = 0;
366
367
368 #define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname;  _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr();
369
370
371 #define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \
372     CQuickBytes __qb##ptrname; \
373     int __l##ptrname; \
374     LPWSTR ptrname = 0; \
375     __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \
376     if (__l##ptrname <= MAKE_MAX_LENGTH) { \
377         ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR));  \
378         if (ptrname) { \
379             if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \
380                 ptrname[__l##ptrname] = 0; \
381             } else { \
382                 ptrname = 0; \
383             } \
384         } \
385     }
386
387 #define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str)   MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1)
388
389 // This method takes the number of characters
390 #define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage)        \
391     CQuickBytes __qb##ptrname; \
392     int __l##ptrname; \
393     __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL);           \
394     if (__l##ptrname > MAKE_MAX_LENGTH) \
395         MAKE_TOOLONGACTION; \
396     ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
397     BOOL __b##ptrname; \
398     DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname);  \
399     if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \
400         MAKE_TRANSLATIONFAILED; \
401     } \
402     ptrname[__l##ptrname] = 0;
403
404 #define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage)        \
405     CQuickBytes __qb##ptrname; \
406     int __l##ptrname; \
407     __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL);           \
408     if (__l##ptrname > MAKE_MAX_LENGTH) \
409         MAKE_TOOLONGACTION; \
410     ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \
411     DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL);  \
412     if (_pCnt == 0 && _nCharacters > 0) { \
413         MAKE_TRANSLATIONFAILED; \
414     } \
415     ptrname[__l##ptrname] = 0;
416
417 #define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt)        \
418        MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP)
419
420
421 inline
422 LPWSTR DuplicateString(
423     LPCWSTR wszString,
424     size_t  cchString)
425 {
426     STATIC_CONTRACT_NOTHROW;
427
428     LPWSTR wszDup = NULL;
429     if (wszString != NULL)
430     {
431         wszDup = new (nothrow) WCHAR[cchString + 1];
432         if (wszDup != NULL)
433         {
434             wcscpy_s(wszDup, cchString + 1, wszString);
435         }
436     }
437     return wszDup;
438 }
439
440 inline
441 LPWSTR DuplicateString(
442     LPCWSTR wszString)
443 {
444     STATIC_CONTRACT_NOTHROW;
445
446     if (wszString != NULL)
447     {
448         return DuplicateString(wszString, wcslen(wszString));
449     }
450     else
451     {
452         return NULL;
453     }
454 }
455
456 void DECLSPEC_NORETURN ThrowOutOfMemory();
457
458 inline
459 LPWSTR DuplicateStringThrowing(
460     LPCWSTR wszString,
461     size_t cchString)
462 {
463     STATIC_CONTRACT_THROWS;
464
465     if (wszString == NULL)
466         return NULL;
467
468     LPWSTR wszDup = DuplicateString(wszString, cchString);
469     if (wszDup == NULL)
470         ThrowOutOfMemory();
471
472     return wszDup;
473 }
474
475 inline
476 LPWSTR DuplicateStringThrowing(
477     LPCWSTR wszString)
478 {
479     STATIC_CONTRACT_THROWS;
480
481     if (wszString == NULL)
482         return NULL;
483
484     LPWSTR wszDup = DuplicateString(wszString);
485     if (wszDup == NULL)
486         ThrowOutOfMemory();
487
488     return wszDup;
489 }
490
491
492 //*****************************************************************************
493 // Placement new is used to new and object at an exact location.  The pointer
494 // is simply returned to the caller without actually using the heap.  The
495 // advantage here is that you cause the ctor() code for the object to be run.
496 // This is ideal for heaps of C++ objects that need to get init'd multiple times.
497 // Example:
498 //      void        *pMem = GetMemFromSomePlace();
499 //      Foo *p = new (pMem) Foo;
500 //      DoSomething(p);
501 //      p->~Foo();
502 //*****************************************************************************
503 #ifndef __PLACEMENT_NEW_INLINE
504 #define __PLACEMENT_NEW_INLINE
505 inline void *__cdecl operator new(size_t, void *_P)
506 {
507     LIMITED_METHOD_DAC_CONTRACT;
508
509     return (_P);
510 }
511 #endif // __PLACEMENT_NEW_INLINE
512
513
514 /********************************************************************************/
515 /* portability helpers */
516 #ifdef _WIN64
517 #define IN_WIN64(x)     x
518 #define IN_WIN32(x)
519 #else
520 #define IN_WIN64(x)
521 #define IN_WIN32(x)     x
522 #endif
523
524 void * __cdecl
525 operator new(size_t n);
526
527 _Ret_bytecap_(n) void * __cdecl
528 operator new[](size_t n);
529
530 void __cdecl
531 operator delete(void *p) NOEXCEPT;
532
533 void __cdecl
534 operator delete[](void *p) NOEXCEPT;
535
536 #ifdef _DEBUG_IMPL
537 HRESULT _OutOfMemory(LPCSTR szFile, int iLine);
538 #define OutOfMemory() _OutOfMemory(__FILE__, __LINE__)
539 #else
540 inline HRESULT OutOfMemory()
541 {
542     LIMITED_METHOD_CONTRACT;
543     return (E_OUTOFMEMORY);
544 }
545 #endif
546
547 //*****************************************************************************
548 // Handle accessing localizable resource strings
549 //*****************************************************************************
550 // NOTE: Should use locale names as much as possible.  LCIDs don't support
551 // custom cultures on Vista+.
552 // TODO: This should always use the names
553 #ifdef FEATURE_USE_LCID    
554 typedef LCID LocaleID;
555 typedef LCID LocaleIDValue;
556 #else
557 typedef LPCWSTR LocaleID;
558 typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH];
559 #endif
560
561 // Notes about the culture callbacks:
562 // - The language we're operating in can change at *runtime*!
563 // - A process may operate in *multiple* languages.
564 //     (ex: Each thread may have it's own language)
565 // - If we don't care what language we're in (or have no way of knowing),
566 //     then return a 0-length name and UICULTUREID_DONTCARE for the culture ID.
567 // - GetCultureName() and the GetCultureId() must be in sync (refer to the
568 //     same language).
569 // - We have two functions separate functions for better performance.
570 //     - The name is used to resolve a directory for MsCorRC.dll.
571 //     - The id is used as a key to map to a dll hinstance.
572
573 // Callback to obtain both the culture name and the culture's parent culture name
574 typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames);
575 #ifdef FEATURE_USE_LCID
576 // Callback to return the culture ID.
577 const LCID UICULTUREID_DONTCARE = (LCID)-1;
578 #else
579 const LPCWSTR UICULTUREID_DONTCARE = NULL;
580 #endif
581
582 typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*);
583
584 HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName);
585
586 HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
587
588 BOOL CLRFreeLibrary(HMODULE hModule);
589
590 // Prevent people from using LoadStringRC & LoadStringRCEx from inside the product since it
591 // causes issues with having the wrong version picked up inside the shim.
592 #define LoadStringRC __error("From inside the CLR, use UtilLoadStringRC; LoadStringRC is only meant to be exported.")
593 #define LoadStringRCEx __error("From inside the CLR, use UtilLoadStringRCEx; LoadStringRC is only meant to be exported.")
594
595 // Load a string using the resources for the current module.
596 STDAPI UtilLoadStringRC(UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE);
597
598 #if defined(ENABLE_DOWNLEVEL_FOR_NLS) || defined(FEATURE_USE_LCID)
599 STDAPI UtilLoadStringRCEx(LCID lcid, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed);
600 #endif
601
602 // Specify callbacks so that UtilLoadStringRC can find out which language we're in.
603 // If no callbacks specified (or both parameters are NULL), we default to the
604 // resource dll in the root (which is probably english).
605 void SetResourceCultureCallbacks(
606     FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
607     FPGETTHREADUICULTUREID fpGetThreadUICultureId
608 );
609
610 void GetResourceCultureCallbacks(
611         FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
612         FPGETTHREADUICULTUREID* fpGetThreadUICultureId
613 );
614
615 #if !defined(DACCESS_COMPILE)
616 // Get the MUI ID, on downlevel platforms where MUI is not supported it
617 // returns the default system ID.
618 extern int GetMUILanguageID(LocaleIDValue* pResult);
619 extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames);
620
621 #endif // !defined(DACCESS_COMPILE)
622
623 //*****************************************************************************
624 // Use this class by privately deriving from noncopyable to disallow copying of 
625 // your class.
626 //*****************************************************************************
627 class noncopyable
628 {
629 protected:
630     noncopyable()
631     {}
632     ~noncopyable()
633     {}
634
635 private:
636     noncopyable(const noncopyable&);
637     const noncopyable& operator=(const noncopyable&);
638 };
639
640 //*****************************************************************************
641 // Must associate each handle to an instance of a resource dll with the int
642 // that it represents
643 //*****************************************************************************
644 typedef HINSTANCE HRESOURCEDLL;
645
646
647 class CCulturedHInstance
648 {
649     LocaleIDValue   m_LangId;
650     HRESOURCEDLL    m_hInst;
651     BOOL            m_fMissing;
652     
653 public:
654     CCulturedHInstance()
655     {
656         LIMITED_METHOD_CONTRACT;
657         m_hInst = NULL;
658         m_fMissing = FALSE;
659     }
660     
661     BOOL HasID(LocaleID id)
662     {
663         _ASSERTE(m_hInst != NULL || m_fMissing);
664         if (id == UICULTUREID_DONTCARE)
665             return FALSE;
666         
667 #ifdef FEATURE_USE_LCID
668         return id == m_LangId;
669 #else
670         return wcscmp(id, m_LangId) == 0;
671 #endif
672     }
673     
674     HRESOURCEDLL GetLibraryHandle()
675     {
676         return m_hInst;
677     }
678     
679     BOOL IsSet()
680     {
681         return m_hInst != NULL;
682     }
683
684     BOOL IsMissing()
685     {
686         return m_fMissing;
687     }
688
689     void SetMissing(LocaleID id)
690     {
691         _ASSERTE(m_hInst == NULL);
692         SetId(id);
693         m_fMissing = TRUE;
694     }
695     
696     void Set(LocaleID id, HRESOURCEDLL hInst)
697     {
698         _ASSERTE(m_hInst == NULL);
699         _ASSERTE(m_fMissing == FALSE);
700         SetId(id);
701         m_hInst = hInst;
702     }
703   private:
704     void SetId(LocaleID id)
705     {
706 #ifdef FEATURE_USE_LCID
707         m_LangId = id;
708 #else
709         if (id != UICULTUREID_DONTCARE)
710         {
711             wcsncpy_s(m_LangId, NumItems(m_LangId), id, NumItems(m_LangId));
712             m_LangId[NumItems(m_LangId)-1] = W('\0');
713         }
714         else
715         {
716             m_LangId[0] = W('\0');
717         }
718 #endif
719     }
720  };
721
722 #ifndef DACCESS_COMPILE
723 void AddThreadPreferredUILanguages(StringArrayList* pArray);
724 #endif
725 //*****************************************************************************
726 // CCompRC manages string Resource access for COM+. This includes loading
727 // the MsCorRC.dll for resources as well allowing each thread to use a
728 // a different localized version.
729 //*****************************************************************************
730 class CCompRC
731 {
732 public:
733
734     enum ResourceCategory
735     {
736         // must be present
737         Required,                   
738         
739         // present in Desktop CLR and Core CLR + debug pack, an error
740         // If missing, get a generic error message instead
741         Error,           
742         
743         // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing)
744         // if missing, get a generic "resource not found" message instead
745         Debugging,           
746
747         // present in Desktop CLR, optional for CoreCLR
748         DesktopCLR,       
749
750         // might not be present, non essential
751         Optional
752     };
753
754     CCompRC()
755     {
756         // This constructor will be fired up on startup. Make sure it doesn't
757         // do anything besides zero-out out values.
758         m_bUseFallback = FALSE;
759
760         m_fpGetThreadUICultureId = NULL;
761         m_fpGetThreadUICultureNames = NULL;
762         
763
764         m_pHash = NULL;
765         m_nHashSize = 0;
766         m_csMap = NULL;
767         m_pResourceFile = NULL;
768 #ifdef FEATURE_PAL
769         m_pResourceDomain = NULL;
770 #endif // FEATURE_PAL
771
772     }// CCompRC
773
774     HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE);
775     void Destroy();
776
777     BOOL ShouldUseFallback()
778     {
779         LIMITED_METHOD_CONTRACT;
780         return m_bUseFallback;
781     };
782
783     static void SetIsMscoree() {s_bIsMscoree = TRUE;}
784
785     HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL);    
786     HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed);
787
788     void SetResourceCultureCallbacks(
789         FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
790         FPGETTHREADUICULTUREID fpGetThreadUICultureId
791     );
792
793     void GetResourceCultureCallbacks(
794         FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
795         FPGETTHREADUICULTUREID* fpGetThreadUICultureId
796     );
797
798     HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst);
799
800     // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR)
801     static CCompRC* GetDefaultResourceDll();
802     // Get the generic messages dll (Silverlight only, mscorrc.dll)
803     static CCompRC* GetFallbackResourceDll();
804     static void ShutdownDefaultResourceDll();
805     static void GetDefaultCallbacks(
806                     FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames,
807                     FPGETTHREADUICULTUREID* fpGetThreadUICultureId)
808     {
809         WRAPPER_NO_CONTRACT;
810         m_DefaultResourceDll.GetResourceCultureCallbacks(
811                     fpGetThreadUICultureNames,
812                     fpGetThreadUICultureId);
813     }
814
815     static void SetDefaultCallbacks(
816                 FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames,
817                 FPGETTHREADUICULTUREID fpGetThreadUICultureId)
818     {
819         WRAPPER_NO_CONTRACT;
820         // Either both are NULL or neither are NULL
821         _ASSERTE((fpGetThreadUICultureNames != NULL) ==
822                  (fpGetThreadUICultureId != NULL));
823
824         m_DefaultResourceDll.SetResourceCultureCallbacks(
825                 fpGetThreadUICultureNames,
826                 fpGetThreadUICultureId);
827
828         m_FallbackResourceDll.SetResourceCultureCallbacks(
829                 fpGetThreadUICultureNames,
830                 fpGetThreadUICultureId);
831
832     }
833
834 #ifdef USE_FORMATMESSAGE_WRAPPER
835
836 DWORD
837 PALAPI
838 static 
839 FormatMessage(
840            IN DWORD dwFlags,
841            IN LPCVOID lpSource,
842            IN DWORD dwMessageId,
843            IN DWORD dwLanguageId,
844            OUT LPWSTR lpBuffer,
845            IN DWORD nSize,
846            IN va_list *Arguments);
847 #endif // USE_FORMATMESSAGE_WRAPPER
848
849
850 private:
851     HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst);
852 #ifndef DACCESS_COMPILE
853     HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst,
854                               SString& rcPath);
855     HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst);
856     HRESULT LoadLibrary(HRESOURCEDLL * pHInst);
857     HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName);
858 #endif
859
860     // We do not have global constructors any more
861     static LONG     m_dwDefaultInitialized;
862     static CCompRC  m_DefaultResourceDll;
863     static LPCWSTR  m_pDefaultResource;
864
865     // fallback resources if debug pack is not installed
866     static LONG     m_dwFallbackInitialized;
867     static CCompRC  m_FallbackResourceDll;
868     static LPCWSTR  m_pFallbackResource;
869
870     // We must map between a thread's int and a dll instance.
871     // Since we only expect 1 language almost all of the time, we'll special case
872     // that and then use a variable size map for everything else.
873     CCulturedHInstance m_Primary;
874     CCulturedHInstance * m_pHash;
875     int m_nHashSize;
876
877     CRITSEC_COOKIE m_csMap;
878
879     LPCWSTR m_pResourceFile;
880 #ifdef FEATURE_PAL
881     // Resource domain is an ANSI string identifying a native resources file
882     static LPCSTR  m_pDefaultResourceDomain;
883     static LPCSTR  m_pFallbackResourceDomain;
884     LPCSTR m_pResourceDomain;
885 #endif // FEATURE_PAL
886
887     // Main accessors for hash
888     HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing);
889     HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE);
890
891     FPGETTHREADUICULTUREID m_fpGetThreadUICultureId;
892     FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames;
893
894     BOOL m_bUseFallback;
895     static BOOL s_bIsMscoree;
896 };
897
898 HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax);
899
900
901 int UtilMessageBox(
902                   HWND hWnd,        // Handle to Owner Window
903                   UINT uText,       // Resource Identifier for Text message
904                   UINT uCaption,    // Resource Identifier for Caption
905                   UINT uType,       // Style of MessageBox
906                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
907                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
908                   ...);             // Additional Arguments
909
910 int UtilMessageBoxNonLocalized(
911                   HWND hWnd,        // Handle to Owner Window
912                   LPCWSTR lpText,    // Resource Identifier for Text message
913                   LPCWSTR lpTitle,   // Resource Identifier for Caption
914                   UINT uType,       // Style of MessageBox
915                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
916                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
917                   ...);             // Additional Arguments
918
919 int UtilMessageBoxVA(
920                   HWND hWnd,        // Handle to Owner Window
921                   UINT uText,       // Resource Identifier for Text message
922                   UINT uCaption,    // Resource Identifier for Caption
923                   UINT uType,       // Style of MessageBox
924                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
925                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
926                   va_list args);    // Additional Arguments
927
928 int UtilMessageBoxNonLocalizedVA(
929                   HWND hWnd,        // Handle to Owner Window
930                   LPCWSTR lpText,    // Text message
931                   LPCWSTR lpCaption, // Caption
932                   UINT uType,       // Style of MessageBox
933                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
934                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
935                   BOOL * pInputFromUser,            // To distinguish between user pressing abort vs. assuming abort.
936                   va_list args);    // Additional Arguments
937
938 int UtilMessageBoxNonLocalizedVA(
939                   HWND hWnd,        // Handle to Owner Window
940                   LPCWSTR lpText,    // Text message
941                   LPCWSTR lpCaption, // Caption
942                   LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher).
943                   UINT uType,       // Style of MessageBox
944                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
945                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
946                   BOOL * pInputFromUser,            // To distinguish between user pressing abort vs. assuming abort.
947                   va_list args);    // Additional Arguments
948
949 int UtilMessageBoxCatastrophic(
950                   UINT uText,       // Text for MessageBox
951                   UINT uTitle,      // Title for MessageBox
952                   UINT uType,       // Style of MessageBox
953                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
954                   ...);
955
956 int UtilMessageBoxCatastrophicNonLocalized(
957                   LPCWSTR lpText,    // Text for MessageBox
958                   LPCWSTR lpTitle,   // Title for MessageBox
959                   UINT uType,       // Style of MessageBox
960                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
961                   ...);
962
963 int UtilMessageBoxCatastrophicVA(
964                   UINT uText,       // Text for MessageBox
965                   UINT uTitle,      // Title for MessageBox
966                   UINT uType,       // Style of MessageBox
967                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
968                   va_list args);    // Additional Arguments
969
970 int UtilMessageBoxCatastrophicNonLocalizedVA(
971                   LPCWSTR lpText,    // Text for MessageBox
972                   LPCWSTR lpTitle,   // Title for MessageBox
973                   UINT uType,       // Style of MessageBox
974                   BOOL ShowFileNameInTitle, // Flag to show FileName in Caption
975                   va_list args);    // Additional Arguments
976
977
978 // The HRESULT_FROM_WIN32 macro evaluates its arguments three times.
979 // <TODO>TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to
980 //  this helper function avoid code bloat</TODO>
981 inline HRESULT HRESULT_FROM_GetLastError()
982 {
983     WRAPPER_NO_CONTRACT;
984     DWORD dw = GetLastError();
985     // Make sure we return a failure
986     if (dw == ERROR_SUCCESS)
987     {
988         _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!");
989         return E_FAIL;
990     }
991     else
992         return HRESULT_FROM_WIN32(dw);
993 }
994
995 inline HRESULT HRESULT_FROM_GetLastErrorNA()
996 {
997     WRAPPER_NO_CONTRACT;
998     DWORD dw = GetLastError();
999     // Make sure we return a failure
1000     if (dw == ERROR_SUCCESS)
1001         return E_FAIL;
1002     else
1003         return HRESULT_FROM_WIN32(dw);
1004 }
1005
1006 inline HRESULT BadError(HRESULT hr)
1007 {
1008     LIMITED_METHOD_CONTRACT;
1009     _ASSERTE(!"Serious Error");
1010     return (hr);
1011 }
1012
1013 #define TESTANDRETURN(test, hrVal)              \
1014 {                                               \
1015     int ___test = (int)(test);                  \
1016     if (! ___test)                              \
1017         return hrVal;                           \
1018 }
1019
1020 #define TESTANDRETURNPOINTER(pointer)           \
1021     TESTANDRETURN(pointer!=NULL, E_POINTER)
1022
1023 #define TESTANDRETURNMEMORY(pointer)            \
1024     TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY)
1025
1026 #define TESTANDRETURNHR(hr)                     \
1027     TESTANDRETURN(SUCCEEDED(hr), hr)
1028
1029 #define TESTANDRETURNARG(argtest)               \
1030     TESTANDRETURN(argtest, E_INVALIDARG)
1031
1032 // Quick validity check for HANDLEs that are returned by Win32 APIs that
1033 // use INVALID_HANDLE_VALUE instead of NULL to indicate an error
1034 inline BOOL IsValidHandle(HANDLE h)
1035 {
1036     LIMITED_METHOD_CONTRACT;
1037     return ((h != NULL) && (h != INVALID_HANDLE_VALUE));
1038 }
1039
1040 // Count the bits in a value in order iBits time.
1041 inline int CountBits(int iNum)
1042 {
1043     LIMITED_METHOD_CONTRACT;
1044     int iBits;
1045     for (iBits=0;  iNum;  iBits++)
1046         iNum = iNum & (iNum - 1);
1047     return (iBits);
1048 }
1049
1050 #include "bitposition.h"
1051
1052 // Used to remove trailing zeros from Decimal types.
1053 // NOTE: Assumes hi32 bits are empty (used for conversions from Cy->Dec)
1054 inline HRESULT DecimalCanonicalize(DECIMAL* dec)
1055 {
1056     WRAPPER_NO_CONTRACT;
1057
1058     // Clear the VARENUM field
1059     (*(USHORT*)dec) = 0;
1060
1061     // Remove trailing zeros:
1062     DECIMAL temp;
1063     DECIMAL templast;
1064     temp = templast = *dec;
1065
1066     // Ensure the hi 32 bits are empty (should be if we came from a currency)
1067     if ((DECIMAL_HI32(temp) != 0) || (DECIMAL_SCALE(temp) > 4))
1068         return DISP_E_OVERFLOW;
1069
1070     // Return immediately if dec represents a zero.
1071     if (DECIMAL_LO32(temp) == 0 && DECIMAL_MID32(temp) == 0)
1072         return S_OK;
1073
1074     // Compare to the original to see if we've
1075     // lost non-zero digits (and make sure we don't overflow the scale BYTE)
1076
1077 #ifdef _PREFAST_
1078 #pragma warning(push)
1079 #pragma warning(disable:6219) // "Suppress PREFast warning about Implicit cast between semantically different integer types" 
1080 #endif
1081     while ((DECIMAL_SCALE(temp) <= 4) && (VARCMP_EQ == VarDecCmp(dec, &temp)))
1082     {
1083
1084 #ifdef _PREFAST_
1085 #pragma warning(pop)
1086 #endif
1087         templast = temp;
1088
1089         // Remove the last digit and normalize.  Ignore temp.Hi32
1090         // as Currency values will have a max of 64 bits of data.
1091         DECIMAL_SCALE(temp)--;
1092         UINT64 temp64 = (((UINT64) DECIMAL_MID32(temp)) << 32) + DECIMAL_LO32(temp);
1093         temp64 /= 10;
1094
1095         DECIMAL_MID32(temp) = (ULONG)(temp64 >> 32);
1096         DECIMAL_LO32(temp) = (ULONG)temp64;
1097     }
1098     *dec = templast;
1099
1100     return S_OK;
1101 }
1102
1103 //*****************************************************************************
1104 //
1105 // Paths functions. Use these instead of the CRT.
1106 //
1107 //*****************************************************************************
1108 // secure version! Specify the size of the each buffer in count of elements
1109 void    SplitPath(register const WCHAR *path,
1110                   __inout_z __inout_ecount_opt(driveSizeInWords) WCHAR *drive, int driveSizeInWords,
1111                   __inout_z __inout_ecount_opt(dirSizeInWords) WCHAR *dir, int dirSizeInWords,
1112                   __inout_z __inout_ecount_opt(fnameSizeInWords) WCHAR *fname, size_t fnameSizeInWords,
1113                   __inout_z __inout_ecount_opt(extSizeInWords) WCHAR *ext, size_t extSizeInWords);
1114
1115 //*******************************************************************************
1116 // A much more sensible version that just points to each section of the string.
1117 //*******************************************************************************
1118 void    SplitPathInterior(
1119     __in      LPCWSTR wszPath,
1120     __out_opt LPCWSTR *pwszDrive,    __out_opt size_t *pcchDrive,
1121     __out_opt LPCWSTR *pwszDir,      __out_opt size_t *pcchDir,
1122     __out_opt LPCWSTR *pwszFileName, __out_opt size_t *pcchFileName,
1123     __out_opt LPCWSTR *pwszExt,      __out_opt size_t *pcchExt);
1124
1125
1126 void    MakePath(__out CQuickWSTR &path,
1127                  __in LPCWSTR drive,
1128                  __in LPCWSTR dir,
1129                  __in LPCWSTR fname,
1130                  __in LPCWSTR ext);
1131
1132 WCHAR * FullPath(__out_ecount (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen);
1133
1134 //*****************************************************************************
1135 //
1136 // SString version of the path functions.
1137 //
1138 //*****************************************************************************
1139 void    SplitPath(__in SString const &path,
1140                   __inout_opt SString *drive,
1141                   __inout_opt SString *dir,
1142                   __inout_opt SString *fname,
1143                   __inout_opt SString *ext);
1144
1145 #if !defined(NO_CLRCONFIG)
1146
1147 //*****************************************************************************
1148 //
1149 // **** REGUTIL - Static helper functions for reading/writing to Windows registry.
1150 //
1151 //*****************************************************************************
1152
1153
1154 class REGUTIL
1155 {
1156 public:
1157 //*****************************************************************************
1158
1159     enum CORConfigLevel
1160     {
1161         COR_CONFIG_ENV          = 0x01,
1162         COR_CONFIG_USER         = 0x02,
1163         COR_CONFIG_MACHINE      = 0x04,
1164         COR_CONFIG_FUSION       = 0x08,
1165
1166         COR_CONFIG_REGISTRY     = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION),
1167         COR_CONFIG_ALL          = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE),
1168     };
1169
1170     //
1171     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
1172     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1173     // 
1174     static DWORD GetConfigDWORD_DontUse_(
1175         LPCWSTR        name,
1176         DWORD          defValue,
1177         CORConfigLevel level = COR_CONFIG_ALL,
1178         BOOL           fPrependCOMPLUS = TRUE);
1179
1180     //
1181     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
1182     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1183     // 
1184     static HRESULT GetConfigDWORD_DontUse_(
1185         LPCWSTR name,
1186         DWORD defValue,
1187         __out DWORD * result,
1188         CORConfigLevel level = COR_CONFIG_ALL,
1189         BOOL fPrependCOMPLUS = TRUE);
1190     
1191     static ULONGLONG GetConfigULONGLONG_DontUse_(
1192         LPCWSTR        name,
1193         ULONGLONG      defValue,
1194         CORConfigLevel level = COR_CONFIG_ALL,
1195         BOOL           fPrependCOMPLUS = TRUE);
1196
1197     //
1198     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
1199     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1200     // 
1201     static DWORD GetConfigFlag_DontUse_(
1202         LPCWSTR        name,
1203         DWORD          bitToSet,
1204         BOOL           defValue = FALSE);
1205
1206     //
1207     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
1208     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1209     // 
1210     static LPWSTR GetConfigString_DontUse_(
1211         LPCWSTR name,
1212         BOOL fPrependCOMPLUS = TRUE,
1213         CORConfigLevel level = COR_CONFIG_ALL,
1214         BOOL fUsePerfCache = TRUE);
1215
1216     static void   FreeConfigString(__in __in_z LPWSTR name);
1217
1218 private:
1219     static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS);
1220 public:
1221
1222     static BOOL UseRegistry();
1223
1224 private:
1225 //*****************************************************************************
1226 // Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that
1227 // you can safely cast to a DWORD if fGetDWORD is TRUE.
1228 //*****************************************************************************    
1229     static HRESULT GetConfigInteger(
1230         LPCWSTR name,
1231         ULONGLONG defValue,
1232         __out ULONGLONG * result,
1233         BOOL fGetDWORD = TRUE,
1234         CORConfigLevel level = COR_CONFIG_ALL,
1235         BOOL fPrependCOMPLUS = TRUE);
1236 public:
1237
1238
1239 //*****************************************************************************
1240 // (Optional) Initialize the config registry cache
1241 // (see ConfigCacheValueNameSeenPerhaps, below.)
1242 //*****************************************************************************
1243     static void InitOptionalConfigCache();
1244
1245 private:
1246
1247
1248 //*****************************************************************************
1249 // Return TRUE if the registry value name might have been seen in the registry
1250 // at startup;
1251 // return FALSE if the value was definitely not seen at startup.
1252 //
1253 // Perf Optimization for VSWhidbey:113373.
1254 //*****************************************************************************
1255     static BOOL RegCacheValueNameSeenPerhaps(
1256         LPCWSTR name);
1257 //*****************************************************************************
1258 // Return TRUE if the environment variable name might have been seen at startup;
1259 // return FALSE if the value was definitely not seen at startup.
1260 //*****************************************************************************
1261     static BOOL EnvCacheValueNameSeenPerhaps(
1262         LPCWSTR name);
1263
1264     static BOOL s_fUseRegCache; // Enable registry cache; if FALSE, CCVNSP
1265                                  // always returns TRUE.
1266     static BOOL s_fUseEnvCache; // Enable env cache.
1267
1268     static BOOL s_fUseRegistry; // Allow lookups in the registry
1269
1270     // Open the .NetFramework keys once and cache the handles
1271     static HKEY s_hMachineFrameworkKey;
1272     static HKEY s_hUserFrameworkKey;
1273 };
1274
1275 // need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig
1276 #include "clrconfig.h" 
1277
1278 //-----------------------------------------------------------------------------
1279 // Wrapper for configuration strings.
1280 // This serves as a holder to call FreeConfigString.
1281 class ConfigStringHolder
1282 {
1283 public:
1284     ConfigStringHolder() { m_wszString = NULL; }
1285     ~ConfigStringHolder()
1286     {
1287         Clear();
1288     }
1289
1290     //
1291     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
1292     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
1293     // 
1294     void Init_DontUse_(LPCWSTR wszName)
1295     {
1296         Clear();
1297         m_wszString = REGUTIL::GetConfigString_DontUse_(wszName);
1298     }
1299
1300     // Free resources.
1301     void Clear()
1302     {
1303         if (m_wszString != NULL)
1304         {
1305             REGUTIL::FreeConfigString(m_wszString);
1306             m_wszString = NULL;
1307         }
1308     }
1309
1310     // Get the string value. NULL if not set.
1311     LPCWSTR Value()
1312     {
1313         return m_wszString;
1314     }
1315
1316 private:
1317     LPWSTR m_wszString;
1318 };
1319
1320 #endif // defined(NO_CLRCONFIG)
1321
1322 #include "ostype.h"
1323
1324 #define CLRGetTickCount64() GetTickCount64()
1325
1326 //
1327 // Use this function to initialize the s_CodeAllocHint
1328 // during startup. base is runtime .dll base address,
1329 // size is runtime .dll virtual size.
1330 //
1331 void InitCodeAllocHint(SIZE_T base, SIZE_T size, int randomPageOffset);
1332
1333
1334 //
1335 // Use this function to reset the s_CodeAllocHint
1336 // after unloading an AppDomain
1337 //
1338 void ResetCodeAllocHint();
1339
1340 //
1341 // Returns TRUE if p is located in near clr.dll that allows us
1342 // to use rel32 IP-relative addressing modes.
1343 //
1344 BOOL IsPreferredExecutableRange(void * p);
1345
1346 //
1347 // Allocate free memory that will be used for executable code
1348 // Handles the special requirements that we have on 64-bit platforms
1349 // where we want the executable memory to be located near mscorwks
1350 //
1351 BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize, 
1352                                  DWORD flAllocationType,
1353                                  DWORD flProtect);
1354
1355 //
1356 // Allocate free memory within the range [pMinAddr..pMaxAddr] using
1357 // ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it.
1358 //
1359 BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr,
1360                                    const BYTE *pMaxAddr,
1361                                    SIZE_T dwSize, 
1362                                    DWORD flAllocationType,
1363                                    DWORD flProtect);
1364
1365 //
1366 // Allocate free memory with specific alignment                                   
1367 //
1368 LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment);
1369                                    
1370 //******************************************************************************
1371 // Returns the number of processors that a process has been configured to run on
1372 //******************************************************************************
1373 class NumaNodeInfo 
1374 {
1375 private:
1376     static BOOL m_enableGCNumaAware;
1377     static BOOL InitNumaNodeInfoAPI();
1378
1379 public:
1380     static BOOL CanEnableGCNumaAware();
1381     static void InitNumaNodeInfo();
1382
1383 #if !defined(FEATURE_REDHAWK)&& !defined(FEATURE_PAL)
1384 private:        // apis types
1385
1386     //GetNumaHighestNodeNumber()
1387     typedef BOOL
1388     (WINAPI *PGNHNN)(PULONG);
1389     //VirtualAllocExNuma()
1390     typedef LPVOID
1391     (WINAPI *PVAExN)(HANDLE,LPVOID,SIZE_T,DWORD,DWORD,DWORD);
1392
1393     // api pfns and members
1394     static PGNHNN   m_pGetNumaHighestNodeNumber;
1395     static PVAExN   m_pVirtualAllocExNuma;
1396
1397 public:         // functions
1398
1399     static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size,
1400                                      DWORD allocType, DWORD prot, DWORD node);
1401
1402 private:
1403     //GetNumaProcessorNodeEx()
1404     typedef BOOL
1405     (WINAPI *PGNPNEx)(PPROCESSOR_NUMBER, PUSHORT);
1406     static PGNPNEx  m_pGetNumaProcessorNodeEx;
1407
1408 public:
1409     static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no);
1410 #endif
1411 };
1412
1413 struct CPU_Group_Info 
1414 {
1415     WORD        nr_active;      // at most 64
1416     WORD        reserved[1];
1417     WORD        begin;
1418     WORD        end;
1419     DWORD_PTR   active_mask;
1420     DWORD       groupWeight;
1421     DWORD       activeThreadWeight;
1422 };
1423
1424 class CPUGroupInfo
1425 {
1426 private:
1427     static LONG m_initialization;
1428     static WORD m_nGroups;
1429     static WORD m_nProcessors;
1430     static BOOL m_enableGCCPUGroups;
1431     static BOOL m_threadUseAllCpuGroups;
1432     static WORD m_initialGroup;
1433     static CPU_Group_Info *m_CPUGroupInfoArray;
1434
1435     static BOOL InitCPUGroupInfoAPI();
1436     static BOOL InitCPUGroupInfoArray();
1437     static BOOL InitCPUGroupInfoRange();
1438     static void InitCPUGroupInfo();
1439     static BOOL IsInitialized();
1440
1441 public:
1442     static void EnsureInitialized();
1443     static BOOL CanEnableGCCPUGroups();
1444     static BOOL CanEnableThreadUseAllCpuGroups();
1445     static WORD GetNumActiveProcessors();
1446     static void GetGroupForProcessor(WORD processor_number, 
1447                     WORD *group_number, WORD *group_processor_number);
1448     static DWORD CalculateCurrentProcessorNumber();
1449     //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize);
1450
1451 #if !defined(FEATURE_REDHAWK) && !defined(FEATURE_PAL)
1452 private:
1453     //GetLogicalProcessorInforomationEx()
1454     typedef BOOL
1455     (WINAPI *PGLPIEx)(DWORD, SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *, PDWORD);
1456     //SetThreadGroupAffinity()
1457     typedef BOOL
1458     (WINAPI *PSTGA)(HANDLE, GROUP_AFFINITY *, GROUP_AFFINITY *);
1459     //GetThreadGroupAffinity()
1460     typedef BOOL
1461     (WINAPI *PGTGA)(HANDLE, GROUP_AFFINITY *);
1462     //GetCurrentProcessorNumberEx()
1463     typedef void
1464     (WINAPI *PGCPNEx)(PROCESSOR_NUMBER *);
1465     //GetSystemTimes()
1466     typedef BOOL
1467     (WINAPI *PGST)(FILETIME *, FILETIME *, FILETIME *);
1468     //NtQuerySystemInformationEx()
1469     //typedef int
1470     //(WINAPI *PNTQSIEx)(SYSTEM_INFORMATION_CLASS, PULONG, ULONG, PVOID, ULONG, PULONG);
1471     static PGLPIEx m_pGetLogicalProcessorInformationEx;
1472     static PSTGA   m_pSetThreadGroupAffinity;
1473     static PGTGA   m_pGetThreadGroupAffinity;
1474     static PGCPNEx m_pGetCurrentProcessorNumberEx;
1475     static PGST    m_pGetSystemTimes;
1476     //static PNTQSIEx m_pNtQuerySystemInformationEx;
1477
1478 public:
1479     static BOOL GetLogicalProcessorInformationEx(DWORD relationship,
1480                    SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count); 
1481     static BOOL SetThreadGroupAffinity(HANDLE h,
1482                     GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity);
1483     static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity);
1484     static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime);
1485     static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf);
1486     static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf);
1487 #endif
1488 };
1489
1490 int GetCurrentProcessCpuCount();
1491 DWORD_PTR GetCurrentProcessCpuMask();
1492
1493 //*****************************************************************************
1494 // Return != 0 if the bit at the specified index in the array is on and 0 if
1495 // it is off.
1496 //*****************************************************************************
1497 inline int GetBit(PTR_BYTE pcBits,int iBit)
1498 {
1499     LIMITED_METHOD_CONTRACT;
1500     return (pcBits[iBit>>3] & (1 << (iBit & 0x7)));
1501 }
1502
1503 #ifdef DACCESS_COMPILE
1504 inline int GetBit(BYTE const * pcBits,int iBit)
1505 {
1506     WRAPPER_NO_CONTRACT;
1507     return GetBit(dac_cast<PTR_BYTE>(pcBits), iBit);
1508 }
1509 #endif
1510
1511 //*****************************************************************************
1512 // Set the state of the bit at the specified index based on the value of bOn.
1513 //*****************************************************************************
1514 inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn)
1515 {
1516     LIMITED_METHOD_CONTRACT;
1517     if (bOn)
1518         pcBits[iBit>>3] |= (1 << (iBit & 0x7));
1519     else
1520         pcBits[iBit>>3] &= ~(1 << (iBit & 0x7));
1521 }
1522
1523 #ifdef DACCESS_COMPILE
1524 inline void SetBit(BYTE * pcBits,int iBit,int bOn)
1525 {
1526     WRAPPER_NO_CONTRACT;
1527     SetBit(dac_cast<PTR_BYTE>(pcBits), iBit, bOn);
1528 }
1529 #endif
1530
1531 template<typename T>
1532 class SimpleListNode
1533 {
1534 public:
1535     SimpleListNode<T>(const T& _t)
1536     {
1537         data = _t;
1538         next = 0;
1539     }
1540
1541     T                  data;
1542     SimpleListNode<T>* next;
1543 };
1544
1545 template<typename T>
1546 class SimpleList
1547 {
1548 public:
1549     typedef SimpleListNode<T> NodeType;
1550
1551     SimpleList<T>()
1552     {
1553         head = NULL;
1554     }
1555
1556     void LinkHead(NodeType* pNode)
1557     {
1558         pNode->next = head;
1559                       head = pNode;
1560     }
1561
1562     NodeType* UnlinkHead()
1563     {
1564         NodeType* ret = head;
1565
1566         if (head)
1567         {
1568             head = head->next;
1569         }
1570         return ret;
1571     }
1572
1573     NodeType* Head()
1574     {
1575         return head;
1576     }
1577
1578 protected:
1579
1580     NodeType* head;
1581 };
1582
1583
1584 template < typename T, typename U >
1585 struct Pair
1586 {
1587 public:
1588     typedef Pair< T, U > this_type;
1589     typedef T first_type;
1590     typedef U second_type;
1591
1592     Pair()
1593     {}
1594
1595     Pair( T const & t, U const & u )
1596         : m_first( t )
1597         , m_second( u )
1598     { SUPPORTS_DAC; }
1599
1600     Pair( this_type const & obj )
1601         : m_first( obj.m_first )
1602         , m_second( obj.m_second )
1603     {}
1604
1605     this_type & operator=( this_type const & obj )
1606     {
1607         m_first = obj.m_first;
1608         m_second = obj.m_second;
1609         return *this;
1610     }
1611
1612     T & First()
1613     {
1614         return m_first;
1615     }
1616
1617     T const & First() const
1618     {
1619         return m_first;
1620     }
1621
1622     U & Second()
1623     {
1624         return m_second;
1625     }
1626
1627     U const & Second() const
1628     {
1629         return m_second;
1630     }
1631
1632     bool operator==(const Pair& rhs) const
1633     {
1634         return ((this->First()  == rhs.First()) &&
1635                 (this->Second() == rhs.Second()));
1636     }
1637
1638     bool operator!=(const Pair& rhs) const
1639     {
1640         return !(*this == rhs);
1641     }
1642
1643 private:
1644     first_type  m_first;
1645     second_type m_second;
1646 };
1647
1648
1649 template < typename T, typename U >
1650 Pair< T, U > MakePair( T const & t, U const & u )
1651 {
1652     SUPPORTS_DAC;
1653     return Pair< T, U >( t, u );
1654 }
1655
1656
1657 //*****************************************************************************
1658 // This class implements a dynamic array of structures for which the order of
1659 // the elements is unimportant.  This means that any item placed in the list
1660 // may be swapped to any other location in the list at any time.  If the order
1661 // of the items you place in the array is important, then use the CStructArray
1662 // class.
1663 //*****************************************************************************
1664
1665 template <class T,
1666           int iGrowInc,
1667           class ALLOCATOR>
1668 class CUnorderedArrayWithAllocator
1669 {
1670     int         m_iCount;               // # of elements used in the list.
1671     int         m_iSize;                // # of elements allocated in the list.
1672 public:
1673 #ifndef DACCESS_COMPILE
1674     T           *m_pTable;              // Pointer to the list of elements.
1675 #else
1676     TADDR        m_pTable;              // Pointer to the list of elements.
1677 #endif
1678
1679 public:
1680
1681 #ifndef DACCESS_COMPILE
1682
1683     CUnorderedArrayWithAllocator() :
1684         m_iCount(0),
1685         m_iSize(0),
1686         m_pTable(NULL)
1687     {
1688         LIMITED_METHOD_CONTRACT;
1689     }
1690     ~CUnorderedArrayWithAllocator()
1691     {
1692         LIMITED_METHOD_CONTRACT;
1693         // Free the chunk of memory.
1694         if (m_pTable != NULL)
1695             ALLOCATOR::Free(this, m_pTable);
1696     }
1697
1698     void Clear()
1699     {
1700         WRAPPER_NO_CONTRACT;
1701         m_iCount = 0;
1702         if (m_iSize > iGrowInc)
1703         {
1704             T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc);
1705             if (tmp) {
1706                 ALLOCATOR::Free(this, m_pTable);
1707                 m_pTable = tmp;
1708                 m_iSize = iGrowInc;
1709             }
1710         }
1711     }
1712
1713     void Clear(int iFirst, int iCount)
1714     {
1715         WRAPPER_NO_CONTRACT;
1716         int     iSize;
1717
1718         if (iFirst + iCount < m_iCount)
1719             memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount)));
1720
1721         m_iCount -= iCount;
1722
1723         iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0);
1724         if (m_iSize > iGrowInc && iSize < m_iSize)
1725         {
1726             T *tmp = ALLOCATOR::AllocNoThrow(this, iSize);
1727             if (tmp) {
1728                 memcpy (tmp, m_pTable, iSize * sizeof(T));
1729                 delete [] m_pTable;
1730                 m_pTable = tmp;
1731                 m_iSize = iSize;
1732             }
1733         }
1734         _ASSERTE(m_iCount <= m_iSize);
1735     }
1736
1737     T *Table()
1738     {
1739         LIMITED_METHOD_CONTRACT;
1740         return (m_pTable);
1741     }
1742
1743     T *Append()
1744     {
1745         CONTRACTL {
1746             NOTHROW;
1747         } CONTRACTL_END;
1748
1749         // The array should grow, if we can't fit one more element into the array.
1750         if (m_iSize <= m_iCount && GrowNoThrow() == NULL)
1751             return (NULL);
1752         return (&m_pTable[m_iCount++]);
1753     }
1754
1755     T *AppendThrowing()
1756     {
1757         CONTRACTL {
1758             THROWS;
1759         } CONTRACTL_END;
1760
1761         // The array should grow, if we can't fit one more element into the array.
1762         if (m_iSize <= m_iCount)
1763             Grow();
1764         return (&m_pTable[m_iCount++]);
1765     }
1766
1767     void Delete(const T &Entry)
1768     {
1769         LIMITED_METHOD_CONTRACT;
1770         --m_iCount;
1771         for (int i=0; i <= m_iCount; ++i)
1772             if (m_pTable[i] == Entry)
1773             {
1774                 m_pTable[i] = m_pTable[m_iCount];
1775                 return;
1776             }
1777
1778         // Just in case we didn't find it.
1779         ++m_iCount;
1780     }
1781
1782     void DeleteByIndex(int i)
1783     {
1784         LIMITED_METHOD_CONTRACT;
1785         --m_iCount;
1786         m_pTable[i] = m_pTable[m_iCount];
1787     }
1788
1789     void Swap(int i,int j)
1790     {
1791         LIMITED_METHOD_CONTRACT;
1792         T       tmp;
1793
1794         if (i == j)
1795             return;
1796         tmp = m_pTable[i];
1797         m_pTable[i] = m_pTable[j];
1798         m_pTable[j] = tmp;
1799     }
1800
1801 #else
1802
1803     TADDR Table()
1804     {
1805         LIMITED_METHOD_CONTRACT;
1806         SUPPORTS_DAC;
1807         return (m_pTable);
1808     }
1809
1810     void EnumMemoryRegions(void)
1811     {
1812         SUPPORTS_DAC;
1813         DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T));
1814     }
1815
1816 #endif // #ifndef DACCESS_COMPILE
1817
1818     USHORT Count()
1819     {
1820         LIMITED_METHOD_CONTRACT;
1821         SUPPORTS_DAC;
1822         _ASSERTE(FitsIn<USHORT>(m_iCount));
1823         return static_cast<USHORT>(m_iCount);
1824     }
1825
1826 private:
1827     T *Grow();
1828     T *GrowNoThrow();
1829 };
1830
1831
1832 #ifndef DACCESS_COMPILE
1833
1834 //*****************************************************************************
1835 // Increase the size of the array.
1836 //*****************************************************************************
1837 template <class T,
1838           int iGrowInc,
1839           class ALLOCATOR>
1840 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::GrowNoThrow()  // NULL if can't grow.
1841 {
1842     WRAPPER_NO_CONTRACT;
1843     T       *pTemp;
1844
1845     // try to allocate memory for reallocation.
1846     if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL)
1847         return (NULL);
1848     memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1849     ALLOCATOR::Free(this, m_pTable);
1850     m_pTable = pTemp;
1851     m_iSize += iGrowInc;
1852     _ASSERTE(m_iSize > 0);
1853     return (pTemp);
1854 }
1855
1856 template <class T,
1857           int iGrowInc,
1858           class ALLOCATOR>
1859 T *CUnorderedArrayWithAllocator<T,iGrowInc,ALLOCATOR>::Grow()  // exception if can't grow.
1860 {
1861     WRAPPER_NO_CONTRACT;
1862     T       *pTemp;
1863
1864     // try to allocate memory for reallocation.
1865     pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc);
1866     memcpy (pTemp, m_pTable, m_iSize*sizeof(T));
1867     ALLOCATOR::Free(this, m_pTable);
1868     m_pTable = pTemp;
1869     m_iSize += iGrowInc;
1870     _ASSERTE(m_iSize > 0);
1871     return (pTemp);
1872 }
1873
1874 #endif // #ifndef DACCESS_COMPILE
1875
1876
1877 template <class T>
1878 class CUnorderedArray__Allocator
1879 {
1880 public:
1881
1882     static T *AllocThrowing (void*, int nElements)
1883     {
1884         return new T[nElements];
1885     }
1886
1887     static T *AllocNoThrow (void*, int nElements)
1888     {
1889         return new (nothrow) T[nElements];
1890     }
1891
1892     static void Free (void*, T *pTable)
1893     {
1894         delete [] pTable;
1895     }
1896 };
1897
1898
1899 template <class T,int iGrowInc>
1900 class CUnorderedArray : public CUnorderedArrayWithAllocator<T, iGrowInc, CUnorderedArray__Allocator<T> >
1901 {
1902 public:
1903
1904     CUnorderedArray ()
1905     {
1906         LIMITED_METHOD_CONTRACT;
1907     }
1908 };
1909
1910
1911 //Used by the debugger.  Included here in hopes somebody else might, too
1912 typedef CUnorderedArray<SIZE_T, 17> SIZE_T_UNORDERED_ARRAY;
1913
1914
1915 //*****************************************************************************
1916 // This class implements a dynamic array of structures for which the insert
1917 // order is important.  Inserts will slide all elements after the location
1918 // down, deletes slide all values over the deleted item.  If the order of the
1919 // items in the array is unimportant to you, then CUnorderedArray may provide
1920 // the same feature set at lower cost.
1921 //*****************************************************************************
1922 class CStructArray
1923 {
1924     BYTE        *m_pList;               // Pointer to the list of elements.
1925     int         m_iCount;               // # of elements used in the list.
1926     int         m_iSize;                // # of elements allocated in the list.
1927     int         m_iGrowInc;             // Growth increment.
1928     short       m_iElemSize;            // Size of an array element.
1929     bool        m_bFree;                // true if data is automatically maintained.
1930
1931 public:
1932     CStructArray(short iElemSize, short iGrowInc = 1) :
1933         m_pList(NULL),
1934         m_iCount(0),
1935         m_iSize(0),
1936         m_iGrowInc(iGrowInc),
1937         m_iElemSize(iElemSize),
1938         m_bFree(true)
1939     {
1940         LIMITED_METHOD_CONTRACT;
1941     }
1942     ~CStructArray()
1943     {
1944         WRAPPER_NO_CONTRACT;
1945         Clear();
1946     }
1947
1948     void *Insert(int iIndex);
1949     void *InsertThrowing(int iIndex);
1950     void *Append();
1951     void *AppendThrowing();
1952     int AllocateBlock(int iCount);
1953     void AllocateBlockThrowing(int iCount);
1954     void Delete(int iIndex);
1955     void *Ptr()
1956     {
1957         LIMITED_METHOD_CONTRACT;
1958         return (m_pList);
1959     }
1960     void *Get(int iIndex)
1961     {
1962         WRAPPER_NO_CONTRACT;
1963         _ASSERTE(iIndex < m_iCount);
1964         return ((void *) ((size_t) Ptr() + (iIndex * m_iElemSize)));
1965     }
1966     int Size()
1967     {
1968         LIMITED_METHOD_CONTRACT;
1969         return (m_iCount * m_iElemSize);
1970     }
1971     int Count()
1972     {
1973         LIMITED_METHOD_CONTRACT;
1974         return (m_iCount);
1975     }
1976     void Clear();
1977     void ClearCount()
1978     {
1979         LIMITED_METHOD_CONTRACT;
1980         m_iCount = 0;
1981     }
1982
1983     void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1)
1984     {
1985         LIMITED_METHOD_CONTRACT;
1986         m_iElemSize = iElemSize;
1987         m_iGrowInc = (short) iGrowInc;
1988         m_pList = (BYTE*)pList;
1989         m_iCount = iCount;
1990         m_iSize = iSize;
1991         m_bFree = false;
1992     }
1993
1994 private:
1995     void Grow(int iCount);
1996 };
1997
1998
1999 //*****************************************************************************
2000 // This template simplifies access to a CStructArray by removing void * and
2001 // adding some operator overloads.
2002 //*****************************************************************************
2003 template <class T>
2004 class CDynArray : public CStructArray
2005 {
2006 public:
2007     CDynArray(short iGrowInc=16) :
2008         CStructArray(sizeof(T), iGrowInc)
2009     {
2010         LIMITED_METHOD_CONTRACT;
2011     }
2012
2013     T *Insert(int iIndex)
2014     {
2015         WRAPPER_NO_CONTRACT;
2016         return ((T *)CStructArray::Insert((int)iIndex));
2017     }
2018
2019     T *InsertThrowing(int iIndex)
2020     {
2021         WRAPPER_NO_CONTRACT;
2022         return ((T *)CStructArray::InsertThrowing((int)iIndex));
2023     }
2024
2025     T *Append()
2026     {
2027         WRAPPER_NO_CONTRACT;
2028         return ((T *)CStructArray::Append());
2029     }
2030
2031     T *AppendThrowing()
2032     {
2033         WRAPPER_NO_CONTRACT;
2034         return ((T *)CStructArray::AppendThrowing());
2035     }
2036
2037     T *Ptr()
2038     {
2039         WRAPPER_NO_CONTRACT;
2040         return ((T *)CStructArray::Ptr());
2041     }
2042
2043     T *Get(int iIndex)
2044     {
2045         WRAPPER_NO_CONTRACT;
2046         return (Ptr() + iIndex);
2047     }
2048     T &operator[](int iIndex)
2049     {
2050         WRAPPER_NO_CONTRACT;
2051         return (*(Ptr() + iIndex));
2052     }
2053     int ItemIndex(T *p)
2054     {
2055         WRAPPER_NO_CONTRACT;
2056         return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T));
2057     }
2058     void Move(int iFrom, int iTo)
2059     {
2060         WRAPPER_NO_CONTRACT;
2061         T       tmp;
2062
2063         _ASSERTE(iFrom >= 0 && iFrom < Count() &&
2064                  iTo >= 0 && iTo < Count());
2065
2066         tmp = *(Ptr() + iFrom);
2067         if (iTo > iFrom)
2068             memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T));
2069         else
2070             memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T));
2071         *(Ptr() + iTo) = tmp;
2072     }
2073 };
2074
2075 // Some common arrays.
2076 typedef CDynArray<int> INTARRAY;
2077 typedef CDynArray<short> SHORTARRAY;
2078 typedef CDynArray<int> LONGARRAY;
2079 typedef CDynArray<USHORT> USHORTARRAY;
2080 typedef CDynArray<ULONG> ULONGARRAY;
2081 typedef CDynArray<BYTE> BYTEARRAY;
2082 typedef CDynArray<mdToken> TOKENARRAY;
2083
2084 template <class T> class CStackArray : public CStructArray
2085 {
2086 public:
2087     CStackArray(short iGrowInc=4) :
2088         CStructArray(sizeof(T), iGrowInc),
2089         m_curPos(0)
2090     {
2091         LIMITED_METHOD_CONTRACT;
2092     }
2093
2094     void Push(T p)
2095     {
2096         WRAPPER_NO_CONTRACT;
2097         // We should only inc m_curPos after we grow the array.
2098         T *pT = (T *)CStructArray::InsertThrowing(m_curPos);
2099         m_curPos ++;
2100         *pT = p;
2101     }
2102
2103     T * Pop()
2104     {
2105         WRAPPER_NO_CONTRACT;
2106         T * retPtr;
2107
2108         _ASSERTE(m_curPos > 0);
2109
2110         retPtr = (T *)CStructArray::Get(m_curPos-1);
2111         CStructArray::Delete(m_curPos--);
2112
2113         return (retPtr);
2114     }
2115
2116     int Count()
2117     {
2118         LIMITED_METHOD_CONTRACT;
2119         return(m_curPos);
2120     }
2121
2122 private:
2123     int m_curPos;
2124 };
2125
2126
2127 //*****************************************************************************
2128 // This template manages a list of free entries by their 0 based offset.  By
2129 // making it a template, you can use whatever size free chain will match your
2130 // maximum count of items.  -1 is reserved.
2131 //*****************************************************************************
2132 template <class T> class TFreeList
2133 {
2134 public:
2135     void Init(
2136         T           *rgList,
2137         int         iCount)
2138     {
2139         LIMITED_METHOD_CONTRACT;
2140         // Save off values.
2141         m_rgList = rgList;
2142         m_iCount = iCount;
2143         m_iNext = 0;
2144
2145         // Init free list.
2146         int i;
2147         for (i=0;  i<iCount - 1;  i++)
2148             m_rgList[i] = i + 1;
2149         m_rgList[i] = (T) -1;
2150     }
2151
2152     T GetFreeEntry()                        // Index of free item, or -1.
2153     {
2154         LIMITED_METHOD_CONTRACT;
2155         T           iNext;
2156
2157         if (m_iNext == (T) -1)
2158             return (-1);
2159
2160         iNext = m_iNext;
2161         m_iNext = m_rgList[m_iNext];
2162         return (iNext);
2163     }
2164
2165     void DelFreeEntry(T iEntry)
2166     {
2167         LIMITED_METHOD_CONTRACT;
2168         _ASSERTE(iEntry < m_iCount);
2169         m_rgList[iEntry] = m_iNext;
2170         m_iNext = iEntry;
2171     }
2172
2173     // This function can only be used when it is guaranteed that the free
2174     // array is contigous, for example, right after creation to quickly
2175     // get a range of items from the heap.
2176     void ReserveRange(int iCount)
2177     {
2178         LIMITED_METHOD_CONTRACT;
2179         _ASSERTE(iCount < m_iCount);
2180         _ASSERTE(m_iNext == 0);
2181         m_iNext = iCount;
2182     }
2183
2184 private:
2185     T           *m_rgList;              // List of free info.
2186     int         m_iCount;               // How many entries to manage.
2187     T           m_iNext;                // Next item to get.
2188 };
2189
2190
2191 //*****************************************************************************
2192 //*****************************************************************************
2193 template <class T> class CQuickSort
2194 {
2195 protected:
2196     T           *m_pBase;                   // Base of array to sort.
2197 private:
2198     SSIZE_T     m_iCount;                   // How many items in array.
2199     SSIZE_T     m_iElemSize;                // Size of one element.
2200 public:
2201     CQuickSort(
2202         T           *pBase,                 // Address of first element.
2203         SSIZE_T     iCount) :               // How many there are.
2204         m_pBase(pBase),
2205         m_iCount(iCount),
2206         m_iElemSize(sizeof(T))
2207     {
2208         LIMITED_METHOD_DAC_CONTRACT;
2209     }
2210
2211 //*****************************************************************************
2212 // Call to sort the array.
2213 //*****************************************************************************
2214     inline void Sort()
2215     {
2216         WRAPPER_NO_CONTRACT;
2217         SortRange(0, m_iCount - 1);
2218     }
2219
2220 protected:
2221 //*****************************************************************************
2222 // Override this function to do the comparison.
2223 //*****************************************************************************
2224     virtual FORCEINLINE int Compare(        // -1, 0, or 1
2225         T           *psFirst,               // First item to compare.
2226         T           *psSecond)              // Second item to compare.
2227     {
2228         LIMITED_METHOD_DAC_CONTRACT;
2229         return (memcmp(psFirst, psSecond, sizeof(T)));
2230 //      return (::Compare(*psFirst, *psSecond));
2231     }
2232
2233     virtual FORCEINLINE void Swap(
2234         SSIZE_T     iFirst,
2235         SSIZE_T     iSecond)
2236     {
2237         LIMITED_METHOD_DAC_CONTRACT;
2238         if (iFirst == iSecond) return;
2239         T sTemp( m_pBase[iFirst] );
2240         m_pBase[iFirst] = m_pBase[iSecond];
2241         m_pBase[iSecond] = sTemp;
2242     }
2243
2244 private:
2245     inline void SortRange(
2246         SSIZE_T     iLeft,
2247         SSIZE_T     iRight)
2248     {
2249         WRAPPER_NO_CONTRACT;
2250         SSIZE_T     iLast;
2251         SSIZE_T     i;                      // loop variable.
2252         
2253         for (;;)
2254         {
2255             // if less than two elements you're done.
2256             if (iLeft >= iRight)
2257                 return;
2258             
2259             // ASSERT that we now have valid indicies.  This is statically provable
2260             // since this private function is only called with valid indicies,
2261             // and iLeft and iRight only converge towards eachother.  However,
2262             // PreFast can't detect this because it doesn't know about our callers.
2263             COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount);
2264             COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount);
2265             
2266             // The mid-element is the pivot, move it to the left.
2267             Swap(iLeft, (iLeft + iRight) / 2);
2268             iLast = iLeft;
2269             
2270             // move everything that is smaller than the pivot to the left.
2271             for (i = iLeft + 1; i <= iRight; i++)
2272             {
2273                 if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0)
2274                 {
2275                     Swap(i, ++iLast);
2276                 }
2277             }
2278             
2279             // Put the pivot to the point where it is in between smaller and larger elements.
2280             Swap(iLeft, iLast);
2281             
2282             // Sort each partition.
2283             SSIZE_T iLeftLast = iLast - 1;
2284             SSIZE_T iRightFirst = iLast + 1;
2285             if (iLeftLast - iLeft < iRight - iRightFirst)
2286             {   // Left partition is smaller, sort it recursively
2287                 SortRange(iLeft, iLeftLast);
2288                 // Tail call to sort the right (bigger) partition
2289                 iLeft = iRightFirst;
2290                 //iRight = iRight;
2291                 continue;
2292             }
2293             else
2294             {   // Right partition is smaller, sort it recursively
2295                 SortRange(iRightFirst, iRight);
2296                 // Tail call to sort the left (bigger) partition
2297                 //iLeft = iLeft;
2298                 iRight = iLeftLast;
2299                 continue;
2300             }
2301         }
2302     }
2303 };
2304
2305 //*****************************************************************************
2306 // Faster and simpler version of the binary search below.
2307 //*****************************************************************************
2308 template <class T>
2309 const T * BinarySearch(const T * pBase, int iCount, const T & find)
2310 {
2311     WRAPPER_NO_CONTRACT;
2312
2313     int iFirst = 0;
2314     int iLast  = iCount - 1;
2315
2316     // It is faster to use linear search once we get down to a small number of elements.
2317     while (iLast - iFirst > 10)
2318     {
2319         int iMid = (iLast + iFirst) / 2;
2320         
2321         if (find < pBase[iMid])
2322             iLast = iMid - 1;
2323         else
2324             iFirst = iMid;
2325     }
2326
2327     for (int i = iFirst; i <= iLast; i++)
2328     {
2329         if (find == pBase[i])
2330             return &pBase[i];
2331
2332         if (find < pBase[i])
2333             break;
2334     }
2335
2336     return NULL;
2337 }
2338
2339 //*****************************************************************************
2340 // This template encapsulates a binary search algorithm on the given type
2341 // of data.
2342 //*****************************************************************************
2343 template <class T> class CBinarySearch
2344 {
2345 private:
2346     const T     *m_pBase;                   // Base of array to sort.
2347     int         m_iCount;                   // How many items in array.
2348
2349 public:
2350     CBinarySearch(
2351         const T     *pBase,                 // Address of first element.
2352         int         iCount) :               // Value to find.
2353         m_pBase(pBase),
2354         m_iCount(iCount)
2355     {
2356         LIMITED_METHOD_CONTRACT;
2357     }
2358
2359 //*****************************************************************************
2360 // Searches for the item passed to ctor.
2361 //*****************************************************************************
2362     const T *Find(                          // Pointer to found item in array.
2363         const T     *psFind,                // The key to find.
2364         int         *piInsert = NULL)       // Index to insert at.
2365     {
2366         WRAPPER_NO_CONTRACT;
2367         int         iMid, iFirst, iLast;    // Loop control.
2368         int         iCmp;                   // Comparison.
2369
2370         iFirst = 0;
2371         iLast = m_iCount - 1;
2372         while (iFirst <= iLast)
2373         {
2374             iMid = (iLast + iFirst) / 2;
2375             iCmp = Compare(psFind, &m_pBase[iMid]);
2376             if (iCmp == 0)
2377             {
2378                 if (piInsert != NULL)
2379                     *piInsert = iMid;
2380                 return (&m_pBase[iMid]);
2381             }
2382             else if (iCmp < 0)
2383                 iLast = iMid - 1;
2384             else
2385                 iFirst = iMid + 1;
2386         }
2387         if (piInsert != NULL)
2388             *piInsert = iFirst;
2389         return (NULL);
2390     }
2391
2392 //*****************************************************************************
2393 // Override this function to do the comparison if a comparison operator is
2394 // not valid for your data type (such as a struct).
2395 //*****************************************************************************
2396     virtual int Compare(                    // -1, 0, or 1
2397         const T     *psFirst,               // Key you are looking for.
2398         const T     *psSecond)              // Item to compare to.
2399     {
2400         LIMITED_METHOD_CONTRACT;
2401         return (memcmp(psFirst, psSecond, sizeof(T)));
2402 //      return (::Compare(*psFirst, *psSecond));
2403     }
2404 };
2405
2406 //*****************************************************************************
2407 // The information that the hash table implementation stores at the beginning
2408 // of every record that can be but in the hash table.
2409 //*****************************************************************************
2410 typedef DPTR(struct HASHENTRY) PTR_HASHENTRY;
2411 struct HASHENTRY
2412 {
2413     ULONG      iPrev;                  // Previous bucket in the chain.
2414     ULONG      iNext;                  // Next bucket in the chain.
2415 };
2416
2417 typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY;
2418 struct FREEHASHENTRY : HASHENTRY
2419 {
2420     ULONG      iFree;
2421 };
2422
2423 //*****************************************************************************
2424 // Used by the FindFirst/FindNextEntry functions.  These api's allow you to
2425 // do a sequential scan of all entries.
2426 //*****************************************************************************
2427 struct HASHFIND
2428 {
2429     ULONG      iBucket;            // The next bucket to look in.
2430     ULONG      iNext;
2431 };
2432
2433
2434 //*****************************************************************************
2435 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2436 // The hashtable implementation that should be used instead is code:SHash.
2437 // If code:SHash does not work for you, talk to mailto:clrdeag.
2438 //*****************************************************************************
2439 // This is a class that implements a chain and bucket hash table.
2440 //
2441 // The data is actually supplied as an array of structures by the user of this class.
2442 // This allows the buckets to use small indices to point to the chain, instead of pointers.
2443 //
2444 // Each entry in the array contains a HASHENTRY structure immediately
2445 // followed by the key used to hash the structure.
2446 //
2447 // The HASHENTRY part of every structure is used to implement the chain of
2448 // entries in a single bucket.
2449 //
2450 // This implementation does not support rehashing the buckets if the table grows
2451 // to big.
2452 // @TODO: Fix this by adding an abstract function Hash() which must be implemented
2453 // by all clients.
2454 //
2455 //*****************************************************************************
2456 class CHashTable
2457 {
2458     friend class DebuggerRCThread; //RCthread actually needs access to
2459     //fields of derrived class DebuggerPatchTable
2460
2461 protected:
2462     TADDR       m_pcEntries;            // Pointer to the array of structs.
2463     ULONG      m_iEntrySize;           // Size of the structs.
2464
2465     ULONG      m_iBuckets;             // # of chains we are hashing into.
2466     PTR_ULONG  m_piBuckets;           // Ptr to the array of bucket chains.
2467
2468     INDEBUG(unsigned    m_maxSearch;)   // For evaluating perf characteristics
2469
2470     HASHENTRY *EntryPtr(ULONG iEntry)
2471     {
2472         LIMITED_METHOD_DAC_CONTRACT;
2473         return (PTR_HASHENTRY(m_pcEntries + (iEntry * m_iEntrySize)));
2474     }
2475
2476     ULONG     ItemIndex(HASHENTRY *p)
2477     {
2478         SUPPORTS_DAC;
2479         LIMITED_METHOD_CONTRACT;
2480         return (ULONG)((dac_cast<TADDR>(p) - m_pcEntries) / m_iEntrySize);
2481     }
2482
2483
2484 public:
2485
2486     CHashTable(
2487         ULONG      iBuckets) :         // # of chains we are hashing into.
2488         m_pcEntries((TADDR)NULL),
2489         m_iBuckets(iBuckets)
2490     {
2491         LIMITED_METHOD_CONTRACT;
2492
2493         m_piBuckets = NULL;
2494
2495         INDEBUG(m_maxSearch = 0;)
2496     }
2497
2498     CHashTable() :         // # of chains we are hashing into.
2499         m_pcEntries((TADDR)NULL),
2500         m_iBuckets(5)
2501     {
2502         LIMITED_METHOD_CONTRACT;
2503
2504         m_piBuckets = NULL;
2505
2506         INDEBUG(m_maxSearch = 0;)
2507     }
2508
2509 #ifndef DACCESS_COMPILE
2510
2511     ~CHashTable()
2512     {
2513         LIMITED_METHOD_CONTRACT;
2514         if (m_piBuckets != NULL)
2515         {
2516             delete [] m_piBuckets;
2517             m_piBuckets = NULL;
2518         }
2519     }
2520
2521 //*****************************************************************************
2522 // This is the second part of construction where we do all of the work that
2523 // can fail.  We also take the array of structs here because the calling class
2524 // presumably needs to allocate it in its NewInit.
2525 //*****************************************************************************
2526     HRESULT NewInit(                    // Return status.
2527         BYTE        *pcEntries,         // Array of structs we are managing.
2528         ULONG      iEntrySize);        // Size of the entries.
2529
2530 //*****************************************************************************
2531 // This can be called to change the pointer to the table that the hash table
2532 // is managing.  You might call this if (for example) you realloc the size
2533 // of the table and its pointer is different.
2534 //*****************************************************************************
2535     void SetTable(
2536         BYTE        *pcEntries)         // Array of structs we are managing.
2537     {
2538         LIMITED_METHOD_CONTRACT;
2539         m_pcEntries = (TADDR)pcEntries;
2540     }
2541
2542 //*****************************************************************************
2543 // Clear the hash table as if there were nothing in it.
2544 //*****************************************************************************
2545     void Clear()
2546     {
2547         LIMITED_METHOD_CONTRACT;
2548         _ASSERTE(m_piBuckets != NULL);
2549         memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG));
2550     }
2551
2552 //*****************************************************************************
2553 // Add the struct at the specified index in m_pcEntries to the hash chains.
2554 //*****************************************************************************
2555     BYTE *Add(                          // New entry.
2556         ULONG      iHash,              // Hash value of entry to add.
2557         ULONG      iIndex);            // Index of struct in m_pcEntries.
2558
2559 //*****************************************************************************
2560 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2561 //*****************************************************************************
2562     void Delete(
2563         ULONG      iHash,              // Hash value of entry to delete.
2564         ULONG      iIndex);            // Index of struct in m_pcEntries.
2565
2566     void Delete(
2567         ULONG      iHash,              // Hash value of entry to delete.
2568         HASHENTRY   *psEntry);          // The struct to delete.
2569
2570 //*****************************************************************************
2571 // The item at the specified index has been moved, update the previous and
2572 // next item.
2573 //*****************************************************************************
2574     void Move(
2575         ULONG      iHash,              // Hash value for the item.
2576         ULONG      iNew);              // New location.
2577
2578 #endif // #ifndef DACCESS_COMPILE
2579
2580 //*****************************************************************************
2581 // Return a boolean indicating whether or not this hash table has been inited.
2582 //*****************************************************************************
2583     int IsInited()
2584     {
2585         LIMITED_METHOD_CONTRACT;
2586         return (m_piBuckets != NULL);
2587     }
2588
2589 //*****************************************************************************
2590 // Search the hash table for an entry with the specified key value.
2591 //*****************************************************************************
2592     BYTE *Find(                         // Index of struct in m_pcEntries.
2593         ULONG      iHash,              // Hash value of the item.
2594         SIZE_T     key);               // The key to match.
2595
2596 //*****************************************************************************
2597 // Search the hash table for the next entry with the specified key value.
2598 //*****************************************************************************
2599     ULONG FindNext(                    // Index of struct in m_pcEntries.
2600         SIZE_T     key,                // The key to match.
2601         ULONG      iIndex);            // Index of previous match.
2602
2603 //*****************************************************************************
2604 // Returns the first entry in the first hash bucket and inits the search
2605 // struct.  Use the FindNextEntry function to continue walking the list.  The
2606 // return order is not gauranteed.
2607 //*****************************************************************************
2608     BYTE *FindFirstEntry(               // First entry found, or 0.
2609         HASHFIND    *psSrch)            // Search object.
2610     {
2611         WRAPPER_NO_CONTRACT;
2612         if (m_piBuckets == 0)
2613             return (0);
2614         psSrch->iBucket = 1;
2615         psSrch->iNext = m_piBuckets[0];
2616         return (FindNextEntry(psSrch));
2617     }
2618
2619 //*****************************************************************************
2620 // Returns the next entry in the list.
2621 //*****************************************************************************
2622     BYTE *FindNextEntry(                // The next entry, or0 for end of list.
2623         HASHFIND    *psSrch);           // Search object.
2624
2625 #ifdef DACCESS_COMPILE
2626     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags,
2627                            ULONG numEntries);
2628 #endif
2629
2630 protected:
2631     virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0;
2632 };
2633
2634
2635 class CNewData
2636 {
2637 public:
2638     static BYTE *Alloc(int iSize, int iMaxSize)
2639     {
2640         WRAPPER_NO_CONTRACT;
2641         return (new BYTE[iSize]);
2642     }
2643     static void Free(BYTE *pPtr, int iSize)
2644     {
2645         LIMITED_METHOD_CONTRACT;
2646         delete [] pPtr;
2647     }
2648     static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2649     {
2650         WRAPPER_NO_CONTRACT;
2651         BYTE *p;
2652         S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2653         //check for overflow
2654         if(newSize.IsOverflow())
2655             p = NULL;
2656         else
2657             p = new (nothrow) BYTE[newSize.Value()];
2658         if (p == 0) return (0);
2659         memcpy (p, pPtr, iCurSize);
2660         delete [] pPtr;
2661         pPtr = p;
2662         return pPtr;
2663     }
2664     static void Clean(BYTE * pData, int iSize)
2665     {
2666     }
2667     static int RoundSize(int iSize)
2668     {
2669         LIMITED_METHOD_CONTRACT;
2670         return (iSize);
2671     }
2672     static int GrowSize(int iCurSize)
2673     {
2674         LIMITED_METHOD_CONTRACT;
2675         int newSize = (3 * iCurSize) / 2;
2676         return (newSize < 256) ? 256 : newSize;
2677     }
2678 };
2679
2680 class CNewDataNoThrow
2681 {
2682 public:
2683     static BYTE *Alloc(int iSize, int iMaxSize)
2684     {
2685         WRAPPER_NO_CONTRACT;
2686         return (new (nothrow) BYTE[iSize]);
2687     }
2688     static void Free(BYTE *pPtr, int iSize)
2689     {
2690         LIMITED_METHOD_CONTRACT;
2691         delete [] pPtr;
2692     }
2693     static BYTE *Grow(BYTE *&pPtr, int iCurSize)
2694     {
2695         WRAPPER_NO_CONTRACT;
2696         BYTE *p;
2697         S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize));
2698         //check for overflow
2699         if(newSize.IsOverflow())
2700             p = NULL;
2701         else
2702             p = new (nothrow) BYTE[newSize.Value()];
2703         if (p == 0) return (0);
2704         memcpy (p, pPtr, iCurSize);
2705         delete [] pPtr;
2706         pPtr = p;
2707         return pPtr;
2708     }
2709     static void Clean(BYTE * pData, int iSize)
2710     {
2711     }
2712     static int RoundSize(int iSize)
2713     {
2714         LIMITED_METHOD_CONTRACT;
2715         return (iSize);
2716     }
2717     static int GrowSize(int iCurSize)
2718     {
2719         LIMITED_METHOD_CONTRACT;
2720         int newSize = (3 * iCurSize) / 2;
2721         return (newSize < 256) ? 256 : newSize;
2722     }
2723 };
2724
2725
2726 //*****************************************************************************
2727 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
2728 // The hashtable implementation that should be used instead is code:SHash.
2729 // If code:SHash does not work for you, talk to mailto:clrdeag.
2730 //*****************************************************************************
2731 // CHashTable expects the data to be in a single array - this is provided by
2732 // CHashTableAndData.
2733 // The array is allocated using the MemMgr type. CNewData and
2734 // CNewDataNoThrow can be used for this.
2735 //*****************************************************************************
2736 template <class MemMgr>
2737 class CHashTableAndData : public CHashTable
2738 {
2739 public:
2740     ULONG      m_iFree;                // Index into m_pcEntries[] of next available slot
2741     ULONG      m_iEntries;             // size of m_pcEntries[]
2742
2743 public:
2744
2745     CHashTableAndData() :
2746         CHashTable()
2747     {
2748         LIMITED_METHOD_CONTRACT;
2749     }
2750
2751     CHashTableAndData(
2752         ULONG      iBuckets) :         // # of chains we are hashing into.
2753         CHashTable(iBuckets)
2754     {
2755         LIMITED_METHOD_CONTRACT;
2756     }
2757
2758 #ifndef DACCESS_COMPILE
2759
2760     ~CHashTableAndData()
2761     {
2762         WRAPPER_NO_CONTRACT;
2763         if (m_pcEntries != NULL)
2764             MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize));
2765     }
2766
2767 //*****************************************************************************
2768 // This is the second part of construction where we do all of the work that
2769 // can fail.  We also take the array of structs here because the calling class
2770 // presumably needs to allocate it in its NewInit.
2771 //*****************************************************************************
2772     HRESULT NewInit(                    // Return status.
2773         ULONG      iEntries,           // # of entries.
2774         ULONG      iEntrySize,         // Size of the entries.
2775         int         iMaxSize);          // Max size of data.
2776
2777 //*****************************************************************************
2778 // Clear the hash table as if there were nothing in it.
2779 //*****************************************************************************
2780     void Clear()
2781     {
2782         WRAPPER_NO_CONTRACT;
2783         m_iFree = 0;
2784         InitFreeChain(0, m_iEntries);
2785         CHashTable::Clear();
2786     }
2787
2788 //*****************************************************************************
2789 // Grabs a slot for the new entry to be added.
2790 // The caller should fill in the non-HASHENTRY part of the returned slot
2791 //*****************************************************************************
2792     BYTE *Add(
2793         ULONG      iHash)              // Hash value of entry to add.
2794     {
2795         WRAPPER_NO_CONTRACT;
2796         FREEHASHENTRY *psEntry;
2797
2798         // Make the table bigger if necessary.
2799         if (m_iFree == UINT32_MAX && !Grow())
2800             return (NULL);
2801
2802         // Add the first entry from the free list to the hash chain.
2803         psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree);
2804         m_iFree = psEntry->iFree;
2805
2806         // If we're recycling memory, give our memory-allocator a chance to re-init it.
2807
2808         // Each entry is prefixed with a header - we don't want to trash that.
2809         SIZE_T cbHeader = sizeof(FREEHASHENTRY);
2810         MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader));
2811
2812         return ((BYTE *) psEntry);
2813     }
2814
2815 //*****************************************************************************
2816 // Delete the struct at the specified index in m_pcEntries from the hash chains.
2817 //*****************************************************************************
2818     void Delete(
2819         ULONG      iHash,              // Hash value of entry to delete.
2820         ULONG      iIndex)             // Index of struct in m_pcEntries.
2821     {
2822         WRAPPER_NO_CONTRACT;
2823         CHashTable::Delete(iHash, iIndex);
2824         ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree;
2825         m_iFree = iIndex;
2826     }
2827
2828     void Delete(
2829         ULONG      iHash,              // Hash value of entry to delete.
2830         HASHENTRY   *psEntry)           // The struct to delete.
2831     {
2832         WRAPPER_NO_CONTRACT;
2833         CHashTable::Delete(iHash, psEntry);
2834         ((FREEHASHENTRY *) psEntry)->iFree = m_iFree;
2835         m_iFree = ItemIndex(psEntry);
2836     }
2837
2838 #endif // #ifndef DACCESS_COMPILE
2839
2840     // This is a sad legacy workaround. The debugger's patch table (implemented as this
2841     // class) is shared across process. We publish the runtime offsets of
2842     // some key fields. Since those fields are private, we have to provide
2843     // accessors here. So if you're not using these functions, don't start.
2844     // We can hopefully remove them.
2845     // Note that we can't just make RCThread a friend of this class (we tried
2846     // originally) because the inheritence chain has a private modifier,
2847     // so DebuggerPatchTable::m_pcEntries is illegal.
2848     static SIZE_T helper_GetOffsetOfEntries()
2849     {
2850         LIMITED_METHOD_CONTRACT;
2851         return offsetof(CHashTableAndData, m_pcEntries);
2852     }
2853
2854     static SIZE_T helper_GetOffsetOfCount()
2855     {
2856         LIMITED_METHOD_CONTRACT;
2857         return offsetof(CHashTableAndData, m_iEntries);
2858     }
2859
2860 #ifdef DACCESS_COMPILE
2861     void EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
2862     {
2863         SUPPORTS_DAC;
2864         CHashTable::EnumMemoryRegions(flags, m_iEntries);
2865     }
2866 #endif
2867
2868 private:
2869     void InitFreeChain(ULONG iStart,ULONG iEnd);
2870     int Grow();
2871 };
2872
2873 #ifndef DACCESS_COMPILE
2874
2875 //*****************************************************************************
2876 // This is the second part of construction where we do all of the work that
2877 // can fail.  We also take the array of structs here because the calling class
2878 // presumably needs to allocate it in its NewInit.
2879 //*****************************************************************************
2880 template<class MemMgr>
2881 HRESULT CHashTableAndData<MemMgr>::NewInit(// Return status.
2882     ULONG      iEntries,               // # of entries.
2883     ULONG      iEntrySize,             // Size of the entries.
2884     int         iMaxSize)               // Max size of data.
2885 {
2886     WRAPPER_NO_CONTRACT;
2887     BYTE        *pcEntries;
2888     HRESULT     hr;
2889
2890
2891     // note that this function can throw because it depends on the <M>::Alloc
2892
2893     // Allocate the memory for the entries.
2894     if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize),
2895                                    MemMgr::RoundSize(iMaxSize))) == 0)
2896         return (E_OUTOFMEMORY);
2897     m_iEntries = iEntries;
2898
2899     // Init the base table.
2900     if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize)))
2901         MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize));
2902     else
2903     {
2904         // Init the free chain.
2905         m_iFree = 0;
2906         InitFreeChain(0, iEntries);
2907     }
2908     return (hr);
2909 }
2910
2911 //*****************************************************************************
2912 // Initialize a range of records such that they are linked together to be put
2913 // on the free chain.
2914 //*****************************************************************************
2915 template<class MemMgr>
2916 void CHashTableAndData<MemMgr>::InitFreeChain(
2917     ULONG      iStart,                 // Index to start initializing.
2918     ULONG      iEnd)                   // Index to stop initializing
2919 {
2920     LIMITED_METHOD_CONTRACT;
2921     BYTE* pcPtr;
2922     _ASSERTE(iEnd > iStart);
2923
2924     pcPtr = (BYTE*)m_pcEntries + iStart * m_iEntrySize;
2925     for (++iStart; iStart < iEnd; ++iStart)
2926     {
2927         ((FREEHASHENTRY *) pcPtr)->iFree = iStart;
2928         pcPtr += m_iEntrySize;
2929     }
2930     ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX;
2931 }
2932
2933 //*****************************************************************************
2934 // Attempt to increase the amount of space available for the record heap.
2935 //*****************************************************************************
2936 template<class MemMgr>
2937 int CHashTableAndData<MemMgr>::Grow()   // 1 if successful, 0 if not.
2938 {
2939     WRAPPER_NO_CONTRACT;
2940     int         iCurSize;               // Current size in bytes.
2941     int         iEntries;               // New # of entries.
2942
2943     _ASSERTE(m_pcEntries != NULL);
2944     _ASSERTE(m_iFree == UINT32_MAX);
2945
2946     // Compute the current size and new # of entries.
2947     S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize);
2948     if( iTotEntrySize.IsOverflow() )
2949     {
2950         _ASSERTE( !"CHashTableAndData overflow!" );
2951         return (0);
2952     }    
2953     iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() );
2954     iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize;
2955
2956     if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) )
2957     {
2958         _ASSERTE( !"CHashTableAndData overflow!" );
2959         return (0);
2960     }
2961
2962     // Try to expand the array.
2963     if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0)
2964         return (0);
2965
2966     // Init the newly allocated space.
2967     InitFreeChain(m_iEntries, iEntries);
2968     m_iFree = m_iEntries;
2969     m_iEntries = iEntries;
2970     return (1);
2971 }
2972
2973 #endif // #ifndef DACCESS_COMPILE
2974
2975 //*****************************************************************************
2976 //*****************************************************************************
2977
2978 inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data)
2979 {
2980     LIMITED_METHOD_DAC_CONTRACT;
2981     return ((currentHash << 5) + currentHash) ^ data;
2982 }
2983
2984 inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr)
2985 {
2986     WRAPPER_NO_CONTRACT;
2987     SUPPORTS_DAC;
2988     return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast<TADDR>(ptr))));
2989 }
2990
2991 inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c)
2992 {
2993     LIMITED_METHOD_DAC_CONTRACT;
2994
2995     /*
2996     lookup3.c, by Bob Jenkins, May 2006, Public Domain.
2997
2998     These are functions for producing 32-bit hashes for hash table lookup.
2999     hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() 
3000     are externally useful functions.  Routines to test the hash are included 
3001     if SELF_TEST is defined.  You can use this free for any purpose.  It's in
3002     the public domain.  It has no warranty.
3003     */
3004
3005     #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
3006     c ^= b; c -= rot32(b,14);
3007     a ^= c; a -= rot32(c,11);
3008     b ^= a; b -= rot32(a,25);
3009     c ^= b; c -= rot32(b,16);
3010     a ^= c; a -= rot32(c,4); 
3011     b ^= a; b -= rot32(a,14);
3012     c ^= b; c -= rot32(b,24);
3013
3014     return c;
3015 }
3016
3017 inline ULONG HashBytes(BYTE const *pbData, size_t iSize)
3018 {
3019     LIMITED_METHOD_CONTRACT;
3020     ULONG   hash = 5381;
3021
3022     BYTE const *pbDataEnd = pbData + iSize;
3023
3024     for (/**/ ; pbData < pbDataEnd; pbData++)
3025     {
3026         hash = ((hash << 5) + hash) ^ *pbData;
3027     }
3028     return hash;
3029 }
3030
3031 // Helper function for hashing a string char by char.
3032 inline ULONG HashStringA(LPCSTR szStr)
3033 {
3034     LIMITED_METHOD_CONTRACT;
3035     ULONG   hash = 5381;
3036     int     c;
3037
3038     while ((c = *szStr) != 0)
3039     {
3040         hash = ((hash << 5) + hash) ^ c;
3041         ++szStr;
3042     }
3043     return hash;
3044 }
3045
3046 inline ULONG HashString(LPCWSTR szStr)
3047 {
3048     LIMITED_METHOD_CONTRACT;
3049     ULONG   hash = 5381;
3050     int     c;
3051
3052     while ((c = *szStr) != 0)
3053     {
3054         hash = ((hash << 5) + hash) ^ c;
3055         ++szStr;
3056     }
3057     return hash;
3058 }
3059
3060 inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr)
3061 {
3062     LIMITED_METHOD_CONTRACT;
3063     ULONG   hash = 5381;
3064
3065     // hash the string two characters at a time
3066     ULONG *ptr = (ULONG *)szStr;
3067     
3068     // we assume that szStr is null-terminated
3069     _ASSERTE(cchStr <= wcslen(szStr));
3070     SIZE_T cDwordCount = (cchStr + 1) / 2;
3071
3072     for (SIZE_T i = 0; i < cDwordCount; i++)
3073     {
3074         hash = ((hash << 5) + hash) ^ ptr[i];
3075     }
3076
3077     return hash;
3078 }
3079
3080 // Case-insensitive string hash function.
3081 inline ULONG HashiStringA(LPCSTR szStr)
3082 {
3083     LIMITED_METHOD_CONTRACT;
3084     ULONG   hash = 5381;
3085     while (*szStr != 0)
3086     {
3087         hash = ((hash << 5) + hash) ^ toupper(*szStr);
3088         szStr++;
3089     }
3090     return hash;
3091 }
3092
3093 // Case-insensitive string hash function.
3094 inline ULONG HashiString(LPCWSTR szStr)
3095 {
3096     LIMITED_METHOD_CONTRACT;
3097     ULONG   hash = 5381;
3098     while (*szStr != 0)
3099     {
3100         hash = ((hash << 5) + hash) ^ towupper(*szStr);
3101         szStr++;
3102     }
3103     return hash;
3104 }
3105
3106 // Case-insensitive string hash function.
3107 inline ULONG HashiStringN(LPCWSTR szStr, DWORD count)
3108 {
3109     LIMITED_METHOD_CONTRACT;
3110     ULONG   hash = 5381;
3111     while (*szStr != 0 && count--)
3112     {
3113         hash = ((hash << 5) + hash) ^ towupper(*szStr);
3114         szStr++;
3115     }
3116     return hash;
3117 }
3118
3119 // Case-insensitive string hash function when all of the
3120 // characters in the string are known to be below 0x80.
3121 // Knowing this is much more efficient than calling
3122 // towupper above.
3123 inline ULONG HashiStringKnownLower80(LPCWSTR szStr) {
3124     LIMITED_METHOD_CONTRACT;
3125     ULONG hash = 5381;
3126     int c;
3127     int mask = ~0x20;
3128     while ((c = *szStr)!=0) {
3129         //If we have a lowercase character, ANDing off 0x20
3130         //(mask) will make it an uppercase character.
3131         if (c>='a' && c<='z') {
3132             c&=mask;
3133         }
3134         hash = ((hash << 5) + hash) ^ c;
3135         ++szStr;
3136     }
3137     return hash;
3138 }
3139
3140 inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) {
3141     LIMITED_METHOD_CONTRACT;
3142     ULONG hash = 5381;
3143     int c;
3144     int mask = ~0x20;
3145     while ((c = *szStr) !=0 && count--) {
3146         //If we have a lowercase character, ANDing off 0x20
3147         //(mask) will make it an uppercase character.
3148         if (c>='a' && c<='z') {
3149             c&=mask;
3150         }
3151         hash = ((hash << 5) + hash) ^ c;
3152         ++szStr;
3153     }
3154     return hash;
3155 }
3156
3157 //*****************************************************************************
3158 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3159 // The hashtable implementation that should be used instead is code:SHash.
3160 // If code:SHash does not work for you, talk to mailto:clrdeag.
3161 //*****************************************************************************
3162 // This class implements a closed hashing table.  Values are hashed to a bucket,
3163 // and if that bucket is full already, then the value is placed in the next
3164 // free bucket starting after the desired target (with wrap around).  If the
3165 // table becomes 75% full, it is grown and rehashed to reduce lookups.  This
3166 // class is best used in a reltively small lookup table where hashing is
3167 // not going to cause many collisions.  By not having the collision chain
3168 // logic, a lot of memory is saved.
3169 //
3170 // The user of the template is required to supply several methods which decide
3171 // how each element can be marked as free, deleted, or used.  It would have
3172 // been possible to write this with more internal logic, but that would require
3173 // either (a) more overhead to add status on top of elements, or (b) hard
3174 // coded types like one for strings, one for ints, etc... This gives you the
3175 // flexibility of adding logic to your type.
3176 //*****************************************************************************
3177 class CClosedHashBase
3178 {
3179     BYTE *EntryPtr(int iEntry)
3180     {
3181         LIMITED_METHOD_CONTRACT;
3182         return (m_rgData + (iEntry * m_iEntrySize));
3183     }
3184
3185     BYTE *EntryPtr(int iEntry, BYTE *rgData)
3186     {
3187         LIMITED_METHOD_CONTRACT;
3188         return (rgData + (iEntry * m_iEntrySize));
3189     }
3190
3191 public:
3192     enum ELEMENTSTATUS
3193     {
3194         FREE,                               // Item is not in use right now.
3195         DELETED,                            // Item is deleted.
3196         USED                                // Item is in use.
3197     };
3198
3199     CClosedHashBase(
3200         int         iBuckets,               // How many buckets should we start with.
3201         int         iEntrySize,             // Size of an entry.
3202         bool        bPerfect) :             // true if bucket size will hash with no collisions.
3203         m_bPerfect(bPerfect),
3204         m_iBuckets(iBuckets),
3205         m_iEntrySize(iEntrySize),
3206         m_iCount(0),
3207         m_iCollisions(0),
3208         m_rgData(0)
3209     {
3210         LIMITED_METHOD_CONTRACT;
3211         m_iSize = iBuckets + 7;
3212     }
3213
3214     virtual ~CClosedHashBase()
3215     {
3216         WRAPPER_NO_CONTRACT;
3217         Clear();
3218     }
3219
3220     virtual void Clear()
3221     {
3222         LIMITED_METHOD_CONTRACT;
3223         delete [] m_rgData;
3224         m_iCount = 0;
3225         m_iCollisions = 0;
3226         m_rgData = 0;
3227     }
3228
3229 //*****************************************************************************
3230 // Accessors for getting at the underlying data.  Be careful to use Count()
3231 // only when you want the number of buckets actually used.
3232 //*****************************************************************************
3233
3234     int Count()
3235     {
3236         LIMITED_METHOD_CONTRACT;
3237         return (m_iCount);
3238     }
3239
3240     int Collisions()
3241     {
3242         LIMITED_METHOD_CONTRACT;
3243         return (m_iCollisions);
3244     }
3245
3246     int Buckets()
3247     {
3248         LIMITED_METHOD_CONTRACT;
3249         return (m_iBuckets);
3250     }
3251
3252     void SetBuckets(int iBuckets, bool bPerfect=false)
3253     {
3254         LIMITED_METHOD_CONTRACT;
3255         _ASSERTE(m_rgData == 0);
3256         m_iBuckets = iBuckets;
3257         m_iSize = m_iBuckets + 7;
3258         m_bPerfect = bPerfect;
3259     }
3260
3261     BYTE *Data()
3262     {
3263         LIMITED_METHOD_CONTRACT;
3264         return (m_rgData);
3265     }
3266
3267 //*****************************************************************************
3268 // Add a new item to hash table given the key value.  If this new entry
3269 // exceeds maximum size, then the table will grow and be re-hashed, which
3270 // may cause a memory error.
3271 //*****************************************************************************
3272     BYTE *Add(                              // New item to fill out on success.
3273         void        *pData)                 // The value to hash on.
3274     {
3275         WRAPPER_NO_CONTRACT;
3276         // If we haven't allocated any memory, or it is too small, fix it.
3277         if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect))
3278         {
3279             if (!ReHash())
3280                 return (0);
3281         }
3282
3283         return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount));
3284     }
3285
3286 //*****************************************************************************
3287 // Delete the given value.  This will simply mark the entry as deleted (in
3288 // order to keep the collision chain intact).  There is an optimization that
3289 // consecutive deleted entries leading up to a free entry are themselves freed
3290 // to reduce collisions later on.
3291 //*****************************************************************************
3292     void Delete(
3293         void        *pData);                // Key value to delete.
3294
3295
3296 //*****************************************************************************
3297 //  Callback function passed to DeleteLoop.
3298 //*****************************************************************************
3299     typedef BOOL (* DELETELOOPFUNC)(        // Delete current item?
3300          BYTE *pEntry,                      // Bucket entry to evaluate
3301          void *pCustomizer);                // User-defined value
3302
3303 //*****************************************************************************
3304 // Iterates over all active values, passing each one to pDeleteLoopFunc.
3305 // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer
3306 // and faster than using FindNext() and Delete().
3307 //*****************************************************************************
3308     void DeleteLoop(
3309         DELETELOOPFUNC pDeleteLoopFunc,     // Decides whether to delete item
3310         void *pCustomizer);                 // Extra value passed to deletefunc.
3311
3312
3313 //*****************************************************************************
3314 // Lookup a key value and return a pointer to the element if found.
3315 //*****************************************************************************
3316     BYTE *Find(                             // The item if found, 0 if not.
3317         void        *pData);                // The key to lookup.
3318
3319 //*****************************************************************************
3320 // Look for an item in the table.  If it isn't found, then create a new one and
3321 // return that.
3322 //*****************************************************************************
3323     BYTE *FindOrAdd(                        // The item if found, 0 if not.
3324         void        *pData,                 // The key to lookup.
3325         bool        &bNew);                 // true if created.
3326
3327 //*****************************************************************************
3328 // The following functions are used to traverse each used entry.  This code
3329 // will skip over deleted and free entries freeing the caller up from such
3330 // logic.
3331 //*****************************************************************************
3332     BYTE *GetFirst()                        // The first entry, 0 if none.
3333     {
3334         WRAPPER_NO_CONTRACT;
3335         int         i;                      // Loop control.
3336
3337         // If we've never allocated the table there can't be any to get.
3338         if (m_rgData == 0)
3339             return (0);
3340
3341         // Find the first one.
3342         for (i=0;  i<m_iSize;  i++)
3343         {
3344             if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3345                 return (EntryPtr(i));
3346         }
3347         return (0);
3348     }
3349
3350     BYTE *GetNext(BYTE *Prev)               // The next entry, 0 if done.
3351     {
3352         WRAPPER_NO_CONTRACT;
3353         int         i;                      // Loop control.
3354
3355         for (i = (int)(((size_t) Prev - (size_t) &m_rgData[0]) / m_iEntrySize) + 1; i<m_iSize;  i++)
3356         {
3357             if (Status(EntryPtr(i)) != FREE && Status(EntryPtr(i)) != DELETED)
3358                 return (EntryPtr(i));
3359         }
3360         return (0);
3361     }
3362
3363 private:
3364 //*****************************************************************************
3365 // Hash is called with a pointer to an element in the table.  You must override
3366 // this method and provide a hash algorithm for your element type.
3367 //*****************************************************************************
3368     virtual unsigned int Hash(             // The key value.
3369         void const  *pData)=0;              // Raw data to hash.
3370
3371 //*****************************************************************************
3372 // Compare is used in the typical memcmp way, 0 is eqaulity, -1/1 indicate
3373 // direction of miscompare.  In this system everything is always equal or not.
3374 //*****************************************************************************
3375     virtual unsigned int Compare(          // 0, -1, or 1.
3376         void const  *pData,                 // Raw key data on lookup.
3377         BYTE        *pElement)=0;           // The element to compare data against.
3378
3379 //*****************************************************************************
3380 // Return true if the element is free to be used.
3381 //*****************************************************************************
3382     virtual ELEMENTSTATUS Status(           // The status of the entry.
3383         BYTE        *pElement)=0;           // The element to check.
3384
3385 //*****************************************************************************
3386 // Sets the status of the given element.
3387 //*****************************************************************************
3388     virtual void SetStatus(
3389         BYTE        *pElement,              // The element to set status for.
3390         ELEMENTSTATUS eStatus)=0;           // New status.
3391
3392 //*****************************************************************************
3393 // Returns the internal key value for an element.
3394 //*****************************************************************************
3395     virtual void *GetKey(                   // The data to hash on.
3396         BYTE        *pElement)=0;           // The element to return data ptr for.
3397
3398 //*****************************************************************************
3399 // This helper actually does the add for you.
3400 //*****************************************************************************
3401     BYTE *DoAdd(void *pData, BYTE *rgData, int &iBuckets, int iSize,
3402                 int &iCollisions, int &iCount);
3403
3404 //*****************************************************************************
3405 // This function is called either to init the table in the first place, or
3406 // to rehash the table if we ran out of room.
3407 //*****************************************************************************
3408     bool ReHash();                          // true if successful.
3409
3410 //*****************************************************************************
3411 // Walk each item in the table and mark it free.
3412 //*****************************************************************************
3413     void InitFree(BYTE *ptr, int iSize)
3414     {
3415         WRAPPER_NO_CONTRACT;
3416         int         i;
3417         for (i=0;  i<iSize;  i++, ptr += m_iEntrySize)
3418             SetStatus(ptr, FREE);
3419     }
3420
3421 private:
3422     bool        m_bPerfect;                 // true if the table size guarantees
3423                                             //  no collisions.
3424     int         m_iBuckets;                 // How many buckets do we have.
3425     int         m_iEntrySize;               // Size of an entry.
3426     int         m_iSize;                    // How many elements can we have.
3427     int         m_iCount;                   // How many items cannot be used (NON free, i.e. USED+DELETED).
3428     int         m_iCollisions;              // How many have we had.
3429     BYTE        *m_rgData;                  // Data element list.
3430 };
3431
3432 //*****************************************************************************
3433 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3434 // The hashtable implementation that should be used instead is code:SHash.
3435 // If code:SHash does not work for you, talk to mailto:clrdeag.
3436 //*****************************************************************************
3437 template <class T> class CClosedHash : public CClosedHashBase
3438 {
3439 public:
3440     CClosedHash(
3441         int         iBuckets,               // How many buckets should we start with.
3442         bool        bPerfect=false) :       // true if bucket size will hash with no collisions.
3443         CClosedHashBase(iBuckets, sizeof(T), bPerfect)
3444     {
3445         WRAPPER_NO_CONTRACT;
3446     }
3447
3448     T &operator[](int iIndex)
3449     {
3450         WRAPPER_NO_CONTRACT;
3451         return ((T &) *(Data() + (iIndex * sizeof(T))));
3452     }
3453
3454
3455 //*****************************************************************************
3456 // Add a new item to hash table given the key value.  If this new entry
3457 // exceeds maximum size, then the table will grow and be re-hashed, which
3458 // may cause a memory error.
3459 //*****************************************************************************
3460     T *Add(                                 // New item to fill out on success.
3461         void        *pData)                 // The value to hash on.
3462     {
3463         WRAPPER_NO_CONTRACT;
3464         return ((T *) CClosedHashBase::Add(pData));
3465     }
3466
3467 //*****************************************************************************
3468 // Lookup a key value and return a pointer to the element if found.
3469 //*****************************************************************************
3470     T *Find(                                // The item if found, 0 if not.
3471         void        *pData)                 // The key to lookup.
3472     {
3473         WRAPPER_NO_CONTRACT;
3474         return ((T *) CClosedHashBase::Find(pData));
3475     }
3476
3477 //*****************************************************************************
3478 // Look for an item in the table.  If it isn't found, then create a new one and
3479 // return that.
3480 //*****************************************************************************
3481     T *FindOrAdd(                           // The item if found, 0 if not.
3482         void        *pData,                 // The key to lookup.
3483         bool        &bNew)                  // true if created.
3484     {
3485         WRAPPER_NO_CONTRACT;
3486         return ((T *) CClosedHashBase::FindOrAdd(pData, bNew));
3487     }
3488
3489
3490 //*****************************************************************************
3491 // The following functions are used to traverse each used entry.  This code
3492 // will skip over deleted and free entries freeing the caller up from such
3493 // logic.
3494 //*****************************************************************************
3495     T *GetFirst()                           // The first entry, 0 if none.
3496     {
3497         WRAPPER_NO_CONTRACT;
3498         return ((T *) CClosedHashBase::GetFirst());
3499     }
3500
3501     T *GetNext(T *Prev)                     // The next entry, 0 if done.
3502     {
3503         WRAPPER_NO_CONTRACT;
3504         return ((T *) CClosedHashBase::GetNext((BYTE *) Prev));
3505     }
3506 };
3507
3508
3509 //*****************************************************************************
3510 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3511 // The hashtable implementation that should be used instead is code:SHash.
3512 // If code:SHash does not work for you, talk to mailto:clrdeag.
3513 //*****************************************************************************
3514 // Closed hash with typed parameters.  The derived class is the second
3515 //  parameter to the template.  The derived class must implement:
3516 //    unsigned long Hash(const T *pData);
3517 //    unsigned long Compare(const T *p1, T *p2);
3518 //    ELEMENTSTATUS Status(T *pEntry);
3519 //    void SetStatus(T *pEntry, ELEMENTSTATUS s);
3520 //    void* GetKey(T *pEntry);
3521 //*****************************************************************************
3522 template<class T, class H>class CClosedHashEx : public CClosedHash<T>
3523 {
3524 public:
3525     CClosedHashEx(
3526         int         iBuckets,               // How many buckets should we start with.
3527         bool        bPerfect=false) :       // true if bucket size will hash with no collisions.
3528         CClosedHash<T> (iBuckets, bPerfect)
3529     {
3530         WRAPPER_NO_CONTRACT;
3531     }
3532
3533     unsigned int Hash(const void *pData)
3534     {
3535         WRAPPER_NO_CONTRACT;
3536         return static_cast<H*>(this)->Hash((const T*)pData);
3537     }
3538
3539     unsigned int Compare(const void *p1, BYTE *p2)
3540     {
3541         WRAPPER_NO_CONTRACT;
3542         return static_cast<H*>(this)->Compare((const T*)p1, (T*)p2);
3543     }
3544
3545     typename CClosedHash<T>::ELEMENTSTATUS Status(BYTE *p)
3546     {
3547         WRAPPER_NO_CONTRACT;
3548         return static_cast<H*>(this)->Status((T*)p);
3549     }
3550
3551     void SetStatus(BYTE *p, typename CClosedHash<T>::ELEMENTSTATUS s)
3552     {
3553         WRAPPER_NO_CONTRACT;
3554         static_cast<H*>(this)->SetStatus((T*)p, s);
3555     }
3556
3557     void* GetKey(BYTE *p)
3558     {
3559         WRAPPER_NO_CONTRACT;
3560         return static_cast<H*>(this)->GetKey((T*)p);
3561     }
3562 };
3563
3564
3565 //*****************************************************************************
3566 // IMPORTANT: This data structure is deprecated, please do not add any new uses.
3567 // The hashtable implementation that should be used instead is code:SHash.
3568 // If code:SHash does not work for you, talk to mailto:clrdeag.
3569 //*****************************************************************************
3570 // This template is another form of a closed hash table.  It handles collisions
3571 // through a linked chain.  To use it, derive your hashed item from HASHLINK
3572 // and implement the virtual functions required.  1.5 * ibuckets will be
3573 // allocated, with the extra .5 used for collisions.  If you add to the point
3574 // where no free nodes are available, the entire table is grown to make room.
3575 // The advantage to this system is that collisions are always directly known,
3576 // there either is one or there isn't.
3577 //*****************************************************************************
3578 struct HASHLINK
3579 {
3580     ULONG       iNext;                  // Offset for next entry.
3581 };
3582
3583 template <class T> class CChainedHash
3584 {
3585     friend class VerifyLayoutsMD;
3586 public:
3587     CChainedHash(int iBuckets=32) :
3588         m_rgData(0),
3589         m_iBuckets(iBuckets),
3590         m_iCount(0),
3591         m_iMaxChain(0),
3592         m_iFree(0)
3593     {
3594         LIMITED_METHOD_CONTRACT;
3595         m_iSize = iBuckets + (iBuckets / 2);
3596     }
3597
3598     ~CChainedHash()
3599     {
3600         LIMITED_METHOD_CONTRACT;
3601         if (m_rgData)
3602             delete [] m_rgData;
3603     }
3604
3605     void SetBuckets(int iBuckets)
3606     {
3607         LIMITED_METHOD_CONTRACT;
3608         _ASSERTE(m_rgData == 0);
3609         // if iBuckets==0, then we'll allocate a zero size array and AV on dereference.
3610         _ASSERTE(iBuckets > 0);
3611         m_iBuckets = iBuckets;
3612         m_iSize = iBuckets + (iBuckets / 2);
3613     }
3614
3615     T *Add(void const *pData)
3616     {
3617         WRAPPER_NO_CONTRACT;
3618         ULONG       iHash;
3619         int         iBucket;
3620         T           *pItem;
3621
3622         // Build the list if required.
3623         if (m_rgData == 0 || m_iFree == 0xffffffff)
3624         {
3625             if (!ReHash())
3626                 return (0);
3627         }
3628
3629         // Hash the item and pick a bucket.
3630         iHash = Hash(pData);
3631         iBucket = iHash % m_iBuckets;
3632
3633         // Use the bucket if it is free.
3634         if (InUse(&m_rgData[iBucket]) == false)
3635         {
3636             pItem = &m_rgData[iBucket];
3637             pItem->iNext = 0xffffffff;
3638         }
3639         // Else take one off of the free list for use.
3640         else
3641         {
3642             ULONG       iEntry;
3643
3644             // Pull an item from the free list.
3645             iEntry = m_iFree;
3646             pItem = &m_rgData[m_iFree];
3647             m_iFree = pItem->iNext;
3648
3649             // Link the new node in after the bucket.
3650             pItem->iNext = m_rgData[iBucket].iNext;
3651             m_rgData[iBucket].iNext = iEntry;
3652         }
3653         ++m_iCount;
3654         return (pItem);
3655     }
3656
3657     T *Find(void const *pData, bool bAddIfNew=false)
3658     {
3659         WRAPPER_NO_CONTRACT;
3660         ULONG       iHash;
3661         int         iBucket;
3662         T           *pItem;
3663
3664         // Check states for lookup.
3665         if (m_rgData == 0)
3666         {
3667             // If we won't be adding, then we are through.
3668             if (bAddIfNew == false)
3669                 return (0);
3670
3671             // Otherwise, create the table.
3672             if (!ReHash())
3673                 return (0);
3674         }
3675
3676         // Hash the item and pick a bucket.
3677         iHash = Hash(pData);
3678         iBucket = iHash % m_iBuckets;
3679
3680         // If it isn't in use, then there it wasn't found.
3681         if (!InUse(&m_rgData[iBucket]))
3682         {
3683             if (bAddIfNew == false)
3684                 pItem = 0;
3685             else
3686             {
3687                 pItem = &m_rgData[iBucket];
3688                 pItem->iNext = 0xffffffff;
3689                 ++m_iCount;
3690             }
3691         }
3692         // Scan the list for the one we want.
3693         else
3694         {
3695             ULONG iChain = 0;
3696             for (pItem=(T *) &m_rgData[iBucket];  pItem;  pItem=GetNext(pItem))
3697             {
3698                 if (Cmp(pData, pItem) == 0)
3699                     break;
3700                 ++iChain;
3701             }
3702
3703             if (!pItem && bAddIfNew)
3704             {
3705                 ULONG       iEntry;
3706
3707                 // Record maximum chain length.
3708                 if (iChain > m_iMaxChain)
3709                     m_iMaxChain = iChain;
3710
3711                 // Now need more room.
3712                 if (m_iFree == 0xffffffff)
3713                 {
3714                     if (!ReHash())
3715                         return (0);
3716                 }
3717
3718                 // Pull an item from the free list.
3719                 iEntry = m_iFree;
3720                 pItem = &m_rgData[m_iFree];
3721                 m_iFree = pItem->iNext;
3722
3723                 // Link the new node in after the bucket.
3724                 pItem->iNext = m_rgData[iBucket].iNext;
3725                 m_rgData[iBucket].iNext = iEntry;
3726                 ++m_iCount;
3727             }
3728         }
3729         return (pItem);
3730     }
3731
3732     int Count()
3733     {
3734         LIMITED_METHOD_CONTRACT;
3735         return (m_iCount);
3736     }
3737
3738     int Buckets()
3739     {
3740         LIMITED_METHOD_CONTRACT;
3741         return (m_iBuckets);
3742     }
3743
3744     ULONG MaxChainLength()
3745     {
3746         LIMITED_METHOD_CONTRACT;
3747         return (m_iMaxChain);
3748     }
3749
3750     virtual void Clear()
3751     {
3752         LIMITED_METHOD_CONTRACT;
3753         // Free up the memory.
3754         if (m_rgData)
3755         {
3756             delete [] m_rgData;
3757             m_rgData = 0;
3758         }
3759
3760         m_rgData = 0;
3761         m_iFree = 0;
3762         m_iCount = 0;
3763         m_iMaxChain = 0;
3764     }
3765
3766     virtual bool InUse(T *pItem)=0;
3767     virtual void SetFree(T *pItem)=0;
3768     virtual ULONG Hash(void const *pData)=0;
3769     virtual int Cmp(void const *pData, void *pItem)=0;
3770 private:
3771     inline T *GetNext(T *pItem)
3772     {
3773         LIMITED_METHOD_CONTRACT;
3774         if (pItem->iNext != 0xffffffff)
3775             return ((T *) &m_rgData[pItem->iNext]);
3776         return (0);
3777     }
3778
3779     bool ReHash()
3780     {
3781         WRAPPER_NO_CONTRACT;
3782         T           *rgTemp;
3783         int         iNewSize;
3784
3785         // If this is a first time allocation, then just malloc it.
3786         if (!m_rgData)
3787         {
3788             if ((m_rgData = new (nothrow) T[m_iSize]) == 0)
3789                 return (false);
3790
3791             int i;
3792             for (i=0;  i<m_iSize;  i++)
3793                 SetFree(&m_rgData[i]);
3794
3795             m_iFree = m_iBuckets;
3796             for (i=m_iBuckets;  i<m_iSize;  i++)
3797                 ((T *) &m_rgData[i])->iNext = i + 1;
3798             ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff;
3799             return (true);
3800         }
3801
3802         // Otherwise we need more room on the free chain, so allocate some.
3803         iNewSize = m_iSize + (m_iSize / 2);
3804
3805         // Allocate/realloc memory.
3806         if ((rgTemp = new (nothrow) T[iNewSize]) == 0)
3807             return (false);
3808
3809         memcpy (rgTemp,m_rgData,m_iSize*sizeof(T));
3810         delete [] m_rgData;
3811
3812         // Init new entries, save the new free chain, and reset internals.
3813         m_iFree = m_iSize;
3814         for (int i=m_iFree;  i<iNewSize;  i++)
3815         {
3816             SetFree(&rgTemp[i]);
3817             ((T *) &rgTemp[i])->iNext = i + 1;
3818         }
3819         ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff;
3820
3821         m_rgData = rgTemp;
3822         m_iSize = iNewSize;
3823         return (true);
3824     }
3825
3826 private:
3827     T           *m_rgData;              // Data to store items in.
3828     int         m_iBuckets;             // How many buckets we want.
3829     int         m_iSize;                // How many are allocated.
3830     int         m_iCount;               // How many are we using.
3831     ULONG       m_iMaxChain;            // Max chain length.
3832     ULONG       m_iFree;                // Free chain.
3833 };
3834
3835
3836 //*****************************************************************************
3837 //
3838 //********** String helper functions.
3839 //
3840 //*****************************************************************************
3841
3842 //*****************************************************************************
3843 // Checks if string length exceeds the specified limit
3844 //*****************************************************************************
3845 inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N)
3846 {
3847     LIMITED_METHOD_CONTRACT;
3848     unsigned i = 0;
3849     if(pstr)
3850     {
3851         for(i=0; (i < N)&&(pstr[i]); i++);
3852     }
3853     return (i >= N);
3854 }
3855
3856
3857 //*****************************************************************************
3858 // Class to parse a list of simple assembly names and then find a match
3859 //*****************************************************************************
3860
3861 class AssemblyNamesList
3862 {
3863     struct AssemblyName
3864     {
3865         LPUTF8          m_assemblyName;
3866         AssemblyName   *m_next;         // Next name
3867     };
3868
3869     AssemblyName       *m_pNames;       // List of names
3870
3871 public:
3872
3873     bool IsInList(LPCUTF8 assemblyName);
3874
3875     bool IsEmpty()
3876     {
3877         LIMITED_METHOD_CONTRACT;
3878         return m_pNames == 0;
3879     }
3880
3881     AssemblyNamesList(__in LPWSTR list);
3882     ~AssemblyNamesList();
3883 };
3884
3885 //*****************************************************************************
3886 // Class to parse a list of method names and then find a match
3887 //*****************************************************************************
3888
3889 struct CORINFO_SIG_INFO;
3890
3891 class MethodNamesListBase
3892 {
3893     struct MethodName
3894     {
3895         LPUTF8      methodName;     // NULL means wildcard
3896         LPUTF8      className;      // NULL means wildcard
3897         int         numArgs;        // number of args for the method, -1 is wildcard
3898         MethodName *next;           // Next name
3899     };
3900
3901     MethodName     *pNames;         // List of names
3902
3903     bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs);
3904
3905 public:
3906     void Init()
3907     {
3908         LIMITED_METHOD_CONTRACT;
3909         pNames = 0;
3910     }
3911
3912     void Init(__in __in_z LPWSTR list)
3913     {
3914         WRAPPER_NO_CONTRACT;
3915         pNames = 0;
3916         Insert(list);
3917     }
3918
3919     void Destroy();
3920
3921     void Insert(__in __in_z LPWSTR list);
3922
3923     bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
3924     bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
3925     bool IsEmpty()
3926     {
3927         LIMITED_METHOD_CONTRACT;
3928         return pNames == 0;
3929     }
3930 };
3931
3932 class MethodNamesList : public MethodNamesListBase
3933 {
3934 public:
3935     MethodNamesList()
3936     {
3937         WRAPPER_NO_CONTRACT;
3938         Init();
3939     }
3940
3941     MethodNamesList(__in LPWSTR list)
3942     {
3943         WRAPPER_NO_CONTRACT;
3944         Init(list);
3945     }
3946
3947     ~MethodNamesList()
3948     {
3949         WRAPPER_NO_CONTRACT;
3950         Destroy();
3951     }
3952 };
3953
3954 #if !defined(NO_CLRCONFIG)
3955
3956 /**************************************************************************/
3957 /* simple wrappers around the REGUTIL and MethodNameList routines that make
3958    the lookup lazy */
3959
3960 /* to be used as static variable - no constructor/destructor, assumes zero
3961    initialized memory */
3962
3963 class ConfigDWORD
3964 {
3965 public:
3966     //
3967     // NOTE: The following function is deprecated; use the CLRConfig class instead. 
3968     // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h.
3969     // 
3970     inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0)
3971     {
3972         WRAPPER_NO_CONTRACT;
3973         // make sure that the memory was zero initialized
3974         _ASSERTE(m_inited == 0 || m_inited == 1);
3975
3976         if (!m_inited) init_DontUse_(keyName, defaultVal);
3977         return m_value;
3978     }
3979     inline DWORD val(const CLRConfig::ConfigDWORDInfo & info)
3980     {
3981         WRAPPER_NO_CONTRACT;
3982         // make sure that the memory was zero initialized
3983         _ASSERTE(m_inited == 0 || m_inited == 1);
3984
3985         if (!m_inited) init(info);
3986         return m_value;
3987     }
3988
3989 private:
3990     void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0);
3991     void init(const CLRConfig::ConfigDWORDInfo & info);
3992
3993 private:
3994     DWORD  m_value;
3995     BYTE m_inited;
3996 };
3997
3998 /**************************************************************************/
3999 class ConfigString
4000 {
4001 public:
4002     inline LPWSTR val(const CLRConfig::ConfigStringInfo & info)
4003     {
4004         WRAPPER_NO_CONTRACT;
4005         // make sure that the memory was zero initialized
4006         _ASSERTE(m_inited == 0 || m_inited == 1);
4007
4008         if (!m_inited) init(info);
4009         return m_value;
4010     }
4011
4012     bool isInitialized()
4013     {
4014         WRAPPER_NO_CONTRACT;
4015
4016         // make sure that the memory was zero initialized
4017         _ASSERTE(m_inited == 0 || m_inited == 1);
4018
4019         return m_inited == 1;
4020     }
4021
4022 private:
4023     void init(const CLRConfig::ConfigStringInfo & info);
4024
4025 private:
4026     LPWSTR m_value;
4027     BYTE m_inited;
4028 };
4029
4030 /**************************************************************************/
4031 class ConfigMethodSet
4032 {
4033 public:
4034     bool isEmpty()
4035     {
4036         WRAPPER_NO_CONTRACT;
4037         _ASSERTE(m_inited == 1);
4038         return m_list.IsEmpty();
4039     }
4040
4041     bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL);
4042     bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo);
4043
4044     inline void ensureInit(const CLRConfig::ConfigStringInfo & info)
4045     {
4046         WRAPPER_NO_CONTRACT;
4047         // make sure that the memory was zero initialized
4048         _ASSERTE(m_inited == 0 || m_inited == 1);
4049
4050         if (!m_inited) init(info);
4051     }
4052
4053 private:
4054     void init(const CLRConfig::ConfigStringInfo & info);
4055
4056 private:
4057     MethodNamesListBase m_list;
4058
4059     BYTE m_inited;
4060 };
4061
4062 #endif // !defined(NO_CLRCONFIG)
4063
4064 //*****************************************************************************
4065 // Convert a pointer to a string into a GUID.
4066 //*****************************************************************************
4067 HRESULT LPCSTRToGuid(                   // Return status.
4068     LPCSTR      szGuid,                 // String to convert.
4069     GUID        *psGuid);               // Buffer for converted GUID.
4070
4071 //*****************************************************************************
4072 // Convert a GUID into a pointer to a string
4073 //*****************************************************************************
4074 int GuidToLPWSTR(                  // Return status.
4075     GUID        Guid,                  // [IN] The GUID to convert.
4076     __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored
4077     DWORD       cchGuid);              // [IN] Size in wide chars of szGuid
4078
4079 //*****************************************************************************
4080 // Parse a Wide char string into a GUID
4081 //*****************************************************************************
4082 BOOL LPWSTRToGuid(
4083     GUID      * Guid,                         // [OUT] The GUID to fill in
4084     __in_ecount(cchGuid)   LPCWSTR szGuid,    // [IN] String to parse
4085     DWORD       cchGuid);                     // [IN] Count in wchars in string
4086
4087 typedef VPTR(class RangeList) PTR_RangeList;
4088
4089 class RangeList
4090 {
4091   public:
4092     VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList)
4093
4094 #ifndef DACCESS_COMPILE
4095     RangeList();
4096     ~RangeList();
4097 #else
4098     RangeList()
4099     {
4100         LIMITED_METHOD_CONTRACT;
4101     }
4102 #endif
4103
4104     // Wrappers to make the virtual calls DAC-safe.
4105     BOOL AddRange(const BYTE *start, const BYTE *end, void *id)
4106     {
4107         return this->AddRangeWorker(start, end, id);
4108     }
4109     
4110     void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL)
4111     {
4112         return this->RemoveRangesWorker(id, start, end);
4113     }
4114     
4115     BOOL IsInRange(TADDR address, TADDR *pID = NULL)
4116     {
4117         SUPPORTS_DAC;
4118     
4119         return this->IsInRangeWorker(address, pID);
4120     }
4121
4122 #ifndef DACCESS_COMPILE
4123
4124     // You can overload these two for synchronization (as LockedRangeList does)
4125     virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id);
4126     // If both "start" and "end" are NULL, then this method deletes all ranges with
4127     // the given id (i.e. the original behaviour).  Otherwise, it ignores the given
4128     // id and deletes all ranges falling in the region [start, end).
4129     virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL);
4130 #else
4131     virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id)
4132     {
4133         return TRUE;
4134     }
4135     virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { }
4136 #endif // !DACCESS_COMPILE
4137
4138     virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL);
4139
4140 #ifdef DACCESS_COMPILE
4141     void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4142 #endif
4143
4144     enum
4145     {
4146         RANGE_COUNT = 10
4147     };
4148
4149    
4150   private:
4151     struct Range
4152     {
4153         TADDR start;
4154         TADDR end;
4155         TADDR id;
4156     };
4157
4158     struct RangeListBlock
4159     {
4160         Range                ranges[RANGE_COUNT];
4161         DPTR(RangeListBlock) next;
4162
4163 #ifdef DACCESS_COMPILE
4164         void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags);
4165 #endif
4166
4167     };
4168
4169     void InitBlock(RangeListBlock *block);
4170
4171     RangeListBlock       m_starterBlock;
4172     DPTR(RangeListBlock) m_firstEmptyBlock;
4173     TADDR                m_firstEmptyRange;
4174 };
4175
4176
4177 //
4178 // A private function to do the equavilent of a CoCreateInstance in
4179 // cases where we can't make the real call. Use this when, for
4180 // instance, you need to create a symbol reader in the Runtime but
4181 // we're not CoInitialized. Obviously, this is only good for COM
4182 // objects for which CoCreateInstance is just a glorified
4183 // find-and-load-me operation.
4184 //
4185
4186 HRESULT FakeCoCreateInstanceEx(REFCLSID       rclsid,
4187                                LPCWSTR        wszDllPath,
4188                                REFIID         riid,
4189                                void **        ppv,
4190                                HMODULE *      phmodDll);
4191
4192 // Provided for backward compatibility and for code that doesn't need the HMODULE of the
4193 // DLL that was loaded to create the COM object.  See comment at implementation of
4194 // code:FakeCoCreateInstanceEx for more details.
4195 inline HRESULT FakeCoCreateInstance(REFCLSID   rclsid,
4196                                     REFIID     riid,
4197                                     void **    ppv)
4198 {
4199     CONTRACTL
4200     {
4201         NOTHROW;
4202     }
4203     CONTRACTL_END;
4204
4205     return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL);
4206 };
4207
4208 HRESULT FakeCoCallDllGetClassObject(REFCLSID       rclsid,
4209                                LPCWSTR        wszDllPath,
4210                                REFIID riid,
4211                                void **        ppv,
4212                                HMODULE *      phmodDll);
4213
4214 //*****************************************************************************
4215 // Gets the directory based on the location of the module. This routine
4216 // is called at COR setup time. Set is called during EEStartup and by the
4217 // MetaData dispenser.
4218 //*****************************************************************************
4219 HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength);
4220 LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL);
4221
4222 //*****************************************************************************
4223 // This function validates the given Method/Field/Standalone signature. (util.cpp)
4224 //*****************************************************************************
4225 struct IMDInternalImport;
4226 HRESULT validateTokenSig(
4227     mdToken             tk,                     // [IN] Token whose signature needs to be validated.
4228     PCCOR_SIGNATURE     pbSig,                  // [IN] Signature.
4229     ULONG               cbSig,                  // [IN] Size in bytes of the signature.
4230     DWORD               dwFlags,                // [IN] Method flags.
4231     IMDInternalImport*  pImport);               // [IN] Internal MD Import interface ptr
4232
4233 //*****************************************************************************
4234 // Determine the version number of the runtime that was used to build the
4235 // specified image. The pMetadata pointer passed in is the pointer to the
4236 // metadata contained in the image.
4237 //*****************************************************************************
4238 HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString);
4239 void  AdjustImageRuntimeVersion (SString* pVersion);
4240
4241 //*****************************************************************************
4242 // The registry keys and values that contain the information regarding
4243 // the default registered unmanaged debugger.
4244 //*****************************************************************************
4245 SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4246 SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications");
4247
4248 SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
4249 SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger");
4250 SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto");
4251 SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList");
4252
4253 BOOL GetRegistryLongValue(HKEY    hKeyParent,              // Parent key.
4254                           LPCWSTR szKey,                   // Key name to look at.
4255                           LPCWSTR szName,                  // Name of value to get.
4256                           long    *pValue,                 // Put value here, if found.
4257                           BOOL    fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64
4258
4259 HRESULT GetCurrentModuleFileName(SString& pBuffer);
4260
4261 //*****************************************************************************
4262 // Retrieve information regarding what registered default debugger
4263 //*****************************************************************************
4264 void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto);
4265 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto);
4266
4267 void TrimWhiteSpace(__inout_ecount(*pcch)  LPCWSTR *pwsz, __inout LPDWORD pcch);
4268
4269
4270 //*****************************************************************************
4271 // Convert a UTF8 string to Unicode, into a CQuickArray<WCHAR>.
4272 //*****************************************************************************
4273 HRESULT Utf2Quick(
4274     LPCUTF8     pStr,                   // The string to convert.
4275     CQuickArray<WCHAR> &rStr,           // The QuickArray<WCHAR> to convert it into.
4276     int         iCurLen);               // Inital characters in the array to leave (default 0).
4277
4278 //*****************************************************************************
4279 //  Extract the movl 64-bit unsigned immediate from an IA64 bundle
4280 //  (Format X2)
4281 //*****************************************************************************
4282 UINT64 GetIA64Imm64(UINT64 * pBundle);
4283 UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1);
4284
4285 //*****************************************************************************
4286 //  Deposit the movl 64-bit unsigned immediate into an IA64 bundle
4287 //  (Format X2)
4288 //*****************************************************************************
4289 void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64);
4290
4291 //*****************************************************************************
4292 //  Extract the IP-Relative signed 25-bit immediate from an IA64 bundle
4293 //  (Formats B1, B2 or B3)
4294 //  Note that due to branch target alignment requirements
4295 //       the lowest four bits in the result will always be zero.
4296 //*****************************************************************************
4297 INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot);
4298 INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot);
4299
4300 //*****************************************************************************
4301 //  Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle
4302 //  (Formats B1, B2 or B3)
4303 //  Note that due to branch target alignment requirements
4304 //       the lowest four bits are required to be zero.
4305 //*****************************************************************************
4306 void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25);
4307
4308 //*****************************************************************************
4309 //  Extract the IP-Relative signed 64-bit immediate from an IA64 bundle
4310 //  (Formats X3 or X4)
4311 //*****************************************************************************
4312 INT64 GetIA64Rel64(UINT64 * pBundle);
4313 INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1);
4314
4315 //*****************************************************************************
4316 //  Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle
4317 //  (Formats X3 or X4)
4318 //*****************************************************************************
4319 void PutIA64Rel64(UINT64 * pBundle, INT64 imm64);
4320
4321 //*****************************************************************************
4322 //  Extract the 32-bit immediate from movw/movt Thumb2 sequence
4323 //*****************************************************************************
4324 UINT32 GetThumb2Mov32(UINT16 * p);
4325
4326 //*****************************************************************************
4327 //  Deposit the 32-bit immediate into movw/movt Thumb2 sequence
4328 //*****************************************************************************
4329 void PutThumb2Mov32(UINT16 * p, UINT32 imm32);
4330
4331 //*****************************************************************************
4332 //  Extract the 24-bit rel offset from bl instruction
4333 //*****************************************************************************
4334 INT32 GetThumb2BlRel24(UINT16 * p);
4335
4336 //*****************************************************************************
4337 //  Extract the 24-bit rel offset from bl instruction
4338 //*****************************************************************************
4339 void PutThumb2BlRel24(UINT16 * p, INT32 imm24);
4340
4341 //*****************************************************************************
4342 //  Extract the PC-Relative offset from a b or bl instruction 
4343 //*****************************************************************************
4344 INT32 GetArm64Rel28(UINT32 * pCode);
4345
4346 //*****************************************************************************
4347 //  Extract the PC-Relative page address from an adrp instruction
4348 //*****************************************************************************
4349 INT32 GetArm64Rel21(UINT32 * pCode);
4350
4351 //*****************************************************************************
4352 //  Extract the page offset from an add instruction
4353 //*****************************************************************************
4354 INT32 GetArm64Rel12(UINT32 * pCode);
4355
4356 //*****************************************************************************
4357 //  Deposit the PC-Relative offset 'imm28' into a b or bl instruction 
4358 //*****************************************************************************
4359 void PutArm64Rel28(UINT32 * pCode, INT32 imm28);
4360
4361 //*****************************************************************************
4362 //  Deposit the PC-Relative page address 'imm21' into an adrp instruction
4363 //*****************************************************************************
4364 void PutArm64Rel21(UINT32 * pCode, INT32 imm21);
4365
4366 //*****************************************************************************
4367 //  Deposit the page offset 'imm12' into an add instruction
4368 //*****************************************************************************
4369 void PutArm64Rel12(UINT32 * pCode, INT32 imm12);
4370
4371 //*****************************************************************************
4372 // Returns whether the offset fits into bl instruction
4373 //*****************************************************************************
4374 inline bool FitsInThumb2BlRel24(INT32 imm24)
4375 {
4376     return ((imm24 << 7) >> 7) == imm24;
4377 }
4378
4379 //*****************************************************************************
4380 // Returns whether the offset fits into an Arm64 b or bl instruction
4381 //*****************************************************************************
4382 inline bool FitsInRel28(INT32 val32)
4383 {
4384     return (val32 >= -0x08000000) && (val32 < 0x08000000);
4385 }
4386
4387 //*****************************************************************************
4388 // Returns whether the offset fits into an Arm64 adrp instruction
4389 //*****************************************************************************
4390 inline bool FitsInRel21(INT32 val32)
4391 {
4392     return (val32 >= 0) && (val32 <= 0x001FFFFF);
4393 }
4394
4395 //*****************************************************************************
4396 // Returns whether the offset fits into an Arm64 add instruction
4397 //*****************************************************************************
4398 inline bool FitsInRel12(INT32 val32)
4399 {
4400     return (val32 >= 0) && (val32 <= 0x00000FFF);
4401 }
4402
4403 //*****************************************************************************
4404 // Returns whether the offset fits into an Arm64 b or bl instruction
4405 //*****************************************************************************
4406 inline bool FitsInRel28(INT64 val64)
4407 {
4408     return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL);
4409 }
4410
4411 //*****************************************************************************
4412 // Splits a command line into argc/argv lists, using the VC7 parsing rules.
4413 // This functions interface mimics the CommandLineToArgvW api.
4414 // If function fails, returns NULL.
4415 // If function suceeds, call delete [] on return pointer when done.
4416 //*****************************************************************************
4417 LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs);
4418
4419 //
4420 // TEB access can be dangerous when using fibers because a fiber may
4421 // run on multiple threads.  If the TEB pointer is retrieved and saved
4422 // and then a fiber is moved to a different thread, when it accesses
4423 // the saved TEB pointer, it will be looking at the TEB state for a
4424 // different fiber.
4425 //
4426 // These accessors serve the purpose of retrieving information from the
4427 // TEB in a manner that ensures that the current fiber will not switch
4428 // threads while the access is occuring.
4429 //
4430 class ClrTeb
4431 {
4432 public:
4433 #if defined(FEATURE_PAL)
4434
4435     // returns pointer that uniquely identifies the fiber
4436     static void* GetFiberPtrId()
4437     {
4438         LIMITED_METHOD_CONTRACT;
4439         // not fiber for FEATURE_PAL - use the regular thread ID
4440         return (void *)(size_t)GetCurrentThreadId();
4441     }
4442
4443     static void* InvalidFiberPtrId()
4444     {
4445         return NULL;
4446     }
4447
4448     static void* GetStackBase()
4449     {
4450         return PAL_GetStackBase();
4451     }
4452
4453     static void* GetStackLimit()
4454     {
4455         return PAL_GetStackLimit();
4456     }
4457
4458 #else // !FEATURE_PAL
4459
4460     // returns pointer that uniquely identifies the fiber
4461     static void* GetFiberPtrId()
4462     {
4463         LIMITED_METHOD_CONTRACT;
4464         // stackbase is the unique fiber identifier
4465         return NtCurrentTeb()->NtTib.StackBase;
4466     }
4467
4468     static void* GetStackBase()
4469     {
4470         LIMITED_METHOD_CONTRACT;
4471         return NtCurrentTeb()->NtTib.StackBase;
4472     }
4473
4474     static void* GetStackLimit()
4475     {
4476         LIMITED_METHOD_CONTRACT;
4477         return NtCurrentTeb()->NtTib.StackLimit;
4478     }
4479
4480     // Please don't start to use this method unless you absolutely have to.
4481     // The reason why this is added is for WIN64 to support LEGACY PE-style TLS
4482     // variables.  On X86 it is supported by the JIT compilers themselves.  On
4483     // WIN64 we build more logic into the JIT helper for accessing fields.
4484     static void* GetLegacyThreadLocalStoragePointer()
4485     {
4486         LIMITED_METHOD_CONTRACT;
4487         return NtCurrentTeb()->ThreadLocalStoragePointer;
4488     }
4489
4490     static void* GetOleReservedPtr()
4491     {
4492         LIMITED_METHOD_CONTRACT;
4493         return NtCurrentTeb()->ReservedForOle;
4494     }
4495
4496     static void* GetProcessEnvironmentBlock()
4497     {
4498         LIMITED_METHOD_CONTRACT;
4499         return NtCurrentTeb()->ProcessEnvironmentBlock;
4500     }
4501
4502
4503     static void* InvalidFiberPtrId()
4504     {
4505         return (void*) 1;
4506     }
4507 #endif // !FEATURE_PAL
4508 };
4509
4510 #if !defined(DACCESS_COMPILE)
4511
4512 // check if current thread is a GC thread (concurrent or server)
4513 inline BOOL IsGCSpecialThread ()
4514 {
4515     STATIC_CONTRACT_NOTHROW;
4516     STATIC_CONTRACT_GC_NOTRIGGER;
4517     STATIC_CONTRACT_MODE_ANY;
4518     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4519
4520     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC);
4521 }
4522
4523 // check if current thread is a Gate thread
4524 inline BOOL IsGateSpecialThread ()
4525 {
4526     STATIC_CONTRACT_NOTHROW;
4527     STATIC_CONTRACT_GC_NOTRIGGER;
4528     STATIC_CONTRACT_MODE_ANY;
4529
4530     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate);
4531 }
4532
4533 // check if current thread is a Timer thread
4534 inline BOOL IsTimerSpecialThread ()
4535 {
4536     STATIC_CONTRACT_NOTHROW;
4537     STATIC_CONTRACT_GC_NOTRIGGER;
4538     STATIC_CONTRACT_MODE_ANY;
4539
4540     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer);
4541 }
4542
4543 // check if current thread is a debugger helper thread
4544 inline BOOL IsDbgHelperSpecialThread ()
4545 {
4546     STATIC_CONTRACT_NOTHROW;
4547     STATIC_CONTRACT_GC_NOTRIGGER;
4548     STATIC_CONTRACT_MODE_ANY;
4549
4550     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper);
4551 }
4552
4553 // check if current thread is a debugger helper thread
4554 inline BOOL IsETWRundownSpecialThread ()
4555 {
4556     STATIC_CONTRACT_NOTHROW;
4557     STATIC_CONTRACT_GC_NOTRIGGER;
4558     STATIC_CONTRACT_MODE_ANY;
4559
4560     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread);
4561 }
4562
4563 // check if current thread is a generic instantiation lookup compare thread
4564 inline BOOL IsGenericInstantiationLookupCompareThread ()
4565 {
4566     STATIC_CONTRACT_NOTHROW;
4567     STATIC_CONTRACT_GC_NOTRIGGER;
4568     STATIC_CONTRACT_MODE_ANY;
4569
4570     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare);
4571 }
4572
4573 // check if current thread is a thread which is performing shutdown
4574 inline BOOL IsShutdownSpecialThread ()
4575 {
4576     STATIC_CONTRACT_NOTHROW;
4577     STATIC_CONTRACT_GC_NOTRIGGER;
4578     STATIC_CONTRACT_MODE_ANY;
4579
4580     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown);
4581 }
4582
4583 inline BOOL IsThreadPoolIOCompletionSpecialThread ()
4584 {
4585     STATIC_CONTRACT_NOTHROW;
4586     STATIC_CONTRACT_GC_NOTRIGGER;
4587     STATIC_CONTRACT_MODE_ANY;
4588
4589     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion);
4590 }
4591
4592 inline BOOL IsThreadPoolWorkerSpecialThread ()
4593 {
4594     STATIC_CONTRACT_NOTHROW;
4595     STATIC_CONTRACT_GC_NOTRIGGER;
4596     STATIC_CONTRACT_MODE_ANY;
4597
4598     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker);
4599 }
4600
4601 inline BOOL IsWaitSpecialThread ()
4602 {
4603     STATIC_CONTRACT_NOTHROW;
4604     STATIC_CONTRACT_GC_NOTRIGGER;
4605     STATIC_CONTRACT_MODE_ANY;
4606
4607     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait);
4608 }
4609
4610 // check if current thread is a thread which is performing shutdown
4611 inline BOOL IsSuspendEEThread ()
4612 {
4613     STATIC_CONTRACT_NOTHROW;
4614     STATIC_CONTRACT_GC_NOTRIGGER;
4615     STATIC_CONTRACT_MODE_ANY;
4616
4617     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE);
4618 }
4619
4620 inline BOOL IsFinalizerThread ()
4621 {
4622     STATIC_CONTRACT_NOTHROW;
4623     STATIC_CONTRACT_GC_NOTRIGGER;
4624     STATIC_CONTRACT_MODE_ANY;
4625
4626     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer);
4627 }
4628
4629 inline BOOL IsADUnloadHelperThread ()
4630 {
4631     STATIC_CONTRACT_NOTHROW;
4632     STATIC_CONTRACT_GC_NOTRIGGER;
4633     STATIC_CONTRACT_MODE_ANY;
4634
4635     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ADUnloadHelper);
4636 }
4637
4638 inline BOOL IsShutdownHelperThread ()
4639 {
4640     STATIC_CONTRACT_NOTHROW;
4641     STATIC_CONTRACT_GC_NOTRIGGER;
4642     STATIC_CONTRACT_MODE_ANY;
4643
4644     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper);
4645 }
4646
4647 inline BOOL IsProfilerAttachThread ()
4648 {
4649     STATIC_CONTRACT_NOTHROW;
4650     STATIC_CONTRACT_GC_NOTRIGGER;
4651     STATIC_CONTRACT_MODE_ANY;
4652
4653     return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach);
4654 }
4655
4656 // set specical type for current thread
4657 inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag)
4658 {
4659     STATIC_CONTRACT_NOTHROW;
4660     STATIC_CONTRACT_GC_NOTRIGGER;
4661     STATIC_CONTRACT_MODE_ANY;
4662     STATIC_CONTRACT_SO_TOLERANT;
4663
4664     ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag));
4665 }
4666
4667 // clear specical type for current thread
4668 inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag)
4669 {
4670     STATIC_CONTRACT_NOTHROW;
4671     STATIC_CONTRACT_GC_NOTRIGGER;
4672     STATIC_CONTRACT_MODE_ANY;
4673
4674     ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag));
4675 }
4676
4677 #endif //!DACCESS_COMPILE
4678
4679 #ifdef DACCESS_COMPILE
4680 #define SET_THREAD_TYPE_STACKWALKER(pThread)
4681 #define CLEAR_THREAD_TYPE_STACKWALKER()
4682 #else   // DACCESS_COMPILE
4683 #define SET_THREAD_TYPE_STACKWALKER(pThread)   ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread)
4684 #define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL)
4685 #endif  // DACCESS_COMPILE
4686
4687 inline BOOL IsStackWalkerThread()
4688 {
4689     STATIC_CONTRACT_NOTHROW;
4690     STATIC_CONTRACT_GC_NOTRIGGER;
4691     STATIC_CONTRACT_MODE_ANY;
4692     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
4693
4694 #if defined(DACCESS_COMPILE)
4695     return FALSE;
4696 #else
4697     return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL;
4698 #endif
4699 }
4700
4701 inline BOOL IsGCThread ()
4702 {
4703     STATIC_CONTRACT_NOTHROW;
4704     STATIC_CONTRACT_GC_NOTRIGGER;
4705     STATIC_CONTRACT_MODE_ANY;
4706     STATIC_CONTRACT_SUPPORTS_DAC;
4707     STATIC_CONTRACT_SO_TOLERANT;
4708
4709 #if !defined(DACCESS_COMPILE)
4710     return IsGCSpecialThread () || IsSuspendEEThread ();
4711 #else
4712     return FALSE;
4713 #endif
4714 }
4715
4716 class ClrFlsThreadTypeSwitch
4717 {
4718 public:
4719     ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag)
4720     {
4721         STATIC_CONTRACT_NOTHROW;
4722         STATIC_CONTRACT_GC_NOTRIGGER;
4723         STATIC_CONTRACT_MODE_ANY;
4724
4725 #ifndef DACCESS_COMPILE
4726         m_flag = flag;
4727         m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag);
4728
4729         // In debug builds, remember the full group of flags that were set at the time
4730         // the constructor was called.  This will be used in ASSERTs in the destructor
4731         INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType));
4732         
4733         if (!m_fPreviouslySet)
4734         {
4735             ClrFlsSetThreadType(flag);
4736         }
4737 #endif // DACCESS_COMPILE
4738     }
4739
4740     ~ClrFlsThreadTypeSwitch ()
4741     {
4742         STATIC_CONTRACT_NOTHROW;
4743         STATIC_CONTRACT_GC_NOTRIGGER;
4744         STATIC_CONTRACT_MODE_ANY;
4745
4746 #ifndef DACCESS_COMPILE
4747         // This holder should only be used to set (and thus restore) ONE thread type flag
4748         // at a time. If more than that one flag was modified since this holder was
4749         // instantiated, then this holder still restores only the flag it knows about. To
4750         // prevent confusion, assert if some other flag was modified, so the user doesn't
4751         // expect the holder to restore the entire original set of flags.
4752         // 
4753         // The expression below says that the only difference between the previous flag
4754         // group and the current flag group should be m_flag (or no difference at all, if
4755         // m_flag's state didn't actually change).
4756         _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag);
4757
4758         if (m_fPreviouslySet)
4759         {
4760             ClrFlsSetThreadType(m_flag);
4761         }
4762         else
4763         {
4764             ClrFlsClearThreadType(m_flag);
4765         }
4766 #endif // DACCESS_COMPILE
4767     }
4768
4769 private:
4770     TlsThreadTypeFlag m_flag;
4771     BOOL m_fPreviouslySet;
4772     INDEBUG(size_t m_nPreviousFlagGroup);
4773 };
4774
4775 class ClrFlsValueSwitch
4776 {
4777 public:
4778     ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value)
4779     {
4780         STATIC_CONTRACT_NOTHROW;
4781         STATIC_CONTRACT_GC_NOTRIGGER;
4782         STATIC_CONTRACT_MODE_ANY;
4783
4784 #ifndef DACCESS_COMPILE
4785         m_slot = slot;
4786         m_PreviousValue = ClrFlsGetValue(slot);
4787         ClrFlsSetValue(slot, value);
4788 #endif // DACCESS_COMPILE
4789     }
4790
4791     ~ClrFlsValueSwitch ()
4792     {
4793         STATIC_CONTRACT_NOTHROW;
4794         STATIC_CONTRACT_GC_NOTRIGGER;
4795         STATIC_CONTRACT_MODE_ANY;
4796
4797 #ifndef DACCESS_COMPILE
4798         ClrFlsSetValue(m_slot, m_PreviousValue);
4799 #endif // DACCESS_COMPILE
4800     }
4801
4802 private:
4803     PVOID m_PreviousValue;
4804     PredefinedTlsSlots m_slot;
4805 };
4806
4807 //*********************************************************************************
4808
4809 // When we're hosted, operations called by the host (such as Thread::YieldTask)
4810 // may not cause calls back into the host, as the host needs not be reentrant.
4811 // Use the following holder for code in which calls into the host are forbidden.
4812 // (If a call into the host is attempted nevertheless, an assert will fire.)
4813
4814 class ForbidCallsIntoHostOnThisThread
4815 {
4816 private:
4817     static Volatile<PVOID> s_pvOwningFiber;
4818
4819     FORCEINLINE static BOOL Enter(BOOL)
4820     {
4821         WRAPPER_NO_CONTRACT;
4822         return InterlockedCompareExchangePointer(
4823             &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL;
4824     }
4825
4826     FORCEINLINE static void Leave(BOOL)
4827     {
4828         LIMITED_METHOD_CONTRACT;
4829         s_pvOwningFiber = NULL;
4830     }
4831
4832 public:
4833     typedef ConditionalStateHolder<BOOL, ForbidCallsIntoHostOnThisThread::Enter, ForbidCallsIntoHostOnThisThread::Leave> Holder;
4834
4835     FORCEINLINE static BOOL CanThisThreadCallIntoHost()
4836     {
4837         WRAPPER_NO_CONTRACT;
4838         return s_pvOwningFiber != ClrTeb::GetFiberPtrId();
4839     }
4840 };
4841
4842 typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder;
4843
4844 FORCEINLINE BOOL CanThisThreadCallIntoHost()
4845 {
4846     WRAPPER_NO_CONTRACT;
4847     return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost();
4848 }
4849
4850 //*********************************************************************************
4851
4852 #include "contract.inl"
4853
4854 namespace util
4855 {
4856     //  compare adapters
4857     //  
4858     
4859     template < typename T >
4860     struct less
4861     {
4862         bool operator()( T const & first, T const & second ) const
4863         {
4864             return first < second;
4865         }
4866     };
4867
4868     template < typename T >
4869     struct greater
4870     {
4871         bool operator()( T const & first, T const & second ) const
4872         {
4873             return first > second;
4874         }
4875     };
4876     
4877
4878     //  sort adapters
4879     //
4880
4881     template< typename Iter, typename Pred >
4882     void sort( Iter begin, Iter end, Pred pred );
4883
4884     template< typename T, typename Pred >
4885     void sort( T * begin, T * end, Pred pred )
4886     {
4887         struct sort_helper : CQuickSort< T >
4888         {
4889             sort_helper( T * begin, T * end, Pred pred )
4890                 : CQuickSort< T >( begin, end - begin )
4891                 , m_pred( pred )
4892             {}
4893             
4894             virtual int Compare( T * first, T * second )
4895             {
4896                 return m_pred( *first, *second ) ? -1
4897                             : ( m_pred( *second, *first ) ? 1 : 0 );
4898             }
4899
4900             Pred m_pred;
4901         };
4902
4903         sort_helper sort_obj( begin, end, pred );
4904         sort_obj.Sort();
4905     }
4906     
4907
4908     template < typename Iter >
4909     void sort( Iter begin, Iter end );
4910
4911     template < typename T >
4912     void sort( T * begin, T * end )
4913     {
4914         util::sort( begin, end, util::less< T >() );
4915     }
4916
4917     
4918     // binary search adapters
4919     //
4920
4921     template < typename Iter, typename T, typename Pred >
4922     Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred );
4923
4924     template < typename T, typename Pred >
4925     T * lower_bound( T * begin, T * end, T const & val, Pred pred )
4926     {
4927         for (; begin != end; )
4928         {
4929             T * mid = begin + ( end - begin ) / 2;
4930             if ( pred( *mid, val ) )
4931                 begin = ++mid;
4932             else
4933                 end = mid;
4934         }
4935
4936         return begin;
4937     }
4938
4939
4940     template < typename Iter, typename T >
4941     Iter lower_bound( Iter begin, Iter end, T const & val );
4942
4943     template < typename T >
4944     T * lower_bound( T * begin, T * end, T const & val )
4945     {
4946         return util::lower_bound( begin, end, val, util::less< T >() );
4947     }
4948 }
4949
4950
4951 /* ------------------------------------------------------------------------ *
4952  * Overloaded operators for the executable heap
4953  * ------------------------------------------------------------------------ */
4954
4955 #ifndef FEATURE_PAL
4956
4957 struct CExecutable { int x; };
4958 extern const CExecutable executable;
4959
4960 void * __cdecl operator new(size_t n, const CExecutable&);
4961 void * __cdecl operator new[](size_t n, const CExecutable&);
4962 void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&);
4963 void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&);
4964
4965
4966 //
4967 // Executable heap delete to match the executable heap new above.
4968 //
4969 template<class T> void DeleteExecutable(T *p)
4970 {
4971     if (p != NULL)
4972     {
4973         p->T::~T();
4974
4975         ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p);
4976     }
4977 }
4978
4979 #endif // FEATURE_PAL
4980
4981 INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);)
4982
4983 BOOL NoGuiOnAssert();
4984 #ifdef _DEBUG
4985 VOID TerminateOnAssert();
4986 #endif // _DEBUG
4987
4988 class HighCharHelper {
4989 public:
4990     static inline BOOL IsHighChar(int c) {
4991         return (BOOL)HighCharTable[c];
4992     }
4993
4994 private:
4995     static const BYTE HighCharTable[];
4996 };
4997
4998
4999 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack);
5000
5001 FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); }
5002
5003 typedef Wrapper<BSTR, DoNothing, HolderSysFreeString> BSTRHolder;
5004
5005 BOOL FileExists(LPCWSTR filename);
5006
5007
5008 // a class for general x.x version info
5009 class MajorMinorVersionInfo
5010 {
5011 protected:
5012     WORD version[2];
5013     BOOL bInitialized;
5014 public:
5015     //cctors
5016     MajorMinorVersionInfo() 
5017     {
5018         LIMITED_METHOD_CONTRACT;
5019         bInitialized = FALSE;
5020         ZeroMemory(version,sizeof(version));
5021     };
5022
5023     MajorMinorVersionInfo(WORD wMajor, WORD wMinor) 
5024     {
5025         WRAPPER_NO_CONTRACT;
5026         Init(wMajor,wMinor);
5027     };
5028
5029     // getters
5030     BOOL IsInitialized() const 
5031     {
5032         LIMITED_METHOD_CONTRACT;
5033         return bInitialized;
5034     };
5035
5036     WORD Major() const 
5037     {
5038         LIMITED_METHOD_CONTRACT;
5039         return version[0];
5040     };
5041
5042     WORD Minor() const 
5043     {
5044         LIMITED_METHOD_CONTRACT;
5045         return version[1];
5046     };
5047
5048     // setters
5049     void Init(WORD wMajor, WORD wMinor) 
5050     {
5051         LIMITED_METHOD_CONTRACT;
5052         version[0]=wMajor;
5053         version[1]=wMinor;
5054         bInitialized=TRUE;
5055     };
5056 };
5057
5058 // CLR runtime version info in Major/Minor form
5059 class RUNTIMEVERSIONINFO : public MajorMinorVersionInfo 
5060 {
5061     static RUNTIMEVERSIONINFO notDefined;
5062 public:
5063     // cctors
5064     RUNTIMEVERSIONINFO() {};
5065
5066     RUNTIMEVERSIONINFO(WORD wMajor, WORD wMinor) : 
5067       MajorMinorVersionInfo(wMajor,wMinor){};  
5068
5069     // CLR version specific helpers
5070     BOOL IsPreWhidbey() const
5071     {
5072         WRAPPER_NO_CONTRACT;
5073         return (Major() == 1) && (Minor() <= 1); 
5074     }
5075
5076     static const RUNTIMEVERSIONINFO& NotApplicable()
5077     {
5078         LIMITED_METHOD_CONTRACT;
5079         return notDefined;
5080     }
5081 };
5082
5083
5084 // HMODULE_TGT represents a handle to a module in the target process.  In non-DAC builds this is identical
5085 // to HMODULE (HINSTANCE), which is the base address of the module.  In DAC builds this must be a target address,
5086 // and so is represented by TADDR. 
5087
5088 #ifdef DACCESS_COMPILE
5089 typedef TADDR HMODULE_TGT;
5090 #else
5091 typedef HMODULE HMODULE_TGT;
5092 #endif
5093
5094 BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip);
5095
5096 //----------------------------------------------------------------------------------------
5097 // The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical
5098 // callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call
5099 // InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime
5100 // calls a special initialization routine exposed by the loaded module with the callbacks,
5101 // which in turn calls InitUtilcode.
5102 //
5103 // This structure collects all of the critical callback info passed in InitUtilcode().
5104 // Note that one of them is GetCLRFunction() which is itself a gofer for many other
5105 // callbacks. If a callback fetch be safely deferred until we have TLS and stack probe
5106 // functionality running, it should be added to that function rather than this structure.
5107 // Things like IEE are here because that callback has to be set up before GetCLRFunction()
5108 // can be safely called.
5109 //----------------------------------------------------------------------------------------
5110 struct CoreClrCallbacks
5111 {
5112     typedef IExecutionEngine* (__stdcall * pfnIEE_t)();
5113     typedef HRESULT (__stdcall * pfnGetCORSystemDirectory_t)(SString& pbuffer);
5114     typedef void* (__stdcall * pfnGetCLRFunction_t)(LPCSTR functionName);
5115
5116     HINSTANCE                   m_hmodCoreCLR;
5117     pfnIEE_t                    m_pfnIEE;
5118     pfnGetCORSystemDirectory_t  m_pfnGetCORSystemDirectory;
5119     pfnGetCLRFunction_t         m_pfnGetCLRFunction;
5120 };
5121
5122
5123 // For DAC, we include this functionality only when EH SxS is enabled.
5124
5125 //----------------------------------------------------------------------------------------
5126 // CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback
5127 // pointers it needs.
5128 //----------------------------------------------------------------------------------------
5129 VOID InitUtilcode(const CoreClrCallbacks &cccallbacks);
5130 CoreClrCallbacks const & GetClrCallbacks();
5131
5132 //----------------------------------------------------------------------------------------
5133 // Stuff below is for utilcode.lib eyes only.
5134 //----------------------------------------------------------------------------------------
5135
5136 // Stores callback pointers provided by InitUtilcode().
5137 extern CoreClrCallbacks g_CoreClrCallbacks;
5138
5139 // Throws up a helpful dialog if InitUtilcode() wasn't called.
5140 #ifdef _DEBUG
5141 void OnUninitializedCoreClrCallbacks();
5142 #define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks()
5143 #else  //_DEBUG
5144 #define VALIDATECORECLRCALLBACKS()
5145 #endif //_DEBUG
5146
5147
5148 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
5149
5150 // Corrupting Exception limited support for outside the VM folder
5151 BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
5152
5153 #endif // FEATURE_CORRUPTING_EXCEPTIONS
5154
5155
5156 BOOL IsV2RuntimeLoaded(void);
5157
5158 namespace UtilCode
5159 {
5160     // These are type-safe versions of Interlocked[Compare]Exchange
5161     // They avoid invoking struct cast operations via reinterpreting
5162     // the struct's address as a LONG* or LONGLONG* and dereferencing it.
5163     // 
5164     // If we had a global ::operator & (unary), we would love to use that
5165     // to ensure we were not also accidentally getting a structs's provided
5166     // operator &. TODO: probe with a static_assert?
5167
5168     template <typename T, int SIZE = sizeof(T)>
5169     struct InterlockedCompareExchangeHelper;
5170
5171     template <typename T>
5172     struct InterlockedCompareExchangeHelper<T, sizeof(LONG)>
5173     {
5174         static inline T InterlockedExchange(
5175             T volatile * target,
5176             T            value)
5177         {
5178             static_assert_no_msg(sizeof(T) == sizeof(LONG));
5179             LONG res = ::InterlockedExchange(
5180                 reinterpret_cast<LONG volatile *>(target),
5181                 *reinterpret_cast<LONG *>(/*::operator*/&(value)));
5182             return *reinterpret_cast<T*>(&res);
5183         }
5184
5185         static inline T InterlockedCompareExchange(
5186             T volatile * destination,
5187             T            exchange,
5188             T            comparand)
5189         {
5190             static_assert_no_msg(sizeof(T) == sizeof(LONG));
5191             LONG res = ::InterlockedCompareExchange(
5192                 reinterpret_cast<LONG volatile *>(destination),
5193                 *reinterpret_cast<LONG*>(/*::operator*/&(exchange)),
5194                 *reinterpret_cast<LONG*>(/*::operator*/&(comparand)));
5195             return *reinterpret_cast<T*>(&res);
5196         }
5197     };
5198  
5199     template <typename T>
5200     struct InterlockedCompareExchangeHelper<T, sizeof(LONGLONG)>
5201     {
5202         static inline T InterlockedExchange(
5203             T volatile * target,
5204             T            value)
5205         {
5206             static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5207             LONGLONG res = ::InterlockedExchange64(
5208                 reinterpret_cast<LONGLONG volatile *>(target),
5209                 *reinterpret_cast<LONGLONG *>(/*::operator*/&(value)));
5210             return *reinterpret_cast<T*>(&res);
5211         }
5212
5213         static inline T InterlockedCompareExchange(
5214             T volatile * destination,
5215             T            exchange,
5216             T            comparand)
5217         {
5218             static_assert_no_msg(sizeof(T) == sizeof(LONGLONG));
5219             LONGLONG res = ::InterlockedCompareExchange64(
5220                 reinterpret_cast<LONGLONG volatile *>(destination),
5221                 *reinterpret_cast<LONGLONG*>(/*::operator*/&(exchange)),
5222                 *reinterpret_cast<LONGLONG*>(/*::operator*/&(comparand)));
5223             return *reinterpret_cast<T*>(&res);
5224         }
5225     };
5226 }
5227  
5228 template <typename T>
5229 inline T InterlockedExchangeT(
5230     T volatile * target,
5231     T            value)
5232 {
5233     return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedExchange(
5234         target, value);
5235 }
5236
5237 template <typename T>
5238 inline T InterlockedCompareExchangeT(
5239     T volatile * destination,
5240     T            exchange,
5241     T            comparand)
5242 {
5243     return ::UtilCode::InterlockedCompareExchangeHelper<T>::InterlockedCompareExchange(
5244         destination, exchange, comparand);
5245 }
5246
5247 // Pointer variants for Interlocked[Compare]ExchangePointer
5248 // If the underlying type is a const type, we have to remove its constness
5249 // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments.
5250 template <typename T>
5251 inline T* InterlockedExchangeT(
5252     T* volatile * target,
5253     T*            value)
5254 {
5255     //STATIC_ASSERT(value == 0);
5256     typedef typename std::remove_const<T>::type * non_const_ptr_t;
5257     return reinterpret_cast<T*>(InterlockedExchangePointer(
5258         reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(target)),
5259         reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(value))));
5260 }
5261
5262 template <typename T>
5263 inline T* InterlockedCompareExchangeT(
5264     T* volatile * destination,
5265     T*            exchange,
5266     T*            comparand)
5267 {
5268     //STATIC_ASSERT(exchange == 0);
5269     typedef typename std::remove_const<T>::type * non_const_ptr_t;
5270     return reinterpret_cast<T*>(InterlockedCompareExchangePointer(
5271         reinterpret_cast<PVOID volatile *>(const_cast<non_const_ptr_t volatile *>(destination)),
5272         reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(exchange)), 
5273         reinterpret_cast<PVOID>(const_cast<non_const_ptr_t>(comparand))));
5274 }
5275
5276 // NULL pointer variants of the above to avoid having to cast NULL
5277 // to the appropriate pointer type.
5278 template <typename T>
5279 inline T* InterlockedExchangeT(
5280     T* volatile *   target,
5281     int             value) // When NULL is provided as argument.
5282 {
5283     //STATIC_ASSERT(value == 0);
5284     return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5285 }
5286
5287 template <typename T>
5288 inline T* InterlockedCompareExchangeT(
5289     T* volatile *   destination,
5290     int             exchange,  // When NULL is provided as argument.
5291     T*              comparand)
5292 {
5293     //STATIC_ASSERT(exchange == 0);
5294     return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5295 }
5296
5297 template <typename T>
5298 inline T* InterlockedCompareExchangeT(
5299     T* volatile *   destination,
5300     T*              exchange,
5301     int             comparand) // When NULL is provided as argument.
5302 {
5303     //STATIC_ASSERT(comparand == 0);
5304     return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5305 }
5306
5307 // NULL pointer variants of the above to avoid having to cast NULL
5308 // to the appropriate pointer type.
5309 template <typename T>
5310 inline T* InterlockedExchangeT(
5311     T* volatile *  target,
5312     std::nullptr_t value) // When nullptr is provided as argument.
5313 {
5314     //STATIC_ASSERT(value == 0);
5315     return InterlockedExchangeT(target, reinterpret_cast<T*>(value));
5316 }
5317
5318 template <typename T>
5319 inline T* InterlockedCompareExchangeT(
5320     T* volatile *  destination,
5321     std::nullptr_t exchange,  // When nullptr is provided as argument.
5322     T*             comparand)
5323 {
5324     //STATIC_ASSERT(exchange == 0);
5325     return InterlockedCompareExchangeT(destination, reinterpret_cast<T*>(exchange), comparand);
5326 }
5327
5328 template <typename T>
5329 inline T* InterlockedCompareExchangeT(
5330     T* volatile *  destination,
5331     T*             exchange,
5332     std::nullptr_t comparand) // When nullptr is provided as argument.
5333 {
5334     //STATIC_ASSERT(comparand == 0);
5335     return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast<T*>(comparand));
5336 }
5337
5338 #undef InterlockedExchangePointer
5339 #define InterlockedExchangePointer Use_InterlockedExchangeT
5340 #undef InterlockedCompareExchangePointer
5341 #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT
5342
5343 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
5344 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
5345 HRESULT GetHModuleDirectory(HMODULE hMod, SString& wszPath);
5346 HRESULT CopySystemDirectory(const SString& pPathString, SString& pbuffer);
5347
5348 HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true);
5349 // This is a slight variation that can be used for anything else
5350 typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR);
5351 void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL);
5352
5353 BOOL IsClrHostedLegacyComObject(REFCLSID rclsid);
5354
5355
5356
5357
5358 // Helper to support termination due to heap corruption
5359 // It's not supported on Win2K, so we have to manually delay load it
5360 void EnableTerminationOnHeapCorruption();
5361
5362
5363
5364 namespace Clr { namespace Util
5365 {
5366     // This api returns a pointer to a null-terminated string that contains the local appdata directory
5367     // or it returns NULL in the case that the directory could not be found. The return value from this function
5368     // is not actually checked for existence. 
5369     HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory);
5370     HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory);
5371
5372 namespace Reg
5373 {
5374     HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue);
5375     __success(return == S_OK)
5376     HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue);
5377 }
5378
5379 #ifdef FEATURE_COMINTEROP
5380 namespace Com
5381 {
5382     HRESULT FindServerUsingCLSID(REFCLSID rclsid, SString & ssServerName);
5383     HRESULT FindServerUsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszServerName);
5384     HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name);
5385     HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, __deref_out __deref_out_z LPWSTR* pwszInprocServer32Name);
5386     BOOL IsMscoreeInprocServer32(const SString & ssInprocServer32Name);
5387     BOOL CLSIDHasMscoreeAsInprocServer32(REFCLSID rclsid);
5388 }
5389 #endif // FEATURE_COMINTEROP
5390
5391 namespace Win32
5392 {
5393     static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\");
5394     static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\";
5395
5396     void GetModuleFileName(
5397         HMODULE hModule,
5398         SString & ssFileName,
5399         bool fAllowLongFileNames = false);
5400
5401     __success(return == S_OK)
5402     HRESULT GetModuleFileName(
5403         HMODULE hModule,
5404         __deref_out_z LPWSTR * pwszFileName,
5405         bool fAllowLongFileNames = false);
5406
5407     void GetFullPathName(
5408         SString const & ssFileName,
5409         SString & ssPathName,
5410         DWORD * pdwFilePartIdx,
5411         bool fAllowLongFileNames = false);
5412 }
5413
5414 }}
5415
5416 #if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE)
5417     // Forward declaration of AppX::IsAppXProcess
5418     namespace AppX { bool IsAppXProcess(); }
5419
5420     // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes.
5421     inline DWORD GetLoadWithAlteredSearchPathFlag()
5422     {
5423         WRAPPER_NO_CONTRACT;
5424         return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
5425     }
5426 #else // FEATURE_APPX && !DACCESS_COMPILE
5427     // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally.
5428     inline DWORD GetLoadWithAlteredSearchPathFlag()
5429     {
5430         LIMITED_METHOD_CONTRACT;
5431         #ifdef LOAD_WITH_ALTERED_SEARCH_PATH
5432             return LOAD_WITH_ALTERED_SEARCH_PATH;
5433         #else
5434             return 0;
5435         #endif
5436     }
5437 #endif // FEATURE_APPX && !DACCESS_COMPILE
5438
5439 // clr::SafeAddRef and clr::SafeRelease helpers.
5440 namespace clr
5441 {
5442     //=================================================================================================================
5443     template <typename ItfT>
5444     static inline 
5445     typename std::enable_if< std::is_pointer<ItfT>::value, ItfT >::type
5446     SafeAddRef(ItfT pItf)
5447     {
5448         STATIC_CONTRACT_LIMITED_METHOD;
5449         if (pItf != nullptr)
5450         {
5451             pItf->AddRef();
5452         }
5453         return pItf;
5454     }
5455
5456     //=================================================================================================================
5457     template <typename ItfT>
5458     typename std::enable_if< std::is_pointer<ItfT>::value && std::is_reference<ItfT>::value, ULONG >::type
5459     SafeRelease(ItfT pItf)
5460     {
5461         STATIC_CONTRACT_LIMITED_METHOD;
5462         ULONG res = 0;
5463         if (pItf != nullptr)
5464         {
5465             res = pItf->Release();
5466             pItf = nullptr;
5467         }
5468         return res;
5469     }
5470
5471     //=================================================================================================================
5472     template <typename ItfT>
5473     typename std::enable_if< std::is_pointer<ItfT>::value && !std::is_reference<ItfT>::value, ULONG >::type
5474     SafeRelease(ItfT pItf)
5475     {
5476         STATIC_CONTRACT_LIMITED_METHOD;
5477         ULONG res = 0;
5478         if (pItf != nullptr)
5479         {
5480             res = pItf->Release();
5481         }
5482         return res;
5483     }
5484 }
5485
5486 // clr::SafeDelete
5487 namespace clr
5488 {
5489     //=================================================================================================================
5490     template <typename PtrT>
5491     static inline 
5492     typename std::enable_if< std::is_pointer<PtrT>::value, PtrT >::type
5493     SafeDelete(PtrT & ptr)
5494     {
5495         STATIC_CONTRACT_LIMITED_METHOD;
5496         if (ptr != nullptr)
5497         {
5498             delete ptr;
5499             ptr = nullptr;
5500         }
5501     }
5502 }
5503
5504 // ======================================================================================
5505 // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp)
5506
5507 struct SpinConstants
5508 {
5509     DWORD dwInitialDuration;
5510     DWORD dwMaximumDuration;
5511     DWORD dwBackoffFactor;
5512     DWORD dwRepetitions;
5513 };
5514
5515 extern SpinConstants g_SpinConstants;
5516
5517 // ======================================================================================
5518
5519 void* __stdcall GetCLRFunction(LPCSTR FunctionName);
5520
5521 #endif // __UtilCode_h__