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