[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / util_nodependencies.cpp
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 // Util_NoDependencies.cpp
6 // 
7
8 // 
9 // This contains a bunch of C++ utility classes needed also for UtilCode without dependencies 
10 // (standalone version without CLR/clr.dll/mscoree.dll dependencies).
11 // 
12 //*****************************************************************************
13
14 #include "stdafx.h"
15 #include "utilcode.h"
16 #include "ex.h"
17
18 #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) || defined(_DEBUG)
19
20 RunningOnStatusEnum gRunningOnStatus = RUNNING_ON_STATUS_UNINITED;
21
22 #define NON_SUPPORTED_PLATFORM_MSGBOX_TITLE             W("Platform not supported")
23 #define NON_SUPPORTED_PLATFORM_MSGBOX_TEXT              W("The minimum supported platform is Windows 7")
24 #define NON_SUPPORTED_PLATFORM_TERMINATE_ERROR_CODE     0xBAD1BAD1
25
26 //*****************************************************************************
27 // One time initialization of the OS version
28 //*****************************************************************************
29 void InitRunningOnVersionStatus ()
30 {
31 #ifndef FEATURE_PAL
32     STATIC_CONTRACT_NOTHROW;
33     STATIC_CONTRACT_GC_NOTRIGGER;
34     STATIC_CONTRACT_CANNOT_TAKE_LOCK;
35
36     BOOL fSupportedPlatform = FALSE;
37     OSVERSIONINFOEX sVer;
38     DWORDLONG dwlConditionMask;
39
40     ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
41     sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
42
43     sVer.dwMajorVersion = 6;
44     sVer.dwMinorVersion = 2;
45     sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
46
47
48     dwlConditionMask = 0;
49     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
50     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
51     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
52
53     if(VerifyVersionInfo(&sVer, VER_MAJORVERSION | VER_PLATFORMID | VER_MINORVERSION, dwlConditionMask))
54     {
55         gRunningOnStatus = RUNNING_ON_WIN8;
56         fSupportedPlatform = TRUE;
57         goto CHECK_SUPPORTED;
58     }
59
60
61     ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
62     sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
63
64     sVer.dwMajorVersion = 6;
65     sVer.dwMinorVersion = 1;
66     sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
67
68
69     dwlConditionMask = 0;
70     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
71     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
72     dwlConditionMask = VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
73
74     if(VerifyVersionInfo(&sVer, VER_MAJORVERSION | VER_PLATFORMID | VER_MINORVERSION, dwlConditionMask))
75     {
76         gRunningOnStatus = RUNNING_ON_WIN7;
77         fSupportedPlatform = TRUE;
78         goto CHECK_SUPPORTED;
79     }
80
81 CHECK_SUPPORTED:
82
83     if (!fSupportedPlatform)
84     {
85         // The current platform isn't supported. Display a message box to this effect and exit.
86         // Note that this should never happen since the .NET Fx setup should not install on 
87         // non supported platforms (which is why the message box text isn't localized).
88         UtilMessageBoxCatastrophicNonLocalized(NON_SUPPORTED_PLATFORM_MSGBOX_TITLE, NON_SUPPORTED_PLATFORM_MSGBOX_TEXT, MB_OK | MB_ICONERROR, TRUE);
89         TerminateProcess(GetCurrentProcess(), NON_SUPPORTED_PLATFORM_TERMINATE_ERROR_CODE);
90     }
91 #endif // FEATURE_PAL
92 } // InitRunningOnVersionStatus
93
94 #ifndef _WIN64
95 //------------------------------------------------------------------------------
96 // Returns TRUE if we are running on a 64-bit OS in WoW, FALSE otherwise.
97 BOOL RunningInWow64()
98 {
99     #ifdef PLATFORM_UNIX
100     return FALSE;
101     #else
102     static int s_Wow64Process;
103
104     if (s_Wow64Process == 0)
105     {
106         BOOL fWow64Process = FALSE;
107
108         if (!IsWow64Process(GetCurrentProcess(), &fWow64Process))
109             fWow64Process = FALSE;
110
111         s_Wow64Process = fWow64Process ? 1 : -1;
112     }
113
114     return (s_Wow64Process == 1) ? TRUE : FALSE;
115     #endif
116 }
117 #endif
118
119 #ifndef FEATURE_PAL
120 //------------------------------------------------------------------------------
121 //
122 // GetRegistryLongValue - Reads a configuration LONG value from the registry.
123 //
124 // Parameters
125 //    hKeyParent             -- Parent key
126 //    szKey                  -- key to open
127 //    szName                 -- name of the value
128 //    pValue                 -- put value here, if found
129 //    fReadNonVirtualizedKey -- whether to read 64-bit hive on WOW64
130 //
131 // Returns
132 //   TRUE  -- If the value was found and read
133 //   FALSE -- The value was not found, could not be read, or was not DWORD
134 //
135 // Exceptions
136 //   None
137 //------------------------------------------------------------------------------
138 BOOL GetRegistryLongValue(HKEY    hKeyParent,
139                           LPCWSTR szKey,
140                           LPCWSTR szName,
141                           long    *pValue,
142                           BOOL    fReadNonVirtualizedKey)
143 {
144     CONTRACTL
145     {
146         NOTHROW;
147         GC_NOTRIGGER;
148     }
149     CONTRACTL_END;
150
151     DWORD       ret;                    // Return value from registry operation.
152     HKEYHolder  hkey;                   // Registry key.
153     long        iValue;                 // The value to read.
154     DWORD       iType;                  // Type of value to get.
155     DWORD       iSize;                  // Size of buffer.
156     REGSAM      samDesired = KEY_READ;  // Desired access rights to the key
157
158     if (fReadNonVirtualizedKey)
159     {
160         if (RunningInWow64())
161         {
162             samDesired |= KEY_WOW64_64KEY;
163         }
164     }
165
166     ret = WszRegOpenKeyEx(hKeyParent, szKey, 0, samDesired, &hkey);
167
168     // If we opened the key, see if there is a value.
169     if (ret == ERROR_SUCCESS)
170     {
171         iType = REG_DWORD;
172         iSize = sizeof(long);
173         ret = WszRegQueryValueEx(hkey, szName, NULL, &iType, reinterpret_cast<BYTE*>(&iValue), &iSize);
174
175         if (ret == ERROR_SUCCESS && iType == REG_DWORD && iSize == sizeof(long))
176         {   // We successfully read a DWORD value.
177             *pValue = iValue;
178             return TRUE;
179         }
180     }
181     
182     return FALSE;
183 } // GetRegistryLongValue
184
185 //----------------------------------------------------------------------------
186 // 
187 // GetCurrentModuleFileName - Retrieve the current module's filename 
188 // 
189 // Arguments:
190 //    pBuffer - output string buffer
191 //
192 // Return Value:
193 //    S_OK on success, else detailed error code.
194 //
195 // Note:
196 //
197 //----------------------------------------------------------------------------
198 HRESULT GetCurrentModuleFileName(SString& pBuffer)
199 {
200     LIMITED_METHOD_CONTRACT;
201
202    
203     DWORD ret = WszGetModuleFileName(NULL, pBuffer);
204
205     if (ret == 0)
206     {   
207         return E_UNEXPECTED;
208     }
209
210     
211     return S_OK;
212 }
213
214 //----------------------------------------------------------------------------
215 // 
216 // IsCurrentModuleFileNameInAutoExclusionList - decide if the current module's filename 
217 //                                              is in the AutoExclusionList list
218 // 
219 // Arguments:
220 //    None
221 //
222 // Return Value:
223 //    TRUE or FALSE
224 //
225 // Note:
226 //    This function cannot be used in out of process scenarios like DAC because it
227 //    looks at current module's filename.   In OOP we want to use target process's 
228 //    module's filename.
229 //
230 //----------------------------------------------------------------------------
231 BOOL IsCurrentModuleFileNameInAutoExclusionList()
232 {
233     CONTRACTL
234     {
235         NOTHROW;
236         GC_NOTRIGGER;
237     }
238     CONTRACTL_END;
239
240     HKEYHolder hKeyHolder;
241
242     // Look for "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList"
243     DWORD ret = WszRegOpenKeyEx(HKEY_LOCAL_MACHINE, kUnmanagedDebuggerAutoExclusionListKey, 0, KEY_READ, &hKeyHolder);
244
245     if (ret != ERROR_SUCCESS)
246     {   
247         // there's not even an AutoExclusionList hive
248         return FALSE;
249     }
250
251     PathString wszAppName;
252     
253     // Get the appname to look up in the exclusion or inclusion list.
254     if (GetCurrentModuleFileName(wszAppName) != S_OK)
255     {
256         // Assume it is not on the exclusion list if we cannot find the module's filename.
257         return FALSE;
258     }
259
260     // Look in AutoExclusionList key for appName get the size of any value stored there.
261     DWORD value, valueType, valueSize = sizeof(value);
262     ret = WszRegQueryValueEx(hKeyHolder, wszAppName, 0, &valueType, reinterpret_cast<BYTE*>(&value), &valueSize);
263     if ((ret == ERROR_SUCCESS) && (valueType == REG_DWORD) && (value == 1))
264     {   
265         return TRUE;
266     }
267     
268     return FALSE;
269 } // IsCurrentModuleFileNameInAutoExclusionList
270
271 //*****************************************************************************
272 // Retrieve information regarding what registered default debugger
273 //*****************************************************************************
274 void GetDebuggerSettingInfo(SString &ssDebuggerString, BOOL *pfAuto)
275 {
276     CONTRACTL
277     {
278         NOTHROW;
279         GC_NOTRIGGER;
280     }
281     CONTRACTL_END;
282
283     EX_TRY
284     {
285         DWORD cchDebuggerString = MAX_LONGPATH;
286         INDEBUG(DWORD cchOldDebuggerString = cchDebuggerString);
287
288         WCHAR * buf = ssDebuggerString.OpenUnicodeBuffer(cchDebuggerString);   
289         HRESULT hr = GetDebuggerSettingInfoWorker(buf, &cchDebuggerString, pfAuto);
290         ssDebuggerString.CloseBuffer(cchDebuggerString);
291
292         while (hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))
293         {
294             _ASSERTE(cchDebuggerString > cchOldDebuggerString);
295             INDEBUG(cchOldDebuggerString = cchDebuggerString);
296
297             buf = ssDebuggerString.OpenUnicodeBuffer(cchDebuggerString);   
298             hr = GetDebuggerSettingInfoWorker(buf, &cchDebuggerString, pfAuto);
299             ssDebuggerString.CloseBuffer(cchDebuggerString);
300         }
301
302         if (*ssDebuggerString.GetUnicode() == W('\0'))
303         {
304             ssDebuggerString.Clear();
305         }
306
307         if (FAILED(hr))
308         {
309             ssDebuggerString.Clear();
310             if (pfAuto)
311             {
312                 *pfAuto = FALSE;
313             }
314         }
315     }
316     EX_CATCH
317     {
318         ssDebuggerString.Clear();
319         if (pfAuto)
320         {
321             *pfAuto = FALSE;
322         }
323     }
324     EX_END_CATCH(SwallowAllExceptions);
325 } // GetDebuggerSettingInfo
326
327 //---------------------------------------------------------------------------------------
328 //
329 // GetDebuggerSettingInfoWorker - retrieve information regarding what registered default debugger
330 // 
331 // Arguments:
332 //      * wszDebuggerString - [out] the string buffer to store the registered debugger launch 
333 //                            string
334 //      * pcchDebuggerString - [in, out] the size of string buffer in characters
335 //      * pfAuto - [in] the flag to indicate whether the debugger neeeds to be launched 
336 //                 automatically
337 //
338 // Return Value:
339 //    HRESULT indicating success or failure.
340 //    
341 // Notes:
342 //     * wszDebuggerString can be NULL.   When wszDebuggerString is NULL, pcchDebuggerString should
343 //     * point to a DWORD of zero.   pcchDebuggerString cannot be NULL, and the DWORD pointed by 
344 //     * pcchDebuggerString will store the used or required string buffer size in characters.
345 HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto)
346 {
347     CONTRACTL
348     {
349         NOTHROW;
350         GC_NOTRIGGER;
351         PRECONDITION(pcchDebuggerString != NULL);
352     }
353     CONTRACTL_END;
354
355     if ((pcchDebuggerString == NULL) || ((wszDebuggerString == NULL) && (*pcchDebuggerString != 0)))
356     {
357         return E_INVALIDARG;
358     }
359
360     // Initialize the output values before we start.
361     if ((wszDebuggerString != NULL) && (*pcchDebuggerString > 0))
362     {
363         *wszDebuggerString = W('\0');
364     }
365
366     if (pfAuto != NULL)
367     {
368         *pfAuto = FALSE;
369     }
370
371     HKEYHolder hKeyHolder;
372
373     // Look for "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug"
374     DWORD ret = WszRegOpenKeyEx(HKEY_LOCAL_MACHINE, kUnmanagedDebuggerKey, 0, KEY_READ, &hKeyHolder);
375
376     if (ret != ERROR_SUCCESS)
377     {   // Wow, there's not even an AeDebug hive, so no native debugger, no auto.
378         return S_OK;
379     }
380
381     // Look in AeDebug key for "Debugger"; get the size of any value stored there.
382     DWORD valueType, valueSize = 0;
383     ret = WszRegQueryValueEx(hKeyHolder, kUnmanagedDebuggerValue, 0, &valueType, 0, &valueSize);   
384
385     _ASSERTE(pcchDebuggerString != NULL);
386     if ((wszDebuggerString == NULL) || (*pcchDebuggerString < valueSize / sizeof(WCHAR)))
387     {
388         *pcchDebuggerString = valueSize / sizeof(WCHAR) + 1;
389         return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
390     }
391
392     *pcchDebuggerString = valueSize / sizeof(WCHAR);
393     
394     // The size of an empty string with the null terminator is 2.
395     BOOL fIsDebuggerStringEmptry = valueSize <= 2 ? TRUE : FALSE; 
396
397     if ((ret != ERROR_SUCCESS) || (valueType != REG_SZ) || fIsDebuggerStringEmptry)
398     {   
399         return S_OK;
400     }
401
402     _ASSERTE(wszDebuggerString != NULL);
403     ret = WszRegQueryValueEx(hKeyHolder, kUnmanagedDebuggerValue, NULL, NULL, reinterpret_cast< LPBYTE >(wszDebuggerString), &valueSize);
404     if (ret != ERROR_SUCCESS)
405     {
406         *wszDebuggerString = W('\0');
407         return S_OK;
408     }   
409
410     // The callers are in nothrow scope, so we must swallow exceptions and reset the output parameters to the 
411     // default values if exceptions like OOM ever happen.
412     EX_TRY
413     {
414         if (pfAuto != NULL)
415         {
416             BOOL fAuto = FALSE;
417
418             // Get the appname to look up in DebugApplications key.
419             PathString wzAppName;
420             long iValue;
421
422             // Check DebugApplications setting
423             if ((SUCCEEDED(GetCurrentModuleFileName(wzAppName))) &&
424                 (
425                     GetRegistryLongValue(HKEY_LOCAL_MACHINE, kDebugApplicationsPoliciesKey, wzAppName, &iValue, TRUE) ||
426                     GetRegistryLongValue(HKEY_LOCAL_MACHINE, kDebugApplicationsKey, wzAppName, &iValue, TRUE) ||
427                     GetRegistryLongValue(HKEY_CURRENT_USER,  kDebugApplicationsPoliciesKey, wzAppName, &iValue, TRUE) ||
428                     GetRegistryLongValue(HKEY_CURRENT_USER,  kDebugApplicationsKey, wzAppName, &iValue, TRUE)
429                 ) &&
430                 (iValue == 1))
431             {
432                 fAuto = TRUE;
433             }
434             else
435             {
436                 // Look in AeDebug key for "Auto"; get the size of any value stored there.
437                 ret = WszRegQueryValueEx(hKeyHolder, kUnmanagedDebuggerAutoValue, 0, &valueType, 0, &valueSize);
438                 if ((ret == ERROR_SUCCESS) && (valueType == REG_SZ) && (valueSize / sizeof(WCHAR) < MAX_LONGPATH))
439                 {   
440                     WCHAR wzAutoKey[MAX_LONGPATH];
441                     valueSize = NumItems(wzAutoKey) * sizeof(WCHAR);
442                     WszRegQueryValueEx(hKeyHolder, kUnmanagedDebuggerAutoValue, NULL, NULL, reinterpret_cast< LPBYTE >(wzAutoKey), &valueSize);
443
444                     // The OS's behavior is to consider Auto to be FALSE unless the first character is set
445                     // to 1. They don't take into consideration the following characters. Also if the value 
446                     // isn't present they assume an Auto value of FALSE.
447                     if ((wzAutoKey[0] == W('1')) && !IsCurrentModuleFileNameInAutoExclusionList())
448                     {
449                         fAuto = TRUE;
450                     }
451                 }
452             }
453
454             *pfAuto = fAuto;
455         }
456     }
457     EX_CATCH
458     {
459         if ((wszDebuggerString != NULL) && (*pcchDebuggerString > 0))
460         {
461             *wszDebuggerString = W('\0');
462         }
463
464         if (pfAuto != NULL)
465         {
466             *pfAuto = FALSE;
467         }
468     }
469     EX_END_CATCH(SwallowAllExceptions);
470
471     return S_OK;
472 } // GetDebuggerSettingInfoWorker
473 #endif // FEATURE_PAL
474
475 #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) || defined(_DEBUG)
476
477 //*****************************************************************************
478 // Convert hex value into a wide string of hex digits 
479 //*****************************************************************************
480 HRESULT GetStr(
481                                  DWORD  hHexNum, 
482     __out_ecount((cbHexNum * 2)) LPWSTR szHexNum, 
483                                  DWORD  cbHexNum)
484 {
485     CONTRACTL
486     {
487         NOTHROW;
488     }
489     CONTRACTL_END;
490     
491     _ASSERTE (szHexNum);
492     cbHexNum *= 2; // each nibble is a char
493     while (cbHexNum != 0)
494     {
495         DWORD thisHexDigit = hHexNum % 16;
496         hHexNum /= 16;
497         cbHexNum--;
498         if (thisHexDigit < 10)
499         {
500             *(szHexNum+cbHexNum) = (BYTE)(thisHexDigit + W('0'));
501         }
502         else
503         {
504             *(szHexNum+cbHexNum) = (BYTE)(thisHexDigit - 10 + W('A'));
505         }
506     }
507     return S_OK;
508 }
509
510 //*****************************************************************************
511 // Convert a GUID into a pointer to a Wide char string
512 //*****************************************************************************
513 int 
514 GuidToLPWSTR(
515                           GUID   Guid,      // The GUID to convert.
516     __out_ecount(cchGuid) LPWSTR szGuid,    // String into which the GUID is stored
517                           DWORD  cchGuid)   // Count in wchars
518 {
519     CONTRACTL
520     {
521         NOTHROW;
522     }
523     CONTRACTL_END;
524     
525     int         i;
526     
527     // successive fields break the GUID into the form DWORD-WORD-WORD-WORD-WORD.DWORD 
528     // covering the 128-bit GUID. The string includes enclosing braces, which are an OLE convention.
529
530     if (cchGuid < 39) // 38 chars + 1 null terminating.
531         return 0;
532
533     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
534     // ^
535     szGuid[0]  = W('{');
536
537     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
538     //  ^^^^^^^^
539     if (FAILED (GetStr(Guid.Data1, szGuid+1 , 4))) return 0;
540
541     szGuid[9]  = W('-');
542     
543     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
544     //           ^^^^
545     if (FAILED (GetStr(Guid.Data2, szGuid+10, 2))) return 0;
546
547     szGuid[14] = W('-');
548     
549     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
550     //                ^^^^
551     if (FAILED (GetStr(Guid.Data3, szGuid+15, 2))) return 0;
552
553     szGuid[19] = W('-');
554     
555     // Get the last two fields (which are byte arrays).
556     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
557     //                     ^^^^
558     for (i=0; i < 2; ++i)
559         if (FAILED(GetStr(Guid.Data4[i], szGuid + 20 + (i * 2), 1)))
560             return (0);
561
562     szGuid[24] = W('-');
563     
564     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
565     //                          ^^^^^^^^^^^^
566     for (i=0; i < 6; ++i)
567         if (FAILED(GetStr(Guid.Data4[i+2], szGuid + 25 + (i * 2), 1)))
568             return (0);
569
570     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
571     //                                      ^
572     szGuid[37] = W('}');
573     szGuid[38] = W('\0');
574
575     return 39;
576 } // GuidToLPWSTR
577
578 //*****************************************************************************
579 // Convert wide string of (at most eight) hex digits into a hex value
580 //*****************************************************************************
581 HRESULT GetHex(
582                                 DWORD * phHexNum, 
583     __in_ecount((cbHexNum * 2)) LPCWSTR szHexNum, 
584                                 DWORD   cbHexNum)
585 {
586     CONTRACTL
587     {
588         NOTHROW;
589     }
590     CONTRACTL_END;
591     
592     _ASSERTE (szHexNum && phHexNum);
593     _ASSERTE(cbHexNum == 1 || cbHexNum == 2 || cbHexNum == 4);
594
595     cbHexNum *= 2; // each nibble is a char
596     DWORD val = 0;
597     for (DWORD i = 0; i < cbHexNum; ++i)
598     {
599         DWORD nibble = 0;
600         if (szHexNum[i] >= W('0') && szHexNum[i] <= W('9'))
601         {
602             nibble = szHexNum[i] - '0';
603         }
604         else if (szHexNum[i] >= W('A') && szHexNum[i] <= W('F'))
605         {
606             nibble = 10 + szHexNum[i] - 'A';
607         }
608         else if (szHexNum[i] >= W('a') && szHexNum[i] <= W('f'))
609         {
610             nibble = 10 + szHexNum[i] - 'a';
611         }
612         else
613         {
614             return E_FAIL;
615         }
616         val = (val << 4) + nibble;
617     }
618     *phHexNum = val;
619     return S_OK;
620 }
621
622 //*****************************************************************************
623 // Parse a Wide char string into a GUID
624 //*****************************************************************************
625 BOOL 
626 LPWSTRToGuid(
627                          GUID  * Guid,      // [OUT] The GUID to fill in
628     __in_ecount(cchGuid) LPCWSTR szGuid,    // [IN] String to parse
629                          DWORD   cchGuid)   // [IN] Count in wchars in string
630 {
631     CONTRACTL
632     {
633         NOTHROW;
634     }
635     CONTRACTL_END;
636     
637     int         i;
638     DWORD dw;
639
640     // successive fields break the GUID into the form DWORD-WORD-WORD-WORD-WORD.DWORD 
641     // covering the 128-bit GUID. The string includes enclosing braces, which are an OLE convention.
642
643     if (cchGuid < 38) // 38 chars + 1 null terminating.
644         return FALSE;
645
646     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
647     // ^
648     if (szGuid[0] != W('{')) return FALSE;
649
650     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
651     //  ^^^^^^^^
652     if (FAILED (GetHex(&dw, szGuid+1 , 4))) return FALSE;
653     Guid->Data1 = dw;
654
655     if (szGuid[9] != W('-')) return FALSE;
656     
657     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
658     //           ^^^^
659     if (FAILED (GetHex(&dw, szGuid+10, 2))) return FALSE;
660     Guid->Data2 = (WORD)dw;
661
662     if (szGuid[14] != W('-')) return FALSE;
663     
664     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
665     //                ^^^^
666     if (FAILED (GetHex(&dw, szGuid+15, 2))) return FALSE;
667     Guid->Data3 = (WORD)dw;
668
669     if (szGuid[19] != W('-')) return FALSE;
670     
671     // Get the last two fields (which are byte arrays).
672     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
673     //                     ^^^^
674     for (i=0; i < 2; ++i)
675     {
676         if (FAILED(GetHex(&dw, szGuid + 20 + (i * 2), 1))) return FALSE;
677         Guid->Data4[i] = (BYTE)dw;
678     }
679
680     if (szGuid[24] != W('-')) return FALSE;
681     
682     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
683     //                          ^^^^^^^^^^^^
684     for (i=0; i < 6; ++i)
685     {
686         if (FAILED(GetHex(&dw, szGuid + 25 + (i * 2), 1))) return FALSE;
687         Guid->Data4[i+2] = (BYTE)dw;
688     }
689
690     // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
691     //                                      ^
692     if (szGuid[37] != W('}')) return FALSE;
693
694     return TRUE;
695 } // GuidToLPWSTR
696
697
698 #ifdef _DEBUG
699 // Always write regardless of registry.
700 void _cdecl DbgWriteEx(LPCTSTR szFmt, ...)
701 {
702     CONTRACTL
703     {
704         NOTHROW;
705     }
706     CONTRACTL_END;
707     
708     WCHAR rcBuff[1024];
709     va_list marker;
710
711     va_start(marker, szFmt);
712     _vsnwprintf_s(rcBuff, _countof(rcBuff), _TRUNCATE, szFmt, marker);
713     va_end(marker);
714     WszOutputDebugString(rcBuff);
715 }
716 #endif //_DEBUG
717
718 /**************************************************************************/
719 void ConfigDWORD::init(const CLRConfig::ConfigDWORDInfo & info)
720 {
721     CONTRACTL
722     {
723         NOTHROW;
724     }
725     CONTRACTL_END;
726     
727     // make sure that the memory was zero initialized
728     _ASSERTE(m_inited == 0 || m_inited == 1);
729
730     m_value = CLRConfig::GetConfigValue(info);
731     m_inited = 1;
732 }
733
734 //---------------------------------------------------------------------------------------
735 // 
736 // Takes a const input string, and returns the start & size of the substring that has all
737 // leading and trailing whitespace removed. The original string is not modified.
738 // 
739 // Arguments:
740 //      * pwsz - [in] points to const string we want to trim; [out] points to beginning
741 //          of trimmed substring of input string
742 //      * pcch - [in] Points to length in chars of input string (not counting null
743 //          terminator); [out] Points to length in chars of trimmed substring (not
744 //          counting null terminator)
745 // 
746 void TrimWhiteSpace(__deref_inout_ecount(*pcch)  LPCWSTR *pwsz, __inout LPDWORD pcch)
747 {
748     LIMITED_METHOD_DAC_CONTRACT;
749
750     _ASSERTE (pwsz != NULL);
751     _ASSERTE (*pwsz != NULL);
752     _ASSERTE (pcch != NULL);
753
754     DWORD cch = *pcch;
755     LPCWSTR wszBeginning = *pwsz;
756     LPCWSTR wszEnd = wszBeginning + (cch - 1);
757
758     while ((cch != 0) && iswspace(*wszBeginning))
759     {
760         wszBeginning++;
761         cch--;
762     }
763
764     while ((cch != 0) && iswspace(*wszEnd))
765     {
766         wszEnd--;
767         cch--;
768     }
769
770     *pwsz = wszBeginning;
771     *pcch = cch;
772 } // TrimWhiteSpace
773
774 BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack)
775 {
776     // We need to make sure there will be a reserved but never committed page at the end
777     // of the stack. We do here the check NT does when it creates the user stack to decide
778     // if there is going to be a guard page. However, that is not enough, as if we only
779     // have a guard page, we have nothing to protect us from going pass it. Well, in 
780     // fact, there is something that we will protect you, there are certain places 
781     // (RTLUnwind) in NT that will check that the current frame is within stack limits. 
782     // If we are not it will bomb out. We will also bomb out if we touch the hard guard
783     // page.
784     // 
785     // For situation B, teb->StackLimit is at the beggining of the user stack (ie
786     // before updating StackLimit it checks if it was able to create a new guard page,
787     // in this case, it can't), which makes the check fail in RtlUnwind. 
788     //
789     //    Situation A  [ Hard guard page | Guard page | user stack]
790     //
791     //    Situation B  [ Guard page | User stack ]
792     //
793     //    Situation C  [ User stack ( no room for guard page) ]
794     //
795     //    Situation D (W9x) : Guard page or not, w9x has a 64k reserved region below
796     //                        the stack, we don't need any checks at all
797     //
798     // We really want to be in situation A all the time, so we add one more page
799     // to our requirements (we require guard page + hard guard)
800         
801     SYSTEM_INFO sysInfo;
802     ::GetSystemInfo(&sysInfo);    
803
804     // OS rounds up sizes the following way to decide if it marks a guard page
805     sizeReservedStack = ALIGN(sizeReservedStack, ((size_t)sysInfo.dwAllocationGranularity));   // Allocation granularity
806     sizeCommitedStack = ALIGN(sizeCommitedStack, ((size_t)sysInfo.dwPageSize));  // Page Size
807  
808     // OS wont create guard page, we can't execute managed code safely.
809     // We also have to make sure we have a 'hard' guard, thus we add another
810     // page to the memory we would need comitted.
811     // That is, the following code will check if sizeReservedStack is at least 2 pages 
812     // more than sizeCommitedStack.
813     return (sizeReservedStack > sizeCommitedStack + ((size_t)sysInfo.dwPageSize));     
814 } // ThreadWillCreateGuardPage
815
816 //The following characters have special sorting weights when combined with other
817 //characters, which means we can't use our fast sorting algorithm on them.
818 //Most of these are pretty rare control characters, but apostrophe and hyphen
819 //are fairly common and force us down the slower path.  This is because we want
820 //"word sorting", which means that "coop" and "co-op" sort together, instead of
821 //separately as they would if we were doing a string sort.
822 //      0x0001   6    3    2   2   0  ;Start Of Heading
823 //      0x0002   6    4    2   2   0  ;Start Of Text
824 //      0x0003   6    5    2   2   0  ;End Of Text
825 //      0x0004   6    6    2   2   0  ;End Of Transmission
826 //      0x0005   6    7    2   2   0  ;Enquiry
827 //      0x0006   6    8    2   2   0  ;Acknowledge
828 //      0x0007   6    9    2   2   0  ;Bell
829 //      0x0008   6   10    2   2   0  ;Backspace
830
831 //      0x000e   6   11    2   2   0  ;Shift Out
832 //      0x000f   6   12    2   2   0  ;Shift In
833 //      0x0010   6   13    2   2   0  ;Data Link Escape
834 //      0x0011   6   14    2   2   0  ;Device Control One
835 //      0x0012   6   15    2   2   0  ;Device Control Two
836 //      0x0013   6   16    2   2   0  ;Device Control Three
837 //      0x0014   6   17    2   2   0  ;Device Control Four
838 //      0x0015   6   18    2   2   0  ;Negative Acknowledge
839 //      0x0016   6   19    2   2   0  ;Synchronous Idle
840 //      0x0017   6   20    2   2   0  ;End Of Transmission Block
841 //      0x0018   6   21    2   2   0  ;Cancel
842 //      0x0019   6   22    2   2   0  ;End Of Medium
843 //      0x001a   6   23    2   2   0  ;Substitute
844 //      0x001b   6   24    2   2   0  ;Escape
845 //      0x001c   6   25    2   2   0  ;File Separator
846 //      0x001d   6   26    2   2   0  ;Group Separator
847 //      0x001e   6   27    2   2   0  ;Record Separator
848 //      0x001f   6   28    2   2   0  ;Unit Separator
849
850 //      0x0027   6  128    2   2   0  ;Apostrophe-Quote
851 //      0x002d   6  130    2   2   0  ;Hyphen-Minus
852
853 //      0x007f   6   29    2   2   0  ;Delete
854
855 const BYTE 
856 HighCharHelper::HighCharTable[]= {
857     TRUE,     /* 0x0, 0x0 */
858     TRUE, /* 0x1, .*/
859     TRUE, /* 0x2, .*/
860     TRUE, /* 0x3, .*/
861     TRUE, /* 0x4, .*/
862     TRUE, /* 0x5, .*/
863     TRUE, /* 0x6, .*/
864     TRUE, /* 0x7, .*/
865     TRUE, /* 0x8, .*/
866     FALSE, /* 0x9,   */
867 #ifdef PLATFORM_UNIX
868     TRUE, /* 0xA,  */
869 #else    
870     FALSE, /* 0xA,  */
871 #endif // PLATFORM_UNIX
872     FALSE, /* 0xB, .*/
873     FALSE, /* 0xC, .*/
874 #ifdef PLATFORM_UNIX
875     TRUE, /* 0xD,  */
876 #else    
877     FALSE, /* 0xD,  */
878 #endif // PLATFORM_UNIX
879     TRUE, /* 0xE, .*/
880     TRUE, /* 0xF, .*/
881     TRUE, /* 0x10, .*/
882     TRUE, /* 0x11, .*/
883     TRUE, /* 0x12, .*/
884     TRUE, /* 0x13, .*/
885     TRUE, /* 0x14, .*/
886     TRUE, /* 0x15, .*/
887     TRUE, /* 0x16, .*/
888     TRUE, /* 0x17, .*/
889     TRUE, /* 0x18, .*/
890     TRUE, /* 0x19, .*/
891     TRUE, /* 0x1A, */
892     TRUE, /* 0x1B, .*/
893     TRUE, /* 0x1C, .*/
894     TRUE, /* 0x1D, .*/
895     TRUE, /* 0x1E, .*/
896     TRUE, /* 0x1F, .*/
897     FALSE, /*0x20,  */
898     FALSE, /*0x21, !*/
899     FALSE, /*0x22, "*/
900     FALSE, /*0x23,  #*/
901     FALSE, /*0x24,  $*/
902     FALSE, /*0x25,  %*/
903     FALSE, /*0x26,  &*/
904     TRUE,  /*0x27, '*/
905     FALSE, /*0x28, (*/
906     FALSE, /*0x29, )*/
907     FALSE, /*0x2A **/
908     FALSE, /*0x2B, +*/
909     FALSE, /*0x2C, ,*/
910     TRUE,  /*0x2D, -*/
911     FALSE, /*0x2E, .*/
912     FALSE, /*0x2F, /*/
913     FALSE, /*0x30, 0*/
914     FALSE, /*0x31, 1*/
915     FALSE, /*0x32, 2*/
916     FALSE, /*0x33, 3*/
917     FALSE, /*0x34, 4*/
918     FALSE, /*0x35, 5*/
919     FALSE, /*0x36, 6*/
920     FALSE, /*0x37, 7*/
921     FALSE, /*0x38, 8*/
922     FALSE, /*0x39, 9*/
923     FALSE, /*0x3A, :*/
924     FALSE, /*0x3B, ;*/
925     FALSE, /*0x3C, <*/
926     FALSE, /*0x3D, =*/
927     FALSE, /*0x3E, >*/
928     FALSE, /*0x3F, ?*/
929     FALSE, /*0x40, @*/
930     FALSE, /*0x41, A*/
931     FALSE, /*0x42, B*/
932     FALSE, /*0x43, C*/
933     FALSE, /*0x44, D*/
934     FALSE, /*0x45, E*/
935     FALSE, /*0x46, F*/
936     FALSE, /*0x47, G*/
937     FALSE, /*0x48, H*/
938     FALSE, /*0x49, I*/
939     FALSE, /*0x4A, J*/
940     FALSE, /*0x4B, K*/
941     FALSE, /*0x4C, L*/
942     FALSE, /*0x4D, M*/
943     FALSE, /*0x4E, N*/
944     FALSE, /*0x4F, O*/
945     FALSE, /*0x50, P*/
946     FALSE, /*0x51, Q*/
947     FALSE, /*0x52, R*/
948     FALSE, /*0x53, S*/
949     FALSE, /*0x54, T*/
950     FALSE, /*0x55, U*/
951     FALSE, /*0x56, V*/
952     FALSE, /*0x57, W*/
953     FALSE, /*0x58, X*/
954     FALSE, /*0x59, Y*/
955     FALSE, /*0x5A, Z*/
956     FALSE, /*0x5B, [*/
957     FALSE, /*0x5C, \*/
958     FALSE, /*0x5D, ]*/
959     FALSE, /*0x5E, ^*/
960     FALSE, /*0x5F, _*/
961     FALSE, /*0x60, `*/
962     FALSE, /*0x61, a*/
963     FALSE, /*0x62, b*/
964     FALSE, /*0x63, c*/
965     FALSE, /*0x64, d*/
966     FALSE, /*0x65, e*/
967     FALSE, /*0x66, f*/
968     FALSE, /*0x67, g*/
969     FALSE, /*0x68, h*/
970     FALSE, /*0x69, i*/
971     FALSE, /*0x6A, j*/
972     FALSE, /*0x6B, k*/
973     FALSE, /*0x6C, l*/
974     FALSE, /*0x6D, m*/
975     FALSE, /*0x6E, n*/
976     FALSE, /*0x6F, o*/
977     FALSE, /*0x70, p*/
978     FALSE, /*0x71, q*/
979     FALSE, /*0x72, r*/
980     FALSE, /*0x73, s*/
981     FALSE, /*0x74, t*/
982     FALSE, /*0x75, u*/
983     FALSE, /*0x76, v*/
984     FALSE, /*0x77, w*/
985     FALSE, /*0x78, x*/
986     FALSE, /*0x79, y*/
987     FALSE, /*0x7A, z*/
988     FALSE, /*0x7B, {*/
989     FALSE, /*0x7C, |*/
990     FALSE, /*0x7D, }*/
991     FALSE, /*0x7E, ~*/
992     TRUE, /*0x7F, \7f*/
993 };  // HighCharHelper::HighCharTable