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 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 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 227 static __forceinline void* __cdecl invalid_function_sentinel() throw() 228 { 229 return reinterpret_cast<void*>(static_cast<uintptr_t>(-1)); 230 } 231 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 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 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 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 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 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 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; 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. 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 894 extern "C" bool __cdecl __acrt_can_use_xstate_apis() 895 { 896 return try_get_LocateXStateFeature() != nullptr; 897 } 898 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 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