xref: /reactos/sdk/lib/ucrt/inc/corecrt_internal.h (revision 04e0dc4a)
1 //
2 // corecrt_internal.h
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // CoreCRT Internals
7 //
8 #pragma once
9 
10 #include <corecrt.h>
11 #include <corecrt_startup.h>
12 #include <corecrt_terminate.h>
13 #include <corecrt_wctype.h>
14 #include <crtdbg.h>
15 #include <ctype.h>
16 #include <errno.h>
17 #include <excpt.h>
18 #include <internal_shared.h>
19 #include <limits.h>
20 #include <malloc.h>
21 #include <process.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <vcruntime_startup.h>
25 #include <windows.h>
26 #include <appmodel.h>
27 
28 #ifdef __cplusplus
29     #include <roapi.h>
30 #endif
31 
32 _CRT_BEGIN_C_HEADER
33 
34 #define _DEFINE_SET_FUNCTION(function_name, type, variable_name) \
35     __inline void function_name(type value)                      \
36     {                                                            \
37         __pragma(warning(push))                                  \
38         __pragma(warning(disable:4996))                          \
39         variable_name = value;                                   \
40         __pragma(warning(pop))                                   \
41     }
42 
43 
44 
45 #if defined _M_IX86
46     #define _CRT_LINKER_SYMBOL_PREFIX "_"
47 #elif defined _M_X64 || defined _M_ARM || defined _M_ARM64
48     #define _CRT_LINKER_SYMBOL_PREFIX ""
49 #else
50     #error Unsupported architecture
51 #endif
52 
53 #define _CRT_LINKER_FORCE_INCLUDE(name) \
54     __pragma(comment(linker,            \
55         "/include:"                     \
56         _CRT_LINKER_SYMBOL_PREFIX #name \
57         ))
58 
59 
60 
61 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 //
63 // CRT SAL Annotations
64 //
65 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 // This macro can be used to annotate a buffer when it has the option that
67 // _CRT_UNBOUNDED_BUFFER_SIZE may be passed as its size in order to invoke unsafe behavior.
68 // void example(
69 //    _Maybe_unsafe_(_Out_writes_z_, buffer_count) char * const buffer,
70 //    _In_                                         size_t const buffer_size
71 // )
72 #define _CRT_UNBOUNDED_BUFFER_SIZE (static_cast<size_t>(-1))
73 #define _Maybe_unsafe_(buffer_annotation, expr)                                                    \
74         _When_((expr < _CRT_UNBOUNDED_BUFFER_SIZE), buffer_annotation(expr))                       \
75         _When_((expr >= _CRT_UNBOUNDED_BUFFER_SIZE), buffer_annotation(_Inexpressible_("unsafe")))
76 
77 
78 
79 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 //
81 // Forward declarations of __crt_state_management types
82 //
83 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 #ifdef __cplusplus
85 extern "C++"
86 {
87     namespace __crt_state_management
88     {
89         template <typename T>
90         class dual_state_global;
91     }
92 }
93 #endif
94 
95 
96 
97 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 //
99 // Dual-state globals (that shouldn't be exported directly)
100 //
101 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 #ifdef __cplusplus
103     extern __crt_state_management::dual_state_global<int>               _fmode;
104     extern __crt_state_management::dual_state_global<unsigned char*>    _mbctype;
105     extern __crt_state_management::dual_state_global<unsigned char*>    _mbcasemap;
106 #endif
107 
108 
109 
110 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111 //
112 // Dynamic Initialization Support
113 //
114 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 #define _CORECRT_GENERATE_FORWARDER(prefix, callconv, name, callee_name)                     \
116     __pragma(warning(push))                                                                  \
117     __pragma(warning(disable: 4100)) /* unreferenced formal parameter */                     \
118     template <typename... Params>                                                            \
119     prefix auto callconv name(Params&&... args) throw() -> decltype(callee_name(args...))    \
120     {                                                                                        \
121         _BEGIN_SECURE_CRT_DEPRECATION_DISABLE                                                \
122         return callee_name(args...);                                                         \
123         _END_SECURE_CRT_DEPRECATION_DISABLE                                                  \
124     }                                                                                        \
125     __pragma(warning(pop))
126 
127 extern size_t const _sys_first_posix_error;
128 extern size_t const _sys_last_posix_error;
129 extern char const* const _sys_posix_errlist[];
130 
131 _Ret_z_
_get_sys_err_msg(size_t const m)132 __inline char const* _get_sys_err_msg(size_t const m)
133 {
134     _BEGIN_SECURE_CRT_DEPRECATION_DISABLE
135     if (m > _sys_last_posix_error || ((size_t)_sys_nerr < m && m < _sys_first_posix_error))
136         return _sys_errlist[_sys_nerr];
137     if (m <= (size_t)_sys_nerr)
138         return _sys_errlist[m];
139     else
140         return _sys_posix_errlist[m - _sys_first_posix_error];
141     _END_SECURE_CRT_DEPRECATION_DISABLE
142 }
143 
144 #ifdef __cplusplus
145     // The maximum number of characters (including null terminator) of a system
146     // error message.  Note:  This value must correspond to the number of characters
147     // in the longest message in the error list.
148     size_t const max_system_error_message_count = 38;
149 
150     // The number of characters in the per-thread strerror buffer.  This has room
151     // for a 94 character user-provided prefix, a ": " delimiter, and one of the
152     // system error messages.
153     size_t const strerror_buffer_count = (94 + max_system_error_message_count + 2);
154 #endif
155 
156 
157 
158 _Success_(return != 0)
159 char* __cdecl __acrt_getpath(
160     _In_z_                       char const* delimited_paths,
161     _Out_writes_z_(buffer_count) char*       buffer,
162     _In_                         size_t      buffer_count
163     );
164 
165 _Success_(return != 0)
166 wchar_t* __cdecl __acrt_wgetpath(
167     _In_z_                       wchar_t const* delimited_paths,
168     _Out_writes_z_(buffer_count) wchar_t*       buffer,
169     _In_                         size_t         buffer_count
170     );
171 
172 _Success_(return == 0)
173 errno_t __acrt_expand_narrow_argv_wildcards(
174     _In_z_               char**  argv,
175     _Out_ _Deref_post_z_ char*** result
176     );
177 
178 _Success_(return == 0)
179 errno_t __acrt_expand_wide_argv_wildcards(
180     _In_                 wchar_t**  argv,
181     _Out_ _Deref_post_z_ wchar_t*** result
182     );
183 
184 _Success_(return == 0)
185 _Ret_range_(-1, 0)
186 int __cdecl __acrt_pack_narrow_command_line_and_environment(
187     _In_z_                    char const* const* argv,
188     _In_opt_z_                char const* const* envp,
189     _Outptr_result_maybenull_ char**             command_line_result,
190     _Outptr_result_maybenull_ char**             environment_block_result
191     );
192 
193 _Success_(return == 0)
194 _Ret_range_(-1, 0)
195 int __cdecl __acrt_pack_wide_command_line_and_environment(
196     _In_z_                    wchar_t const* const* argv,
197     _In_opt_z_                wchar_t const* const* envp,
198     _Outptr_result_maybenull_ wchar_t**             command_line_result,
199     _Outptr_result_maybenull_ wchar_t**             environment_block_result
200     );
201 
202 _Ret_z_
203 _Success_(return != 0)
204 char** __acrt_capture_narrow_argv(
205     _In_                             va_list*    arglist,
206     _In_z_                           char const* first_argument,
207     _When_(return == caller_array, _Post_z_)
208     _Out_writes_(caller_array_count) char**      caller_array,
209     _In_                             size_t      caller_array_count
210     );
211 
212 _Ret_z_
213 _Success_(return != 0)
214 wchar_t** __acrt_capture_wide_argv(
215     _In_                             va_list*       arglist,
216     _In_z_                           wchar_t const* first_argument,
217     _When_(return == caller_array, _Post_z_)
218     _Out_writes_(caller_array_count) wchar_t**      caller_array,
219     _In_                             size_t         caller_array_count
220     );
221 
222 void __cdecl __acrt_call_reportfault(
223     int   nDbgHookCode,
224     DWORD dwExceptionCode,
225     DWORD dwExceptionFlags
226     );
227 
228 
229 
230 #ifndef _M_CEE_PURE
231     _DEFINE_SET_FUNCTION(_set_pgmptr,  _In_z_ char*,    _pgmptr)
232     _DEFINE_SET_FUNCTION(_set_wpgmptr, _In_z_ wchar_t*, _wpgmptr)
233 #endif
234 
235 
236 
237 extern _CRT_ALLOC_HOOK _pfnAllocHook;
238 
239 BOOL __cdecl __acrt_CreateProcessA(
240     _In_opt_    LPCSTR                lpApplicationName,
241     _Inout_opt_ LPSTR                 lpCommandLine,
242     _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
243     _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
244     _In_        BOOL                  bInheritHandles,
245     _In_        DWORD                 dwCreationFlags,
246     _In_opt_    LPVOID                lpEnvironment,
247     _In_opt_    LPCSTR                lpCurrentDirectory,
248     _In_        LPSTARTUPINFOW        lpStartupInfo,
249     _Out_       LPPROCESS_INFORMATION lpProcessInformation
250     );
251 
252 _Success_(return > 0)
253 DWORD __cdecl __acrt_GetTempPath2A(
254     DWORD nBufferLength,
255     _Out_writes_to_(nBufferLength, return + 1) PSTR lpBuffer
256     );
257 
258 DWORD __cdecl __acrt_GetModuleFileNameA(
259     _In_opt_                HMODULE hModule,
260     _When_(return < nSize, _Out_writes_to_(nSize, return + 1))
261     _When_(return == nSize, _Out_writes_all_(nSize) _Null_terminated_) char * lpFilename,
262     _In_range_(1, MAX_PATH) DWORD   nSize
263     );
264 
265 HMODULE __cdecl __acrt_LoadLibraryExA(
266     _In_       LPCSTR lpFileName,
267     _Reserved_ HANDLE  hFile,
268     _In_       DWORD   dwFlags
269     );
270 
271 BOOL __cdecl __acrt_SetEnvironmentVariableA(
272     _In_     LPCSTR lpName,
273     _In_opt_ LPCSTR lpValue
274     );
275 
276 BOOL __cdecl __acrt_SetCurrentDirectoryA(
277     _In_ LPCSTR lpPathName
278     );
279 
280 
281 // Adding some defines which are used in dbgrpt.c
282 #define DBGRPT_MAX_MSG 4096
283 #define DBGRPT_TOOLONGMSG "_CrtDbgReport: String too long or IO Error"
284 #define DBGRPT_INVALIDMSG "_CrtDbgReport: String too long or Invalid characters in String"
285 
286 #ifdef __cplusplus
287 extern "C++"
288 {
289     template <typename Character>
290     struct __crt_report_hook_node
291     {
292         using hook_type = int(__CRTDECL*)(int, Character*, int*);
293 
294         __crt_report_hook_node* prev;
295         __crt_report_hook_node* next;
296         unsigned                refcount;
297         hook_type               hook;
298     };
299 }
300 #endif
301 
302 _Success_(return != 0)
303 unsigned char* __cdecl __acrt_allocate_buffer_for_argv(
304     _In_ size_t argument_count,
305     _In_ size_t character_count,
306     _In_ size_t character_size
307     );
308 
309 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
310 //
311 // CoreCRT Shared Initialization Support
312 //
313 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
314 typedef bool (__cdecl* __acrt_initialize_pft  )(void);
315 typedef bool (__cdecl* __acrt_uninitialize_pft)(bool);
316 
317 typedef struct __acrt_initializer
318 {
319     __acrt_initialize_pft   _initialize;
320     __acrt_uninitialize_pft _uninitialize;
321 } __acrt_initializer;
322 
323 bool __cdecl __acrt_execute_initializers(
324     _In_reads_(last - first) _In_ __acrt_initializer const* first,
325     _In_reads_(0) __acrt_initializer const* last
326     );
327 
328 bool __cdecl __acrt_execute_uninitializers(
329     _In_reads_(last - first) __acrt_initializer const* first,
330     _In_reads_(0) __acrt_initializer const* last
331     );
332 
333 
334 
335 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336 //
337 // CoreCRT Fatal Runtime Error Reporting
338 //
339 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
340 void __cdecl __acrt_report_runtime_error(_In_z_ wchar_t const* message);
341 
342 int __cdecl __acrt_show_narrow_message_box(
343     _In_opt_z_ char const* text,
344     _In_opt_z_ char const* caption,
345     _In_       unsigned    type
346     );
347 
348 int __cdecl __acrt_show_wide_message_box(
349     _In_opt_z_ wchar_t const* text,
350     _In_opt_z_ wchar_t const* caption,
351     _In_       unsigned       type
352     );
353 
354 
355 
356 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357 //
358 // AppCRT Initialization
359 //
360 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 bool __cdecl __acrt_initialize_winapi_thunks(void);
362 bool __cdecl __acrt_uninitialize_winapi_thunks(_In_ bool terminating);
363 
364 bool __cdecl __acrt_initialize_locks(void);
365 bool __cdecl __acrt_uninitialize_locks(_In_ bool terminating);
366 
367 bool __cdecl __acrt_initialize_heap(void);
368 bool __cdecl __acrt_uninitialize_heap(_In_ bool terminating);
369 
370 bool __cdecl __acrt_initialize_ptd(void);
371 bool __cdecl __acrt_uninitialize_ptd(_In_ bool terminating);
372 
373 bool __cdecl __acrt_initialize_lowio(void);
374 bool __cdecl __acrt_uninitialize_lowio(_In_ bool terminating);
375 
376 bool __cdecl __acrt_initialize_command_line(void);
377 bool __cdecl __acrt_uninitialize_command_line(_In_ bool terminating);
378 
379 void __cdecl __acrt_initialize_invalid_parameter_handler(_In_opt_ void* encoded_null);
380 void __cdecl __acrt_initialize_new_handler(_In_opt_ void* encoded_null);
381 void __cdecl __acrt_initialize_signal_handlers(_In_opt_ void* encoded_null);
382 void __cdecl __acrt_initialize_thread_local_exit_callback(_In_opt_ void * encoded_null);
383 
384 
385 
386 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
387 //
388 // AppCRT Locale
389 //
390 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391 // The offset to where ctype will point.  Look in initctype.cpp for how it is
392 // being used.  It was introduced so that pctype can work with unsigned char
393 // types and EOF.  It is used only in initctype and setlocale.
394 #define _COFFSET 127
395 
396 // Maximum lengths for the language name, country name, and full locale name.
397 #define MAX_LANG_LEN 64
398 #define MAX_CTRY_LEN 64
399 #define MAX_LC_LEN   (MAX_LANG_LEN + MAX_CTRY_LEN + 3)
400 
401 #define MAX_CP_LEN   16  // Maximum code page name length
402 #define CATNAMES_LEN 57  // "LC_COLLATE=;LC_CTYPE=;..." length
403 
404 #define LC_INT_TYPE  0
405 #define LC_STR_TYPE  1
406 #define LC_WSTR_TYPE 2
407 
408 #define _WSETLOCALE_AVOID_SYNC_LOCALE_BIT   0x10
409 #define _PER_THREAD_LOCALE_BIT              0x2
410 #define _GLOBAL_LOCALE_BIT                  0x1
411 
412 
413 
414 typedef struct __crt_locale_string_table
415 {
416     wchar_t* szName;
417     wchar_t  chAbbrev[4];
418 } __crt_locale_string_table;
419 
420 typedef struct __crt_locale_strings
421 {
422     wchar_t szLanguage  [MAX_LANG_LEN];
423     wchar_t szCountry   [MAX_CTRY_LEN];
424     wchar_t szCodePage  [MAX_CP_LEN];
425     wchar_t szLocaleName[LOCALE_NAME_MAX_LENGTH];
426 } __crt_locale_strings;
427 
428 typedef struct __crt_lc_time_data
429 {
430     char*    wday_abbr [ 7];
431     char*    wday      [ 7];
432     char*    month_abbr[12];
433     char*    month     [12];
434     char*    ampm      [ 2];
435     char*    ww_sdatefmt;
436     char*    ww_ldatefmt;
437     char*    ww_timefmt;
438     int      ww_caltype;
439     long     refcount;
440     wchar_t* _W_wday_abbr [ 7];
441     wchar_t* _W_wday      [ 7];
442     wchar_t* _W_month_abbr[12];
443     wchar_t* _W_month     [12];
444     wchar_t* _W_ampm      [ 2];
445     wchar_t* _W_ww_sdatefmt;
446     wchar_t* _W_ww_ldatefmt;
447     wchar_t* _W_ww_timefmt;
448     wchar_t* _W_ww_locale_name;
449 } __crt_lc_time_data;
450 
451 typedef struct __crt_ctype_compatibility_data
452 {
453     unsigned long id;
454     int           is_clike;
455 } __crt_ctype_compatibility_data;
456 
457 typedef struct __crt_qualified_locale_data
458 {
459     // Static data for qualified locale code
460     wchar_t const* pchLanguage;
461     wchar_t const* pchCountry;
462     int            iLocState;
463     int            iPrimaryLen;
464     BOOL           bAbbrevLanguage;
465     BOOL           bAbbrevCountry;
466     UINT           _cachecp;
467     wchar_t        _cachein [MAX_LC_LEN];
468     wchar_t        _cacheout[MAX_LC_LEN];
469 
470     // Static data for LC_CTYPE
471     __crt_ctype_compatibility_data _Loc_c[5];
472     wchar_t                        _cacheLocaleName[LOCALE_NAME_MAX_LENGTH];
473 } __crt_qualified_locale_data;
474 
475 typedef struct __crt_qualified_locale_data_downlevel
476 {
477     // Static data for the downlevel qualified locale code
478     int iLcidState;
479     LCID lcidLanguage;
480     LCID lcidCountry;
481 } __crt_qualified_locale_data_downlevel;
482 
483 typedef struct __crt_multibyte_data
484 {
485     long           refcount;
486     int            mbcodepage;
487     int            ismbcodepage;
488     unsigned short mbulinfo[6];
489     unsigned char  mbctype[257];
490     unsigned char  mbcasemap[256];
491     wchar_t const* mblocalename;
492 } __crt_multibyte_data;
493 
494 typedef struct __crt_locale_refcount
495 {
496     char*    locale;
497     wchar_t* wlocale;
498     long*    refcount;
499     long*    wrefcount;
500 } __crt_locale_refcount;
501 
502 typedef struct __crt_locale_data
503 {
504     __crt_locale_data_public  _public;
505     long                      refcount;
506     unsigned int              lc_collate_cp;
507     unsigned int              lc_time_cp;
508     int                       lc_clike;
509     __crt_locale_refcount     lc_category[6];
510     long*                     lconv_intl_refcount;
511     long*                     lconv_num_refcount;
512     long*                     lconv_mon_refcount;
513     struct lconv*             lconv;
514     long*                     ctype1_refcount;
515     unsigned short*           ctype1;
516     unsigned char const*      pclmap;
517     unsigned char const*      pcumap;
518     __crt_lc_time_data const* lc_time_curr;
519     wchar_t*                  locale_name[6];
520 } __crt_locale_data;
521 
522 // Unusual: < 0 => string length
523 //           else scan up to specified size or string length, whichever comes first
524 // The name is based on _In_NLS_string_.
525 #define _In_CRT_NLS_string_(size) _When_((size) < 0,  _In_z_)                               \
526                                   _When_((size) >= _String_length_(_Curr_), _Pre_z_)        \
527                                   _When_((size) < _String_length_(_Curr_), _In_reads_(size))
528 
529 // Wrappers for locale-related Windows API functionality
530 int __cdecl __acrt_CompareStringA(
531     _In_opt_               _locale_t _Plocinfo,
532     _In_                   LPCWSTR   _LocaleName,
533     _In_                   DWORD     _DwCmpFlags,
534     _In_CRT_NLS_string_(_CchCount1) PCCH _LpString1,
535     _In_                   int       _CchCount1,
536     _In_CRT_NLS_string_(_CchCount2) PCCH _LpString2,
537     _In_                   int       _CchCount2,
538     _In_                   int       _CodePage
539     );
540 
541 int __cdecl __acrt_CompareStringW(
542     _In_                   LPCWSTR  _LocaleName,
543     _In_                   DWORD    _DwCmpFlags,
544     _In_CRT_NLS_string_(_CchCount1) PCWCH _LpString1,
545     _In_                   int      _CchCount1,
546     _In_CRT_NLS_string_(_CchCount2) PCWCH _LpString2,
547     _In_                   int      _CchCount2
548     );
549 
550 int __cdecl __acrt_GetLocaleInfoA(
551     _In_opt_ _locale_t _Locale,
552     _In_     int       _LCType,
553     _In_     LPCWSTR   _LocaleName,
554     _In_     LCTYPE    _FieldType,
555     _Out_    void*     _Address
556     );
557 
558 _Success_(return)
559 BOOL __cdecl __acrt_GetStringTypeA(
560     _In_opt_            _locale_t _Plocinfo,
561     _In_                DWORD     _DWInfoType,
562     _In_NLS_string_(_CchSrc) PCCH _LpSrcStr,
563     _In_                int       _CchSrc,
564     _Out_               LPWORD    _LpCharType,
565     _In_                int       _CodePage,
566     _In_                BOOL      _BError
567     );
568 
569 _Success_(return)
570 BOOL __cdecl __acrt_GetStringTypeW(
571     _In_                DWORD       _DWInfoType,
572     _In_NLS_string_(_CchSrc) PCWCH  _LpSrcStr,
573     _In_                int         _CchSrc,
574     _Out_               LPWORD      _LpCharType
575 );
576 
577 _Success_(return != 0)
578 int __cdecl __acrt_LCMapStringA(
579     _In_opt_                   _locale_t _Plocinfo,
580     _In_                       LPCWSTR   _LocaleName,
581     _In_                       DWORD     _DwMapFlag,
582     _In_CRT_NLS_string_(_CchSrc) PCCH    _LpSrcStr,
583     _In_                       int       _CchSrc,
584     _Out_writes_opt_(_CchDest) PCH       _LpDestStr,
585     _In_                       int       _CchDest,
586     _In_                       int       _CodePage,
587     _In_                       BOOL      _BError
588     );
589 
590 _Success_(return != 0)
591 int __cdecl __acrt_LCMapStringW(
592     _In_                       LPCWSTR _LocaleName,
593     _In_                       DWORD   _DWMapFlag,
594     _In_CRT_NLS_string_(_CchSrc) PCWCH _LpSrcStr,
595     _In_                       int     _CchSrc,
596     _Out_writes_opt_(_CchDest) PWCH    _LpDestStr,
597     _In_                       int     _CchDest
598     );
599 
600 _Success_(return != 0)
601 int __cdecl __acrt_MultiByteToWideChar(
602     _In_                           UINT    _CodePage,
603     _In_                           DWORD   _DWFlags,
604     _In_                           LPCSTR  _LpMultiByteStr,
605     _In_                           int     _CbMultiByte,
606     _Out_writes_opt_(_CchWideChar) LPWSTR  _LpWideCharStr,
607     _In_                           int     _CchWideChar
608     );
609 
610 _Success_(return != 0)
611 int __cdecl __acrt_WideCharToMultiByte(
612     _In_                           UINT    _CodePage,
613     _In_                           DWORD   _DWFlags,
614     _In_                           LPCWSTR _LpWideCharStr,
615     _In_                           int     _CchWideChar,
616     _Out_writes_opt_(_CbMultiByte) LPSTR   _LpMultiByteStr,
617     _In_                           int     _CbMultiByte,
618     _In_opt_                       LPCSTR  _LpDefaultChar,
619     _Out_opt_                      LPBOOL  _LpUsedDefaultChar
620     );
621 
622 // Case-insensitive ASCII comparisons
623 _Check_return_
624 int __cdecl __ascii_memicmp(
625     _In_reads_bytes_(count) void const * lhs,
626     _In_reads_bytes_(count) void const * rhs,
627     _In_                    size_t       count
628     );
629 
630 _Check_return_
631 int __cdecl __ascii_stricmp(
632     _In_z_ char const * lhs,
633     _In_z_ char const * rhs
634     );
635 
636 _Check_return_
637 int __cdecl __ascii_strnicmp(
638     _In_reads_or_z_(count) char const * lhs,
639     _In_reads_or_z_(count) char const * rhs,
640     _In_                   size_t       count
641     );
642 
643 _Check_return_
644 int __cdecl __ascii_wcsicmp(
645     _In_z_ const wchar_t * lhs,
646     _In_z_ const wchar_t * rhs
647     );
648 
649 _Check_return_
650 int __cdecl __ascii_wcsnicmp(
651     _In_reads_or_z_(count) const wchar_t * lhs,
652     _In_reads_or_z_(count) const wchar_t * rhs,
653     _In_                  size_t          count
654     );
655 
656 
657 // Locale reference counting
658 void __cdecl __acrt_add_locale_ref    (__crt_locale_data*);
659 void __cdecl __acrt_release_locale_ref(__crt_locale_data*);
660 void __cdecl __acrt_free_locale       (__crt_locale_data*);
661 
662 long __cdecl __acrt_locale_add_lc_time_reference(
663     _In_opt_ __crt_lc_time_data const* lc_time
664     );
665 
666 long __cdecl __acrt_locale_release_lc_time_reference(
667     _In_opt_ __crt_lc_time_data const* lc_time
668     );
669 
670 void __cdecl __acrt_locale_free_lc_time_if_unreferenced(
671     _In_opt_ __crt_lc_time_data const* lc_time
672     );
673 
674 // Initialization and cleanup functions for locale categories
675 _Success_(return == 0)
676 int __cdecl __acrt_locale_initialize_ctype(
677     _Inout_ __crt_locale_data* locale_data
678     );
679 
680 _Success_(return == 0)
681 int __cdecl __acrt_locale_initialize_monetary(
682     _Inout_ __crt_locale_data* locale_data
683     );
684 
685 _Success_(return == 0)
686 int __cdecl __acrt_locale_initialize_numeric(
687     _Inout_ __crt_locale_data* locale_data
688     );
689 
690 _Success_(return == 0)
691 int __cdecl __acrt_locale_initialize_time(
692     _Inout_ __crt_locale_data* locale_data
693     );
694 
695 void __cdecl __acrt_locale_free_monetary(
696     _Inout_ struct lconv* lconv
697     );
698 
699 void __cdecl __acrt_locale_free_numeric(
700     _Inout_ struct lconv* lconv
701     );
702 
703 void __cdecl __acrt_locale_free_time(
704     _Inout_opt_ __crt_lc_time_data* lc_time_data
705     );
706 
707 
708 
709 // Locale synchronization
710 __crt_locale_data*    __cdecl __acrt_update_thread_locale_data   (void);
711 __crt_multibyte_data* __cdecl __acrt_update_thread_multibyte_data(void);
712 
713 
714 
715 _Success_(return != 0)
716 _Ret_z_
717 _Check_return_
718 wchar_t* __cdecl __acrt_copy_locale_name(
719     _In_z_ wchar_t const* locale_name
720     );
721 
722 _Success_(return != 0)
723 BOOL __cdecl __acrt_get_qualified_locale(
724     _In_      __crt_locale_strings const* input_strings,
725     _Out_opt_ UINT*                       code_page,
726     _Out_opt_ __crt_locale_strings*       result_strings
727     );
728 
729 _Success_(return != 0)
730 BOOL __cdecl __acrt_get_qualified_locale_downlevel(
731     _In_      __crt_locale_strings const* input_strings,
732     _Out_opt_ UINT*                       code_page,
733     _Out_opt_ __crt_locale_strings*       result_strings
734     );
735 
736 
737 // Global variable that is nonzero if the locale has been changed on any thread.
738 // Do not touch this global variable; call __acrt_locale_changed instead.
739 extern long __acrt_locale_changed_data;
740 
741 #ifdef __cplusplus
742 
743     // Returns true if the locale has been changed on any thread.
__acrt_locale_changed()744     __inline bool __cdecl __acrt_locale_changed()
745     {
746         // No need for __crt_interlocked_read, since __acrt_locale_changed_data
747         // is a 4 byte natural aligned memory, guaranteed to be atomic
748         // accessed on all platforms.
749         return __acrt_locale_changed_data != FALSE;
750     }
751 
752 #endif
753 
754 void __cdecl __acrt_set_locale_changed(void);
755 
756 
757 // Non-NLS language and country/region string tables:
758 extern __crt_locale_string_table const __acrt_rg_language[];
759 extern size_t                    const __acrt_rg_language_count;
760 
761 extern __crt_locale_string_table const __acrt_rg_country[];
762 extern size_t                    const __acrt_rg_country_count;
763 
764 // The lconv and LC TIME structures for the C locale:
765 extern struct lconv             __acrt_lconv_c;
766 extern __crt_lc_time_data const __lc_time_c;
767 
768 // The initial and current locale states:
769 extern __crt_multibyte_data  __acrt_initial_multibyte_data;
770 extern __crt_locale_data     __acrt_initial_locale_data;
771 extern __crt_locale_pointers __acrt_initial_locale_pointers;
772 
773 #ifdef __cplusplus
774 
775     extern __crt_state_management::dual_state_global<
776         __crt_locale_data*
777     > __acrt_current_locale_data;
778 
779     extern __crt_state_management::dual_state_global<
780         __crt_multibyte_data*
781     > __acrt_current_multibyte_data;
782 
783 #endif
784 
785 
786 // The current lconv structure:
787 extern struct lconv* __acrt_lconv;
788 
789 // Character tables:
790 extern unsigned short const __newctype[];
791 extern unsigned char  const __newclmap[];
792 extern unsigned char  const __newcumap[];
793 
794 // The name of the C locale, as a wide string ("C")
795 extern wchar_t __acrt_wide_c_locale_string[];
796 
797 
798 
799 // The global locale status, to support the threadlocale.obj link option
800 extern int __globallocalestatus;
801 
802 
803 
804 bool __cdecl __acrt_initialize_multibyte(void);
805 
806 
807 
__acrt_isleadbyte_l_noupdate(_In_ int const c,_In_ _locale_t const locale)808 __inline int __CRTDECL __acrt_isleadbyte_l_noupdate(
809     _In_ int       const c,
810     _In_ _locale_t const locale
811     )
812 {
813     return __acrt_locale_get_ctype_array_value(locale->locinfo->_public._locale_pctype, c, _LEADBYTE);
814 }
815 
816 
817 
818 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
819 //
820 // AppCRT Math
821 //
822 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823 void __cdecl __acrt_initialize_user_matherr(void* encoded_null);
824 bool __cdecl __acrt_has_user_matherr(void);
825 int  __cdecl __acrt_invoke_user_matherr(struct _exception*);
826 
827 
828 
829 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
830 //
831 // AppCRT Threading
832 //
833 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
834 typedef struct __acrt_thread_parameter
835 {
836     // The thread procedure and context argument
837     void*   _procedure;
838     void*   _context;
839 
840     // The handle for the newly created thread.  This is initialized only from
841     // _beginthread (not _beginthreadex).  When a thread created via _beginthread
842     // exits, it frees this handle.
843     HANDLE _thread_handle;
844 
845     // The handle for the module in which the user's thread procedure is defined.
846     // This may be null if the handle could not be obtained.  This handle enables
847     // us to bump the reference count of the user's module, to ensure that the
848     // module will not be unloaded while the thread is executing.  When the thread
849     // exits, it frees this handle.
850     HMODULE _module_handle;
851 
852     // This flag is true if RoInitialized was called on the thread to initialize
853     // it into the MTA.
854     bool    _initialized_apartment;
855 } __acrt_thread_parameter;
856 
857 
858 
859 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
860 //
861 // AppCRT Per-Thread Data
862 //
863 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
864 typedef struct __acrt_ptd
865 {
866     // These three data members support signal handling and runtime errors
867     struct __crt_signal_action_t* _pxcptacttab;     // Pointer to the exception-action table
868     EXCEPTION_POINTERS*           _tpxcptinfoptrs;  // Pointer to the exception info pointers
869     int                           _tfpecode;        // Last floating point exception code
870 
871     terminate_handler  _terminate;  // terminate() routine
872 
873     int                  _terrno;          // errno value
874     unsigned long        _tdoserrno;       // _doserrno value
875 
876     unsigned int         _rand_state;      // Previous value of rand()
877 
878     // Per-thread strtok(), wcstok(), and mbstok() data:
879     char*                _strtok_token;
880     unsigned char*       _mbstok_token;
881     wchar_t*             _wcstok_token;
882 
883     // Per-thread tmpnam() data:
884     char*                _tmpnam_narrow_buffer;
885     wchar_t*             _tmpnam_wide_buffer;
886 
887     // Per-thread time library data:
888     char*                _asctime_buffer;  // Pointer to asctime() buffer
889     wchar_t*             _wasctime_buffer; // Pointer to _wasctime() buffer
890     struct tm*           _gmtime_buffer;   // Pointer to gmtime() structure
891 
892     char*                _cvtbuf;          // Pointer to the buffer used by ecvt() and fcvt().
893 
894     // Per-thread error message data:
895     char*      _strerror_buffer;            // Pointer to strerror()  / _strerror()  buffer
896     wchar_t*   _wcserror_buffer;            // Pointer to _wcserror() / __wcserror() buffer
897 
898     // Locale data:
899     __crt_multibyte_data*                  _multibyte_info;
900     __crt_locale_data*                     _locale_info;
901     __crt_qualified_locale_data            _setloc_data;
902     __crt_qualified_locale_data_downlevel* _setloc_downlevel_data;
903     int                                    _own_locale;   // See _configthreadlocale() and __acrt_should_sync_with_global_locale()
904 
905     // The buffer used by _putch(), and the flag indicating whether the buffer
906     // is currently in use or not.
907     unsigned char  _putch_buffer[MB_LEN_MAX];
908     unsigned short _putch_buffer_used;
909 
910     // The thread-local invalid parameter handler
911     _invalid_parameter_handler _thread_local_iph;
912 
913     // If this thread was started by the CRT (_beginthread or _beginthreadex),
914     // then this points to the context with which the thread was created.  If
915     // this thread was not started by the CRT, this pointer is null.
916     __acrt_thread_parameter* _beginthread_context;
917 
918 } __acrt_ptd;
919 
920 __acrt_ptd* __cdecl __acrt_getptd(void);
921 __acrt_ptd* __cdecl __acrt_getptd_head(void);
922 __acrt_ptd* __cdecl __acrt_getptd_noexit(void);
923 void        __cdecl __acrt_freeptd(void);
924 
925 
926 
927 void __cdecl __acrt_errno_map_os_error (unsigned long);
928 int  __cdecl __acrt_errno_from_os_error(unsigned long);
929 
930 
931 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
932 //
933 // AppCRT Multi-Threading and Synchronization
934 //
935 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
936 typedef enum __acrt_lock_id
937 {
938     __acrt_heap_lock,
939     __acrt_debug_lock,
940     __acrt_exit_lock,
941     __acrt_signal_lock,
942     __acrt_locale_lock,
943     __acrt_multibyte_cp_lock,
944     __acrt_time_lock,
945     __acrt_lowio_index_lock,
946     __acrt_stdio_index_lock,
947     __acrt_conio_lock,
948     __acrt_popen_lock,
949     __acrt_environment_lock,
950     __acrt_tempnam_lock,
951     __acrt_os_exit_lock,
952     __acrt_lock_count
953 } __acrt_lock_id;
954 
955 #define _CORECRT_SPINCOUNT 4000
956 
957 void __cdecl __acrt_lock(_In_ __acrt_lock_id lock);
958 void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock);
959 
960 
961 
962 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
963 //
964 // CoreCRT SEH Encapsulation
965 //
966 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
967 #ifdef __cplusplus
968 extern "C++"
969 {
970     template <typename Action>
971     auto __acrt_lock_and_call(__acrt_lock_id const lock_id, Action&& action) throw()
972         -> decltype(action())
973     {
974         return __crt_seh_guarded_call<decltype(action())>()(
975             [lock_id]() { __acrt_lock(lock_id); },
976             action,
977             [lock_id]() { __acrt_unlock(lock_id); });
978     }
979 }
980 #endif
981 
982 
983 
984 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
985 //
986 // AppCRT Heap Internals and Debug Heap Internals
987 //
988 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989 extern HANDLE __acrt_heap;
990 
991 _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size)
992 void* __cdecl _expand_base(
993     _Pre_notnull_ void*  block,
994     _In_          size_t size
995     );
996 
997 // For detection of heap mismatch between MSVCRT and UCRT
998 #define _UCRT_HEAP_MISMATCH_DETECTION   0
999 #define _UCRT_HEAP_MISMATCH_RECOVERY    0
1000 #define _UCRT_HEAP_MISMATCH_BREAK       0
1001 
1002 #define _UCRT_HEAP_MISMATCH_ANY (_UCRT_HEAP_MISMATCH_DETECTION || _UCRT_HEAP_MISMATCH_RECOVERY || _UCRT_HEAP_MISMATCH_BREAK)
1003 
1004 #if _UCRT_HEAP_MISMATCH_ANY && (defined _M_IX86 || defined _M_AMD64)
1005     HANDLE __cdecl __acrt_get_msvcrt_heap_handle(void);
1006 #endif
1007 
1008 
1009 // CRT Allocation macros:
1010 #ifndef _DEBUG
1011     #define _expand_crt    _expand
1012 
1013     #define _strdup_crt    _strdup
1014 
1015     #define _dupenv_s_crt  _dupenv_s
1016     #define _wdupenv_s_crt _wdupenv_s
1017 
1018 #else
1019     #define _expand_crt(p, s)      _expand_dbg(p, s, _CRT_BLOCK)
1020 
1021     #define _strdup_crt(s)         _strdup_dbg(s, _CRT_BLOCK, __FILE__, __LINE__)
1022 
1023     #define _dupenv_s_crt(...)     _dupenv_s_dbg(__VA_ARGS__, _CRT_BLOCK, __FILE__, __LINE__)
1024     #define _wdupenv_s_crt(...)    _wdupenv_s_dbg(__VA_ARGS__, _CRT_BLOCK, __FILE__, __LINE__)
1025 
1026 #endif
1027 
1028 
1029 
1030 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1031 //
1032 // CoreCRT Scoped HANDLE Wrappers
1033 //
1034 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1035 // These classes are similar to the WRL HandleT and its traits.  We cannot use
1036 // HandleT because it has a virtual function, InternalClose().  (Every object
1037 // that uses a HandleT instantiation also has the RTTI data for that HandleT
1038 // instantiation. This RTTI data causes the object to depend on type_info, which
1039 // causes an indirect dependency on operator delete.  This breaks static linking
1040 // of the CRT, when operator delete is replaced in a user-provided object.
1041 #ifdef __cplusplus
1042 extern "C++"
1043 {
1044     struct __crt_handle_traits
1045     {
1046         typedef HANDLE type;
1047 
close__crt_handle_traits1048         static bool close(_In_ type handle) throw()
1049         {
1050             return ::CloseHandle(handle) != FALSE;
1051         }
1052 
get_invalid_value__crt_handle_traits1053         static type get_invalid_value() throw()
1054         {
1055             return INVALID_HANDLE_VALUE;
1056         }
1057     };
1058 
1059     struct __crt_hmodule_traits
1060     {
1061         typedef HMODULE type;
1062 
close__crt_hmodule_traits1063         static bool close(_In_ type handle) throw()
1064         {
1065             return ::FreeLibrary(handle) != FALSE;
1066         }
1067 
get_invalid_value__crt_hmodule_traits1068         static type get_invalid_value() throw()
1069         {
1070             return nullptr;
1071         }
1072     };
1073 
1074     struct __crt_findfile_traits
1075     {
1076         typedef HANDLE type;
1077 
close__crt_findfile_traits1078         static bool close(_In_ type handle) throw()
1079         {
1080             return ::FindClose(handle) != FALSE;
1081         }
1082 
get_invalid_value__crt_findfile_traits1083         static type get_invalid_value() throw()
1084         {
1085             return INVALID_HANDLE_VALUE;
1086         }
1087     };
1088 
1089 
1090 
1091     template <typename Traits>
1092     class __crt_unique_handle_t
1093     {
1094     public:
1095 
1096         typedef Traits                traits_type;
1097         typedef typename Traits::type handle_type;
1098 
throw()1099         explicit __crt_unique_handle_t(handle_type const h = traits_type::get_invalid_value()) throw()
1100             : _handle(h)
1101         {
1102         }
1103 
throw()1104         __crt_unique_handle_t(_Inout_ __crt_unique_handle_t&& h) throw()
1105             : _handle(h._handle)
1106         {
1107             h._handle = traits_type::get_invalid_value();
1108         }
1109 
throw()1110         ~__crt_unique_handle_t() throw()
1111         {
1112             close();
1113         }
1114 
throw()1115         __crt_unique_handle_t& operator=(_Inout_ __crt_unique_handle_t&& h) throw()
1116         {
1117             close();
1118             _handle = h._handle;
1119             h._handle = traits_type::get_invalid_value();
1120             return *this;
1121         }
1122 
attach(handle_type h)1123         void attach(handle_type h) throw()
1124         {
1125             if (h != _handle)
1126             {
1127                 close();
1128                 _handle = h;
1129             }
1130         }
1131 
detach()1132         handle_type detach() throw()
1133         {
1134             handle_type h = _handle;
1135             _handle = traits_type::get_invalid_value();
1136             return h;
1137         }
1138 
get()1139         handle_type get() const throw()
1140         {
1141             return _handle;
1142         }
1143 
close()1144         void close() throw()
1145         {
1146             if (_handle == traits_type::get_invalid_value())
1147                 return;
1148 
1149             traits_type::close(_handle);
1150             _handle = traits_type::get_invalid_value();
1151         }
1152 
is_valid()1153         bool is_valid() const throw()
1154         {
1155             return _handle != traits_type::get_invalid_value();
1156         }
1157 
throw()1158         operator bool() const throw()
1159         {
1160             return is_valid();
1161         }
1162 
get_address_of()1163         handle_type* get_address_of() throw()
1164         {
1165             return &_handle;
1166         }
1167 
release_and_get_address_of()1168         handle_type* release_and_get_address_of() throw()
1169         {
1170             close();
1171             return &_handle;
1172         }
1173 
1174     private:
1175 
1176         __crt_unique_handle_t(__crt_unique_handle_t const&) throw();
1177         __crt_unique_handle_t& operator=(__crt_unique_handle_t const&) throw();
1178 
1179         handle_type _handle;
1180     };
1181 
1182     typedef __crt_unique_handle_t<__crt_handle_traits>   __crt_unique_handle;
1183     typedef __crt_unique_handle_t<__crt_hmodule_traits>  __crt_unique_hmodule;
1184     typedef __crt_unique_handle_t<__crt_findfile_traits> __crt_findfile_handle;
1185 
1186 } // extern "C++"
1187 #endif // __cplusplus
1188 
1189 
1190 
1191 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1192 //
1193 // AppCRT Windows API Thunks
1194 //
1195 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1196 BOOL WINAPI __acrt_AreFileApisANSI(void);
1197 
1198 int WINAPI __acrt_CompareStringEx(
1199     _In_opt_                       LPCWSTR          locale_name,
1200     _In_                           DWORD            flags,
1201     _In_NLS_string_(string1_count) LPCWCH           string1,
1202     _In_                           int              string1_count,
1203     _In_NLS_string_(string2_count) LPCWCH           string2,
1204     _In_                           int              string2_count,
1205     _Reserved_                     LPNLSVERSIONINFO version,
1206     _Reserved_                     LPVOID           reserved,
1207     _Reserved_                     LPARAM           param
1208     );
1209 
1210 BOOL WINAPI __acrt_EnumSystemLocalesEx(
1211     _In_     LOCALE_ENUMPROCEX enum_proc,
1212     _In_     DWORD             flags,
1213     _In_     LPARAM            param,
1214     _In_opt_ LPVOID            reserved
1215     );
1216 
1217 DWORD WINAPI __acrt_FlsAlloc(
1218     _In_opt_ PFLS_CALLBACK_FUNCTION lpCallback
1219     );
1220 
1221 BOOL WINAPI __acrt_FlsFree(
1222     _In_ DWORD dwFlsIndex
1223     );
1224 
1225 PVOID WINAPI __acrt_FlsGetValue(
1226     _In_ DWORD dwFlsIndex
1227     );
1228 
1229 BOOL WINAPI __acrt_FlsSetValue(
1230     _In_     DWORD dwFlsIndex,
1231     _In_opt_ PVOID lpFlsData
1232     );
1233 
1234 int WINAPI __acrt_GetDateFormatEx(
1235     _In_opt_                       LPCWSTR           locale_name,
1236     _In_                           DWORD             flags,
1237     _In_opt_                       SYSTEMTIME CONST* date,
1238     _In_opt_                       LPCWSTR           format,
1239     _Out_writes_opt_(buffer_count) LPWSTR            buffer,
1240     _In_opt_                       int               buffer_count,
1241     _In_opt_                       LPCWSTR           calendar
1242     );
1243 
1244 int WINAPI __acrt_GetTempPath2W(
1245     _In_ DWORD nBufferLength,
1246     _Out_writes_to_opt_(BufferLength, return +1) LPWSTR lpBuffer
1247     );
1248 
1249 DWORD64 WINAPI __acrt_GetEnabledXStateFeatures(void);
1250 
1251 int WINAPI __acrt_GetLocaleInfoEx(
1252     _In_opt_                       LPCWSTR locale_name,
1253     _In_                           LCTYPE  lc_type,
1254     _Out_writes_opt_(data_count)   LPWSTR  data,
1255     _In_                           int     data_count
1256     );
1257 
1258 VOID WINAPI __acrt_GetSystemTimePreciseAsFileTime(
1259     _Out_ LPFILETIME system_time
1260     );
1261 
1262 int WINAPI __acrt_GetTimeFormatEx(
1263     _In_opt_                         LPCWSTR           locale_name,
1264     _In_                             DWORD             flags,
1265     _In_opt_                         SYSTEMTIME CONST* time,
1266     _In_opt_                         LPCWSTR           format,
1267     _Out_writes_opt_(buffer_count)   LPWSTR            buffer,
1268     _In_opt_                         int               buffer_count
1269     );
1270 
1271 int WINAPI __acrt_GetUserDefaultLocaleName(
1272     _Out_writes_(locale_name_count) LPWSTR  locale_name,
1273     _In_                            int     locale_name_count
1274     );
1275 
1276 _Must_inspect_result_
1277 BOOL WINAPI __acrt_GetXStateFeaturesMask(
1278     _In_  PCONTEXT context,
1279     _Out_ PDWORD64 feature_mask
1280     );
1281 
1282 BOOL WINAPI __acrt_InitializeCriticalSectionEx(
1283     _Out_ LPCRITICAL_SECTION critical_section,
1284     _In_  DWORD              spin_count,
1285     _In_  DWORD              flags
1286     );
1287 
1288 BOOL WINAPI __acrt_IsValidLocaleName(
1289     _In_ LPCWSTR locale_name
1290     );
1291 
1292 int WINAPI __acrt_LCMapStringEx(
1293     _In_opt_                            LPCWSTR          locale_name,
1294     _In_                                DWORD            flags,
1295     _In_CRT_NLS_string_(source_count)   LPCWSTR          source,
1296     _In_                                int              source_count,
1297     _Out_writes_opt_(destination_count) LPWSTR           destination,
1298     _In_                                int              destination_count,
1299     _In_opt_                            LPNLSVERSIONINFO version,
1300     _In_opt_                            LPVOID           reserved,
1301     _In_opt_                            LPARAM           sort_handle
1302     );
1303 
1304 int WINAPI __acrt_LCIDToLocaleName(
1305     _In_                         LCID   locale,
1306     _Out_writes_opt_(name_count) LPWSTR name,
1307     _In_                         int    name_count,
1308     _In_                         DWORD  flags
1309     );
1310 
1311 DWORD WINAPI __acrt_LocaleNameToLCID(
1312     _In_ LPCWSTR name,
1313     _In_ DWORD   flags
1314     );
1315 
1316 _Success_(return != NULL)
1317 PVOID WINAPI __acrt_LocateXStateFeature(
1318     _In_      PCONTEXT content,
1319     _In_      DWORD    feature_id,
1320     _Out_opt_ PDWORD   length
1321     );
1322 
1323 int WINAPI __acrt_MessageBoxA(
1324     _In_opt_ HWND   hwnd,
1325     _In_opt_ LPCSTR text,
1326     _In_opt_ LPCSTR caption,
1327     _In_     UINT   type
1328     );
1329 
1330 int WINAPI __acrt_MessageBoxW(
1331     _In_opt_ HWND    hwnd,
1332     _In_opt_ LPCWSTR text,
1333     _In_opt_ LPCWSTR caption,
1334     _In_     UINT    type
1335     );
1336 
1337 void WINAPI __acrt_OutputDebugStringA(
1338     _In_opt_ LPCSTR text
1339     );
1340 
1341 #ifdef __cplusplus
1342     HRESULT WINAPI __acrt_RoInitialize(
1343         _In_ RO_INIT_TYPE init_type
1344         );
1345 #endif
1346 
1347 void WINAPI __acrt_RoUninitialize(void);
1348 
1349 _Success_(return != 0)
1350 BOOLEAN WINAPI __acrt_RtlGenRandom(
1351     _Out_writes_bytes_(buffer_count) PVOID buffer,
1352     _In_                             ULONG buffer_count
1353     );
1354 
1355 LONG WINAPI __acrt_AppPolicyGetProcessTerminationMethodInternal(_Out_ AppPolicyProcessTerminationMethod* policy);
1356 LONG WINAPI __acrt_AppPolicyGetThreadInitializationTypeInternal(_Out_ AppPolicyThreadInitializationType* policy);
1357 LONG WINAPI __acrt_AppPolicyGetShowDeveloperDiagnosticInternal(_Out_ AppPolicyShowDeveloperDiagnostic* policy);
1358 LONG WINAPI __acrt_AppPolicyGetWindowingModelInternal(_Out_ AppPolicyWindowingModel* policy);
1359 
1360 BOOL WINAPI __acrt_SetThreadStackGuarantee(
1361     _Inout_ PULONG stack_size_in_bytes
1362     );
1363 
1364 
1365 bool __cdecl __acrt_can_show_message_box(void);
1366 bool __cdecl __acrt_can_use_vista_locale_apis(void);
1367 void __cdecl __acrt_eagerly_load_locale_apis(void);
1368 bool __cdecl __acrt_can_use_xstate_apis(void);
1369 HWND __cdecl __acrt_get_parent_window(void);
1370 bool __cdecl __acrt_is_interactive(void);
1371 
1372 bool __cdecl __acrt_app_verifier_enabled(void);
1373 bool __cdecl __acrt_is_secure_process(void);
1374 
1375 LCID __cdecl __acrt_DownlevelLocaleNameToLCID(
1376     _In_opt_ LPCWSTR localeName
1377     );
1378 
1379 _Success_(return != 0)
1380 int __cdecl __acrt_DownlevelLCIDToLocaleName(
1381     _In_      LCID   lcid,
1382     _Out_writes_opt_z_(cchLocaleName) LPWSTR outLocaleName,
1383     _In_      int    cchLocaleName
1384     );
1385 
1386 
1387 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1388 //
1389 // AppCRT Signal Handling and Exception Filter
1390 //
1391 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1392 
1393 // Pointer to a signal handler
1394 typedef void (__cdecl* __crt_signal_handler_t)(int);
1395 
1396 // Exception-action table used by the C runtime to identify and dispose of
1397 // exceptions corresponding to C runtime errors or C signals.
1398 struct __crt_signal_action_t
1399 {
1400     // Exception code or number; defined by the host OS.
1401     unsigned long _exception_number;
1402 
1403     // Signal code or number; defined by the CRT.
1404     int _signal_number;
1405 
1406     // Exception action code. Either a special code or the address of
1407     // a handler function. Always determines how the exception filter
1408     // should dispose of the exception.
1409     __crt_signal_handler_t _action;
1410 };
1411 
1412 extern struct __crt_signal_action_t const __acrt_exception_action_table[];
1413 
1414 // Number of entries in the exception-action table
1415 extern size_t const __acrt_signal_action_table_count;
1416 
1417 // Size of exception-action table (in bytes)
1418 extern size_t const __acrt_signal_action_table_size;
1419 
1420 // Index of the first floating point exception entry
1421 extern size_t const __acrt_signal_action_first_fpe_index;
1422 
1423 // Number of FPE entries
1424 extern size_t const __acrt_signal_action_fpe_count;
1425 
1426 __crt_signal_handler_t __cdecl __acrt_get_sigabrt_handler(void);
1427 
1428 
1429 
1430 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1431 //
1432 // DesktopCRT Environment
1433 //
1434 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1435 #ifdef __cplusplus
1436     extern __crt_state_management::dual_state_global<char**>    _environ_table;
1437     extern __crt_state_management::dual_state_global<wchar_t**> _wenviron_table;
1438 #endif
1439 
1440 extern wchar_t** __dcrt_initial_wide_environment;
1441 extern char**    __dcrt_initial_narrow_environment;
1442 
1443 _Ret_opt_z_
1444 char*    __cdecl __dcrt_get_narrow_environment_from_os(void) _CRT_NOEXCEPT;
1445 
1446 _Ret_opt_z_
1447 wchar_t* __cdecl __dcrt_get_wide_environment_from_os(void) _CRT_NOEXCEPT;
1448 
1449 _Deref_ret_opt_z_
1450 char**    __cdecl __dcrt_get_or_create_narrow_environment_nolock(void);
1451 
1452 _Deref_ret_opt_z_
1453 wchar_t** __cdecl __dcrt_get_or_create_wide_environment_nolock(void);
1454 
1455 void __cdecl __dcrt_uninitialize_environments_nolock(void);
1456 
1457 
1458 int __cdecl __dcrt_set_variable_in_narrow_environment_nolock(
1459     _In_ _Post_invalid_ char* option,
1460     _In_                int   is_top_level_call
1461     );
1462 
1463 int __cdecl __dcrt_set_variable_in_wide_environment_nolock(
1464     _In_ _Post_invalid_ wchar_t* option,
1465     _In_                int      is_top_level_call
1466     );
1467 
1468 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1469 //
1470 // Internal fast locale functions with no extra checks
1471 //
1472 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1473 // Only use these when the input char is validated to be an unsigned char and not EOF.
1474 // Ensure locale has already been updated.
_toupper_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1475 _Check_return_ __forceinline unsigned char __cdecl _toupper_fast_internal(
1476     _In_ unsigned char const c,
1477     _In_ _locale_t const     locale
1478     )
1479 {
1480     return locale->locinfo->pcumap[c];
1481 }
1482 
_tolower_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1483 _Check_return_ __forceinline unsigned char __cdecl _tolower_fast_internal(
1484     _In_ unsigned char const c,
1485     _In_ _locale_t const     locale
1486     )
1487 {
1488     return locale->locinfo->pclmap[c];
1489 }
1490 
1491 extern const unsigned short _wctype[];
1492 
_towupper_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1493 _Check_return_ __forceinline wint_t _towupper_fast_internal(
1494     _In_ unsigned char const c,
1495     _In_ _locale_t const     locale
1496     )
1497 {
1498     // Check for iswlower required because upper map assumes using narrow ctype categories.
1499     // towupper uses a locale-sensitive transformation, but only if the wide character
1500     // is considered lowercase in UTF-16.
1501     // _wctype starts at EOF. Add one to map to characters.
1502     if (_wctype[c + 1] & _LOWER)
1503     {
1504         return _toupper_fast_internal(c, locale);
1505     }
1506     return c;
1507 }
1508 
_towupper_internal(_In_ unsigned short const c,_In_ _locale_t const locale)1509 _Check_return_ inline wint_t _towupper_internal(
1510     _In_ unsigned short const c,
1511     _In_ _locale_t const      locale
1512     )
1513 {
1514     if (c < 256)
1515     {
1516         return _towupper_fast_internal((unsigned char) c, locale);
1517     }
1518 
1519     return _towupper_l(c, locale);
1520 }
1521 
_towlower_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1522 _Check_return_ __forceinline wint_t _towlower_fast_internal(
1523     _In_ unsigned char const c,
1524     _In_ _locale_t const     locale
1525     )
1526 {
1527     // Check for iswupper required because lower map assumes using narrow ctype categories.
1528     // towlower uses a locale-sensitive transformation, but only if the wide character
1529     // is considered uppercase in UTF-16.
1530     // _wctype starts at EOF. Add one to map to characters.
1531     if (_wctype[c + 1] & _UPPER)
1532     {
1533         return _tolower_fast_internal(c, locale);
1534     }
1535 
1536     return c;
1537 }
1538 
_towlower_internal(_In_ unsigned short const c,_In_ _locale_t const locale)1539 _Check_return_ inline wint_t _towlower_internal(
1540     _In_ unsigned short const c,
1541     _In_ _locale_t const      locale
1542     )
1543 {
1544     if (c < 256)
1545     {
1546         return _towlower_fast_internal((unsigned char) c, locale);
1547     }
1548 
1549     return _towlower_l(c, locale);
1550 }
1551 
_ctype_fast_check_internal(_In_ unsigned char const c,_In_ int const _Mask,_In_ _locale_t const locale)1552 _Check_return_ __forceinline unsigned short __cdecl _ctype_fast_check_internal(
1553     _In_ unsigned char const c,
1554     _In_ int const           _Mask,
1555     _In_ _locale_t const     locale
1556     )
1557 {
1558     return locale->locinfo->_public._locale_pctype[c] & _Mask;
1559 }
1560 
_isdigit_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1561 _Check_return_ __forceinline unsigned short __cdecl _isdigit_fast_internal(
1562     _In_ unsigned char const c,
1563     _In_ _locale_t const     locale
1564     )
1565 {
1566     return _ctype_fast_check_internal(c, _DIGIT, locale);
1567 }
1568 
1569 // isleadbyte has a macro that casts the first argument to unsigned char
1570 // Instead of using _isleadbyte_l (which requires the caller to cast to unsigned char),
1571 // use _isleadbyte_fast_internal to prevent any unintentional casting errors that may occur.
1572 // As long as the locale is already updated via _LocaleUpdate or retrieved from __crt_cached_ptd_host,
1573 // this function is safe to use.
1574 #define _isleadbyte_l(_C, _L) use_isleadbyte_fast_internal_instead_to_prevent_casting_errors()
1575 
_isleadbyte_fast_internal(_In_ unsigned char const c,_In_ _locale_t const locale)1576 _Check_return_ __forceinline unsigned short __cdecl _isleadbyte_fast_internal(
1577     _In_ unsigned char const c,
1578     _In_ _locale_t const     locale
1579     )
1580 {
1581     return _ctype_fast_check_internal(c, _LEADBYTE, locale);
1582 }
1583 
1584 
1585 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1586 //
1587 // Invalid Parameter Macros
1588 //
1589 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1590 // Invoke Watson if _ExpressionError is not 0; otherwise simply return
1591 // _ExpressionError.
1592 _CRT_SECURITYCRITICAL_ATTRIBUTE
_invoke_watson_if_error(_In_ errno_t expression_error,_In_opt_z_ wchar_t const * expression,_In_opt_z_ wchar_t const * function_name,_In_opt_z_ wchar_t const * file_name,_In_ unsigned int line_number,_In_ uintptr_t reserved)1593 __forceinline void _invoke_watson_if_error(
1594     _In_       errno_t        expression_error,
1595     _In_opt_z_ wchar_t const* expression,
1596     _In_opt_z_ wchar_t const* function_name,
1597     _In_opt_z_ wchar_t const* file_name,
1598     _In_       unsigned int   line_number,
1599     _In_       uintptr_t      reserved
1600     )
1601 {
1602     if (expression_error == 0)
1603     {
1604         return;
1605     }
1606 
1607     _invoke_watson(expression, function_name, file_name, line_number, reserved);
1608 }
1609 
1610 // Invoke Watson if _ExpressionError is not 0 and equal to _ErrorValue1 or
1611 // _ErrorValue2; otherwise simply return _EspressionError.
_invoke_watson_if_oneof(_In_ errno_t expression_error,_In_ errno_t error_value1,_In_ errno_t error_value2,_In_opt_z_ wchar_t const * expression,_In_opt_z_ wchar_t const * function_name,_In_opt_z_ wchar_t const * file_name,_In_ unsigned int line_number,_In_ uintptr_t reserved)1612 __forceinline errno_t _invoke_watson_if_oneof(
1613     _In_       errno_t        expression_error,
1614     _In_       errno_t        error_value1,
1615     _In_       errno_t        error_value2,
1616     _In_opt_z_ wchar_t const* expression,
1617     _In_opt_z_ wchar_t const* function_name,
1618     _In_opt_z_ wchar_t const* file_name,
1619     _In_       unsigned int   line_number,
1620     _In_       uintptr_t      reserved
1621     )
1622 {
1623     if (expression_error == 0 || (expression_error != error_value1 && expression_error != error_value2))
1624     {
1625         return expression_error;
1626     }
1627 
1628     _invoke_watson(expression, function_name, file_name, line_number, reserved);
1629 }
1630 
1631 #ifdef _DEBUG
1632     #define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error((expr), _CRT_WIDE(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0)
1633     #define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof(expr, (errvalue1), (errvalue2), _CRT_WIDE(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0)
1634 #else
1635     #define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error(expr, NULL, NULL, NULL, 0, 0)
1636     #define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof((expr), (errvalue1), (errvalue2), NULL, NULL, NULL, 0, 0)
1637 #endif
1638 
1639 #define _ERRCHECK(e)               _INVOKE_WATSON_IF_ERROR(e)
1640 #define _ERRCHECK_EINVAL(e)        _INVOKE_WATSON_IF_ONEOF(e, EINVAL, EINVAL)
1641 #define _ERRCHECK_EINVAL_ERANGE(e) _INVOKE_WATSON_IF_ONEOF(e, EINVAL, ERANGE)
1642 
1643 #define _ERRCHECK_SPRINTF(_PrintfCall)      \
1644     {                                       \
1645         errno_t _SaveErrno = errno;         \
1646         errno = 0;                          \
1647         if ((_PrintfCall) < 0)              \
1648         {                                   \
1649             _ERRCHECK_EINVAL_ERANGE(errno); \
1650         }                                   \
1651         errno = _SaveErrno;                 \
1652     }
1653 
1654 
1655 
1656 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1657 //
1658 // SecureCRT
1659 //
1660 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1661 // We completely fill the buffer only in debug (see _SECURECRT__FILL_STRING and
1662 // _SECURECRT__FILL_BYTE macros).
1663 #ifndef _SECURECRT_FILL_BUFFER
1664     #ifdef _DEBUG
1665         #define _SECURECRT_FILL_BUFFER 1
1666     #else
1667         #define _SECURECRT_FILL_BUFFER 0
1668     #endif
1669 #endif
1670 
1671 #ifndef _SECURECRT_FILL_BUFFER_THRESHOLD
1672 // _SECURECRT_FILL_BUFFER_THRESHOLD must be a constant for Prefast due to the
1673 // double evaluation. Making it something unique like 42 would pollute Prefast's warnings.
1674     #if defined _PREFAST_ || !defined _DEBUG
1675         #define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)0)
1676     #else
1677         #define _SECURECRT_FILL_BUFFER_THRESHOLD (_CrtGetDebugFillThreshold())
1678     #endif
1679 #endif
1680 
1681 // TODO make this a template so that _CrtGetDebugFillThreshold is not called multiple times.
1682 #if _SECURECRT_FILL_BUFFER
1683     #define _SECURECRT__FILL_STRING(_String, _Count, _Offset)                       \
1684         if ((_Count) != ((size_t)-1) &&                                             \
1685             (_Count) != INT_MAX &&                                                  \
1686             ((size_t)(_Offset)) < (_Count))                                         \
1687         {                                                                           \
1688             size_t max_buffer_count = _SECURECRT_FILL_BUFFER_THRESHOLD;             \
1689             memset(                                                                 \
1690                 (_String) + (_Offset),                                              \
1691                 _SECURECRT_FILL_BUFFER_PATTERN,                                     \
1692                 (max_buffer_count < ((size_t)((_Count) - (_Offset)))                \
1693                     ? max_buffer_count                                              \
1694                     : ((_Count) - (_Offset))) * sizeof(*(_String)));                \
1695         }
1696 #else
1697     #define _SECURECRT__FILL_STRING(_String, _Count, _Offset)
1698 #endif
1699 
1700 #if _SECURECRT_FILL_BUFFER
1701     #define _SECURECRT__FILL_BYTE(_Position)                \
1702         if (_SECURECRT_FILL_BUFFER_THRESHOLD > 0)           \
1703         {                                                   \
1704             (_Position) = _SECURECRT_FILL_BUFFER_PATTERN;   \
1705         }
1706 #else
1707     #define _SECURECRT__FILL_BYTE(_Position)
1708 #endif
1709 
1710 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1711 //
1712 // Precondition Validation Macros
1713 //
1714 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1715 // We use _VALIDATE_STREAM_ANSI_RETURN to ensure that ANSI file operations (e.g.
1716 // fprintf) aren't called on files opened as UNICODE. We do this check only if
1717 // it's an actual FILE pointer & not a string.
1718 #define _VALIDATE_STREAM_ANSI_RETURN(stream, errorcode, retexpr)               \
1719     {                                                                          \
1720         __crt_stdio_stream const _Stream(stream);                              \
1721         int fn;                                                                \
1722         _VALIDATE_RETURN((                                                     \
1723             (_Stream.is_string_backed()) ||                                    \
1724             (fn = _fileno(_Stream.public_stream()),                            \
1725                 ((_textmode_safe(fn) == __crt_lowio_text_mode::ansi) &&        \
1726                 !_tm_unicode_safe(fn)))),                                      \
1727             errorcode, retexpr)                                                \
1728     }
1729 
1730 #define _CHECK_FH_RETURN( handle, errorcode, retexpr )                         \
1731     {                                                                          \
1732         if(handle == _NO_CONSOLE_FILENO)                                       \
1733         {                                                                      \
1734             errno = errorcode;                                                 \
1735             return ( retexpr );                                                \
1736         }                                                                      \
1737     }
1738 
1739 #define _CHECK_FH_CLEAR_OSSERR_RETURN( handle, errorcode, retexpr )            \
1740     {                                                                          \
1741         if(handle == _NO_CONSOLE_FILENO)                                       \
1742         {                                                                      \
1743             _doserrno = 0L;                                                    \
1744             errno = errorcode;                                                 \
1745             return ( retexpr );                                                \
1746         }                                                                      \
1747     }
1748 
1749 #define _CHECK_FH_CLEAR_OSSERR_RETURN_ERRCODE( handle, retexpr )               \
1750     {                                                                          \
1751         if(handle == _NO_CONSOLE_FILENO)                                       \
1752         {                                                                      \
1753             _doserrno = 0L;                                                    \
1754             return ( retexpr );                                                \
1755         }                                                                      \
1756     }
1757 
1758 
1759 
1760 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1761 //
1762 // Redirect-to-Locale Macros
1763 //
1764 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1765 #ifdef __cplusplus
1766     #define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE extern "C"
1767 #else
1768     #define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE
1769 #endif
1770 
1771 #define _REDIRECT_TO_L_VERSION_1(_ReturnType, _FunctionName, _Type1)                          \
1772     _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE                                                      \
1773     _ReturnType __cdecl _FunctionName(_Type1 _Arg1)                                           \
1774     {                                                                                         \
1775         return _FunctionName##_l(_Arg1, NULL);                                                \
1776     }
1777 
1778 #define _REDIRECT_TO_L_VERSION_2(_ReturnType, _FunctionName, _Type1, _Type2)                  \
1779     _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE                                                      \
1780     _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2)                             \
1781     {                                                                                         \
1782         return _FunctionName##_l(_Arg1, _Arg2, NULL);                                         \
1783     }
1784 
1785 #define _REDIRECT_TO_L_VERSION_3(_ReturnType, _FunctionName, _Type1, _Type2, _Type3)          \
1786     _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE                                                      \
1787     _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3)               \
1788     {                                                                                         \
1789         return _FunctionName##_l(_Arg1, _Arg2, _Arg3, NULL);                                  \
1790     }
1791 
1792 #define _REDIRECT_TO_L_VERSION_4(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4)  \
1793     _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE                                                      \
1794     _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4) \
1795     {                                                                                         \
1796         return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, NULL);                           \
1797     }
1798 
1799 
1800 
1801 #ifdef __cplusplus
1802 extern "C++"
1803 {
1804     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1805     //
1806     // Forward declare PTD propagation host
1807     //
1808     // To use the PTD propagation utilities, include corecrt_internal_ptd_propagation.h.
1809     // That header also opts into removing old validation macros that would use errno,
1810     // so the __crt_cached_ptd_host is declared here so that headers don't need to be fully converted.
1811     //
1812     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1813 
1814     class __crt_cached_ptd_host;
1815 
1816     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1817     //
1818     // Internals with PTD propagation
1819     //
1820     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1821 
1822     extern "C" void __cdecl __acrt_errno_map_os_error_ptd(unsigned long, __crt_cached_ptd_host&);
1823 
1824     extern "C" void __cdecl _invalid_parameter_internal(
1825         _In_opt_z_ wchar_t const*,
1826         _In_opt_z_ wchar_t const*,
1827         _In_opt_z_ wchar_t const*,
1828         _In_       unsigned int,
1829         _In_       uintptr_t,
1830         _Inout_    __crt_cached_ptd_host&
1831         );
1832 
1833     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1834     //
1835     // Locale Update
1836     //
1837     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1838     extern "C" void __acrt_update_locale_info(
1839         _In_     __acrt_ptd*        const ptd,
1840         _Inout_ __crt_locale_data** const data
1841         );
1842 
1843     extern "C" void __acrt_update_multibyte_info(
1844         _In_    __acrt_ptd*            const ptd,
1845         _Inout_ __crt_multibyte_data** const data
1846         );
1847 
1848     // Querying the global state index queries TLS.
1849     // If the global state index is known, use the explicit functions to avoid a GetFlsValue call.
1850     extern "C" void __acrt_update_locale_info_explicit(
1851         _In_     __acrt_ptd*        const ptd,
1852         _Inout_ __crt_locale_data** const data,
1853         _In_    size_t              const current_global_state_index
1854         );
1855 
1856     extern "C" void __acrt_update_multibyte_info_explicit(
1857         _In_    __acrt_ptd*            const ptd,
1858         _Inout_ __crt_multibyte_data** const data,
1859         _In_    size_t                 const current_global_state_index
1860         );
1861 
__acrt_should_sync_with_global_locale(_In_ __acrt_ptd * const ptd)1862     extern "C" __inline bool __acrt_should_sync_with_global_locale(
1863         _In_ __acrt_ptd* const ptd
1864         )
1865     {
1866         // Check whether per-thread locales are enabled either:
1867         //  * On the thread (_ptd->_own_locale & _PER_THREAD_LOCALE_BIT is set)
1868         //  * Globally (__globallocalestatus & _GLOBAL_LOCALE_BIT is set)
1869 
1870         // If neither are enabled then we want to check the global locale setting
1871         // and synchronize it to our per-thread-data.
1872 
1873         // _own_locale
1874         // bits: 000000000000000000000000 000W 00P1
1875         // P is set after _configthreadlocale(_ENABLE_PER_THREAD_LOCALE).
1876         // W is set in _wsetlocale to prevent resynchronization during _wsetlocale.
1877         // Note that this means when _wsetlocale is ask whether it should to synchronize,
1878         // it should not use __acrt_should_sync_with_global_locale.
1879 
1880         // __globallocalestatus
1881         // bits: 111111111111111111111111 1111 1N1G
1882         // G is set if threadlocale.obj was linked to (via _configthreadlocale(-1)).
1883         // N is whether new locales use the global locale and is unrelated to locale ptd sync.
1884 
1885         // if _ENABLE_PER_THREAD_LOCALE is not set and threadlocale.obj is not linked to
1886         return (ptd->_own_locale & __globallocalestatus) == 0;
1887     }
1888 
1889     // The per-thread locale is sometimes temporarily protected from resynchronization from
1890     // the global locale to ensure calling the public API surface without locale information
1891     // will not cause the locale to be reloaded half way through a call.
1892 
1893     // This is only to protect us from ourselves - a future change can correct the need for these calls.
1894     // Allows different 'bit_value' so that _wsetlocale can also use this.
1895     extern "C" __inline void __acrt_disable_global_locale_sync(
1896         _In_ __acrt_ptd* const ptd,
1897         _In_ int         const bit_value = _PER_THREAD_LOCALE_BIT
1898         )
1899     {
1900         ptd->_own_locale |= bit_value;
1901     }
1902 
1903     extern "C" __inline void __acrt_enable_global_locale_sync(
1904         _In_ __acrt_ptd* const ptd,
1905         _In_ int         const bit_value = _PER_THREAD_LOCALE_BIT
1906         )
1907     {
1908         ptd->_own_locale &= ~bit_value;
1909     }
1910 
1911     class _LocaleUpdate
1912     {   // Retained for old code paths - updating/locking/unlocking locale
1913         // in every function is costly.
1914         // Prefer using __crt_cached_ptd_host&.
1915     public:
1916 
_LocaleUpdate(_locale_t const locale)1917         explicit _LocaleUpdate(_locale_t const locale) throw()
1918             : _updated(false)
1919         {
1920             if (locale)
1921             {
1922                 _locale_pointers = *locale;
1923             }
1924             else if (!__acrt_locale_changed())
1925             {
1926                 _locale_pointers = __acrt_initial_locale_pointers;
1927             }
1928             else
1929             {
1930                 _ptd = __acrt_getptd();
1931                 _locale_pointers.locinfo = _ptd->_locale_info;
1932                 _locale_pointers.mbcinfo = _ptd->_multibyte_info;
1933 
1934                 __acrt_update_locale_info   (_ptd, &_locale_pointers.locinfo);
1935                 __acrt_update_multibyte_info(_ptd, &_locale_pointers.mbcinfo);
1936 
1937                 if ((_ptd->_own_locale & _PER_THREAD_LOCALE_BIT) == 0)
1938                 {
1939                     // Skip re-synchronization with the global locale to prevent the
1940                     // locale from changing half-way through the call.
1941                     __acrt_disable_global_locale_sync(_ptd);
1942                     _updated = true;
1943                 }
1944             }
1945         }
1946 
throw()1947         ~_LocaleUpdate() throw()
1948         {
1949             if (_updated)
1950             {
1951                 __acrt_enable_global_locale_sync(_ptd);
1952             }
1953         }
1954 
GetLocaleT()1955         _locale_t GetLocaleT() throw()
1956         {
1957             return &_locale_pointers;
1958         }
1959 
1960     private:
1961 
1962         __acrt_ptd*           _ptd;
1963         // Using the locale data from the PTD ensures their lifetime
1964         // will last through the end of the call - no need to increment/decrement reference count.
1965         __crt_locale_pointers _locale_pointers;
1966         bool                  _updated;
1967 
1968     };
1969 
1970 
1971     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1972     //
1973     // errno Cache
1974     //
1975     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1976     // Some operations in this file may need to set or query errno many times.  Each
1977     // use of errno requires us to get the PTD from FLS.  To avoid having to do this
1978     // many times, we cache the pointer to errno.  This class encapsulates that
1979     // caching and also defers the initial acquisition of &errno until the first
1980     // time that errno is actually needed (when we aren't calling functions that may
1981     // set errno, there's no need to acquire errno at all).
1982     class __crt_deferred_errno_cache
1983     {   // Retained for old code paths - querying errno is a performance issue.
1984         // Prefer using __crt_cached_ptd_host&.
1985     public:
1986 
__crt_deferred_errno_cache()1987         __crt_deferred_errno_cache() throw()
1988             : _cached_errno{}
1989         {
1990         }
1991 
get()1992         errno_t& get() throw()
1993         {
1994             if (!_cached_errno)
1995             {
1996                 _cached_errno = &errno;
1997             }
1998 
1999             return *_cached_errno;
2000         }
2001 
2002     private:
2003 
2004         errno_t* _cached_errno;
2005     };
2006 
2007 
2008 
2009     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2010     //
2011     // errno and LastError Reset
2012     //
2013     //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2014     #ifndef _M_CEE
2015 
2016     struct __crt_errno_guard
2017     {   // Retained for old code paths - querying errno is a performance issue.
2018         // Prefer using __crt_cached_ptd_host& (via ->get_errno().create_guard()).
2019     public:
2020 
throw__crt_errno_guard2021         __crt_errno_guard(errno_t* const errno_address = &errno) throw()
2022             : _errno_address(errno_address), _stored_errno(*errno_address)
2023         {
2024             *errno_address = 0;
2025         }
2026 
throw__crt_errno_guard2027         ~__crt_errno_guard() throw()
2028         {
2029             if (*_errno_address == 0 && _stored_errno != 0)
2030                 *_errno_address = _stored_errno;
2031         }
2032 
2033     private:
2034 
2035         __crt_errno_guard(__crt_errno_guard const&) throw(); // not implemented
2036         void operator=(__crt_errno_guard const&) throw();    // not implemented
2037 
2038         errno_t* _errno_address;
2039         errno_t  _stored_errno;
2040     };
2041 
2042     // Resets the operating system last error (GetLastError) to its original
2043     // value on scope exit.
2044     class __crt_scoped_get_last_error_reset
2045     {
2046     public:
2047 
__crt_scoped_get_last_error_reset()2048         __crt_scoped_get_last_error_reset() throw()
2049         {
2050             _old_last_error = GetLastError();
2051         }
2052 
throw()2053         ~__crt_scoped_get_last_error_reset() throw()
2054         {
2055             SetLastError(_old_last_error);
2056         }
2057 
2058     private:
2059         __crt_scoped_get_last_error_reset(__crt_scoped_get_last_error_reset const&);
2060         __crt_scoped_get_last_error_reset& operator=(__crt_scoped_get_last_error_reset const&);
2061 
2062         DWORD _old_last_error;
2063     };
2064     #endif // _M_CEE
2065 } // extern "C++"
2066 #endif // __cplusplus
2067 
2068 
2069 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2070 //
2071 // Windows policy APIs
2072 //
2073 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2074 
2075 // Specifies method used to end a process
2076 typedef enum
2077 {
2078     process_end_policy_terminate_process,
2079     process_end_policy_exit_process
2080 } process_end_policy;
2081 
2082 process_end_policy __cdecl __acrt_get_process_end_policy(void);
2083 
2084 // Specifies whether RoInitialize() should be called when creating a thread
2085 typedef enum
2086 {
2087     begin_thread_init_policy_unknown,
2088     begin_thread_init_policy_none,
2089     begin_thread_init_policy_ro_initialize
2090 } begin_thread_init_policy;
2091 
2092 begin_thread_init_policy __cdecl __acrt_get_begin_thread_init_policy(void);
2093 
2094 // Specifies whether the Assert dialog should be shown
2095 typedef enum
2096 {
2097     developer_information_policy_unknown,
2098     developer_information_policy_none,
2099     developer_information_policy_ui
2100 } developer_information_policy;
2101 
2102 developer_information_policy __cdecl __acrt_get_developer_information_policy(void);
2103 
2104 // Specifies what type of Windowing support is available
2105 typedef enum
2106 {
2107     windowing_model_policy_unknown,
2108     windowing_model_policy_hwnd,
2109     windowing_model_policy_corewindow,
2110     windowing_model_policy_legacyphone,
2111     windowing_model_policy_none
2112 } windowing_model_policy;
2113 
2114 windowing_model_policy __cdecl __acrt_get_windowing_model_policy(void);
2115 
2116 
2117 _CRT_END_C_HEADER
2118 
2119 #include <corecrt_internal_state_isolation.h>
2120