From f941b374deb33b1bce9c8d7e3064c7b652d172c4 Mon Sep 17 00:00:00 2001 From: huangqinjin Date: Fri, 9 Sep 2022 22:20:49 +0800 Subject: [PATCH] 10.0.22621.0 --- convert/_fptostr.cpp | 4 +- convert/cfout.cpp | 28 ++++++ inc/corecrt_internal.h | 10 +- inc/corecrt_internal_traits.h | 4 +- include/fenv.h | 1 + include/time.h | 80 +++++++++++++-- internal/peb_access.cpp | 22 ++++ internal/win_policies.cpp | 182 ++++++++++++++++++++++++++++++++++ internal/winapi_thunks.cpp | 24 +++++ startup/exit.cpp | 8 +- stdio/gettemppath.cpp | 8 +- 11 files changed, 343 insertions(+), 28 deletions(-) create mode 100644 internal/peb_access.cpp create mode 100644 internal/win_policies.cpp diff --git a/convert/_fptostr.cpp b/convert/_fptostr.cpp index b010b2a..025d8c9 100644 --- a/convert/_fptostr.cpp +++ b/convert/_fptostr.cpp @@ -90,12 +90,12 @@ static bool should_round_up( if (round_mode == FE_UPWARD) { - return *mantissa_it != '0' && sign != '-'; + return check_trailing(mantissa_it, trailing_digits) && sign != '-'; } if (round_mode == FE_DOWNWARD) { - return *mantissa_it != '0' && sign == '-'; + return check_trailing(mantissa_it, trailing_digits) && sign == '-'; } return false; diff --git a/convert/cfout.cpp b/convert/cfout.cpp index 588a229..4400d65 100644 --- a/convert/cfout.cpp +++ b/convert/cfout.cpp @@ -16,6 +16,33 @@ using namespace __crt_strtox; namespace { + // Guard class for floating point control word modifications in the interrupt exception mask. + class fp_control_word_guard + { + public: + explicit fp_control_word_guard(unsigned int const mask = ~0u) : _mask(mask) + { + _controlfp_s(&_original_control_word, 0, 0); + } + + fp_control_word_guard(unsigned int const new_control, unsigned int const mask) : _mask(mask) + { + unsigned int float_control; + _controlfp_s(&_original_control_word, 0, 0); + _controlfp_s(&float_control, new_control, _mask); + } + + ~fp_control_word_guard() + { + unsigned int reset_cw; + _controlfp_s(&reset_cw, _original_control_word, _mask); + } + + private: + unsigned int _original_control_word; + unsigned int _mask; + }; + class scoped_fp_state_reset { public: @@ -335,5 +362,6 @@ extern "C" __acrt_has_trailing_digits __cdecl __acrt_fltout( // The digit generator produces a truncated sequence of digits. To allow // our caller to correctly round the mantissa, we need to generate an extra // digit. + fp_control_word_guard const fpc(_MCW_EM, _MCW_EM); return convert_to_fos_high_precision(value.x, precision + 1, precision_style, &flt->decpt, result, result_count); } diff --git a/inc/corecrt_internal.h b/inc/corecrt_internal.h index 839e53f..9167944 100644 --- a/inc/corecrt_internal.h +++ b/inc/corecrt_internal.h @@ -250,7 +250,7 @@ BOOL __cdecl __acrt_CreateProcessA( ); _Success_(return > 0) -DWORD __cdecl __acrt_GetTempPathA( +DWORD __cdecl __acrt_GetTempPath2A( DWORD nBufferLength, _Out_writes_to_(nBufferLength, return + 1) PSTR lpBuffer ); @@ -1241,6 +1241,11 @@ int WINAPI __acrt_GetDateFormatEx( _In_opt_ LPCWSTR calendar ); +int WINAPI __acrt_GetTempPath2W( + _In_ DWORD nBufferLength, + _Out_writes_to_opt_(BufferLength, return +1) LPWSTR lpBuffer + ); + DWORD64 WINAPI __acrt_GetEnabledXStateFeatures(void); int WINAPI __acrt_GetLocaleInfoEx( @@ -1364,7 +1369,8 @@ bool __cdecl __acrt_can_use_xstate_apis(void); HWND __cdecl __acrt_get_parent_window(void); bool __cdecl __acrt_is_interactive(void); - +bool __cdecl __acrt_app_verifier_enabled(void); +bool __cdecl __acrt_is_secure_process(void); LCID __cdecl __acrt_DownlevelLocaleNameToLCID( _In_opt_ LPCWSTR localeName diff --git a/inc/corecrt_internal_traits.h b/inc/corecrt_internal_traits.h index 21eb352..d43ba91 100644 --- a/inc/corecrt_internal_traits.h +++ b/inc/corecrt_internal_traits.h @@ -39,7 +39,7 @@ struct __crt_char_traits; _APPLY(get_full_path_name, __acrt_get_full_path_name_narrow_acp_or_utf8, __acrt_get_full_path_name_wide ) \ _APPLY(get_module_file_name, __acrt_GetModuleFileNameA, GetModuleFileNameW ) \ _APPLY(get_or_create_environment_nolock, __dcrt_get_or_create_narrow_environment_nolock, __dcrt_get_or_create_wide_environment_nolock ) \ - _APPLY(get_temp_path, __acrt_GetTempPathA, GetTempPathW ) \ + _APPLY(get_temp_path, __acrt_GetTempPath2A, __acrt_GetTempPath2W ) \ _APPLY(getc_nolock, _getc_nolock, _getwc_nolock ) \ _APPLY(gettche_nolock, _getche_nolock, _getwche_nolock ) \ _APPLY(initialize_environment_nolock, _initialize_narrow_environment, _initialize_wide_environment ) \ @@ -199,7 +199,7 @@ struct __crt_integer_traits // the other needs to be cloned into the other. // // Places where we don't use current global locale, user-supplied locale, or ACP/UTF-8 adapter: -// CP_ACP - __acrt_GetTempPathA (via tmpnam) +// CP_ACP - __acrt_GetTempPath2A (via tmpnam) // * Documented to do so on MSDN. // * Required by API design - static buffer returned to user // * Therefore, characters cannot be modified according to locale. diff --git a/include/fenv.h b/include/fenv.h index 20f5ce3..832c15d 100644 --- a/include/fenv.h +++ b/include/fenv.h @@ -111,6 +111,7 @@ _ACRTIMP int __cdecl fesetround(_In_ int _Round); }; double _Ans = 0.0; + (void) _Ans; // Suppress set-but-not-used warnings. _Ans is not "used" in the traditional static-analysis sense, but it is needed to trigger a floating point exception below. size_t _Index; if ((_Except &= FE_ALL_EXCEPT) == 0) diff --git a/include/time.h b/include/time.h index a0f72aa..9aaf04e 100644 --- a/include/time.h +++ b/include/time.h @@ -18,7 +18,9 @@ _UCRT_DISABLE_CLANG_WARNINGS _CRT_BEGIN_C_HEADER - +#ifndef _CRT_USE_CONFORMING_ANNEX_K_TIME +#define _CRT_USE_CONFORMING_ANNEX_K_TIME 0 +#endif //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // @@ -446,23 +448,51 @@ _ACRTIMP int __cdecl _timespec64_get( return _ctime32_s(_Buffer, _SizeInBytes, _Time); } + #if _CRT_USE_CONFORMING_ANNEX_K_TIME + _Check_return_wat_ + static __inline struct tm* __CRTDECL gmtime_s( + _In_ time_t const* const _Time, + _Out_ struct tm* const _Tm + ) + { + if (_gmtime32_s(_Tm, _Time) == 0) + { + return _Tm; + } + return NULL; + } + + _Check_return_wat_ + static __inline struct tm* __CRTDECL localtime_s( + _In_ time_t const* const _Time, + _Out_ struct tm* const _Tm + ) + { + if (_localtime32_s(_Tm, _Time) == 0) + { + return _Tm; + } + return NULL; + } + #else // _CRT_USE_CONFORMING_ANNEX_K_TIME _Check_return_wat_ static __inline errno_t __CRTDECL gmtime_s( - _Out_ struct tm* const _Tm, - _In_ time_t const* const _Time + _Out_ struct tm* const _Tm, + _In_ time_t const* const _Time ) { return _gmtime32_s(_Tm, _Time); } _Check_return_wat_ - static __inline errno_t __CRTDECL localtime_s( - _Out_ struct tm* const _Tm, - _In_ time_t const* const _Time + static __inline errno_t __CRTDECL localtime_s( + _Out_ struct tm* const _Tm, + _In_ time_t const* const _Time ) { return _localtime32_s(_Tm, _Time); } + #endif // _CRT_USE_CONFORMING_ANNEX_K_TIME #endif #else // ^^^ _USE_32BIT_TIME_T ^^^ // vvv !_USE_32BIT_TIME_T vvv @@ -542,23 +572,51 @@ _ACRTIMP int __cdecl _timespec64_get( return _ctime64_s(_Buffer, _SizeInBytes, _Time); } + #if _CRT_USE_CONFORMING_ANNEX_K_TIME + _Check_return_wat_ + static __inline struct tm* __CRTDECL gmtime_s( + _In_ time_t const* const _Time, + _Out_ struct tm* const _Tm + ) + { + if (_gmtime64_s(_Tm, _Time) == 0) + { + return _Tm; + } + return NULL; + } + + _Check_return_wat_ + static __inline struct tm* __CRTDECL localtime_s( + _In_ time_t const* const _Time, + _Out_ struct tm* const _Tm + ) + { + if (_localtime64_s(_Tm, _Time) == 0) + { + return _Tm; + } + return NULL; + } + #else // _CRT_USE_CONFORMING_ANNEX_K_TIME _Check_return_wat_ static __inline errno_t __CRTDECL gmtime_s( - _Out_ struct tm* const _Tm, - _In_ time_t const* const _Time + _Out_ struct tm* const _Tm, + _In_ time_t const* const _Time ) { return _gmtime64_s(_Tm, _Time); } _Check_return_wat_ - static __inline errno_t __CRTDECL localtime_s( - _Out_ struct tm* const _Tm, - _In_ time_t const* const _Time + static __inline errno_t __CRTDECL localtime_s( + _Out_ struct tm* const _Tm, + _In_ time_t const* const _Time ) { return _localtime64_s(_Tm, _Time); } + #endif // _CRT_USE_CONFORMING_ANNEX_K_TIME #endif #endif // !_USE_32BIT_TIME_T diff --git a/internal/peb_access.cpp b/internal/peb_access.cpp new file mode 100644 index 0000000..4dde7a7 --- /dev/null +++ b/internal/peb_access.cpp @@ -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 +#include +#include + +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; +} diff --git a/internal/win_policies.cpp b/internal/win_policies.cpp new file mode 100644 index 0000000..7226be8 --- /dev/null +++ b/internal/win_policies.cpp @@ -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 + +template +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 +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(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(policyValue)); + if (cached_state) + { + _ASSERTE(cached_state == static_cast(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(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(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(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(AppPolicyWindowingModel_ClassicDesktop); +} \ No newline at end of file diff --git a/internal/winapi_thunks.cpp b/internal/winapi_thunks.cpp index 8131e84..23aaf9e 100644 --- a/internal/winapi_thunks.cpp +++ b/internal/winapi_thunks.cpp @@ -20,6 +20,15 @@ #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 @@ -41,6 +50,7 @@ extern "C" WINBASEAPI PVOID WINAPI LocateXStateFeature( #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") \ @@ -56,6 +66,7 @@ extern "C" WINBASEAPI PVOID WINAPI LocateXStateFeature( _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" ) @@ -81,6 +92,7 @@ extern "C" WINBASEAPI PVOID WINAPI LocateXStateFeature( _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 })) \ @@ -536,6 +548,18 @@ extern "C" int WINAPI __acrt_GetDateFormatEx( 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()) diff --git a/startup/exit.cpp b/startup/exit.cpp index 36f7cc1..4ad3e52 100644 --- a/startup/exit.cpp +++ b/startup/exit.cpp @@ -5,15 +5,10 @@ // // The exit() implementation // -#include -#include -#include #include #include #include - - static long c_termination_complete = FALSE; extern "C" extern _onexit_table_t __acrt_atexit_table; @@ -117,8 +112,7 @@ static bool __cdecl should_call_terminate_process() throw() // If application verifier is running, we still want to call ExitProcess, // to enable tools that require DLLs to be unloaded cleanly at process exit // to do their work. - bool const application_verifier_enabled = (NtCurrentPeb()->NtGlobalFlag & FLG_APPLICATION_VERIFIER) != 0; - if (application_verifier_enabled) + if (__acrt_app_verifier_enabled()) { return false; } diff --git a/stdio/gettemppath.cpp b/stdio/gettemppath.cpp index 4cb9d16..22ff099 100644 --- a/stdio/gettemppath.cpp +++ b/stdio/gettemppath.cpp @@ -3,22 +3,22 @@ // // Copyright (c) Microsoft Corporation. All rights reserved. // -// The __acrt_GetTempPathA() function, which calls GetTempPathW and converts the string to multibyte. +// The __acrt_GetTempPath2A() function, which calls GetTempPathW and converts the string to multibyte. // #include #include -// This function simply calls GetTempPathW() and converts the wide string to multibyte. +// This function simply calls __acrt_GetTempPath2W() and converts the wide string to multibyte. // Note that GetTempPathA is not UTF-8 aware. This is because APIs using temporary paths // must not depend on the current locale setting and must use the ACP or OEMCP since // the returned data must be a static buffer and this behavior is guaranteed by MSDN documentation. -extern "C" DWORD __cdecl __acrt_GetTempPathA(DWORD nBufferLength, LPSTR lpBuffer) +extern "C" DWORD __cdecl __acrt_GetTempPath2A(DWORD nBufferLength, LPSTR lpBuffer) { wchar_t wide_buffer[_MAX_PATH + 1] = {}; - DWORD const get_temp_path_result = GetTempPathW(_countof(wide_buffer), wide_buffer); + DWORD const get_temp_path_result = __acrt_GetTempPath2W(_countof(wide_buffer), wide_buffer); if (get_temp_path_result == 0) { return 0;