1 //
2 // winapi_thunks.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Definitions of wrappers for Windows API functions that cannot be called
7 // directly because they are not available on all supported operating systems.
8 //
9 
10 #include <nt.h>
11 #include <ntrtl.h>
12 #include <nturtl.h>
13 #include <ntsecapi.h>
14 #include <corecrt_internal.h>
15 #include <appmodel.h>
16 #include <roapi.h>
17 
18 // This is simlar to msvcrt.
19 #if _M_AMD64 || _M_ARM || _M_ARM64 || _M_HYBRID
20 #define FLS_ALWAYS_AVAILABLE 1
21 #endif
22 
23  WINBASEAPI
24  _Success_(return > 0 && return < BufferLength)
25  DWORD
26  WINAPI
27  GetTempPath2W(
28      _In_ DWORD BufferLength,
29      _Out_writes_to_opt_(BufferLength,return + 1) LPWSTR Buffer
30      );
31 
32 // The XState APIs are declared by the Windows headers only when building for
33 // x86 and x64.  We declare them here unconditionally so that we can share the
34 // same code for all architectures (we simply avoid use of these functions on
35 // other architectures).
36 extern "C" WINBASEAPI DWORD64 WINAPI GetEnabledXStateFeatures();
37 
38 _Must_inspect_result_
39 extern "C" WINBASEAPI BOOL WINAPI GetXStateFeaturesMask(
40     _In_  PCONTEXT context,
41     _Out_ PDWORD64 feature_mask
42     );
43 
44 _Success_(return != NULL)
45 extern "C" WINBASEAPI PVOID WINAPI LocateXStateFeature(
46     _In_      PCONTEXT context,
47     _In_      DWORD    feature_id,
48     _Out_opt_ PDWORD   length
49     );
50 
51 #define _ACRT_APPLY_TO_LATE_BOUND_MODULES_0                                                              \
52     _APPLY(api_ms_win_core_datetime_l1_1_1,              "api-ms-win-core-datetime-l1-1-1"             ) \
53     _APPLY(api_ms_win_core_file_l1_2_4,                  "api-ms-win-core-file-l1-2-4"                 ) \
54     _APPLY(api_ms_win_core_file_l1_2_2,                  "api-ms-win-core-file-l1-2-2"                 ) \
55     _APPLY(api_ms_win_core_localization_l1_2_1,          "api-ms-win-core-localization-l1-2-1"         ) \
56     _APPLY(api_ms_win_core_localization_obsolete_l1_2_0, "api-ms-win-core-localization-obsolete-l1-2-0") \
57     _APPLY(api_ms_win_core_processthreads_l1_1_2,        "api-ms-win-core-processthreads-l1-1-2"       ) \
58     _APPLY(api_ms_win_core_string_l1_1_0,                "api-ms-win-core-string-l1-1-0"               ) \
59     _APPLY(api_ms_win_core_synch_l1_2_0,                 "api-ms-win-core-synch-l1-2-0"                ) \
60     _APPLY(api_ms_win_core_sysinfo_l1_2_1,               "api-ms-win-core-sysinfo-l1-2-1"              ) \
61     _APPLY(api_ms_win_core_winrt_l1_1_0,                 "api-ms-win-core-winrt-l1-1-0"                ) \
62     _APPLY(api_ms_win_core_xstate_l2_1_0,                "api-ms-win-core-xstate-l2-1-0"               ) \
63     _APPLY(api_ms_win_rtcore_ntuser_window_l1_1_0,       "api-ms-win-rtcore-ntuser-window-l1-1-0"      ) \
64     _APPLY(api_ms_win_security_systemfunctions_l1_1_0,   "api-ms-win-security-systemfunctions-l1-1-0"  ) \
65     _APPLY(ext_ms_win_ntuser_dialogbox_l1_1_0,           "ext-ms-win-ntuser-dialogbox-l1-1-0"          ) \
66     _APPLY(ext_ms_win_ntuser_windowstation_l1_1_0,       "ext-ms-win-ntuser-windowstation-l1-1-0"      ) \
67     _APPLY(advapi32,                                     "advapi32"                                    ) \
68     _APPLY(kernel32,                                     "kernel32"                                    ) \
69     _APPLY(kernelbase,                                   "kernelbase"                                  ) \
70     _APPLY(ntdll,                                        "ntdll"                                       ) \
71     _APPLY(api_ms_win_appmodel_runtime_l1_1_2,           "api-ms-win-appmodel-runtime-l1-1-2"          ) \
72     _APPLY(user32,                                       "user32"                                      )
73 
74 #if FLS_ALWAYS_AVAILABLE
75 
76 #define _ACRT_APPLY_TO_LATE_BOUND_MODULES_1 /* nothing */
77 
78 #else
79 
80 #define _ACRT_APPLY_TO_LATE_BOUND_MODULES_1                                                              \
81     _APPLY(api_ms_win_core_fibers_l1_1_0,                "api-ms-win-core-fibers-l1-1-0"               )
82 
83 #endif
84 
85 #define _ACRT_APPLY_TO_LATE_BOUND_MODULES  \
86     _ACRT_APPLY_TO_LATE_BOUND_MODULES_0 \
87     _ACRT_APPLY_TO_LATE_BOUND_MODULES_1 \
88 
89 #define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_0                                                                                                           \
90     _APPLY(AreFileApisANSI,                             ({ /* api_ms_win_core_file_l1_2_2, */            kernel32                                   })) \
91     _APPLY(CompareStringEx,                             ({ api_ms_win_core_string_l1_1_0,                kernel32                                   })) \
92     _APPLY(EnumSystemLocalesEx,                         ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
93     _APPLY(GetActiveWindow,                             ({ api_ms_win_rtcore_ntuser_window_l1_1_0,       user32                                     })) \
94     _APPLY(GetDateFormatEx,                             ({ api_ms_win_core_datetime_l1_1_1,              kernel32                                   })) \
95     _APPLY(GetTempPath2W,                               ({ api_ms_win_core_file_l1_2_4,                  kernelbase                                 })) \
96     _APPLY(GetEnabledXStateFeatures,                    ({ api_ms_win_core_xstate_l2_1_0,                kernel32                                   })) \
97     _APPLY(GetLastActivePopup,                          ({ ext_ms_win_ntuser_dialogbox_l1_1_0,           user32                                     })) \
98     _APPLY(GetLocaleInfoEx,                             ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
99     _APPLY(GetProcessWindowStation,                     ({ ext_ms_win_ntuser_windowstation_l1_1_0,       user32                                     })) \
100     _APPLY(GetSystemTimePreciseAsFileTime,              ({ api_ms_win_core_sysinfo_l1_2_1                                                           })) \
101     _APPLY(GetTimeFormatEx,                             ({ api_ms_win_core_datetime_l1_1_1,              kernel32                                   })) \
102     _APPLY(GetUserDefaultLocaleName,                    ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
103     _APPLY(GetUserObjectInformationW,                   ({ ext_ms_win_ntuser_windowstation_l1_1_0,       user32                                     })) \
104     _APPLY(GetXStateFeaturesMask,                       ({ api_ms_win_core_xstate_l2_1_0,                kernel32                                   })) \
105     _APPLY(InitializeCriticalSectionEx,                 ({ api_ms_win_core_synch_l1_2_0,                 kernel32                                   })) \
106     _APPLY(IsValidLocaleName,                           ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
107     _APPLY(LCMapStringEx,                               ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
108     _APPLY(LCIDToLocaleName,                            ({ api_ms_win_core_localization_obsolete_l1_2_0, kernel32                                   })) \
109     _APPLY(LocaleNameToLCID,                            ({ api_ms_win_core_localization_l1_2_1,          kernel32                                   })) \
110     _APPLY(LocateXStateFeature,                         ({ api_ms_win_core_xstate_l2_1_0,                kernel32                                   })) \
111     _APPLY(MessageBoxA,                                 ({ ext_ms_win_ntuser_dialogbox_l1_1_0,           user32                                     })) \
112     _APPLY(MessageBoxW,                                 ({ ext_ms_win_ntuser_dialogbox_l1_1_0,           user32                                     })) \
113     _APPLY(RoInitialize,                                ({ api_ms_win_core_winrt_l1_1_0                                                             })) \
114     _APPLY(RoUninitialize,                              ({ api_ms_win_core_winrt_l1_1_0                                                             })) \
115     _APPLY(AppPolicyGetProcessTerminationMethod,        ({ api_ms_win_appmodel_runtime_l1_1_2                                                       })) \
116     _APPLY(AppPolicyGetThreadInitializationType,        ({ api_ms_win_appmodel_runtime_l1_1_2                                                       })) \
117     _APPLY(AppPolicyGetShowDeveloperDiagnostic,         ({ api_ms_win_appmodel_runtime_l1_1_2                                                       })) \
118     _APPLY(AppPolicyGetWindowingModel,                  ({ api_ms_win_appmodel_runtime_l1_1_2                                                       })) \
119     _APPLY(SetThreadStackGuarantee,                     ({ api_ms_win_core_processthreads_l1_1_2,        kernel32                                   })) \
120     _APPLY(SystemFunction036,                           ({ api_ms_win_security_systemfunctions_l1_1_0,   advapi32                                   }))
121 
122 #if FLS_ALWAYS_AVAILABLE
123 
124 #define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1 /* nothing */
125 
126 #else
127 
128 #define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1                                                                                                           \
129     _APPLY(FlsAlloc,                                    ({ api_ms_win_core_fibers_l1_1_0,                kernel32                                   })) \
130     _APPLY(FlsFree,                                     ({ api_ms_win_core_fibers_l1_1_0,                kernel32                                   })) \
131     _APPLY(FlsGetValue,                                 ({ api_ms_win_core_fibers_l1_1_0,                kernel32                                   })) \
132     _APPLY(FlsSetValue,                                 ({ api_ms_win_core_fibers_l1_1_0,                kernel32                                   }))
133 
134 #endif
135 
136 #define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS \
137     _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_0 \
138     _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1 \
139 
140 namespace
141 {
142     // Generate enumerators for each of the modules:
143     enum module_id : unsigned
144     {
145         #define _APPLY(_SYMBOL, _NAME) _SYMBOL,
146         _ACRT_APPLY_TO_LATE_BOUND_MODULES
147         #undef _APPLY
148 
149         module_id_count
150     };
151 
152     // Generate a table of module names that can be indexed by the module_id
153     // enumerators:
154     static wchar_t const* const module_names[module_id_count] =
155     {
156         #define _APPLY(_SYMBOL, _NAME) _CRT_WIDE(_NAME),
157         _ACRT_APPLY_TO_LATE_BOUND_MODULES
158         #undef _APPLY
159     };
160 
161     // Generate enumerators for each of the functions:
162     enum function_id : unsigned
163     {
164         #define _APPLY(_FUNCTION, _MODULES) _CRT_CONCATENATE(_FUNCTION, _id),
165         _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
166         #undef _APPLY
167 
168         function_id_count
169     };
170 
171     // Generate a typedef for each function of the form function_pft.
172     #define _APPLY(_FUNCTION, _MODULES) \
173         using _CRT_CONCATENATE(_FUNCTION, _pft) = decltype(_FUNCTION)*;
174     _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
175     #undef _APPLY
176 }
177 
178 // This table stores the module handles that we have obtained via LoadLibrary.
179 // If a handle is null, we have not yet attempted to load that module.  If a
180 // handle is -1 (INVALID_HANDLE_VALUE), we have attempted to load the module
181 // but the attempt failed.
182 static HMODULE module_handles[module_id_count];
183 
184 // This table stores the function pointers that we have loaded dynamically.  The
185 // function pointers are stored in encoded form via __crt_fast_encode_ponter.  If
186 // a function pointer is an encoded null pointer, we have not yet attempted to
187 // get that function pointer.  If a function pointer is an encoded -1, we have
188 // attempted to get that function pointer but the attempt failed.
189 static void* encoded_function_pointers[function_id_count];
190 
__acrt_initialize_winapi_thunks()191 extern "C" bool __cdecl __acrt_initialize_winapi_thunks()
192 {
193     void* const encoded_nullptr = __crt_fast_encode_pointer(nullptr);
194 
195     for (void*& p : encoded_function_pointers)
196     {
197         p = encoded_nullptr;
198     }
199 
200     return true;
201 }
202 
__acrt_uninitialize_winapi_thunks(bool const terminating)203 extern "C" bool __cdecl __acrt_uninitialize_winapi_thunks(bool const terminating)
204 {
205     // If the process is terminating, there's no need to free any module handles
206     if (terminating)
207     {
208         return true;
209     }
210 
211     for (HMODULE& module : module_handles)
212     {
213         if (module)
214         {
215             if (module != INVALID_HANDLE_VALUE)
216             {
217                 FreeLibrary(module);
218             }
219 
220             module = nullptr;
221         }
222     }
223 
224     return true;
225 }
226 
invalid_function_sentinel()227 static __forceinline void* __cdecl invalid_function_sentinel() throw()
228 {
229     return reinterpret_cast<void*>(static_cast<uintptr_t>(-1));
230 }
231 
try_load_library_from_system_directory(wchar_t const * const name)232 static HMODULE __cdecl try_load_library_from_system_directory(wchar_t const* const name) throw()
233 {
234     HMODULE const handle = LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
235     if (handle)
236     {
237         return handle;
238     }
239 
240     // LOAD_LIBRARY_SEARCH_SYSTEM32 is only supported by Windows 7 and above; if
241     // the OS does not support this flag, try again without it.  On these OSes,
242     // all APISets will be forwarders.  To prevent DLL hijacking, do not attempt
243     // to load the APISet forwarders dynamically.  This will cause our caller to
244     // fall back to the real DLL (e.g. kernel32).  All of those are known DLLs.
245     if (GetLastError() == ERROR_INVALID_PARAMETER &&
246         wcsncmp(name, L"api-ms-", 7) != 0 &&
247         wcsncmp(name, L"ext-ms-", 7) != 0)
248     {
249         return LoadLibraryExW(name, nullptr, 0);
250     }
251 
252     return nullptr;
253 }
254 
try_get_module(module_id const id)255 static HMODULE __cdecl try_get_module(module_id const id) throw()
256 {
257     // First check to see if we've cached the module handle:
258     if (HMODULE const cached_handle = __crt_interlocked_read_pointer(module_handles + id))
259     {
260         if (cached_handle == INVALID_HANDLE_VALUE)
261         {
262             return nullptr;
263         }
264 
265         return cached_handle;
266     }
267 
268     // If we haven't yet cached the module handle, try to load the library.  If
269     // this fails, cache the sentinel handle value INVALID_HANDLE_VALUE so that
270     // we don't attempt to load the module again:
271     HMODULE const new_handle = try_load_library_from_system_directory(module_names[id]);
272     if (!new_handle)
273     {
274         if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(module_handles + id, INVALID_HANDLE_VALUE))
275         {
276             _ASSERTE(cached_handle == INVALID_HANDLE_VALUE);
277         }
278 
279         return nullptr;
280     }
281 
282     // Swap the new handle into the cache.  If the cache no longer contained a
283     // null handle, then some other thread loaded the module and cached the
284     // handle while we were doing the same.  In that case, we free the handle
285     // once to maintain the reference count:
286     if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(module_handles + id, new_handle))
287     {
288         _ASSERTE(cached_handle == new_handle);
289         FreeLibrary(new_handle);
290     }
291 
292     return new_handle;
293 }
294 
try_get_first_available_module(module_id const * const first,module_id const * const last)295 static HMODULE __cdecl try_get_first_available_module(
296     module_id const* const first,
297     module_id const* const last
298     ) throw()
299 {
300     for (module_id const* it = first; it != last; ++it)
301     {
302         HMODULE const handle = try_get_module(*it);
303         if (handle)
304         {
305             return handle;
306         }
307     }
308 
309     return nullptr;
310 }
311 
try_get_proc_address_from_first_available_module(char const * const name,module_id const * const first_module_id,module_id const * const last_module_id)312 static __forceinline void* __cdecl try_get_proc_address_from_first_available_module(
313     char      const* const name,
314     module_id const* const first_module_id,
315     module_id const* const last_module_id
316     ) throw()
317 {
318     HMODULE const module_handle = try_get_first_available_module(first_module_id, last_module_id);
319     if (!module_handle)
320     {
321         return nullptr;
322     }
323 
324     return reinterpret_cast<void*>(GetProcAddress(module_handle, name));
325 }
326 
try_get_function(function_id const id,char const * const name,module_id const * const first_module_id,module_id const * const last_module_id)327 static void* __cdecl try_get_function(
328     function_id      const id,
329     char      const* const name,
330     module_id const* const first_module_id,
331     module_id const* const last_module_id
332     ) throw()
333 {
334     // First check to see if we've cached the function pointer:
335     {
336         void* const cached_fp = __crt_fast_decode_pointer(
337             __crt_interlocked_read_pointer(encoded_function_pointers + id));
338 
339         if (cached_fp == invalid_function_sentinel())
340         {
341             return nullptr;
342         }
343 
344         if (cached_fp)
345         {
346             return cached_fp;
347         }
348     }
349 
350     // If we haven't yet cached the function pointer, try to import it from any
351     // of the modules in which it might be defined.  If this fails, cache the
352     // sentinel pointer so that we don't attempt to load this function again:
353     void* const new_fp = try_get_proc_address_from_first_available_module(name, first_module_id, last_module_id);
354     if (!new_fp)
355     {
356         void* const cached_fp = __crt_fast_decode_pointer(
357             __crt_interlocked_exchange_pointer(
358                 encoded_function_pointers + id,
359                 __crt_fast_encode_pointer(invalid_function_sentinel())));
360 
361         if (cached_fp)
362         {
363             _ASSERTE(cached_fp == invalid_function_sentinel());
364         }
365 
366         return nullptr;
367     }
368 
369     // Swap the newly obtained function pointer into the cache.  The cache may
370     // no longer contain an encoded null pointer if another thread obtained the
371     // function address while we were doing the same (both threads should have
372     // gotten the same function pointer):
373     {
374         void* const cached_fp = __crt_fast_decode_pointer(
375             __crt_interlocked_exchange_pointer(
376                 encoded_function_pointers + id,
377                 __crt_fast_encode_pointer(new_fp)));
378 
379         if (cached_fp)
380         {
381             _ASSERTE(cached_fp == new_fp);
382         }
383     }
384 
385     return new_fp;
386 }
387 
388 // Generate accessors that wrap the general try_get_function for each function,
389 // passing the correct set of candidate modules and returning a function pointer
390 // of the correct type:
391 #define _APPLY(_FUNCTION, _MODULES)                                                                   \
392     static _CRT_CONCATENATE(_FUNCTION, _pft) __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() throw()  \
393     {                                                                                                 \
394         static module_id const candidate_modules[] = _CRT_UNPARENTHESIZE(_MODULES);                   \
395                                                                                                       \
396         return reinterpret_cast<_CRT_CONCATENATE(_FUNCTION, _pft)>(try_get_function(                  \
397             _CRT_CONCATENATE(_FUNCTION, _id),                                                         \
398             _CRT_STRINGIZE(_FUNCTION),                                                                \
399             candidate_modules,                                                                        \
400             candidate_modules + _countof(candidate_modules)));                                        \
401     }
402 _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
403 #undef _APPLY
404 
__acrt_AreFileApisANSI()405 extern "C" BOOL WINAPI __acrt_AreFileApisANSI()
406 {
407     if (auto const are_file_apis_ansi = try_get_AreFileApisANSI())
408     {
409         return are_file_apis_ansi();
410     }
411 
412     // If we were unable to get the AreFileApisANSI function, we can safely
413     // assume that the file APIs are, in fact, ANSI:
414     return TRUE;
415 }
416 
__acrt_CompareStringEx(LPCWSTR const locale_name,DWORD const flags,LPCWCH const string1,int const string1_count,LPCWCH const string2,int const string2_count,LPNLSVERSIONINFO const version,LPVOID const reserved,LPARAM const param)417 extern "C" int WINAPI __acrt_CompareStringEx(
418     LPCWSTR          const locale_name,
419     DWORD            const flags,
420     LPCWCH           const string1,
421     int              const string1_count,
422     LPCWCH           const string2,
423     int              const string2_count,
424     LPNLSVERSIONINFO const version,
425     LPVOID           const reserved,
426     LPARAM           const param
427     )
428 {
429     if (auto const compare_string_ex = try_get_CompareStringEx())
430     {
431         // On WCOS devices, CompareStringEx may calls into icu.dll which is an OS component using the UCRT.
432         // If icu.dll calls any UCRT export under OS mode (ex: malloc), then CompareStringEx will return under Prog Mode even if
433         // we started in OS mode. To prevent this, an OS mode guard is in place.
434         __crt_state_management::scoped_global_state_reset os_mode_guard;
435         return compare_string_ex(locale_name, flags, string1, string1_count, string2, string2_count, version, reserved, param);
436     }
437 
438     return CompareStringW(__acrt_LocaleNameToLCID(locale_name, 0), flags, string1, string1_count, string2, string2_count);
439 }
440 
441 #ifdef __clang__
442 static LOCALE_ENUMPROCEX static_enum_proc;
LocaleEnumProcW(LPWSTR locale_string)443 static BOOL CALLBACK LocaleEnumProcW(LPWSTR locale_string)
444 {
445     return __crt_fast_decode_pointer(static_enum_proc)(locale_string, 0, 0);
446 }
447 #endif
448 
449 // This has been split into its own function to work around a bug in the Dev12
450 // C++ compiler where nested captureless lambdas are not convertible to the
451 // required function pointer type.
enum_system_locales_ex_nolock(LOCALE_ENUMPROCEX const enum_proc)452 static BOOL enum_system_locales_ex_nolock(
453     LOCALE_ENUMPROCEX const enum_proc
454     ) throw()
455 {
456 #ifndef __clang__
457     static LOCALE_ENUMPROCEX static_enum_proc;
458 #endif
459 
460     static_enum_proc = __crt_fast_encode_pointer(enum_proc);
461     BOOL const result = EnumSystemLocalesW((LOCALE_ENUMPROCW)
462 #ifdef __clang__
463         LocaleEnumProcW,
464 #else
465         [](LPWSTR locale_string)
466         #if defined(__GNUC__) && !defined(__clang__)
467         __stdcall
468         #endif // __GNUC__
469         { return __crt_fast_decode_pointer(static_enum_proc)(locale_string, 0, 0); },
470 #endif
471         LCID_INSTALLED);
472     static_enum_proc = __crt_fast_encode_pointer(nullptr);
473 
474     return result;
475 }
476 
__acrt_EnumSystemLocalesEx(LOCALE_ENUMPROCEX const enum_proc,DWORD const flags,LPARAM const param,LPVOID const reserved)477 extern "C" BOOL WINAPI __acrt_EnumSystemLocalesEx(
478     LOCALE_ENUMPROCEX const enum_proc,
479     DWORD             const flags,
480     LPARAM            const param,
481     LPVOID            const reserved
482     )
483 {
484     if (auto const enum_system_locales_ex = try_get_EnumSystemLocalesEx())
485     {
486         return enum_system_locales_ex(enum_proc, flags, param, reserved);
487     }
488 
489     return __acrt_lock_and_call(__acrt_locale_lock, [&]() -> BOOL
490     {
491         return enum_system_locales_ex_nolock(enum_proc);
492     });
493 }
494 
__acrt_FlsAlloc(PFLS_CALLBACK_FUNCTION const callback)495 extern "C" DWORD WINAPI __acrt_FlsAlloc(PFLS_CALLBACK_FUNCTION const callback)
496 {
497 #if FLS_ALWAYS_AVAILABLE
498     return FlsAlloc(callback);
499 #else
500     if (auto const fls_alloc = try_get_FlsAlloc())
501     {
502         return fls_alloc(callback);
503     }
504 
505     return TlsAlloc();
506 #endif
507 }
508 
__acrt_FlsFree(DWORD const fls_index)509 extern "C" BOOL WINAPI __acrt_FlsFree(DWORD const fls_index)
510 {
511 #if FLS_ALWAYS_AVAILABLE
512     return FlsFree(fls_index);
513 #else
514     if (auto const fls_free = try_get_FlsFree())
515     {
516         return fls_free(fls_index);
517     }
518 
519     return TlsFree(fls_index);
520 #endif
521 }
522 
__acrt_FlsGetValue(DWORD const fls_index)523 extern "C" PVOID WINAPI __acrt_FlsGetValue(DWORD const fls_index)
524 {
525 #if FLS_ALWAYS_AVAILABLE
526     return FlsGetValue(fls_index);
527 #else
528     if (auto const fls_get_value = try_get_FlsGetValue())
529     {
530         return fls_get_value(fls_index);
531     }
532 
533     return TlsGetValue(fls_index);
534 #endif
535 }
536 
__acrt_FlsSetValue(DWORD const fls_index,PVOID const fls_data)537 extern "C" BOOL WINAPI __acrt_FlsSetValue(DWORD const fls_index, PVOID const fls_data)
538 {
539 #if FLS_ALWAYS_AVAILABLE
540     return FlsSetValue(fls_index, fls_data);
541 #else
542     if (auto const fls_set_value = try_get_FlsSetValue())
543     {
544         return fls_set_value(fls_index, fls_data);
545     }
546 
547     return TlsSetValue(fls_index, fls_data);
548 #endif
549 }
550 
__acrt_GetDateFormatEx(LPCWSTR const locale_name,DWORD const flags,SYSTEMTIME CONST * const date,LPCWSTR const format,LPWSTR const buffer,int const buffer_count,LPCWSTR const calendar)551 extern "C" int WINAPI __acrt_GetDateFormatEx(
552     LPCWSTR           const locale_name,
553     DWORD             const flags,
554     SYSTEMTIME CONST* const date,
555     LPCWSTR           const format,
556     LPWSTR            const buffer,
557     int               const buffer_count,
558     LPCWSTR           const calendar
559     )
560 {
561     if (auto const get_date_format_ex = try_get_GetDateFormatEx())
562     {
563         return get_date_format_ex(locale_name, flags, date, format, buffer, buffer_count, calendar);
564     }
565 
566     return GetDateFormatW(__acrt_LocaleNameToLCID(locale_name, 0), flags, date, format, buffer, buffer_count);
567 }
568 
__acrt_GetTempPath2W(DWORD nBufferLength,LPWSTR lpBuffer)569 extern "C" int WINAPI __acrt_GetTempPath2W(
570     DWORD nBufferLength,
571     LPWSTR lpBuffer
572 )
573 {
574     if (auto const get_temp_path2w = try_get_GetTempPath2W())
575     {
576         return get_temp_path2w(nBufferLength, lpBuffer);
577     }
578     return GetTempPathW(nBufferLength, lpBuffer);
579 }
580 
__acrt_GetEnabledXStateFeatures()581 extern "C" DWORD64 WINAPI __acrt_GetEnabledXStateFeatures()
582 {
583     if (auto const get_enabled_xstate_features = try_get_GetEnabledXStateFeatures())
584     {
585         return get_enabled_xstate_features();
586     }
587 
588     abort(); // No fallback; callers should check availablility before calling
589 }
590 
__acrt_GetLocaleInfoEx(LPCWSTR const locale_name,LCTYPE const lc_type,LPWSTR const data,int const data_count)591 extern "C" int WINAPI __acrt_GetLocaleInfoEx(
592     LPCWSTR const locale_name,
593     LCTYPE  const lc_type,
594     LPWSTR  const data,
595     int     const data_count
596     )
597 {
598     if (auto const get_locale_info_ex = try_get_GetLocaleInfoEx())
599     {
600         return get_locale_info_ex(locale_name, lc_type, data, data_count);
601     }
602 
603     return GetLocaleInfoW(__acrt_LocaleNameToLCID(locale_name, 0), lc_type, data, data_count);
604 }
605 
__acrt_GetSystemTimePreciseAsFileTime(LPFILETIME const system_time)606 extern "C" VOID WINAPI __acrt_GetSystemTimePreciseAsFileTime(LPFILETIME const system_time)
607 {
608     if (auto const get_system_time_precise_as_file_time = try_get_GetSystemTimePreciseAsFileTime())
609     {
610         return get_system_time_precise_as_file_time(system_time);
611     }
612 
613     return GetSystemTimeAsFileTime(system_time);
614 }
615 
__acrt_GetTimeFormatEx(LPCWSTR const locale_name,DWORD const flags,SYSTEMTIME CONST * const time,LPCWSTR const format,LPWSTR const buffer,int const buffer_count)616 extern "C" int WINAPI __acrt_GetTimeFormatEx(
617     LPCWSTR           const locale_name,
618     DWORD             const flags,
619     SYSTEMTIME CONST* const time,
620     LPCWSTR           const format,
621     LPWSTR            const buffer,
622     int               const buffer_count
623     )
624 {
625     if (auto const get_time_format_ex = try_get_GetTimeFormatEx())
626     {
627         return get_time_format_ex(locale_name, flags, time, format, buffer, buffer_count);
628     }
629 
630     return GetTimeFormatW(__acrt_LocaleNameToLCID(locale_name, 0), flags, time, format, buffer, buffer_count);
631 }
632 
__acrt_GetUserDefaultLocaleName(LPWSTR const locale_name,int const locale_name_count)633 extern "C" int WINAPI __acrt_GetUserDefaultLocaleName(
634     LPWSTR const locale_name,
635     int    const locale_name_count
636     )
637 {
638     if (auto const get_user_default_locale_name = try_get_GetUserDefaultLocaleName())
639     {
640         return get_user_default_locale_name(locale_name, locale_name_count);
641     }
642 
643     return __acrt_LCIDToLocaleName(GetUserDefaultLCID(), locale_name, locale_name_count, 0);
644 }
645 
__acrt_GetXStateFeaturesMask(PCONTEXT const context,PDWORD64 const feature_mask)646 extern "C" BOOL WINAPI __acrt_GetXStateFeaturesMask(
647     PCONTEXT const context,
648     PDWORD64 const feature_mask
649     )
650 {
651     if (auto const get_xstate_features_mask = try_get_GetXStateFeaturesMask())
652     {
653         return get_xstate_features_mask(context, feature_mask);
654     }
655 
656     abort(); // No fallback; callers should check availablility before calling
657 }
658 
__acrt_InitializeCriticalSectionEx(LPCRITICAL_SECTION const critical_section,DWORD const spin_count,DWORD const flags)659 extern "C" BOOL WINAPI __acrt_InitializeCriticalSectionEx(
660     LPCRITICAL_SECTION const critical_section,
661     DWORD              const spin_count,
662     DWORD              const flags
663     )
664 {
665     if (auto const initialize_critical_section_ex = try_get_InitializeCriticalSectionEx())
666     {
667         return initialize_critical_section_ex(critical_section, spin_count, flags);
668     }
669 
670     return InitializeCriticalSectionAndSpinCount(critical_section, spin_count);
671 }
672 
__acrt_IsValidLocaleName(LPCWSTR const locale_name)673 extern "C" BOOL WINAPI __acrt_IsValidLocaleName(LPCWSTR const locale_name)
674 {
675     if (auto const is_valid_locale_name = try_get_IsValidLocaleName())
676     {
677         return is_valid_locale_name(locale_name);
678     }
679 
680     return IsValidLocale(__acrt_LocaleNameToLCID(locale_name, 0), LCID_INSTALLED);
681 }
682 
__acrt_LCMapStringEx(LPCWSTR const locale_name,DWORD const flags,LPCWSTR const source,int const source_count,LPWSTR const destination,int const destination_count,LPNLSVERSIONINFO const version,LPVOID const reserved,LPARAM const sort_handle)683 extern "C" int WINAPI __acrt_LCMapStringEx(
684     LPCWSTR          const locale_name,
685     DWORD            const flags,
686     LPCWSTR          const source,
687     int              const source_count,
688     LPWSTR           const destination,
689     int              const destination_count,
690     LPNLSVERSIONINFO const version,
691     LPVOID           const reserved,
692     LPARAM           const sort_handle
693     )
694 {
695     if (auto const lc_map_string_ex = try_get_LCMapStringEx())
696     {
697         return lc_map_string_ex(locale_name, flags, source, source_count, destination, destination_count, version, reserved, sort_handle);
698     }
699 #pragma warning(disable:__WARNING_PRECONDITION_NULLTERMINATION_VIOLATION) // 26035 LCMapStringW annotation is presently incorrect 11/26/2014 Jaykrell
700     return LCMapStringW(__acrt_LocaleNameToLCID(locale_name, 0), flags, source, source_count, destination, destination_count);
701 }
702 
__acrt_LCIDToLocaleName(LCID const locale,LPWSTR const name,int const name_count,DWORD const flags)703 extern "C" int WINAPI __acrt_LCIDToLocaleName(
704     LCID   const locale,
705     LPWSTR const name,
706     int    const name_count,
707     DWORD  const flags
708     )
709 {
710     if (auto const lcid_to_locale_name = try_get_LCIDToLocaleName())
711     {
712         return lcid_to_locale_name(locale, name, name_count, flags);
713     }
714 
715     return __acrt_DownlevelLCIDToLocaleName(locale, name, name_count);
716 }
717 
__acrt_LocaleNameToLCID(LPCWSTR const name,DWORD const flags)718 extern "C" LCID WINAPI __acrt_LocaleNameToLCID(
719     LPCWSTR const name,
720     DWORD   const flags
721     )
722 {
723     if (auto const locale_name_to_lcid = try_get_LocaleNameToLCID())
724     {
725         return locale_name_to_lcid(name, flags);
726     }
727 
728     return __acrt_DownlevelLocaleNameToLCID(name);
729 }
730 
__acrt_LocateXStateFeature(PCONTEXT const content,DWORD const feature_id,PDWORD const length)731 extern "C" PVOID WINAPI __acrt_LocateXStateFeature(
732     PCONTEXT const content,
733     DWORD    const feature_id,
734     PDWORD   const length
735     )
736 {
737     if (auto const locate_xstate_feature = try_get_LocateXStateFeature())
738     {
739         return locate_xstate_feature(content, feature_id, length);
740     }
741 
742     abort(); // No fallback; callers should check availablility before calling
743 }
744 
__acrt_MessageBoxA(HWND const hwnd,LPCSTR const text,LPCSTR const caption,UINT const type)745 extern "C" int WINAPI __acrt_MessageBoxA(
746     HWND   const hwnd,
747     LPCSTR const text,
748     LPCSTR const caption,
749     UINT   const type
750     )
751 {
752     if (auto const message_box_a = try_get_MessageBoxA())
753     {
754         return message_box_a(hwnd, text, caption, type);
755     }
756 
757     abort(); // No fallback; callers should check availablility before calling
758 }
759 
__acrt_MessageBoxW(HWND const hwnd,LPCWSTR const text,LPCWSTR const caption,UINT const type)760 extern "C" int WINAPI __acrt_MessageBoxW(
761     HWND    const hwnd,
762     LPCWSTR const text,
763     LPCWSTR const caption,
764     UINT    const type
765     )
766 {
767     if (auto const message_box_w = try_get_MessageBoxW())
768     {
769         return message_box_w(hwnd, text, caption, type);
770     }
771 
772     abort(); // No fallback; callers should check availablility before calling
773 }
774 
__acrt_RtlGenRandom(PVOID const buffer,ULONG const buffer_count)775 extern "C" BOOLEAN WINAPI __acrt_RtlGenRandom(
776     PVOID const buffer,
777     ULONG const buffer_count
778     )
779 {
780     if (auto const rtl_gen_random = try_get_SystemFunction036())
781     {
782         return rtl_gen_random(buffer, buffer_count);
783     }
784 
785     abort(); // No fallback (this function should exist)
786 }
787 
__acrt_RoInitialize(RO_INIT_TYPE const init_type)788 extern "C" HRESULT WINAPI __acrt_RoInitialize(RO_INIT_TYPE const init_type)
789 {
790     if (auto const ro_initialize = try_get_RoInitialize())
791     {
792         return ro_initialize(init_type);
793     }
794 
795     return S_OK; // No fallback (this is a best-effort wrapper)
796 }
797 
__acrt_RoUninitialize()798 extern "C" void WINAPI __acrt_RoUninitialize()
799 {
800     if (auto const ro_uninitialize = try_get_RoUninitialize())
801     {
802         return ro_uninitialize();
803     }
804 
805     // No fallback (this is a best-effort wrapper)
806 }
807 
__acrt_AppPolicyGetProcessTerminationMethodInternal(_Out_ AppPolicyProcessTerminationMethod * policy)808 LONG WINAPI __acrt_AppPolicyGetProcessTerminationMethodInternal(_Out_ AppPolicyProcessTerminationMethod* policy)
809 {
810     if (auto const app_policy_get_process_terminaton_method_claims = try_get_AppPolicyGetProcessTerminationMethod())
811     {
812         return app_policy_get_process_terminaton_method_claims(GetCurrentThreadEffectiveToken(), policy);
813     }
814 
815     return STATUS_NOT_FOUND;
816 }
817 
__acrt_AppPolicyGetThreadInitializationTypeInternal(_Out_ AppPolicyThreadInitializationType * policy)818 LONG WINAPI __acrt_AppPolicyGetThreadInitializationTypeInternal(_Out_ AppPolicyThreadInitializationType* policy)
819 {
820     if (auto const app_policy_get_thread_initialization_type_claims = try_get_AppPolicyGetThreadInitializationType())
821     {
822         return app_policy_get_thread_initialization_type_claims(GetCurrentThreadEffectiveToken(), policy);
823     }
824 
825     return STATUS_NOT_FOUND;
826 }
827 
__acrt_AppPolicyGetShowDeveloperDiagnosticInternal(_Out_ AppPolicyShowDeveloperDiagnostic * policy)828 LONG WINAPI __acrt_AppPolicyGetShowDeveloperDiagnosticInternal(_Out_ AppPolicyShowDeveloperDiagnostic* policy)
829 {
830     if (auto const app_policy_get_show_developer_diagnostic_claims = try_get_AppPolicyGetShowDeveloperDiagnostic())
831     {
832         return app_policy_get_show_developer_diagnostic_claims(GetCurrentThreadEffectiveToken(), policy);
833     }
834 
835     return STATUS_NOT_FOUND;
836 }
837 
__acrt_AppPolicyGetWindowingModelInternal(_Out_ AppPolicyWindowingModel * policy)838 LONG WINAPI __acrt_AppPolicyGetWindowingModelInternal(_Out_ AppPolicyWindowingModel* policy)
839 {
840     if (auto const app_policy_get_windowing_model_claims = try_get_AppPolicyGetWindowingModel())
841     {
842         return app_policy_get_windowing_model_claims(GetCurrentThreadEffectiveToken(), policy);
843     }
844 
845     return STATUS_NOT_FOUND;
846 }
847 
__acrt_SetThreadStackGuarantee(PULONG const stack_size_in_bytes)848 extern "C" BOOL WINAPI __acrt_SetThreadStackGuarantee(PULONG const stack_size_in_bytes)
849 {
850     if (auto const set_thread_stack_guarantee = try_get_SetThreadStackGuarantee())
851     {
852         return set_thread_stack_guarantee(stack_size_in_bytes);
853     }
854 
855     return FALSE;
856 }
857 
__acrt_can_show_message_box()858 extern "C" bool __cdecl __acrt_can_show_message_box()
859 {
860     bool can_show_message_box = false;
861     if (__acrt_get_windowing_model_policy() == windowing_model_policy_hwnd
862         && try_get_MessageBoxA() != nullptr
863         && try_get_MessageBoxW() != nullptr)
864     {
865         can_show_message_box = true;
866     }
867     return can_show_message_box;
868 }
869 
__acrt_can_use_vista_locale_apis()870 extern "C" bool __cdecl __acrt_can_use_vista_locale_apis()
871 {
872     return try_get_CompareStringEx() != nullptr;
873 }
874 
875 // This function simply attempts to get each of the locale-related APIs.  This
876 // allows a caller to "pre-load" the modules in which these APIs are hosted.  We
877 // use this in the _wsetlocale implementation to avoid calls to LoadLibrary while
878 // the locale lock is held.
__acrt_eagerly_load_locale_apis()879 extern "C" void __cdecl __acrt_eagerly_load_locale_apis()
880 {
881     try_get_AreFileApisANSI();
882     try_get_CompareStringEx();
883     try_get_EnumSystemLocalesEx();
884     try_get_GetDateFormatEx();
885     try_get_GetLocaleInfoEx();
886     try_get_GetTimeFormatEx();
887     try_get_GetUserDefaultLocaleName();
888     try_get_IsValidLocaleName();
889     try_get_LCMapStringEx();
890     try_get_LCIDToLocaleName();
891     try_get_LocaleNameToLCID();
892 }
893 
__acrt_can_use_xstate_apis()894 extern "C" bool __cdecl __acrt_can_use_xstate_apis()
895 {
896     return try_get_LocateXStateFeature() != nullptr;
897 }
898 
__acrt_get_parent_window()899 extern "C" HWND __cdecl __acrt_get_parent_window()
900 {
901     auto const get_active_window = try_get_GetActiveWindow();
902     if (!get_active_window)
903     {
904         return nullptr;
905     }
906 
907     HWND const active_window = get_active_window();
908     if (!active_window)
909     {
910         return nullptr;
911     }
912 
913     auto const get_last_active_popup = try_get_GetLastActivePopup();
914     if (!get_last_active_popup)
915     {
916         return active_window;
917     }
918 
919     return get_last_active_popup(active_window);
920 }
921 
__acrt_is_interactive()922 extern "C" bool __cdecl __acrt_is_interactive()
923 {
924     auto const get_process_window_station = try_get_GetProcessWindowStation();
925     if (!get_process_window_station)
926     {
927         return true;
928     }
929 
930     auto const get_user_object_information = try_get_GetUserObjectInformationW();
931     if (!get_user_object_information)
932     {
933         return true;
934     }
935 
936     HWINSTA const hwinsta = get_process_window_station();
937     if (!hwinsta)
938     {
939         return false;
940     }
941 
942     USEROBJECTFLAGS uof{};
943     if (!get_user_object_information(hwinsta, UOI_FLAGS, &uof, sizeof(uof), nullptr))
944     {
945         return false;
946     }
947 
948     if ((uof.dwFlags & WSF_VISIBLE) == 0)
949     {
950         return false;
951     }
952 
953     return true;
954 }
955