Reactos
at master 954 lines 35 kB view raw
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). 36extern "C" WINBASEAPI DWORD64 WINAPI GetEnabledXStateFeatures(); 37 38_Must_inspect_result_ 39extern "C" WINBASEAPI BOOL WINAPI GetXStateFeaturesMask( 40 _In_ PCONTEXT context, 41 _Out_ PDWORD64 feature_mask 42 ); 43 44_Success_(return != NULL) 45extern "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 140namespace 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. 182static 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. 189static void* encoded_function_pointers[function_id_count]; 190 191extern "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 203extern "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 227static __forceinline void* __cdecl invalid_function_sentinel() throw() 228{ 229 return reinterpret_cast<void*>(static_cast<uintptr_t>(-1)); 230} 231 232static 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 255static 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 295static 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 312static __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 327static 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 405extern "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 417extern "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__ 442static LOCALE_ENUMPROCEX static_enum_proc; 443static 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. 452static 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 477extern "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 495extern "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 509extern "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 523extern "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 537extern "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 551extern "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 569extern "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 581extern "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 591extern "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 606extern "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 616extern "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 633extern "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 646extern "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 659extern "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 673extern "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 683extern "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 703extern "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 718extern "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 731extern "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 745extern "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 760extern "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 775extern "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 788extern "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 798extern "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 808LONG 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 818LONG 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 828LONG 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 838LONG 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 848extern "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 858extern "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 870extern "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. 879extern "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 894extern "C" bool __cdecl __acrt_can_use_xstate_apis() 895{ 896 return try_get_LocateXStateFeature() != nullptr; 897} 898 899extern "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 922extern "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}