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