mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 10:01:43 +00:00
[UCRT] Import Microsoft.Windows.SDK.CRTSource version 10.0.22621.3
Imported from https://www.nuget.org/packages/Microsoft.Windows.SDK.CRTSource/10.0.22621.3 License: MIT
This commit is contained in:
parent
f1b60c66f0
commit
04e0dc4a7a
568 changed files with 115483 additions and 0 deletions
79
sdk/lib/ucrt/internal/CreateProcessA.cpp
Normal file
79
sdk/lib/ucrt/internal/CreateProcessA.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// CreateProcessA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_CreateProcessA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
BOOL __cdecl __acrt_CreateProcessA(
|
||||
LPCSTR const lpApplicationName,
|
||||
LPSTR const lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES const lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES const lpThreadAttributes,
|
||||
BOOL const bInheritHandles,
|
||||
DWORD const dwCreationFlags,
|
||||
LPVOID const lpEnvironment,
|
||||
LPCSTR const lpCurrentDirectory,
|
||||
LPSTARTUPINFOW const lpStartupInfo,
|
||||
LPPROCESS_INFORMATION const lpProcessInformation
|
||||
)
|
||||
{
|
||||
__crt_internal_win32_buffer<wchar_t> wide_application_name;
|
||||
__crt_internal_win32_buffer<wchar_t> wide_command_line;
|
||||
__crt_internal_win32_buffer<wchar_t> wide_current_directory;
|
||||
|
||||
errno_t const cvt1 = __acrt_mbs_to_wcs_cp(
|
||||
lpApplicationName,
|
||||
wide_application_name,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt1 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errno_t const cvt2 = __acrt_mbs_to_wcs_cp(
|
||||
lpCommandLine,
|
||||
wide_command_line,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt2 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LPWSTR wide_current_directory_ptr = nullptr;
|
||||
|
||||
if (lpCurrentDirectory != nullptr) {
|
||||
errno_t const cvt3 = __acrt_mbs_to_wcs_cp(
|
||||
lpCurrentDirectory,
|
||||
wide_current_directory,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt3 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wide_current_directory_ptr = wide_current_directory.data();
|
||||
}
|
||||
|
||||
// converted_command_line is an out parameter, but is not reconverted to utf8 string,
|
||||
// since it is only written to in the Wide version. CreateProcessA does not expect it
|
||||
// to have changed.
|
||||
return ::CreateProcessW(
|
||||
wide_application_name.data(),
|
||||
wide_command_line.data(),
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
wide_current_directory_ptr,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation
|
||||
);
|
||||
}
|
40
sdk/lib/ucrt/internal/GetModuleFileNameA.cpp
Normal file
40
sdk/lib/ucrt/internal/GetModuleFileNameA.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// GetModuleFileNameA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_GetModuleFileNameA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
DWORD __cdecl __acrt_GetModuleFileNameA(
|
||||
HMODULE const hModule,
|
||||
char * const lpFilename,
|
||||
DWORD const nSize
|
||||
)
|
||||
{
|
||||
size_t const wide_buffer_size = MAX_PATH + 1;
|
||||
wchar_t wide_buffer[wide_buffer_size];
|
||||
|
||||
DWORD const amount_copied = GetModuleFileNameW(
|
||||
hModule,
|
||||
wide_buffer,
|
||||
wide_buffer_size
|
||||
);
|
||||
|
||||
if (amount_copied == 0) {
|
||||
__acrt_errno_map_os_error(GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
__crt_no_alloc_win32_buffer<char> filename_buffer(lpFilename, static_cast<size_t>(nSize));
|
||||
|
||||
errno_t const cvt = __acrt_wcs_to_mbs_cp(
|
||||
wide_buffer,
|
||||
filename_buffer,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
return static_cast<DWORD>(filename_buffer.size());
|
||||
}
|
34
sdk/lib/ucrt/internal/LoadLibraryExA.cpp
Normal file
34
sdk/lib/ucrt/internal/LoadLibraryExA.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// LoadLibraryExA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_LoadLibraryExA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
HMODULE __cdecl __acrt_LoadLibraryExA(
|
||||
LPCSTR const lpFilename,
|
||||
HANDLE const hFile,
|
||||
DWORD const dwFlags
|
||||
)
|
||||
{
|
||||
__crt_internal_win32_buffer<wchar_t> wide_file_name;
|
||||
|
||||
errno_t const cvt1 = __acrt_mbs_to_wcs_cp(
|
||||
lpFilename,
|
||||
wide_file_name,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt1 != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ::LoadLibraryExW(
|
||||
wide_file_name.data(),
|
||||
hFile,
|
||||
dwFlags
|
||||
);
|
||||
}
|
31
sdk/lib/ucrt/internal/OutputDebugStringA.cpp
Normal file
31
sdk/lib/ucrt/internal/OutputDebugStringA.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// OutputDebugStringA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_OutputDebugStringA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
void WINAPI __acrt_OutputDebugStringA(
|
||||
LPCSTR const text
|
||||
)
|
||||
{
|
||||
if (text == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
size_t const text_size = strlen(text) + 1;
|
||||
if (text_size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Use alloca instead of heap, since this code is executed during asserts
|
||||
auto text_wide = (wchar_t*)_alloca(text_size * sizeof(wchar_t));
|
||||
size_t converted;
|
||||
if (mbstowcs_s(&converted, text_wide, text_size, text, text_size - 1) == 0)
|
||||
{
|
||||
OutputDebugStringW(text_wide);
|
||||
}
|
||||
}
|
28
sdk/lib/ucrt/internal/SetCurrentDirectoryA.cpp
Normal file
28
sdk/lib/ucrt/internal/SetCurrentDirectoryA.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// SetCurrentDirectoryA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_SetCurrentDirectoryA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
BOOL __cdecl __acrt_SetCurrentDirectoryA(
|
||||
LPCSTR const lpPathName
|
||||
)
|
||||
{
|
||||
__crt_internal_win32_buffer<wchar_t> wide_path_name;
|
||||
|
||||
errno_t const cvt1 = __acrt_mbs_to_wcs_cp(
|
||||
lpPathName,
|
||||
wide_path_name,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt1 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return ::SetCurrentDirectoryW(wide_path_name.data());
|
||||
}
|
40
sdk/lib/ucrt/internal/SetEnvironmentVariableA.cpp
Normal file
40
sdk/lib/ucrt/internal/SetEnvironmentVariableA.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// SetEnvironmentVariableA.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definition of __acrt_SetEnvironmentVariableA.
|
||||
//
|
||||
|
||||
#include <corecrt_internal_win32_buffer.h>
|
||||
|
||||
BOOL __cdecl __acrt_SetEnvironmentVariableA(
|
||||
LPCSTR const lpName,
|
||||
LPCSTR const lpValue
|
||||
)
|
||||
{
|
||||
__crt_internal_win32_buffer<wchar_t> wide_name;
|
||||
__crt_internal_win32_buffer<wchar_t> wide_value;
|
||||
|
||||
errno_t const cvt1 = __acrt_mbs_to_wcs_cp(
|
||||
lpName,
|
||||
wide_name,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt1 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
errno_t const cvt2 = __acrt_mbs_to_wcs_cp(
|
||||
lpValue,
|
||||
wide_value,
|
||||
__acrt_get_utf8_acp_compatibility_codepage()
|
||||
);
|
||||
|
||||
if (cvt2 != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return ::SetEnvironmentVariableW(wide_name.data(), wide_value.data());
|
||||
}
|
345
sdk/lib/ucrt/internal/initialization.cpp
Normal file
345
sdk/lib/ucrt/internal/initialization.cpp
Normal file
|
@ -0,0 +1,345 @@
|
|||
//
|
||||
// initialization.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This file defines the main initialization and uninitialization routines for
|
||||
// the AppCRT, shared by both the static and dynamic AppCRT libraries. In the
|
||||
// dynamic AppCRT library, these are called by DllMain. In the static AppCRT
|
||||
// library, these are called by the initialization code.
|
||||
//
|
||||
#include <corecrt_internal.h>
|
||||
#include <corecrt_internal_stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
||||
|
||||
extern _onexit_table_t __acrt_atexit_table;
|
||||
extern _onexit_table_t __acrt_at_quick_exit_table;
|
||||
extern void* __acrt_stdout_buffer;
|
||||
extern void* __acrt_stderr_buffer;
|
||||
|
||||
|
||||
|
||||
static bool __cdecl initialize_global_variables()
|
||||
{
|
||||
__acrt_current_locale_data.initialize(&__acrt_initial_locale_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CRTDLL
|
||||
|
||||
static bool __cdecl initialize_c()
|
||||
{
|
||||
_initialize_onexit_table(&__acrt_atexit_table);
|
||||
_initialize_onexit_table(&__acrt_at_quick_exit_table);
|
||||
|
||||
// Do C initialization:
|
||||
if (_initterm_e(__xi_a, __xi_z) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do C++ initialization:
|
||||
_initterm(__xc_a, __xc_z);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_c(bool)
|
||||
{
|
||||
// Do pre-termination:
|
||||
_initterm(__xp_a, __xp_z);
|
||||
|
||||
// Do termination:
|
||||
_initterm(__xt_a, __xt_z);
|
||||
return true;
|
||||
}
|
||||
|
||||
// C4505: unreferenced local function
|
||||
#pragma warning( suppress: 4505 )
|
||||
static bool __cdecl initialize_environment()
|
||||
{
|
||||
if (_initialize_narrow_environment() < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_get_initial_narrow_environment())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool __cdecl initialize_c()
|
||||
{
|
||||
_initialize_onexit_table(&__acrt_atexit_table);
|
||||
_initialize_onexit_table(&__acrt_at_quick_exit_table);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_c(bool)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// C4505: unreferenced local function
|
||||
#pragma warning( suppress: 4505 )
|
||||
static bool __cdecl initialize_environment()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// C4505: unreferenced local function
|
||||
#pragma warning( suppress: 4505 )
|
||||
static bool __cdecl uninitialize_environment(bool const terminating)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(terminating);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (terminating)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
__dcrt_uninitialize_environments_nolock();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _CRT_GLOBAL_STATE_ISOLATION
|
||||
|
||||
static bool __cdecl initialize_global_state_isolation()
|
||||
{
|
||||
// Configure CRT's per-thread global state mode data
|
||||
return __crt_state_management::initialize_global_state_isolation();
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_global_state_isolation(bool const terminating)
|
||||
{
|
||||
// Configure CRT's per-thread global state mode data
|
||||
__crt_state_management::uninitialize_global_state_isolation(terminating);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool __cdecl initialize_global_state_isolation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_global_state_isolation(bool const /* terminating */)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static bool __cdecl initialize_pointers()
|
||||
{
|
||||
void* const encoded_null = __crt_fast_encode_pointer(nullptr);
|
||||
__acrt_initialize_invalid_parameter_handler(encoded_null);
|
||||
__acrt_initialize_new_handler(encoded_null);
|
||||
__acrt_initialize_signal_handlers(encoded_null);
|
||||
__acrt_initialize_user_matherr(encoded_null);
|
||||
__acrt_initialize_thread_local_exit_callback(encoded_null);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_vcruntime(const bool /* terminating */)
|
||||
{
|
||||
return __vcrt_uninitialize(false);
|
||||
}
|
||||
|
||||
static bool __cdecl uninitialize_allocated_memory(bool const /* terminating */)
|
||||
{
|
||||
__acrt_current_multibyte_data.uninitialize([](__crt_multibyte_data*& multibyte_data)
|
||||
{
|
||||
if (_InterlockedDecrement(&multibyte_data->refcount) == 0 &&
|
||||
multibyte_data != &__acrt_initial_multibyte_data)
|
||||
{
|
||||
_free_crt(multibyte_data);
|
||||
multibyte_data = &__acrt_initial_multibyte_data;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// C4505: unreferenced local function
|
||||
#pragma warning( suppress: 4505 )
|
||||
static bool __cdecl uninitialize_allocated_io_buffers(bool const /* terminating */)
|
||||
{
|
||||
_free_crt(__acrt_stdout_buffer);
|
||||
__acrt_stdout_buffer = nullptr;
|
||||
|
||||
_free_crt(__acrt_stderr_buffer);
|
||||
__acrt_stderr_buffer = nullptr;
|
||||
|
||||
_free_crt(__argv);
|
||||
__argv = nullptr;
|
||||
|
||||
_free_crt(__wargv);
|
||||
__wargv = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __cdecl report_memory_leaks(bool const /* terminating */)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if (_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
|
||||
{
|
||||
_CrtSetDumpClient(nullptr);
|
||||
_CrtDumpMemoryLeaks();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is the table of initializer/uninitializer pairs that is used to perform
|
||||
// AppCRT initialization. Initializers are run first-to-last during AppCRT
|
||||
// initialization, and uninitializers are run last-to-first during termination.
|
||||
static __acrt_initializer const __acrt_initializers[] =
|
||||
{
|
||||
// Init globals that can't be set at compile time because they have c'tors
|
||||
{ initialize_global_variables, nullptr },
|
||||
|
||||
// Global pointers are stored in encoded form; they must be dynamically
|
||||
// initialized to the encoded nullptr value before they are used by the CRT.
|
||||
{ initialize_pointers, nullptr },
|
||||
// Enclaves only require initializers for supported features.
|
||||
#ifndef _UCRT_ENCLAVE_BUILD
|
||||
{ __acrt_initialize_winapi_thunks, __acrt_uninitialize_winapi_thunks },
|
||||
#endif
|
||||
|
||||
// Configure CRT's global state isolation system. This system calls FlsAlloc
|
||||
// and thus must occur after the initialize_pointers initialization, otherwise
|
||||
// it will fall back to call TlsAlloc, then try to use the allocated TLS slot
|
||||
// with the FLS functions. This does not turn out well. By running this
|
||||
// initialization after the initialize_pointers step, we ensure that it can
|
||||
// call FlsAlloc.
|
||||
{ initialize_global_state_isolation, uninitialize_global_state_isolation },
|
||||
|
||||
// The heap and locks must be initialized before most other initialization
|
||||
// takes place, as other initialization steps rely on the heap and locks:
|
||||
{ __acrt_initialize_locks, __acrt_uninitialize_locks },
|
||||
{ __acrt_initialize_heap, __acrt_uninitialize_heap },
|
||||
|
||||
// During uninitialization, before the heap is uninitialized, the AppCRT
|
||||
// needs to notify all VCRuntime instances in the process to allow them to
|
||||
// release any memory that they allocated via the AppCRT heap.
|
||||
//
|
||||
// First, we notify all modules that registered for shutdown notification.
|
||||
// This only occurs in the AppCRT DLL, because the static CRT is only ever
|
||||
// used by a single module, so this notification is never required.
|
||||
//
|
||||
// Then, we notify our own VCRuntime instance. Note that after this point
|
||||
// during uninitialization, no exception handling may take place in any
|
||||
// CRT module.
|
||||
{ nullptr, uninitialize_vcruntime },
|
||||
|
||||
{ __acrt_initialize_ptd, __acrt_uninitialize_ptd },
|
||||
// Enclaves only require initializers for supported features.
|
||||
#ifndef _UCRT_ENCLAVE_BUILD
|
||||
{ __acrt_initialize_lowio, __acrt_uninitialize_lowio },
|
||||
{ __acrt_initialize_command_line, __acrt_uninitialize_command_line },
|
||||
#endif
|
||||
{ __acrt_initialize_multibyte, nullptr },
|
||||
{ nullptr, report_memory_leaks },
|
||||
// Enclaves only require initializers for supported features.
|
||||
#ifndef _UCRT_ENCLAVE_BUILD
|
||||
{ nullptr, uninitialize_allocated_io_buffers },
|
||||
#endif
|
||||
{ nullptr, uninitialize_allocated_memory },
|
||||
// Enclaves only require initializers for supported features.
|
||||
#ifndef _UCRT_ENCLAVE_BUILD
|
||||
{ initialize_environment, uninitialize_environment },
|
||||
#endif
|
||||
{ initialize_c, uninitialize_c },
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
__crt_bool __cdecl __acrt_initialize()
|
||||
{
|
||||
#if defined CRTDLL
|
||||
__isa_available_init();
|
||||
#endif
|
||||
|
||||
return __acrt_execute_initializers(
|
||||
__acrt_initializers,
|
||||
__acrt_initializers + _countof(__acrt_initializers)
|
||||
);
|
||||
}
|
||||
|
||||
__crt_bool __cdecl __acrt_uninitialize(__crt_bool const terminating)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(terminating);
|
||||
|
||||
// If the process is terminating, there's no point in cleaning up, except
|
||||
// in debug builds.
|
||||
#ifndef _DEBUG
|
||||
if (terminating) {
|
||||
#ifndef _UCRT_ENCLAVE_BUILD
|
||||
if (__acrt_stdio_is_initialized()) {
|
||||
_flushall();
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return __acrt_execute_uninitializers(
|
||||
__acrt_initializers,
|
||||
__acrt_initializers + _countof(__acrt_initializers)
|
||||
);
|
||||
}
|
||||
|
||||
__crt_bool __cdecl __acrt_uninitialize_critical(__crt_bool const terminating)
|
||||
{
|
||||
__acrt_uninitialize_ptd(terminating);
|
||||
|
||||
#ifdef _CRT_GLOBAL_STATE_ISOLATION
|
||||
uninitialize_global_state_isolation(terminating);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__crt_bool __cdecl __acrt_thread_attach()
|
||||
{
|
||||
// Create a per-thread data structure for this thread (getptd will attempt
|
||||
// to create a new per-thread data structure if one does not already exist
|
||||
// for this thread):
|
||||
if (__acrt_getptd_noexit() == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__crt_bool __cdecl __acrt_thread_detach()
|
||||
{
|
||||
// Free the per-thread data structure for this thread:
|
||||
__acrt_freeptd();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
71
sdk/lib/ucrt/internal/locks.cpp
Normal file
71
sdk/lib/ucrt/internal/locks.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// locks.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Critical sections used for synchronization in the CoreCRT.
|
||||
//
|
||||
#include <corecrt_internal.h>
|
||||
|
||||
|
||||
|
||||
// This table holds the locks used by the CoreCRT. It is indexed using the
|
||||
// enumerators of the __acrt_lock_id enumeration.
|
||||
static CRITICAL_SECTION __acrt_lock_table[__acrt_lock_count];
|
||||
|
||||
// This variable stores the number of locks that have been successfully
|
||||
// initialized. Locks are initialized in order and are destroyed in reverse
|
||||
// order. The startup and exit code must ensure that initialization and
|
||||
// destruction is synchronized: these functions should never be executed
|
||||
// concurrently.
|
||||
static unsigned __acrt_locks_initialized;
|
||||
|
||||
|
||||
|
||||
extern "C" bool __cdecl __acrt_initialize_locks()
|
||||
{
|
||||
for (unsigned i = 0; i < __acrt_lock_count; ++i)
|
||||
{
|
||||
if (!__acrt_InitializeCriticalSectionEx(&__acrt_lock_table[i], _CORECRT_SPINCOUNT, 0))
|
||||
{
|
||||
__acrt_uninitialize_locks(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
++__acrt_locks_initialized;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_uninitialize_locks(bool const /* terminating */)
|
||||
{
|
||||
for (unsigned i = __acrt_locks_initialized; i > 0; --i)
|
||||
{
|
||||
DeleteCriticalSection(&__acrt_lock_table[i - 1]);
|
||||
--__acrt_locks_initialized;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void __cdecl __acrt_lock(_In_ __acrt_lock_id _Lock)
|
||||
{
|
||||
EnterCriticalSection(&__acrt_lock_table[_Lock]);
|
||||
}
|
||||
|
||||
extern "C" void __cdecl __acrt_unlock(_In_ __acrt_lock_id _Lock)
|
||||
{
|
||||
LeaveCriticalSection(&__acrt_lock_table[_Lock]);
|
||||
}
|
||||
|
||||
extern "C" void __cdecl _lock_locales()
|
||||
{
|
||||
__acrt_eagerly_load_locale_apis();
|
||||
__acrt_lock(__acrt_locale_lock);
|
||||
}
|
||||
|
||||
extern "C" void __cdecl _unlock_locales()
|
||||
{
|
||||
__acrt_unlock(__acrt_locale_lock);
|
||||
}
|
22
sdk/lib/ucrt/internal/peb_access.cpp
Normal file
22
sdk/lib/ucrt/internal/peb_access.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// peb_access.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Wrapper functions to access fields in the PEB.
|
||||
//
|
||||
|
||||
// Using internal headers for definitions. Only call publicly available functions.
|
||||
#include <nt.h>
|
||||
#include <ntrtl.h>
|
||||
#include <nturtl.h>
|
||||
|
||||
extern "C" bool __cdecl __acrt_app_verifier_enabled()
|
||||
{
|
||||
return (NtCurrentTeb()->ProcessEnvironmentBlock->NtGlobalFlag & FLG_APPLICATION_VERIFIER) != 0;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_is_secure_process()
|
||||
{
|
||||
return (NtCurrentTeb()->ProcessEnvironmentBlock->ProcessParameters->Flags & RTL_USER_PROC_SECURE_PROCESS) != 0;
|
||||
}
|
345
sdk/lib/ucrt/internal/per_thread_data.cpp
Normal file
345
sdk/lib/ucrt/internal/per_thread_data.cpp
Normal file
|
@ -0,0 +1,345 @@
|
|||
//
|
||||
// per_thread_data.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Per-Thread Data (PTD) used by the AppCRT.
|
||||
//
|
||||
#include <corecrt_internal.h>
|
||||
#include <corecrt_internal_ptd_propagation.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
|
||||
#ifdef _CRT_GLOBAL_STATE_ISOLATION
|
||||
extern "C" DWORD __crt_global_state_mode_flsindex = FLS_OUT_OF_INDEXES;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void WINAPI destroy_fls(void*) throw();
|
||||
|
||||
|
||||
|
||||
static unsigned long __acrt_flsindex = FLS_OUT_OF_INDEXES;
|
||||
|
||||
|
||||
|
||||
extern "C" bool __cdecl __acrt_initialize_ptd()
|
||||
{
|
||||
__acrt_flsindex = __acrt_FlsAlloc(destroy_fls);
|
||||
if (__acrt_flsindex == FLS_OUT_OF_INDEXES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__acrt_getptd_noexit() == nullptr)
|
||||
{
|
||||
__acrt_uninitialize_ptd(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_uninitialize_ptd(bool)
|
||||
{
|
||||
if (__acrt_flsindex != FLS_OUT_OF_INDEXES)
|
||||
{
|
||||
__acrt_FlsFree(__acrt_flsindex);
|
||||
__acrt_flsindex = FLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __cdecl replace_current_thread_locale_nolock(
|
||||
__acrt_ptd* const ptd,
|
||||
__crt_locale_data* const new_locale_info
|
||||
) throw()
|
||||
{
|
||||
if (ptd->_locale_info)
|
||||
{
|
||||
__acrt_release_locale_ref(ptd->_locale_info);
|
||||
if (ptd->_locale_info != __acrt_current_locale_data.value() &&
|
||||
ptd->_locale_info != &__acrt_initial_locale_data &&
|
||||
ptd->_locale_info->refcount == 0)
|
||||
{
|
||||
__acrt_free_locale(ptd->_locale_info);
|
||||
}
|
||||
}
|
||||
|
||||
ptd->_locale_info = new_locale_info;
|
||||
if (ptd->_locale_info)
|
||||
{
|
||||
__acrt_add_locale_ref(ptd->_locale_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Constructs a single PTD object, copying the given 'locale_data' if provided.
|
||||
static void __cdecl construct_ptd(
|
||||
__acrt_ptd* const ptd,
|
||||
__crt_locale_data** const locale_data
|
||||
) throw()
|
||||
{
|
||||
ptd->_rand_state = 1;
|
||||
ptd->_pxcptacttab = const_cast<__crt_signal_action_t*>(__acrt_exception_action_table);
|
||||
|
||||
// It is necessary to always have GLOBAL_LOCALE_BIT set in perthread data
|
||||
// because when doing bitwise or, we won't get __UPDATE_LOCALE to work when
|
||||
// global per thread locale is set.
|
||||
// See _configthreadlocale() and __acrt_should_sync_with_global_locale().
|
||||
ptd->_own_locale = _GLOBAL_LOCALE_BIT;
|
||||
|
||||
ptd->_multibyte_info = &__acrt_initial_multibyte_data;
|
||||
|
||||
// Initialize _setloc_data. These are the only valuse that need to be
|
||||
// initialized.
|
||||
ptd->_setloc_data._cachein[0] = L'C';
|
||||
ptd->_setloc_data._cacheout[0] = L'C';
|
||||
|
||||
// Downlevel data is not initially used
|
||||
ptd->_setloc_downlevel_data = nullptr;
|
||||
|
||||
__acrt_lock_and_call(__acrt_multibyte_cp_lock, [&]
|
||||
{
|
||||
_InterlockedIncrement(&ptd->_multibyte_info->refcount);
|
||||
});
|
||||
|
||||
// We need to make sure that ptd->ptlocinfo in never nullptr, this saves us
|
||||
// perf counts when UPDATING locale.
|
||||
__acrt_lock_and_call(__acrt_locale_lock, [&]
|
||||
{
|
||||
replace_current_thread_locale_nolock(ptd, *locale_data);
|
||||
});
|
||||
}
|
||||
|
||||
// Constructs each of the 'state_index_count' PTD objects in the array of PTD
|
||||
// objects pointed to by 'ptd'.
|
||||
static void __cdecl construct_ptd_array(__acrt_ptd* const ptd) throw()
|
||||
{
|
||||
for (size_t i = 0; i != __crt_state_management::state_index_count; ++i)
|
||||
{
|
||||
construct_ptd(&ptd[i], &__acrt_current_locale_data.dangerous_get_state_array()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleans up all resources used by a single PTD; does not free the PTD structure
|
||||
// itself.
|
||||
static void __cdecl destroy_ptd(__acrt_ptd* const ptd) throw()
|
||||
{
|
||||
if (ptd->_pxcptacttab != __acrt_exception_action_table)
|
||||
{
|
||||
_free_crt(ptd->_pxcptacttab);
|
||||
}
|
||||
|
||||
_free_crt(ptd->_cvtbuf);
|
||||
_free_crt(ptd->_asctime_buffer);
|
||||
_free_crt(ptd->_wasctime_buffer);
|
||||
_free_crt(ptd->_gmtime_buffer);
|
||||
_free_crt(ptd->_tmpnam_narrow_buffer);
|
||||
_free_crt(ptd->_tmpnam_wide_buffer);
|
||||
_free_crt(ptd->_strerror_buffer);
|
||||
_free_crt(ptd->_wcserror_buffer);
|
||||
_free_crt(ptd->_beginthread_context);
|
||||
|
||||
__acrt_lock_and_call(__acrt_multibyte_cp_lock, [&]
|
||||
{
|
||||
__crt_multibyte_data* const multibyte_data = ptd->_multibyte_info;
|
||||
if (!multibyte_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_InterlockedDecrement(&multibyte_data->refcount) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (multibyte_data == &__acrt_initial_multibyte_data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_free_crt(multibyte_data);
|
||||
});
|
||||
|
||||
__acrt_lock_and_call(__acrt_locale_lock, [&]
|
||||
{
|
||||
replace_current_thread_locale_nolock(ptd, nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
// Destroys each of the 'state_index_count' PTD objects in the array of PTD
|
||||
// objects pointed to by 'ptd'.
|
||||
static void __cdecl destroy_ptd_array(__acrt_ptd* const ptd) throw()
|
||||
{
|
||||
for (size_t i = 0; i != __crt_state_management::state_index_count; ++i)
|
||||
{
|
||||
destroy_ptd(&ptd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// This function is called by the operating system when a thread is being
|
||||
// destroyed, to allow us the opportunity to clean up.
|
||||
static void WINAPI destroy_fls(void* const pfd) throw()
|
||||
{
|
||||
if (!pfd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
destroy_ptd_array(static_cast<__acrt_ptd*>(pfd));
|
||||
_free_crt(pfd);
|
||||
}
|
||||
|
||||
static __forceinline __acrt_ptd* try_get_ptd_head() throw()
|
||||
{
|
||||
// If we haven't allocated per-thread data for this module, return failure:
|
||||
if (__acrt_flsindex == FLS_OUT_OF_INDEXES)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
__acrt_ptd* const ptd_head = static_cast<__acrt_ptd*>(__acrt_FlsGetValue(__acrt_flsindex));
|
||||
if (!ptd_head)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptd_head;
|
||||
}
|
||||
|
||||
_Success_(return != nullptr)
|
||||
static __forceinline __acrt_ptd* internal_get_ptd_head() throw()
|
||||
{
|
||||
// We use the CRT heap to allocate the PTD. If the CRT heap fails to
|
||||
// allocate the requested memory, it will attempt to set errno to ENOMEM,
|
||||
// which will in turn attempt to acquire the PTD, resulting in infinite
|
||||
// recursion that causes a stack overflow.
|
||||
//
|
||||
// We set the PTD to this sentinel value for the duration of the allocation
|
||||
// in order to detect this case.
|
||||
static void* const reentrancy_sentinel = reinterpret_cast<void*>(SIZE_MAX);
|
||||
|
||||
__acrt_ptd* const existing_ptd_head = try_get_ptd_head();
|
||||
if (existing_ptd_head == reentrancy_sentinel)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else if (existing_ptd_head != nullptr)
|
||||
{
|
||||
return existing_ptd_head;
|
||||
}
|
||||
|
||||
if (!__acrt_FlsSetValue(__acrt_flsindex, reentrancy_sentinel))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
__crt_unique_heap_ptr<__acrt_ptd> new_ptd_head(_calloc_crt_t(__acrt_ptd, __crt_state_management::state_index_count));
|
||||
if (!new_ptd_head)
|
||||
{
|
||||
__acrt_FlsSetValue(__acrt_flsindex, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!__acrt_FlsSetValue(__acrt_flsindex, new_ptd_head.get()))
|
||||
{
|
||||
__acrt_FlsSetValue(__acrt_flsindex, nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
construct_ptd_array(new_ptd_head.get());
|
||||
return new_ptd_head.detach();
|
||||
}
|
||||
|
||||
// This functionality has been split out of __acrt_getptd_noexit so that we can
|
||||
// force it to be inlined into both __acrt_getptd_noexit and __acrt_getptd. These
|
||||
// functions are performance critical and this change has substantially improved
|
||||
// __acrt_getptd performance.
|
||||
static __forceinline __acrt_ptd* __cdecl internal_getptd_noexit(
|
||||
__crt_scoped_get_last_error_reset const& last_error_reset,
|
||||
size_t const global_state_index
|
||||
) throw()
|
||||
{
|
||||
UNREFERENCED_PARAMETER(last_error_reset);
|
||||
__acrt_ptd* const ptd_head = internal_get_ptd_head();
|
||||
if (!ptd_head)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ptd_head + global_state_index;
|
||||
}
|
||||
|
||||
static __forceinline __acrt_ptd* __cdecl internal_getptd_noexit() throw()
|
||||
{
|
||||
__crt_scoped_get_last_error_reset const last_error_reset;
|
||||
return internal_getptd_noexit(last_error_reset, __crt_state_management::get_current_state_index(last_error_reset));
|
||||
}
|
||||
|
||||
__acrt_ptd* __cdecl __acrt_getptd_noexit_explicit(__crt_scoped_get_last_error_reset const& last_error_reset, size_t const global_state_index)
|
||||
{ // An extra function to grab the PTD while a GetLastError() reset guard is already in place
|
||||
// and the global state index is already known.
|
||||
|
||||
return internal_getptd_noexit(last_error_reset, global_state_index);
|
||||
}
|
||||
|
||||
extern "C" __acrt_ptd* __cdecl __acrt_getptd_noexit()
|
||||
{
|
||||
return internal_getptd_noexit();
|
||||
}
|
||||
|
||||
extern "C" __acrt_ptd* __cdecl __acrt_getptd()
|
||||
{
|
||||
__acrt_ptd* const ptd = internal_getptd_noexit();
|
||||
if (!ptd)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptd;
|
||||
}
|
||||
|
||||
extern "C" __acrt_ptd* __cdecl __acrt_getptd_head()
|
||||
{
|
||||
__acrt_ptd* const ptd_head = internal_get_ptd_head();
|
||||
if (!ptd_head)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
return ptd_head;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" void __cdecl __acrt_freeptd()
|
||||
{
|
||||
__acrt_ptd* const ptd_head = try_get_ptd_head();
|
||||
if (!ptd_head)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__acrt_FlsSetValue(__acrt_flsindex, nullptr);
|
||||
destroy_fls(ptd_head);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// These functions are simply wrappers around the Windows API functions.
|
||||
extern "C" unsigned long __cdecl __threadid()
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
extern "C" uintptr_t __cdecl __threadhandle()
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(GetCurrentThread());
|
||||
}
|
200
sdk/lib/ucrt/internal/report_runtime_error.cpp
Normal file
200
sdk/lib/ucrt/internal/report_runtime_error.cpp
Normal file
|
@ -0,0 +1,200 @@
|
|||
/***
|
||||
*report_runtime_error.cpp - startup error messages
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
*Purpose:
|
||||
* Prints out banner for runtime error messages.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include <corecrt_internal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
// This is used during the expansion of the runtime error text.
|
||||
#define EOL L"\r\n"
|
||||
|
||||
static bool __cdecl issue_debug_notification(wchar_t const* const message) throw()
|
||||
{
|
||||
// This is referenced only in the Debug CRT build
|
||||
UNREFERENCED_PARAMETER(message);
|
||||
|
||||
#ifdef _DEBUG
|
||||
switch (_CrtDbgReportW(_CRT_ERROR, nullptr, 0, nullptr, L"%ls", message))
|
||||
{
|
||||
case 1:
|
||||
_CrtDbgBreak();
|
||||
return true;
|
||||
|
||||
case 0:
|
||||
return true;
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Enclaves do not support error messages outside of OutputDebugString.
|
||||
#ifdef _UCRT_ENCLAVE_BUILD
|
||||
|
||||
extern "C" void __cdecl __acrt_report_runtime_error(wchar_t const* const message)
|
||||
{
|
||||
// Report the error using the debug
|
||||
issue_debug_notification(message);
|
||||
}
|
||||
|
||||
#else /* ^^^ _UCRT_ENCLAVE_BUILD ^^^ // vvv !_UCRT_ENCLAVE_BUILD vvv */
|
||||
|
||||
/*
|
||||
* __acrt_app_type, together with __error_mode, determine how error messages
|
||||
* are written out.
|
||||
*/
|
||||
static _crt_app_type __acrt_app_type = _crt_unknown_app;
|
||||
|
||||
/***
|
||||
*void _set_app_type(int apptype) - interface to change __acrt_app_type
|
||||
*
|
||||
*Purpose:
|
||||
* Set, or change, the value of __acrt_app_type.
|
||||
*
|
||||
* Set the default debug lib report destination for console apps.
|
||||
*
|
||||
* This function is for INTERNAL USE ONLY.
|
||||
*
|
||||
*Entry:
|
||||
* int modeval = _crt_unknown_app, unknown
|
||||
* _crt_console_app, console, or command line, application
|
||||
* _crt_gui_app, GUI, or Windows, application
|
||||
*
|
||||
*Exit:
|
||||
*
|
||||
*Exceptions:
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
extern "C" void __cdecl _set_app_type(_crt_app_type const new_app_type)
|
||||
{
|
||||
__acrt_app_type = new_app_type;
|
||||
}
|
||||
|
||||
extern "C" _crt_app_type __cdecl _query_app_type()
|
||||
{
|
||||
return __acrt_app_type;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool __cdecl should_write_error_to_console() throw()
|
||||
{
|
||||
int const error_mode = _set_error_mode(_REPORT_ERRMODE);
|
||||
|
||||
if (error_mode == _OUT_TO_STDERR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (error_mode == _OUT_TO_DEFAULT && __acrt_app_type == _crt_console_app)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void write_string_to_console(wchar_t const* const wide_string) throw()
|
||||
{
|
||||
HANDLE const handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (handle == nullptr || handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We convert the wide string to a narrow string by truncating each character.
|
||||
// Currently, the text for each runtime error consists only of ASCII, so this
|
||||
// is acceptable. If the error text is ever localized, this would need to
|
||||
// change.
|
||||
size_t const narrow_buffer_count = 500;
|
||||
char narrow_buffer[narrow_buffer_count];
|
||||
|
||||
char* const narrow_first = narrow_buffer;
|
||||
char* const narrow_last = narrow_first + narrow_buffer_count;
|
||||
|
||||
// Note that this loop copies the null terminator if the loop terminates
|
||||
// befoe running out of buffer space:
|
||||
char* narrow_it = narrow_first;
|
||||
wchar_t const* wide_it = wide_string;
|
||||
do
|
||||
{
|
||||
*narrow_it = static_cast<char>(*wide_it);
|
||||
}
|
||||
while (++narrow_it != narrow_last && *wide_it++ != '\0');
|
||||
|
||||
// If we did run out of buffer space, this will null-terminate the text that
|
||||
// we were able to copy:
|
||||
*(narrow_last - 1) = '\0';
|
||||
|
||||
DWORD const bytes_to_write = static_cast<DWORD>(narrow_it - narrow_first - 1); // Account for null terminator
|
||||
DWORD bytes_written = 0;
|
||||
WriteFile(handle, narrow_buffer, bytes_to_write, &bytes_written, nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" void __cdecl __acrt_report_runtime_error(wchar_t const* const message)
|
||||
{
|
||||
// Before we report the error via the normal path, report the error using
|
||||
// the debug
|
||||
if (issue_debug_notification(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_write_error_to_console())
|
||||
{
|
||||
write_string_to_console(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
#define MSGTEXTPREFIX L"Runtime Error!\n\nProgram: "
|
||||
static wchar_t outmsg[sizeof(MSGTEXTPREFIX) / sizeof(wchar_t) + _MAX_PATH + 2 + 500];
|
||||
// runtime error msg + progname + 2 newline + runtime error text.
|
||||
wchar_t* progname = &outmsg[sizeof(MSGTEXTPREFIX) / sizeof(wchar_t) - 1];
|
||||
size_t progname_size = _countof(outmsg) - (progname - outmsg);
|
||||
wchar_t* pch = progname;
|
||||
|
||||
_ERRCHECK(wcscpy_s(outmsg, _countof(outmsg), MSGTEXTPREFIX));
|
||||
|
||||
progname[MAX_PATH] = L'\0';
|
||||
if (!GetModuleFileNameW(nullptr, progname, MAX_PATH))
|
||||
{
|
||||
_ERRCHECK(wcscpy_s(progname, progname_size, L"<program name unknown>"));
|
||||
}
|
||||
|
||||
#define MAXLINELEN 60
|
||||
if (wcslen(pch) + 1 > MAXLINELEN)
|
||||
{
|
||||
pch += wcslen(progname) + 1 - MAXLINELEN;
|
||||
_ERRCHECK(wcsncpy_s(pch, progname_size - (pch - progname), L"...", 3));
|
||||
}
|
||||
|
||||
_ERRCHECK(wcscat_s(outmsg, _countof(outmsg), L"\n\n"));
|
||||
_ERRCHECK(wcscat_s(outmsg, _countof(outmsg), message));
|
||||
|
||||
// Okay to ignore return value here, this is just to display the message box.
|
||||
// Only caller is abort() (so we shouldn't/can't handle IDABORT), so the process
|
||||
// will end shortly.
|
||||
__acrt_show_wide_message_box(
|
||||
outmsg,
|
||||
L"Microsoft Visual C++ Runtime Library",
|
||||
MB_OK | MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _UCRT_ENCLAVE_BUILD */
|
67
sdk/lib/ucrt/internal/shared_initialization.cpp
Normal file
67
sdk/lib/ucrt/internal/shared_initialization.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// shared_initialization.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Shared initialization logic used by both the AppCRT and the DesktopCRT.
|
||||
//
|
||||
#include <corecrt_internal.h>
|
||||
|
||||
extern "C" bool __cdecl __acrt_execute_initializers(
|
||||
__acrt_initializer const* const first,
|
||||
__acrt_initializer const* const last
|
||||
)
|
||||
{
|
||||
if (first == last)
|
||||
return true;
|
||||
|
||||
// Execute the initializers in [first, last), in order:
|
||||
__acrt_initializer const* it = first;
|
||||
for (; it != last; ++it)
|
||||
{
|
||||
if (it->_initialize == nullptr)
|
||||
continue;
|
||||
|
||||
if (!(it->_initialize)())
|
||||
break;
|
||||
}
|
||||
|
||||
// If we reached the end, all initializers completed successfully:
|
||||
if (it == last)
|
||||
return true;
|
||||
|
||||
// Otherwise, the initializer pointed to by it failed. We need to roll back
|
||||
// the initialization by executing the uninitializers corresponding to each
|
||||
// of the initializers that completed successfully:
|
||||
for (; it != first; --it)
|
||||
{
|
||||
// During initialization roll back, we do not execute uninitializers
|
||||
// that have no corresponding initializer:
|
||||
if ((it - 1)->_initialize == nullptr || (it - 1)->_uninitialize == nullptr)
|
||||
continue;
|
||||
|
||||
(it - 1)->_uninitialize(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_execute_uninitializers(
|
||||
__acrt_initializer const* const first,
|
||||
__acrt_initializer const* const last
|
||||
)
|
||||
{
|
||||
if (first == last)
|
||||
return true;
|
||||
|
||||
// Execute the uninitializers in [first, last), in reverse order:
|
||||
for (__acrt_initializer const* it = last; it != first; --it)
|
||||
{
|
||||
if ((it - 1)->_uninitialize == nullptr)
|
||||
continue;
|
||||
|
||||
(it - 1)->_uninitialize(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
182
sdk/lib/ucrt/internal/win_policies.cpp
Normal file
182
sdk/lib/ucrt/internal/win_policies.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
//
|
||||
// win_policies.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Wrapper functions that determine what policies should apply for the process in question.
|
||||
//
|
||||
|
||||
#include <corecrt_internal.h>
|
||||
|
||||
template<typename TPolicy>
|
||||
static typename TPolicy::policy_type __cdecl get_win_policy(typename TPolicy::appmodel_policy_type defaultValue)
|
||||
{
|
||||
TPolicy::appmodel_policy_type appmodelPolicy = defaultValue;
|
||||
|
||||
// Secure processes cannot load the appmodel DLL, so only attempt loading
|
||||
// policy information if this is not a secure process.
|
||||
if (!__acrt_is_secure_process())
|
||||
{
|
||||
TPolicy::appmodel_get_policy(&appmodelPolicy);
|
||||
}
|
||||
|
||||
return TPolicy::appmodel_policy_to_policy_type(appmodelPolicy);
|
||||
}
|
||||
|
||||
template<typename TPolicy>
|
||||
static typename TPolicy::policy_type __cdecl get_cached_win_policy(typename TPolicy::appmodel_policy_type defaultValue)
|
||||
{
|
||||
static long state_cache = 0;
|
||||
if (long const cached_state = __crt_interlocked_read(&state_cache))
|
||||
{
|
||||
return static_cast<TPolicy::policy_type>(cached_state);
|
||||
}
|
||||
|
||||
TPolicy::appmodel_policy_type appmodelPolicy = defaultValue;
|
||||
|
||||
// Secure processes cannot load the appmodel DLL, so only attempt loading
|
||||
// policy information if this is not a secure process.
|
||||
if (!__acrt_is_secure_process())
|
||||
{
|
||||
TPolicy::appmodel_get_policy(&appmodelPolicy);
|
||||
}
|
||||
|
||||
TPolicy::policy_type const policyValue = TPolicy::appmodel_policy_to_policy_type(appmodelPolicy);
|
||||
|
||||
long const cached_state = _InterlockedExchange(&state_cache, static_cast<long>(policyValue));
|
||||
if (cached_state)
|
||||
{
|
||||
_ASSERTE(cached_state == static_cast<long>(policyValue));
|
||||
}
|
||||
|
||||
return policyValue;
|
||||
}
|
||||
|
||||
// Determines whether ExitProcess() or TerminateProcess() should be used to end the process
|
||||
extern "C" process_end_policy __cdecl __acrt_get_process_end_policy()
|
||||
{
|
||||
struct process_end_policy_properties
|
||||
{
|
||||
typedef process_end_policy policy_type;
|
||||
typedef AppPolicyProcessTerminationMethod appmodel_policy_type;
|
||||
|
||||
static policy_type appmodel_policy_to_policy_type(appmodel_policy_type const appmodelPolicy) throw()
|
||||
{
|
||||
if (appmodelPolicy == AppPolicyProcessTerminationMethod_TerminateProcess)
|
||||
{
|
||||
return process_end_policy_terminate_process;
|
||||
}
|
||||
else
|
||||
{
|
||||
return process_end_policy_exit_process;
|
||||
}
|
||||
}
|
||||
|
||||
static LONG appmodel_get_policy(appmodel_policy_type* appmodelPolicy)
|
||||
{
|
||||
return __acrt_AppPolicyGetProcessTerminationMethodInternal(appmodelPolicy);
|
||||
}
|
||||
};
|
||||
|
||||
return get_win_policy<process_end_policy_properties>(AppPolicyProcessTerminationMethod_ExitProcess);
|
||||
}
|
||||
|
||||
// Determines whether RoInitialize() should be called when creating a thread
|
||||
extern "C" begin_thread_init_policy __cdecl __acrt_get_begin_thread_init_policy()
|
||||
{
|
||||
struct begin_thread_init_policy_properties
|
||||
{
|
||||
typedef begin_thread_init_policy policy_type;
|
||||
typedef AppPolicyThreadInitializationType appmodel_policy_type;
|
||||
|
||||
static_assert(begin_thread_init_policy_unknown == 0, "Default value for cache must be 0");
|
||||
|
||||
static policy_type appmodel_policy_to_policy_type(long const appmodelPolicy) throw()
|
||||
{
|
||||
if (appmodelPolicy == AppPolicyThreadInitializationType_InitializeWinRT)
|
||||
{
|
||||
return begin_thread_init_policy_ro_initialize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return begin_thread_init_policy_none;
|
||||
}
|
||||
}
|
||||
|
||||
static LONG appmodel_get_policy(appmodel_policy_type* appmodelPolicy)
|
||||
{
|
||||
return __acrt_AppPolicyGetThreadInitializationTypeInternal(appmodelPolicy);
|
||||
}
|
||||
};
|
||||
|
||||
return get_cached_win_policy<begin_thread_init_policy_properties>(AppPolicyThreadInitializationType_None);
|
||||
}
|
||||
|
||||
// Determines whether we should attempt to display assert dialog
|
||||
extern "C" developer_information_policy __cdecl __acrt_get_developer_information_policy()
|
||||
{
|
||||
struct developer_information_policy_properties
|
||||
{
|
||||
typedef developer_information_policy policy_type;
|
||||
typedef AppPolicyShowDeveloperDiagnostic appmodel_policy_type;
|
||||
|
||||
static_assert(developer_information_policy_unknown == 0, "Default value for cache must be 0");
|
||||
|
||||
static policy_type appmodel_policy_to_policy_type(long const appmodelPolicy) throw()
|
||||
{
|
||||
if (appmodelPolicy == AppPolicyShowDeveloperDiagnostic_ShowUI)
|
||||
{
|
||||
return developer_information_policy_ui;
|
||||
}
|
||||
else
|
||||
{
|
||||
return developer_information_policy_none;
|
||||
}
|
||||
}
|
||||
|
||||
static LONG appmodel_get_policy(appmodel_policy_type* appmodelPolicy)
|
||||
{
|
||||
return __acrt_AppPolicyGetShowDeveloperDiagnosticInternal(appmodelPolicy);
|
||||
}
|
||||
};
|
||||
|
||||
return get_cached_win_policy<developer_information_policy_properties>(AppPolicyShowDeveloperDiagnostic_ShowUI);
|
||||
}
|
||||
|
||||
// Determines what type of windowing model technology is available
|
||||
extern "C" windowing_model_policy __cdecl __acrt_get_windowing_model_policy()
|
||||
{
|
||||
struct windowing_model_policy_properties
|
||||
{
|
||||
typedef windowing_model_policy policy_type;
|
||||
typedef AppPolicyWindowingModel appmodel_policy_type;
|
||||
|
||||
static_assert(windowing_model_policy_unknown == 0, "Default value for cache must be 0");
|
||||
|
||||
static policy_type appmodel_policy_to_policy_type(long const appmodelPolicy) throw()
|
||||
{
|
||||
switch (appmodelPolicy)
|
||||
{
|
||||
case AppPolicyWindowingModel_ClassicDesktop:
|
||||
return windowing_model_policy_hwnd;
|
||||
|
||||
case AppPolicyWindowingModel_Universal:
|
||||
return windowing_model_policy_corewindow;
|
||||
|
||||
case AppPolicyWindowingModel_ClassicPhone:
|
||||
return windowing_model_policy_legacyphone;
|
||||
|
||||
case AppPolicyWindowingModel_None:
|
||||
default:
|
||||
return windowing_model_policy_none;
|
||||
}
|
||||
}
|
||||
|
||||
static LONG appmodel_get_policy(appmodel_policy_type* appmodelPolicy)
|
||||
{
|
||||
return __acrt_AppPolicyGetWindowingModelInternal(appmodelPolicy);
|
||||
}
|
||||
};
|
||||
|
||||
return get_cached_win_policy<windowing_model_policy_properties>(AppPolicyWindowingModel_ClassicDesktop);
|
||||
}
|
936
sdk/lib/ucrt/internal/winapi_thunks.cpp
Normal file
936
sdk/lib/ucrt/internal/winapi_thunks.cpp
Normal file
|
@ -0,0 +1,936 @@
|
|||
//
|
||||
// winapi_thunks.cpp
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// Definitions of wrappers for Windows API functions that cannot be called
|
||||
// directly because they are not available on all supported operating systems.
|
||||
//
|
||||
|
||||
#include <nt.h>
|
||||
#include <ntrtl.h>
|
||||
#include <nturtl.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <corecrt_internal.h>
|
||||
#include <appmodel.h>
|
||||
#include <roapi.h>
|
||||
|
||||
// This is simlar to msvcrt.
|
||||
#if _M_AMD64 || _M_ARM || _M_ARM64 || _M_HYBRID
|
||||
#define FLS_ALWAYS_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
WINBASEAPI
|
||||
_Success_(return > 0 && return < BufferLength)
|
||||
DWORD
|
||||
WINAPI
|
||||
GetTempPath2W(
|
||||
_In_ DWORD BufferLength,
|
||||
_Out_writes_to_opt_(BufferLength,return + 1) LPWSTR Buffer
|
||||
);
|
||||
|
||||
// The XState APIs are declared by the Windows headers only when building for
|
||||
// x86 and x64. We declare them here unconditionally so that we can share the
|
||||
// same code for all architectures (we simply avoid use of these functions on
|
||||
// other architectures).
|
||||
extern "C" WINBASEAPI DWORD64 WINAPI GetEnabledXStateFeatures();
|
||||
|
||||
_Must_inspect_result_
|
||||
extern "C" WINBASEAPI BOOL WINAPI GetXStateFeaturesMask(
|
||||
_In_ PCONTEXT context,
|
||||
_Out_ PDWORD64 feature_mask
|
||||
);
|
||||
|
||||
_Success_(return != NULL)
|
||||
extern "C" WINBASEAPI PVOID WINAPI LocateXStateFeature(
|
||||
_In_ PCONTEXT context,
|
||||
_In_ DWORD feature_id,
|
||||
_Out_opt_ PDWORD length
|
||||
);
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_MODULES_0 \
|
||||
_APPLY(api_ms_win_core_datetime_l1_1_1, "api-ms-win-core-datetime-l1-1-1" ) \
|
||||
_APPLY(api_ms_win_core_file_l1_2_4, "api-ms-win-core-file-l1-2-4" ) \
|
||||
_APPLY(api_ms_win_core_file_l1_2_2, "api-ms-win-core-file-l1-2-2" ) \
|
||||
_APPLY(api_ms_win_core_localization_l1_2_1, "api-ms-win-core-localization-l1-2-1" ) \
|
||||
_APPLY(api_ms_win_core_localization_obsolete_l1_2_0, "api-ms-win-core-localization-obsolete-l1-2-0") \
|
||||
_APPLY(api_ms_win_core_processthreads_l1_1_2, "api-ms-win-core-processthreads-l1-1-2" ) \
|
||||
_APPLY(api_ms_win_core_string_l1_1_0, "api-ms-win-core-string-l1-1-0" ) \
|
||||
_APPLY(api_ms_win_core_synch_l1_2_0, "api-ms-win-core-synch-l1-2-0" ) \
|
||||
_APPLY(api_ms_win_core_sysinfo_l1_2_1, "api-ms-win-core-sysinfo-l1-2-1" ) \
|
||||
_APPLY(api_ms_win_core_winrt_l1_1_0, "api-ms-win-core-winrt-l1-1-0" ) \
|
||||
_APPLY(api_ms_win_core_xstate_l2_1_0, "api-ms-win-core-xstate-l2-1-0" ) \
|
||||
_APPLY(api_ms_win_rtcore_ntuser_window_l1_1_0, "api-ms-win-rtcore-ntuser-window-l1-1-0" ) \
|
||||
_APPLY(api_ms_win_security_systemfunctions_l1_1_0, "api-ms-win-security-systemfunctions-l1-1-0" ) \
|
||||
_APPLY(ext_ms_win_ntuser_dialogbox_l1_1_0, "ext-ms-win-ntuser-dialogbox-l1-1-0" ) \
|
||||
_APPLY(ext_ms_win_ntuser_windowstation_l1_1_0, "ext-ms-win-ntuser-windowstation-l1-1-0" ) \
|
||||
_APPLY(advapi32, "advapi32" ) \
|
||||
_APPLY(kernel32, "kernel32" ) \
|
||||
_APPLY(kernelbase, "kernelbase" ) \
|
||||
_APPLY(ntdll, "ntdll" ) \
|
||||
_APPLY(api_ms_win_appmodel_runtime_l1_1_2, "api-ms-win-appmodel-runtime-l1-1-2" ) \
|
||||
_APPLY(user32, "user32" )
|
||||
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_MODULES_1 /* nothing */
|
||||
|
||||
#else
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_MODULES_1 \
|
||||
_APPLY(api_ms_win_core_fibers_l1_1_0, "api-ms-win-core-fibers-l1-1-0" )
|
||||
|
||||
#endif
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_MODULES \
|
||||
_ACRT_APPLY_TO_LATE_BOUND_MODULES_0 \
|
||||
_ACRT_APPLY_TO_LATE_BOUND_MODULES_1 \
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_0 \
|
||||
_APPLY(AreFileApisANSI, ({ /* api_ms_win_core_file_l1_2_2, */ kernel32 })) \
|
||||
_APPLY(CompareStringEx, ({ api_ms_win_core_string_l1_1_0, kernel32 })) \
|
||||
_APPLY(EnumSystemLocalesEx, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(GetActiveWindow, ({ api_ms_win_rtcore_ntuser_window_l1_1_0, user32 })) \
|
||||
_APPLY(GetDateFormatEx, ({ api_ms_win_core_datetime_l1_1_1, kernel32 })) \
|
||||
_APPLY(GetTempPath2W, ({ api_ms_win_core_file_l1_2_4, kernelbase })) \
|
||||
_APPLY(GetEnabledXStateFeatures, ({ api_ms_win_core_xstate_l2_1_0, kernel32 })) \
|
||||
_APPLY(GetLastActivePopup, ({ ext_ms_win_ntuser_dialogbox_l1_1_0, user32 })) \
|
||||
_APPLY(GetLocaleInfoEx, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(GetProcessWindowStation, ({ ext_ms_win_ntuser_windowstation_l1_1_0, user32 })) \
|
||||
_APPLY(GetSystemTimePreciseAsFileTime, ({ api_ms_win_core_sysinfo_l1_2_1 })) \
|
||||
_APPLY(GetTimeFormatEx, ({ api_ms_win_core_datetime_l1_1_1, kernel32 })) \
|
||||
_APPLY(GetUserDefaultLocaleName, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(GetUserObjectInformationW, ({ ext_ms_win_ntuser_windowstation_l1_1_0, user32 })) \
|
||||
_APPLY(GetXStateFeaturesMask, ({ api_ms_win_core_xstate_l2_1_0, kernel32 })) \
|
||||
_APPLY(InitializeCriticalSectionEx, ({ api_ms_win_core_synch_l1_2_0, kernel32 })) \
|
||||
_APPLY(IsValidLocaleName, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(LCMapStringEx, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(LCIDToLocaleName, ({ api_ms_win_core_localization_obsolete_l1_2_0, kernel32 })) \
|
||||
_APPLY(LocaleNameToLCID, ({ api_ms_win_core_localization_l1_2_1, kernel32 })) \
|
||||
_APPLY(LocateXStateFeature, ({ api_ms_win_core_xstate_l2_1_0, kernel32 })) \
|
||||
_APPLY(MessageBoxA, ({ ext_ms_win_ntuser_dialogbox_l1_1_0, user32 })) \
|
||||
_APPLY(MessageBoxW, ({ ext_ms_win_ntuser_dialogbox_l1_1_0, user32 })) \
|
||||
_APPLY(RoInitialize, ({ api_ms_win_core_winrt_l1_1_0 })) \
|
||||
_APPLY(RoUninitialize, ({ api_ms_win_core_winrt_l1_1_0 })) \
|
||||
_APPLY(AppPolicyGetProcessTerminationMethod, ({ api_ms_win_appmodel_runtime_l1_1_2 })) \
|
||||
_APPLY(AppPolicyGetThreadInitializationType, ({ api_ms_win_appmodel_runtime_l1_1_2 })) \
|
||||
_APPLY(AppPolicyGetShowDeveloperDiagnostic, ({ api_ms_win_appmodel_runtime_l1_1_2 })) \
|
||||
_APPLY(AppPolicyGetWindowingModel, ({ api_ms_win_appmodel_runtime_l1_1_2 })) \
|
||||
_APPLY(SetThreadStackGuarantee, ({ api_ms_win_core_processthreads_l1_1_2, kernel32 })) \
|
||||
_APPLY(SystemFunction036, ({ api_ms_win_security_systemfunctions_l1_1_0, advapi32 }))
|
||||
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1 /* nothing */
|
||||
|
||||
#else
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1 \
|
||||
_APPLY(FlsAlloc, ({ api_ms_win_core_fibers_l1_1_0, kernel32 })) \
|
||||
_APPLY(FlsFree, ({ api_ms_win_core_fibers_l1_1_0, kernel32 })) \
|
||||
_APPLY(FlsGetValue, ({ api_ms_win_core_fibers_l1_1_0, kernel32 })) \
|
||||
_APPLY(FlsSetValue, ({ api_ms_win_core_fibers_l1_1_0, kernel32 }))
|
||||
|
||||
#endif
|
||||
|
||||
#define _ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS \
|
||||
_ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_0 \
|
||||
_ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS_1 \
|
||||
|
||||
namespace
|
||||
{
|
||||
// Generate enumerators for each of the modules:
|
||||
enum module_id : unsigned
|
||||
{
|
||||
#define _APPLY(_SYMBOL, _NAME) _SYMBOL,
|
||||
_ACRT_APPLY_TO_LATE_BOUND_MODULES
|
||||
#undef _APPLY
|
||||
|
||||
module_id_count
|
||||
};
|
||||
|
||||
// Generate a table of module names that can be indexed by the module_id
|
||||
// enumerators:
|
||||
static wchar_t const* const module_names[module_id_count] =
|
||||
{
|
||||
#define _APPLY(_SYMBOL, _NAME) _CRT_WIDE(_NAME),
|
||||
_ACRT_APPLY_TO_LATE_BOUND_MODULES
|
||||
#undef _APPLY
|
||||
};
|
||||
|
||||
// Generate enumerators for each of the functions:
|
||||
enum function_id : unsigned
|
||||
{
|
||||
#define _APPLY(_FUNCTION, _MODULES) _CRT_CONCATENATE(_FUNCTION, _id),
|
||||
_ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
|
||||
#undef _APPLY
|
||||
|
||||
function_id_count
|
||||
};
|
||||
|
||||
// Generate a typedef for each function of the form function_pft.
|
||||
#define _APPLY(_FUNCTION, _MODULES) \
|
||||
using _CRT_CONCATENATE(_FUNCTION, _pft) = decltype(_FUNCTION)*;
|
||||
_ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
|
||||
#undef _APPLY
|
||||
}
|
||||
|
||||
// This table stores the module handles that we have obtained via LoadLibrary.
|
||||
// If a handle is null, we have not yet attempted to load that module. If a
|
||||
// handle is -1 (INVALID_HANDLE_VALUE), we have attempted to load the module
|
||||
// but the attempt failed.
|
||||
static HMODULE module_handles[module_id_count];
|
||||
|
||||
// This table stores the function pointers that we have loaded dynamically. The
|
||||
// function pointers are stored in encoded form via __crt_fast_encode_ponter. If
|
||||
// a function pointer is an encoded null pointer, we have not yet attempted to
|
||||
// get that function pointer. If a function pointer is an encoded -1, we have
|
||||
// attempted to get that function pointer but the attempt failed.
|
||||
static void* encoded_function_pointers[function_id_count];
|
||||
|
||||
extern "C" bool __cdecl __acrt_initialize_winapi_thunks()
|
||||
{
|
||||
void* const encoded_nullptr = __crt_fast_encode_pointer(nullptr);
|
||||
|
||||
for (void*& p : encoded_function_pointers)
|
||||
{
|
||||
p = encoded_nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_uninitialize_winapi_thunks(bool const terminating)
|
||||
{
|
||||
// If the process is terminating, there's no need to free any module handles
|
||||
if (terminating)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (HMODULE& module : module_handles)
|
||||
{
|
||||
if (module)
|
||||
{
|
||||
if (module != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FreeLibrary(module);
|
||||
}
|
||||
|
||||
module = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static __forceinline void* __cdecl invalid_function_sentinel() throw()
|
||||
{
|
||||
return reinterpret_cast<void*>(static_cast<uintptr_t>(-1));
|
||||
}
|
||||
|
||||
static HMODULE __cdecl try_load_library_from_system_directory(wchar_t const* const name) throw()
|
||||
{
|
||||
HMODULE const handle = LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (handle)
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
// LOAD_LIBRARY_SEARCH_SYSTEM32 is only supported by Windows 7 and above; if
|
||||
// the OS does not support this flag, try again without it. On these OSes,
|
||||
// all APISets will be forwarders. To prevent DLL hijacking, do not attempt
|
||||
// to load the APISet forwarders dynamically. This will cause our caller to
|
||||
// fall back to the real DLL (e.g. kernel32). All of those are known DLLs.
|
||||
if (GetLastError() == ERROR_INVALID_PARAMETER &&
|
||||
wcsncmp(name, L"api-ms-", 7) != 0 &&
|
||||
wcsncmp(name, L"ext-ms-", 7) != 0)
|
||||
{
|
||||
return LoadLibraryExW(name, nullptr, 0);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static HMODULE __cdecl try_get_module(module_id const id) throw()
|
||||
{
|
||||
// First check to see if we've cached the module handle:
|
||||
if (HMODULE const cached_handle = __crt_interlocked_read_pointer(module_handles + id))
|
||||
{
|
||||
if (cached_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cached_handle;
|
||||
}
|
||||
|
||||
// If we haven't yet cached the module handle, try to load the library. If
|
||||
// this fails, cache the sentinel handle value INVALID_HANDLE_VALUE so that
|
||||
// we don't attempt to load the module again:
|
||||
HMODULE const new_handle = try_load_library_from_system_directory(module_names[id]);
|
||||
if (!new_handle)
|
||||
{
|
||||
if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(module_handles + id, INVALID_HANDLE_VALUE))
|
||||
{
|
||||
_ASSERTE(cached_handle == INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Swap the new handle into the cache. If the cache no longer contained a
|
||||
// null handle, then some other thread loaded the module and cached the
|
||||
// handle while we were doing the same. In that case, we free the handle
|
||||
// once to maintain the reference count:
|
||||
if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(module_handles + id, new_handle))
|
||||
{
|
||||
_ASSERTE(cached_handle == new_handle);
|
||||
FreeLibrary(new_handle);
|
||||
}
|
||||
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
static HMODULE __cdecl try_get_first_available_module(
|
||||
module_id const* const first,
|
||||
module_id const* const last
|
||||
) throw()
|
||||
{
|
||||
for (module_id const* it = first; it != last; ++it)
|
||||
{
|
||||
HMODULE const handle = try_get_module(*it);
|
||||
if (handle)
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static __forceinline void* __cdecl 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
|
||||
) throw()
|
||||
{
|
||||
HMODULE const module_handle = try_get_first_available_module(first_module_id, last_module_id);
|
||||
if (!module_handle)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<void*>(GetProcAddress(module_handle, name));
|
||||
}
|
||||
|
||||
static void* __cdecl 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
|
||||
) throw()
|
||||
{
|
||||
// First check to see if we've cached the function pointer:
|
||||
{
|
||||
void* const cached_fp = __crt_fast_decode_pointer(
|
||||
__crt_interlocked_read_pointer(encoded_function_pointers + id));
|
||||
|
||||
if (cached_fp == invalid_function_sentinel())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cached_fp)
|
||||
{
|
||||
return cached_fp;
|
||||
}
|
||||
}
|
||||
|
||||
// If we haven't yet cached the function pointer, try to import it from any
|
||||
// of the modules in which it might be defined. If this fails, cache the
|
||||
// sentinel pointer so that we don't attempt to load this function again:
|
||||
void* const new_fp = try_get_proc_address_from_first_available_module(name, first_module_id, last_module_id);
|
||||
if (!new_fp)
|
||||
{
|
||||
void* const cached_fp = __crt_fast_decode_pointer(
|
||||
__crt_interlocked_exchange_pointer(
|
||||
encoded_function_pointers + id,
|
||||
__crt_fast_encode_pointer(invalid_function_sentinel())));
|
||||
|
||||
if (cached_fp)
|
||||
{
|
||||
_ASSERTE(cached_fp == invalid_function_sentinel());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Swap the newly obtained function pointer into the cache. The cache may
|
||||
// no longer contain an encoded null pointer if another thread obtained the
|
||||
// function address while we were doing the same (both threads should have
|
||||
// gotten the same function pointer):
|
||||
{
|
||||
void* const cached_fp = __crt_fast_decode_pointer(
|
||||
__crt_interlocked_exchange_pointer(
|
||||
encoded_function_pointers + id,
|
||||
__crt_fast_encode_pointer(new_fp)));
|
||||
|
||||
if (cached_fp)
|
||||
{
|
||||
_ASSERTE(cached_fp == new_fp);
|
||||
}
|
||||
}
|
||||
|
||||
return new_fp;
|
||||
}
|
||||
|
||||
// Generate accessors that wrap the general try_get_function for each function,
|
||||
// passing the correct set of candidate modules and returning a function pointer
|
||||
// of the correct type:
|
||||
#define _APPLY(_FUNCTION, _MODULES) \
|
||||
static _CRT_CONCATENATE(_FUNCTION, _pft) __cdecl _CRT_CONCATENATE(try_get_, _FUNCTION)() throw() \
|
||||
{ \
|
||||
static module_id const candidate_modules[] = _CRT_UNPARENTHESIZE(_MODULES); \
|
||||
\
|
||||
return reinterpret_cast<_CRT_CONCATENATE(_FUNCTION, _pft)>(try_get_function( \
|
||||
_CRT_CONCATENATE(_FUNCTION, _id), \
|
||||
_CRT_STRINGIZE(_FUNCTION), \
|
||||
candidate_modules, \
|
||||
candidate_modules + _countof(candidate_modules))); \
|
||||
}
|
||||
_ACRT_APPLY_TO_LATE_BOUND_FUNCTIONS
|
||||
#undef _APPLY
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_AreFileApisANSI()
|
||||
{
|
||||
if (auto const are_file_apis_ansi = try_get_AreFileApisANSI())
|
||||
{
|
||||
return are_file_apis_ansi();
|
||||
}
|
||||
|
||||
// If we were unable to get the AreFileApisANSI function, we can safely
|
||||
// assume that the file APIs are, in fact, ANSI:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __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
|
||||
)
|
||||
{
|
||||
if (auto const compare_string_ex = try_get_CompareStringEx())
|
||||
{
|
||||
// On WCOS devices, CompareStringEx may calls into icu.dll which is an OS component using the UCRT.
|
||||
// If icu.dll calls any UCRT export under OS mode (ex: malloc), then CompareStringEx will return under Prog Mode even if
|
||||
// we started in OS mode. To prevent this, an OS mode guard is in place.
|
||||
__crt_state_management::scoped_global_state_reset os_mode_guard;
|
||||
return compare_string_ex(locale_name, flags, string1, string1_count, string2, string2_count, version, reserved, param);
|
||||
}
|
||||
|
||||
return CompareStringW(__acrt_LocaleNameToLCID(locale_name, 0), flags, string1, string1_count, string2, string2_count);
|
||||
}
|
||||
|
||||
// This has been split into its own function to work around a bug in the Dev12
|
||||
// C++ compiler where nested captureless lambdas are not convertible to the
|
||||
// required function pointer type.
|
||||
static BOOL enum_system_locales_ex_nolock(
|
||||
LOCALE_ENUMPROCEX const enum_proc
|
||||
) throw()
|
||||
{
|
||||
static LOCALE_ENUMPROCEX static_enum_proc;
|
||||
|
||||
static_enum_proc = __crt_fast_encode_pointer(enum_proc);
|
||||
BOOL const result = EnumSystemLocalesW(
|
||||
[](LPWSTR locale_string) { return __crt_fast_decode_pointer(static_enum_proc)(locale_string, 0, 0); },
|
||||
LCID_INSTALLED);
|
||||
static_enum_proc = __crt_fast_encode_pointer(nullptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_EnumSystemLocalesEx(
|
||||
LOCALE_ENUMPROCEX const enum_proc,
|
||||
DWORD const flags,
|
||||
LPARAM const param,
|
||||
LPVOID const reserved
|
||||
)
|
||||
{
|
||||
if (auto const enum_system_locales_ex = try_get_EnumSystemLocalesEx())
|
||||
{
|
||||
return enum_system_locales_ex(enum_proc, flags, param, reserved);
|
||||
}
|
||||
|
||||
return __acrt_lock_and_call(__acrt_locale_lock, [&]() -> BOOL
|
||||
{
|
||||
return enum_system_locales_ex_nolock(enum_proc);
|
||||
});
|
||||
}
|
||||
|
||||
extern "C" DWORD WINAPI __acrt_FlsAlloc(PFLS_CALLBACK_FUNCTION const callback)
|
||||
{
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
return FlsAlloc(callback);
|
||||
#else
|
||||
if (auto const fls_alloc = try_get_FlsAlloc())
|
||||
{
|
||||
return fls_alloc(callback);
|
||||
}
|
||||
|
||||
return TlsAlloc();
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_FlsFree(DWORD const fls_index)
|
||||
{
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
return FlsFree(fls_index);
|
||||
#else
|
||||
if (auto const fls_free = try_get_FlsFree())
|
||||
{
|
||||
return fls_free(fls_index);
|
||||
}
|
||||
|
||||
return TlsFree(fls_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" PVOID WINAPI __acrt_FlsGetValue(DWORD const fls_index)
|
||||
{
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
return FlsGetValue(fls_index);
|
||||
#else
|
||||
if (auto const fls_get_value = try_get_FlsGetValue())
|
||||
{
|
||||
return fls_get_value(fls_index);
|
||||
}
|
||||
|
||||
return TlsGetValue(fls_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_FlsSetValue(DWORD const fls_index, PVOID const fls_data)
|
||||
{
|
||||
#if FLS_ALWAYS_AVAILABLE
|
||||
return FlsSetValue(fls_index, fls_data);
|
||||
#else
|
||||
if (auto const fls_set_value = try_get_FlsSetValue())
|
||||
{
|
||||
return fls_set_value(fls_index, fls_data);
|
||||
}
|
||||
|
||||
return TlsSetValue(fls_index, fls_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __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
|
||||
)
|
||||
{
|
||||
if (auto const get_date_format_ex = try_get_GetDateFormatEx())
|
||||
{
|
||||
return get_date_format_ex(locale_name, flags, date, format, buffer, buffer_count, calendar);
|
||||
}
|
||||
|
||||
return GetDateFormatW(__acrt_LocaleNameToLCID(locale_name, 0), flags, date, format, buffer, buffer_count);
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_GetTempPath2W(
|
||||
DWORD nBufferLength,
|
||||
LPWSTR lpBuffer
|
||||
)
|
||||
{
|
||||
if (auto const get_temp_path2w = try_get_GetTempPath2W())
|
||||
{
|
||||
return get_temp_path2w(nBufferLength, lpBuffer);
|
||||
}
|
||||
return GetTempPathW(nBufferLength, lpBuffer);
|
||||
}
|
||||
|
||||
extern "C" DWORD64 WINAPI __acrt_GetEnabledXStateFeatures()
|
||||
{
|
||||
if (auto const get_enabled_xstate_features = try_get_GetEnabledXStateFeatures())
|
||||
{
|
||||
return get_enabled_xstate_features();
|
||||
}
|
||||
|
||||
abort(); // No fallback; callers should check availablility before calling
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_GetLocaleInfoEx(
|
||||
LPCWSTR const locale_name,
|
||||
LCTYPE const lc_type,
|
||||
LPWSTR const data,
|
||||
int const data_count
|
||||
)
|
||||
{
|
||||
if (auto const get_locale_info_ex = try_get_GetLocaleInfoEx())
|
||||
{
|
||||
return get_locale_info_ex(locale_name, lc_type, data, data_count);
|
||||
}
|
||||
|
||||
return GetLocaleInfoW(__acrt_LocaleNameToLCID(locale_name, 0), lc_type, data, data_count);
|
||||
}
|
||||
|
||||
extern "C" VOID WINAPI __acrt_GetSystemTimePreciseAsFileTime(LPFILETIME const system_time)
|
||||
{
|
||||
if (auto const get_system_time_precise_as_file_time = try_get_GetSystemTimePreciseAsFileTime())
|
||||
{
|
||||
return get_system_time_precise_as_file_time(system_time);
|
||||
}
|
||||
|
||||
return GetSystemTimeAsFileTime(system_time);
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_GetTimeFormatEx(
|
||||
LPCWSTR const locale_name,
|
||||
DWORD const flags,
|
||||
SYSTEMTIME CONST* const time,
|
||||
LPCWSTR const format,
|
||||
LPWSTR const buffer,
|
||||
int const buffer_count
|
||||
)
|
||||
{
|
||||
if (auto const get_time_format_ex = try_get_GetTimeFormatEx())
|
||||
{
|
||||
return get_time_format_ex(locale_name, flags, time, format, buffer, buffer_count);
|
||||
}
|
||||
|
||||
return GetTimeFormatW(__acrt_LocaleNameToLCID(locale_name, 0), flags, time, format, buffer, buffer_count);
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_GetUserDefaultLocaleName(
|
||||
LPWSTR const locale_name,
|
||||
int const locale_name_count
|
||||
)
|
||||
{
|
||||
if (auto const get_user_default_locale_name = try_get_GetUserDefaultLocaleName())
|
||||
{
|
||||
return get_user_default_locale_name(locale_name, locale_name_count);
|
||||
}
|
||||
|
||||
return __acrt_LCIDToLocaleName(GetUserDefaultLCID(), locale_name, locale_name_count, 0);
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_GetXStateFeaturesMask(
|
||||
PCONTEXT const context,
|
||||
PDWORD64 const feature_mask
|
||||
)
|
||||
{
|
||||
if (auto const get_xstate_features_mask = try_get_GetXStateFeaturesMask())
|
||||
{
|
||||
return get_xstate_features_mask(context, feature_mask);
|
||||
}
|
||||
|
||||
abort(); // No fallback; callers should check availablility before calling
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_InitializeCriticalSectionEx(
|
||||
LPCRITICAL_SECTION const critical_section,
|
||||
DWORD const spin_count,
|
||||
DWORD const flags
|
||||
)
|
||||
{
|
||||
if (auto const initialize_critical_section_ex = try_get_InitializeCriticalSectionEx())
|
||||
{
|
||||
return initialize_critical_section_ex(critical_section, spin_count, flags);
|
||||
}
|
||||
|
||||
return InitializeCriticalSectionAndSpinCount(critical_section, spin_count);
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_IsValidLocaleName(LPCWSTR const locale_name)
|
||||
{
|
||||
if (auto const is_valid_locale_name = try_get_IsValidLocaleName())
|
||||
{
|
||||
return is_valid_locale_name(locale_name);
|
||||
}
|
||||
|
||||
return IsValidLocale(__acrt_LocaleNameToLCID(locale_name, 0), LCID_INSTALLED);
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __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
|
||||
)
|
||||
{
|
||||
if (auto const lc_map_string_ex = try_get_LCMapStringEx())
|
||||
{
|
||||
return lc_map_string_ex(locale_name, flags, source, source_count, destination, destination_count, version, reserved, sort_handle);
|
||||
}
|
||||
#pragma warning(disable:__WARNING_PRECONDITION_NULLTERMINATION_VIOLATION) // 26035 LCMapStringW annotation is presently incorrect 11/26/2014 Jaykrell
|
||||
return LCMapStringW(__acrt_LocaleNameToLCID(locale_name, 0), flags, source, source_count, destination, destination_count);
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_LCIDToLocaleName(
|
||||
LCID const locale,
|
||||
LPWSTR const name,
|
||||
int const name_count,
|
||||
DWORD const flags
|
||||
)
|
||||
{
|
||||
if (auto const lcid_to_locale_name = try_get_LCIDToLocaleName())
|
||||
{
|
||||
return lcid_to_locale_name(locale, name, name_count, flags);
|
||||
}
|
||||
|
||||
return __acrt_DownlevelLCIDToLocaleName(locale, name, name_count);
|
||||
}
|
||||
|
||||
extern "C" LCID WINAPI __acrt_LocaleNameToLCID(
|
||||
LPCWSTR const name,
|
||||
DWORD const flags
|
||||
)
|
||||
{
|
||||
if (auto const locale_name_to_lcid = try_get_LocaleNameToLCID())
|
||||
{
|
||||
return locale_name_to_lcid(name, flags);
|
||||
}
|
||||
|
||||
return __acrt_DownlevelLocaleNameToLCID(name);
|
||||
}
|
||||
|
||||
extern "C" PVOID WINAPI __acrt_LocateXStateFeature(
|
||||
PCONTEXT const content,
|
||||
DWORD const feature_id,
|
||||
PDWORD const length
|
||||
)
|
||||
{
|
||||
if (auto const locate_xstate_feature = try_get_LocateXStateFeature())
|
||||
{
|
||||
return locate_xstate_feature(content, feature_id, length);
|
||||
}
|
||||
|
||||
abort(); // No fallback; callers should check availablility before calling
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_MessageBoxA(
|
||||
HWND const hwnd,
|
||||
LPCSTR const text,
|
||||
LPCSTR const caption,
|
||||
UINT const type
|
||||
)
|
||||
{
|
||||
if (auto const message_box_a = try_get_MessageBoxA())
|
||||
{
|
||||
return message_box_a(hwnd, text, caption, type);
|
||||
}
|
||||
|
||||
abort(); // No fallback; callers should check availablility before calling
|
||||
}
|
||||
|
||||
extern "C" int WINAPI __acrt_MessageBoxW(
|
||||
HWND const hwnd,
|
||||
LPCWSTR const text,
|
||||
LPCWSTR const caption,
|
||||
UINT const type
|
||||
)
|
||||
{
|
||||
if (auto const message_box_w = try_get_MessageBoxW())
|
||||
{
|
||||
return message_box_w(hwnd, text, caption, type);
|
||||
}
|
||||
|
||||
abort(); // No fallback; callers should check availablility before calling
|
||||
}
|
||||
|
||||
extern "C" BOOLEAN WINAPI __acrt_RtlGenRandom(
|
||||
PVOID const buffer,
|
||||
ULONG const buffer_count
|
||||
)
|
||||
{
|
||||
if (auto const rtl_gen_random = try_get_SystemFunction036())
|
||||
{
|
||||
return rtl_gen_random(buffer, buffer_count);
|
||||
}
|
||||
|
||||
abort(); // No fallback (this function should exist)
|
||||
}
|
||||
|
||||
extern "C" HRESULT WINAPI __acrt_RoInitialize(RO_INIT_TYPE const init_type)
|
||||
{
|
||||
if (auto const ro_initialize = try_get_RoInitialize())
|
||||
{
|
||||
return ro_initialize(init_type);
|
||||
}
|
||||
|
||||
return S_OK; // No fallback (this is a best-effort wrapper)
|
||||
}
|
||||
|
||||
extern "C" void WINAPI __acrt_RoUninitialize()
|
||||
{
|
||||
if (auto const ro_uninitialize = try_get_RoUninitialize())
|
||||
{
|
||||
return ro_uninitialize();
|
||||
}
|
||||
|
||||
// No fallback (this is a best-effort wrapper)
|
||||
}
|
||||
|
||||
LONG WINAPI __acrt_AppPolicyGetProcessTerminationMethodInternal(_Out_ AppPolicyProcessTerminationMethod* policy)
|
||||
{
|
||||
if (auto const app_policy_get_process_terminaton_method_claims = try_get_AppPolicyGetProcessTerminationMethod())
|
||||
{
|
||||
return app_policy_get_process_terminaton_method_claims(GetCurrentThreadEffectiveToken(), policy);
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
LONG WINAPI __acrt_AppPolicyGetThreadInitializationTypeInternal(_Out_ AppPolicyThreadInitializationType* policy)
|
||||
{
|
||||
if (auto const app_policy_get_thread_initialization_type_claims = try_get_AppPolicyGetThreadInitializationType())
|
||||
{
|
||||
return app_policy_get_thread_initialization_type_claims(GetCurrentThreadEffectiveToken(), policy);
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
LONG WINAPI __acrt_AppPolicyGetShowDeveloperDiagnosticInternal(_Out_ AppPolicyShowDeveloperDiagnostic* policy)
|
||||
{
|
||||
if (auto const app_policy_get_show_developer_diagnostic_claims = try_get_AppPolicyGetShowDeveloperDiagnostic())
|
||||
{
|
||||
return app_policy_get_show_developer_diagnostic_claims(GetCurrentThreadEffectiveToken(), policy);
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
LONG WINAPI __acrt_AppPolicyGetWindowingModelInternal(_Out_ AppPolicyWindowingModel* policy)
|
||||
{
|
||||
if (auto const app_policy_get_windowing_model_claims = try_get_AppPolicyGetWindowingModel())
|
||||
{
|
||||
return app_policy_get_windowing_model_claims(GetCurrentThreadEffectiveToken(), policy);
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
extern "C" BOOL WINAPI __acrt_SetThreadStackGuarantee(PULONG const stack_size_in_bytes)
|
||||
{
|
||||
if (auto const set_thread_stack_guarantee = try_get_SetThreadStackGuarantee())
|
||||
{
|
||||
return set_thread_stack_guarantee(stack_size_in_bytes);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_can_show_message_box()
|
||||
{
|
||||
bool can_show_message_box = false;
|
||||
if (__acrt_get_windowing_model_policy() == windowing_model_policy_hwnd
|
||||
&& try_get_MessageBoxA() != nullptr
|
||||
&& try_get_MessageBoxW() != nullptr)
|
||||
{
|
||||
can_show_message_box = true;
|
||||
}
|
||||
return can_show_message_box;
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_can_use_vista_locale_apis()
|
||||
{
|
||||
return try_get_CompareStringEx() != nullptr;
|
||||
}
|
||||
|
||||
// This function simply attempts to get each of the locale-related APIs. This
|
||||
// allows a caller to "pre-load" the modules in which these APIs are hosted. We
|
||||
// use this in the _wsetlocale implementation to avoid calls to LoadLibrary while
|
||||
// the locale lock is held.
|
||||
extern "C" void __cdecl __acrt_eagerly_load_locale_apis()
|
||||
{
|
||||
try_get_AreFileApisANSI();
|
||||
try_get_CompareStringEx();
|
||||
try_get_EnumSystemLocalesEx();
|
||||
try_get_GetDateFormatEx();
|
||||
try_get_GetLocaleInfoEx();
|
||||
try_get_GetTimeFormatEx();
|
||||
try_get_GetUserDefaultLocaleName();
|
||||
try_get_IsValidLocaleName();
|
||||
try_get_LCMapStringEx();
|
||||
try_get_LCIDToLocaleName();
|
||||
try_get_LocaleNameToLCID();
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_can_use_xstate_apis()
|
||||
{
|
||||
return try_get_LocateXStateFeature() != nullptr;
|
||||
}
|
||||
|
||||
extern "C" HWND __cdecl __acrt_get_parent_window()
|
||||
{
|
||||
auto const get_active_window = try_get_GetActiveWindow();
|
||||
if (!get_active_window)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HWND const active_window = get_active_window();
|
||||
if (!active_window)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto const get_last_active_popup = try_get_GetLastActivePopup();
|
||||
if (!get_last_active_popup)
|
||||
{
|
||||
return active_window;
|
||||
}
|
||||
|
||||
return get_last_active_popup(active_window);
|
||||
}
|
||||
|
||||
extern "C" bool __cdecl __acrt_is_interactive()
|
||||
{
|
||||
auto const get_process_window_station = try_get_GetProcessWindowStation();
|
||||
if (!get_process_window_station)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto const get_user_object_information = try_get_GetUserObjectInformationW();
|
||||
if (!get_user_object_information)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HWINSTA const hwinsta = get_process_window_station();
|
||||
if (!hwinsta)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
USEROBJECTFLAGS uof{};
|
||||
if (!get_user_object_information(hwinsta, UOI_FLAGS, &uof, sizeof(uof), nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((uof.dwFlags & WSF_VISIBLE) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue