diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..46a1f4a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "veil"] + path = veil + url = https://github.com/MiroKaku/Veil.git diff --git a/src/errno.cpp b/src/errno.cpp index 8b07c46..c012dbd 100644 --- a/src/errno.cpp +++ b/src/errno.cpp @@ -131,7 +131,7 @@ int __cdecl __acrt_errno_from_os_error(unsigned long const oserrno) } } -#if WDK_NTDDI_VERSION < 0x0A00000A /*NTDDI_WIN10_FE*/ +#if (WDK_NTDDI_VERSION < 0x0A00000A /*NTDDI_WIN10_FE*/) // These safely set and get the value of the calling thread's errno errno_t __cdecl _set_errno(_In_ int const value) { @@ -147,6 +147,7 @@ errno_t __cdecl _get_errno(_Out_ int* const result) *result = errno; return 0; } +#endif // (WDK_NTDDI_VERSION < 0x0A00000A /*NTDDI_WIN10_FE*/) // These safely set and get the value of the calling thread's doserrno errno_t __cdecl _set_doserrno(_In_ unsigned long const value) @@ -163,7 +164,6 @@ errno_t __cdecl _get_doserrno(_Out_ unsigned long* const result) *result = _doserrno; return 0; } -#endif // These return pointers to the calling thread's errno and doserrno values, diff --git a/src/i386/exsup.asm b/src/i386/exsup.asm index ac0cd3b..6fc3061 100644 --- a/src/i386/exsup.asm +++ b/src/i386/exsup.asm @@ -13,11 +13,11 @@ ;*** ;exsup.asm ; -; Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved. +; Copyright (c) 1993-2001, Microsoft Corporation. All rights reserved. ; ;Purpose: -; Exception handling for i386. This file contains those routines -; common to both C8.0 and C9.0. +; Exception handling for i386. This file contains those routines +; common to both C8.0 and C9.0. ; ;******************************************************************************* diff --git a/src/message.cpp b/src/message.cpp new file mode 100644 index 0000000..c8b24e8 --- /dev/null +++ b/src/message.cpp @@ -0,0 +1,216 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: message.cpp + * DATA: 2022/05/22 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +EXTERN_C NTSTATUS NTAPI RtlFindAndFormatMessage( + _In_ UINT32 Flags, + _In_opt_ LPCVOID Source, + _In_ UINT32 MessageId, + _In_ UINT32 LanguageId, + _Out_ LPWSTR Buffer, + _Inout_ UINT32* Size, + _In_opt_ va_list* Arguments +) +{ + NTSTATUS Status = STATUS_SUCCESS; + PVOID AllocatedBuffer = nullptr; + + ANSI_STRING AnsiMessage{}; + UNICODE_STRING UnicodeMessage{}; + + do + { + /* If this is a Win32 error wrapped as an OLE HRESULT then unwrap it */ + if (((MessageId & 0xffff0000) == 0x80070000) && + BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_SYSTEM) && + !BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_HMODULE) && + !BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_STRING)) + { + MessageId &= 0x0000ffff; + } + + if (Buffer == nullptr) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + if (Flags & FORMAT_MESSAGE_ALLOCATE_BUFFER) + { + *(PVOID*)Buffer = nullptr; + } + + PVOID DllHandle = nullptr; + ULONG MaximumWidth = 0ul; + PWSTR MessageFormat = nullptr; + PMESSAGE_RESOURCE_ENTRY MessageEntry = nullptr; + + __try + { + PVOID BaseDllHandle = ucxxrt::PsSystemDllBase; + + MaximumWidth = Flags & FORMAT_MESSAGE_MAX_WIDTH_MASK; + if (MaximumWidth == FORMAT_MESSAGE_MAX_WIDTH_MASK) + { + MaximumWidth = ULONG_MAX; + } + + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_STRING)) + { + MessageFormat = (PWSTR)Source; + } + else + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_HMODULE)) + { + if (Source == nullptr) + { + DllHandle = BaseDllHandle; + } + else + { + DllHandle = (LPVOID)Source; + } + } + else if (BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_SYSTEM)) + { + DllHandle = BaseDllHandle; + } + else + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + Status = RtlFindMessage( + DllHandle, + PtrToUlong(RT_MESSAGETABLE), + LanguageId, + MessageId, + &MessageEntry); + + if (Status == STATUS_MESSAGE_NOT_FOUND) + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_HMODULE) && + BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_SYSTEM)) + { + DllHandle = BaseDllHandle; + ClearFlag(Flags, FORMAT_MESSAGE_FROM_HMODULE); + + Status = RtlFindMessage( + DllHandle, + PtrToUlong(RT_MESSAGETABLE), + LanguageId, + MessageId, + &MessageEntry); + } + } + + if (!NT_SUCCESS(Status)) + { + break; + } + + if (!BooleanFlagOn(MessageEntry->Flags, MESSAGE_RESOURCE_UNICODE)) + { + RtlInitAnsiString(&AnsiMessage, (PCSZ)MessageEntry->Text); + Status = RtlAnsiStringToUnicodeString(&UnicodeMessage, &AnsiMessage, TRUE); + if (!NT_SUCCESS(Status)) + { + break; + } + + MessageFormat = UnicodeMessage.Buffer; + } + else + { + MessageFormat = (PWSTR)MessageEntry->Text; + } + } + + auto WrittenSize = 256ul; + bool IgnoreInserts = BooleanFlagOn(Flags, FORMAT_MESSAGE_IGNORE_INSERTS); + bool ArgumentsAreAnAnsi = BooleanFlagOn(Flags, FORMAT_MESSAGE_ARGUMENT_ANSI); + bool ArgumentsAreAnArray = BooleanFlagOn(Flags, FORMAT_MESSAGE_ARGUMENT_ARRAY); + + do + { + if (AllocatedBuffer) + { + free(AllocatedBuffer); + } + + AllocatedBuffer = malloc(WrittenSize); + if (AllocatedBuffer == nullptr) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + Status = RtlFormatMessage( + MessageFormat, + MaximumWidth, + IgnoreInserts, + ArgumentsAreAnAnsi, + ArgumentsAreAnArray, + Arguments, + (PWSTR)AllocatedBuffer, + WrittenSize, + &WrittenSize); + if (NT_SUCCESS(Status)) + { + break; + } + + if (Status != STATUS_BUFFER_OVERFLOW) + { + break; + } + + WrittenSize += 256; + + } while (true); + + if (!NT_SUCCESS(Status)) + { + break; + } + + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ALLOCATE_BUFFER)) + { + *(PVOID*)Buffer = AllocatedBuffer; + AllocatedBuffer = nullptr; + } + else if ((WrittenSize / sizeof(WCHAR)) > *Size) + { + Status = STATUS_BUFFER_TOO_SMALL; + break; + } + else + { + RtlMoveMemory(Buffer, AllocatedBuffer, WrittenSize); + } + + *Size = (WrittenSize - sizeof(WCHAR)) / sizeof(WCHAR); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + Status = GetExceptionCode(); + break; + } + + } while (false); + + free(AllocatedBuffer); + RtlFreeUnicodeString(&UnicodeMessage); + + return Status; +} diff --git a/src/stl/syserror.cpp b/src/stl/syserror.cpp new file mode 100644 index 0000000..caf9de3 --- /dev/null +++ b/src/stl/syserror.cpp @@ -0,0 +1,185 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: syserror.cpp + * DATA: 2022/02/27 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// system_error message mapping + +#include +#include "winapi_thunks.h" + +#ifdef _DLL +#include "syserror_import_lib.cpp" +#endif + +namespace { + using _STD errc; + + struct _Win_errtab_t { // maps Windows error to Posix error + int _Windows; + errc _Posix; + }; + + constexpr _Win_errtab_t _Win_errtab[] = { + // table of Windows/Posix pairs + {STATUS_ACCESS_DENIED, errc::permission_denied}, + {STATUS_OBJECT_NAME_EXISTS, errc::file_exists}, + {STATUS_OBJECT_NAME_COLLISION, errc::file_exists}, + {STATUS_OBJECT_NAME_NOT_FOUND, errc::no_such_file_or_directory}, + {STATUS_DEVICE_DOES_NOT_EXIST, errc::no_such_device}, + {STATUS_PIPE_BROKEN, errc::broken_pipe}, + {STATUS_BUFFER_OVERFLOW, errc::filename_too_long}, + {STATUS_DEVICE_BUSY, errc::device_or_resource_busy}, + {STATUS_DS_BUSY, errc::device_or_resource_busy}, + {STATUS_CANNOT_MAKE, errc::permission_denied}, + {STATUS_OPEN_FAILED, errc::io_error}, + {STATUS_IO_DEVICE_ERROR, errc::io_error}, + {STATUS_BAD_CURRENT_DIRECTORY, errc::permission_denied}, + {STATUS_DIRECTORY_NOT_EMPTY, errc::directory_not_empty}, + {STATUS_INVALID_PARAMETER, errc::invalid_argument}, + {STATUS_DISK_FULL, errc::no_space_on_device}, + {STATUS_NOT_IMPLEMENTED, errc::function_not_supported}, + {STATUS_INVALID_HANDLE, errc::invalid_argument}, + {STATUS_ACCESS_VIOLATION, errc::permission_denied}, + {STATUS_OBJECT_NAME_NOT_FOUND, errc::no_such_file_or_directory}, + {STATUS_NO_MEMORY, errc::not_enough_memory}, + {STATUS_DEVICE_NOT_READY, errc::resource_unavailable_try_again}, + {STATUS_NOT_SAME_DEVICE, errc::cross_device_link}, + {STATUS_NOT_SUPPORTED, errc::not_supported}, + {STATUS_REQUEST_ABORTED, errc::operation_canceled}, + {STATUS_OBJECT_PATH_NOT_FOUND, errc::no_such_file_or_directory}, + {STATUS_TOO_MANY_OPENED_FILES, errc::too_many_files_open}, + }; + + struct _Sys_errtab_t { // maps error_code to NTBS + errc _Errcode; + const char* _Name; + }; + + constexpr _Sys_errtab_t _Sys_errtab[] = { + // table of Posix code/name pairs + {errc::address_family_not_supported, "address family not supported"}, + {errc::address_in_use, "address in use"}, + {errc::address_not_available, "address not available"}, + {errc::already_connected, "already connected"}, + {errc::argument_list_too_long, "argument list too long"}, + {errc::argument_out_of_domain, "argument out of domain"}, + {errc::bad_address, "bad address"}, + {errc::bad_file_descriptor, "bad file descriptor"}, + {errc::bad_message, "bad message"}, + {errc::broken_pipe, "broken pipe"}, + {errc::connection_aborted, "connection aborted"}, + {errc::connection_already_in_progress, "connection already in progress"}, + {errc::connection_refused, "connection refused"}, + {errc::connection_reset, "connection reset"}, + {errc::cross_device_link, "cross device link"}, + {errc::destination_address_required, "destination address required"}, + {errc::device_or_resource_busy, "device or resource busy"}, + {errc::directory_not_empty, "directory not empty"}, + {errc::executable_format_error, "executable format error"}, + {errc::file_exists, "file exists"}, + {errc::file_too_large, "file too large"}, + {errc::filename_too_long, "filename too long"}, + {errc::function_not_supported, "function not supported"}, + {errc::host_unreachable, "host unreachable"}, + {errc::identifier_removed, "identifier removed"}, + {errc::illegal_byte_sequence, "illegal byte sequence"}, + {errc::inappropriate_io_control_operation, "inappropriate io control operation"}, + {errc::interrupted, "interrupted"}, + {errc::invalid_argument, "invalid argument"}, + {errc::invalid_seek, "invalid seek"}, + {errc::io_error, "io error"}, + {errc::is_a_directory, "is a directory"}, + {errc::message_size, "message size"}, + {errc::network_down, "network down"}, + {errc::network_reset, "network reset"}, + {errc::network_unreachable, "network unreachable"}, + {errc::no_buffer_space, "no buffer space"}, + {errc::no_child_process, "no child process"}, + {errc::no_link, "no link"}, + {errc::no_lock_available, "no lock available"}, + {errc::no_message_available, "no message available"}, + {errc::no_message, "no message"}, + {errc::no_protocol_option, "no protocol option"}, + {errc::no_space_on_device, "no space on device"}, + {errc::no_stream_resources, "no stream resources"}, + {errc::no_such_device_or_address, "no such device or address"}, + {errc::no_such_device, "no such device"}, + {errc::no_such_file_or_directory, "no such file or directory"}, + {errc::no_such_process, "no such process"}, + {errc::not_a_directory, "not a directory"}, + {errc::not_a_socket, "not a socket"}, + {errc::not_a_stream, "not a stream"}, + {errc::not_connected, "not connected"}, + {errc::not_enough_memory, "not enough memory"}, + {errc::not_supported, "not supported"}, + {errc::operation_canceled, "operation canceled"}, + {errc::operation_in_progress, "operation in progress"}, + {errc::operation_not_permitted, "operation not permitted"}, + {errc::operation_not_supported, "operation not supported"}, + {errc::operation_would_block, "operation would block"}, + {errc::owner_dead, "owner dead"}, + {errc::permission_denied, "permission denied"}, + {errc::protocol_error, "protocol error"}, + {errc::protocol_not_supported, "protocol not supported"}, + {errc::read_only_file_system, "read only file system"}, + {errc::resource_deadlock_would_occur, "resource deadlock would occur"}, + {errc::resource_unavailable_try_again, "resource unavailable try again"}, + {errc::result_out_of_range, "result out of range"}, + {errc::state_not_recoverable, "state not recoverable"}, + {errc::stream_timeout, "stream timeout"}, + {errc::text_file_busy, "text file busy"}, + {errc::timed_out, "timed out"}, + {errc::too_many_files_open_in_system, "too many files open in system"}, + {errc::too_many_files_open, "too many files open"}, + {errc::too_many_links, "too many links"}, + {errc::too_many_symbolic_link_levels, "too many symbolic link levels"}, + {errc::value_too_large, "value too large"}, + {errc::wrong_protocol_type, "wrong protocol type"}, + }; +} // unnamed namespace + +_STD_BEGIN + +_CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Winerror_map(int _Errcode) { + // convert Windows error to Posix error if possible, otherwise 0 + for (const auto& _Entry : _Win_errtab) { + if (_Entry._Windows == _Errcode) { + return static_cast(_Entry._Posix); + } + } + + return 0; +} + +// TRANSITION, ABI: _Winerror_message() is preserved for binary compatibility +_CRTIMP2_PURE unsigned long __CLRCALL_PURE_OR_CDECL _Winerror_message( + unsigned long _Message_id, char* _Narrow, unsigned long _Size) { + // convert to name of Windows error, return 0 for failure, otherwise return number of chars written + // pre: _Size < INT_MAX + const unsigned long _Chars = __vcrt_FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, _Message_id, 0, _Narrow, _Size, nullptr); + + return static_cast(_CSTD __std_get_string_size_without_trailing_whitespace(_Narrow, _Chars)); +} + +_CRTIMP2_PURE const char* __CLRCALL_PURE_OR_CDECL _Syserror_map(int _Errcode) { // convert to name of generic error + for (const auto& _Entry : _Sys_errtab) { + if (static_cast(_Entry._Errcode) == _Errcode) { + return _Entry._Name; + } + } + + return "unknown error"; +} +_STD_END diff --git a/src/stl/syserror_import_lib.cpp b/src/stl/syserror_import_lib.cpp new file mode 100644 index 0000000..afa0d7f --- /dev/null +++ b/src/stl/syserror_import_lib.cpp @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// This must be as small as possible, because its contents are +// injected into the msvcprt.lib and msvcprtd.lib import libraries. +// Do not include or define anything else here. +// In particular, basic_string must not be included here. + +#include <__msvc_system_error_abi.hpp> +#include "winapi_thunks.h" + +namespace +{ + struct _Whitespace_bitmap_t + { + bool _Is_whitespace[256]; + + constexpr _Whitespace_bitmap_t() noexcept : _Is_whitespace{} + { + _Is_whitespace[' '] = true; + _Is_whitespace['\n'] = true; + _Is_whitespace['\r'] = true; + _Is_whitespace['\t'] = true; + _Is_whitespace['\0'] = true; + } + + _NODISCARD constexpr bool _Test(const char _Ch) const noexcept + { + return _Is_whitespace[static_cast(_Ch)]; + } + }; + + constexpr _Whitespace_bitmap_t _Whitespace_bitmap; +} // unnamed namespace + +_EXTERN_C +_NODISCARD size_t __CLRCALL_PURE_OR_STDCALL __std_get_string_size_without_trailing_whitespace( + const char* const _Str, size_t _Size) noexcept +{ + while (_Size != 0 && _Whitespace_bitmap._Test(_Str[_Size - 1])) + { + --_Size; + } + + return _Size; +} + +_NODISCARD size_t __CLRCALL_PURE_OR_STDCALL __std_system_error_allocate_message( + const unsigned long _Message_id, char** const _Ptr_str) noexcept +{ + // convert to name of Windows error, return 0 for failure, otherwise return number of chars in buffer + // __std_system_error_deallocate_message should be called even if 0 is returned + // pre: *_Ptr_str == nullptr + const unsigned long _Chars = + __vcrt_FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, _Message_id, 0, reinterpret_cast(_Ptr_str), 0, nullptr); + + return _CSTD __std_get_string_size_without_trailing_whitespace(*_Ptr_str, _Chars); +} + +void __CLRCALL_PURE_OR_STDCALL __std_system_error_deallocate_message(char* const _Str) noexcept +{ + free(_Str); +} +_END_EXTERN_C diff --git a/src/sys_main.cpp b/src/sys_main.cpp index 9625029..d85b346 100644 --- a/src/sys_main.cpp +++ b/src/sys_main.cpp @@ -18,6 +18,7 @@ _CRT_BEGIN_C_HEADER int __cdecl _do_onexit(); int __cdecl _do_quick_onexit(); +void __cdecl __sysruntime_init(); void __cdecl __initialize_memory(); void __cdecl __acrt_initialize_new_handler(_In_opt_ void* encoded_null); @@ -62,6 +63,9 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Registry) // do feature initializions __isa_available_init(); + // do sysruntime initializions + __sysruntime_init(); + // do memory initializions __initialize_memory(); diff --git a/src/sys_runtime.cpp b/src/sys_runtime.cpp new file mode 100644 index 0000000..4eb7afb --- /dev/null +++ b/src/sys_runtime.cpp @@ -0,0 +1,141 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: sys_runtime.cpp + * DATA: 2022/05/22 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +namespace ucxxrt +{ + extern PVOID PsSystemDllBase = nullptr; + + extern constexpr UNICODE_STRING NtdllKnownDllName = RTL_CONSTANT_STRING(L"\\KnownDlls\\ntdll.dll"); +} + +/** + * get known DLL module extents. + * ref: https://github.com/processhacker/processhacker/blob/2b70d0a678dc06c330545085daf1f8375487b328/KProcessHacker/main.c#L374 + * + * \param[in] SectionName - Name of the section to open. + * \param[out] BaseAddress - On success, populated with the module base. + * \param[out] ImageSize - On success, populated with the module size. + * + * \return Appropriate status. +*/ +_IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C NTSTATUS NTAPI RtlGetKnownDllExtents( + _In_ PUNICODE_STRING SectionName, + _Out_ PVOID* BaseAddress, + _Out_ SIZE_T* ImageSize +) +{ + NTSTATUS Status = STATUS_SUCCESS; + HANDLE SectionHandle = nullptr; + PVOID SectionObject = nullptr; + PVOID MappedBase = nullptr; + SIZE_T MappedSize = 0u; + + do + { + NT_ASSERT(PsInitialSystemProcess == PsGetCurrentProcess()); + + OBJECT_ATTRIBUTES ObjectAttributes; + InitializeObjectAttributes( + &ObjectAttributes, + SectionName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + nullptr, + nullptr); + + Status = ZwOpenSection( + &SectionHandle, + SECTION_MAP_READ | SECTION_QUERY, + &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + break; + } + + SECTION_IMAGE_INFORMATION SectionImageInfo{}; + + Status = ZwQuerySection( + SectionHandle, + SectionImageInformation, + &SectionImageInfo, + sizeof(SectionImageInfo), + nullptr); + if (!NT_SUCCESS(Status)) + { + break; + } + + // + // 21H2 no longer maps ntdll as an image in System. Querying the transfer + // address to get the extents in this context will fail. Rather than rely + // on ZwQueryVirtualMemory at all, we'll map it into system space to get + // the extents. + // + // Note, in the future if Microsoft decides to relocate KnownDLLs in + // every process we'll need to revisit this. That will likely involve + // retrieving the module extents per-process, in our case this is used + // for KPH communications validation so we'll need to the ntdll module + // extents out of PH. + // + + Status = ObReferenceObjectByHandle( + SectionHandle, + SECTION_MAP_READ | SECTION_QUERY, + *MmSectionObjectType, + KernelMode, + &SectionObject, + nullptr); + if (!NT_SUCCESS(Status)) + { + break; + } + + Status = MmMapViewInSystemSpace(SectionObject, &MappedBase, &MappedSize); + if (!NT_SUCCESS(Status)) + { + break; + } + + *BaseAddress = SectionImageInfo.TransferAddress; + *ImageSize = MappedSize; + + } while (false); + + if (MappedBase) + { + MmUnmapViewInSystemSpace(MappedBase); + } + + if (SectionObject) + { + ObDereferenceObject(SectionObject); + } + + if (SectionHandle) + { + ZwClose(SectionHandle); + } + + return Status; +} + +_CRT_BEGIN_C_HEADER + +void __cdecl __sysruntime_init() +{ + using namespace ucxxrt; + + SIZE_T DllSize = 0u; + RtlGetKnownDllExtents(const_cast(&NtdllKnownDllName), &PsSystemDllBase, &DllSize); +} + +_CRT_END_C_HEADER diff --git a/src/unittest.cpp b/src/unittest.cpp index 1d52f99..2f8d80b 100644 --- a/src/unittest.cpp +++ b/src/unittest.cpp @@ -6,8 +6,9 @@ #include #include #include +#include -#define LOG(Format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ucxxrt] " __FUNCTION__ ": " Format "\n", __VA_ARGS__) +#define LOG(Format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ucxxrt] [" __FUNCTION__ ":%u]: " Format "\n", __LINE__, __VA_ARGS__) static std::vector> TestVec; #define TEST(f) TestVec.emplace_back(f) @@ -21,13 +22,13 @@ class Test$StaticObject public: - Test$StaticObject() + Test$StaticObject() noexcept : _Data(new ULONG[1]{ 1 }) { LOG("has called."); } - ~Test$StaticObject() + ~Test$StaticObject() noexcept { LOG("has called."); @@ -61,19 +62,19 @@ void Test$ThrowInt() } catch (int& e) { - LOG("catch Exception: %d", e); + LOG("catch exception: %d", e); } } catch (std::string& e) { ASSERT(false); - LOG("catch Exception: %s", e.c_str()); + LOG("catch exception: %s", e.c_str()); } } catch (...) { ASSERT(false); - LOG("catch Exception: ..."); + LOG("catch exception: ..."); } } @@ -90,18 +91,18 @@ void Test$ThrowObject() catch (int& e) { ASSERT(false); - LOG("catch Exception: %d", e); + LOG("catch exception: %d", e); } } catch (std::string& e) { - LOG("catch Exception: %s", e.c_str()); + LOG("catch exception: %s", e.c_str()); } } catch (...) { ASSERT(false); - LOG("catch Exception: ..."); + LOG("catch exception: ..."); } } @@ -118,18 +119,18 @@ void Test$ThrowUnknow() catch (int& e) { ASSERT(false); - LOG("catch Exception: %d", e); + LOG("catch exception: %d", e); } } catch (std::string& e) { ASSERT(false); - LOG("catch Exception: %s", e.c_str()); + LOG("catch exception: %s", e.c_str()); } } catch (...) { - LOG("catch Exception: ..."); + LOG("catch exception: ..."); } } @@ -203,6 +204,12 @@ std::unordered_map Test$StaticObjectInitializer = { "5", 5 }, }; +void Test$ErrorCode() +{ + std::error_code code(STATUS_INVALID_PARAMETER, std::system_category()); + LOG("%s", code.message().c_str()); +} + EXTERN_C NTSTATUS DriverMain(PDRIVER_OBJECT aDriverObject, PUNICODE_STRING /*aRegistry*/) { LOG("entry."); @@ -213,6 +220,7 @@ EXTERN_C NTSTATUS DriverMain(PDRIVER_OBJECT aDriverObject, PUNICODE_STRING /*aRe TEST(Test$ThrowUnknow); TEST(Test$HashMap); TEST(Test$InitializerList); + TEST(Test$ErrorCode); for (const auto& Test : TestVec) { diff --git a/src/vcruntime/ehdata.h b/src/vcruntime/ehdata.h index 31bd3c3..f06cf48 100644 --- a/src/vcruntime/ehdata.h +++ b/src/vcruntime/ehdata.h @@ -25,63 +25,63 @@ #pragma pack(push, ehdata, 4) -#define TD_HASH(td) ((td).hash) -#define TD_NAME(td) ((td).name) +#define TD_HASH(td) ((td).hash) +#define TD_NAME(td) ((td).name) -#define TD_IS_TYPE_ELLIPSIS(td) ((td == NULL) || (TD_NAME(*td)[0] == '\0')) +#define TD_IS_TYPE_ELLIPSIS(td) ((td == NULL) || (TD_NAME(*td)[0] == '\0')) -#define CT_PROPERTIES(ct) ((ct).properties) +#define CT_PROPERTIES(ct) ((ct).properties) #if _EH_RELATIVE_TYPEINFO -#define CT_PTD_IB(ct,ib) ((TypeDescriptor *)((ib) + (ct).pType)) -#define CT_COPYFUNC_IB(ct,ib) ((void (*)(void*))((ib) + (ct).copyFunction)) +#define CT_PTD_IB(ct,ib) ((TypeDescriptor *)((ib) + (ct).pType)) +#define CT_COPYFUNC_IB(ct,ib) ((void (*)(void*))((ib) + (ct).copyFunction)) #else -#define CT_PTD(ct) ((ct).pType) -#define CT_COPYFUNC(ct) ((ct).copyFunction) +#define CT_PTD(ct) ((ct).pType) +#define CT_COPYFUNC(ct) ((ct).copyFunction) #endif -#define CT_THISDISP(ct) ((ct).thisDisplacement) -#define CT_SIZE(ct) ((ct).sizeOrOffset) -#define CT_OFFSET(ct) ((ct).sizeOrOffset) -#define CT_HASH(ct) (TD_HASH(*CT_PTD(ct))) -#define CT_NAME(ct) (TD_NAME(*CT_PTD(ct))) +#define CT_THISDISP(ct) ((ct).thisDisplacement) +#define CT_SIZE(ct) ((ct).sizeOrOffset) +#define CT_OFFSET(ct) ((ct).sizeOrOffset) +#define CT_HASH(ct) (TD_HASH(*CT_PTD(ct))) +#define CT_NAME(ct) (TD_NAME(*CT_PTD(ct))) #if _EH_RELATIVE_TYPEINFO -#define CT_NAME_IB(ct,ib) (TD_NAME(*CT_PTD_IB(ct, ib))) +#define CT_NAME_IB(ct,ib) (TD_NAME(*CT_PTD_IB(ct, ib))) #endif -#define SET_CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) |= CT_IsSimpleType) -#define SET_CT_BYREFONLY(ct) (CT_PROPERTIES(ct) |= CT_ByReferenceOnly) -#define SET_CT_HASVB(ct) (CT_PROPERTIES(ct) |= CT_HasVirtualBase) -#define SET_CT_ISWINRTHANDLE(ct) (CT_PROPERTIES(ct) |= CT_IsWinRTHandle) -#define SET_CT_ISSTDBADALLOC(ct) (CT_PROPERTIES(ct) |= CT_IsStdBadAlloc) +#define SET_CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) |= CT_IsSimpleType) +#define SET_CT_BYREFONLY(ct) (CT_PROPERTIES(ct) |= CT_ByReferenceOnly) +#define SET_CT_HASVB(ct) (CT_PROPERTIES(ct) |= CT_HasVirtualBase) +#define SET_CT_ISWINRTHANDLE(ct) (CT_PROPERTIES(ct) |= CT_IsWinRTHandle) +#define SET_CT_ISSTDBADALLOC(ct) (CT_PROPERTIES(ct) |= CT_IsStdBadAlloc) -#define CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) & CT_IsSimpleType) // Is it a simple type? -#define CT_BYREFONLY(ct) (CT_PROPERTIES(ct) & CT_ByReferenceOnly) // Must it be caught by reference? -#define CT_HASVB(ct) (CT_PROPERTIES(ct) & CT_HasVirtualBase) // Is this type a class with virtual bases? -#define CT_ISWINRTHANDLE(ct) (CT_PROPERTIES(ct) & CT_IsWinRTHandle) // Is it a winrt handle? -#define CT_ISSTDBADALLOC(ct) (CT_PROPERTIES(ct) & CT_IsStdBadAlloc) // Is it a std::bad_alloc? +#define CT_ISSIMPLETYPE(ct) (CT_PROPERTIES(ct) & CT_IsSimpleType) // Is it a simple type? +#define CT_BYREFONLY(ct) (CT_PROPERTIES(ct) & CT_ByReferenceOnly) // Must it be caught by reference? +#define CT_HASVB(ct) (CT_PROPERTIES(ct) & CT_HasVirtualBase) // Is this type a class with virtual bases? +#define CT_ISWINRTHANDLE(ct) (CT_PROPERTIES(ct) & CT_IsWinRTHandle) // Is it a winrt handle? +#define CT_ISSTDBADALLOC(ct) (CT_PROPERTIES(ct) & CT_IsStdBadAlloc) // Is it a std::bad_alloc? -#define THROW_ATTRS(t) ((t).attributes) +#define THROW_ATTRS(t) ((t).attributes) #if _EH_RELATIVE_TYPEINFO -#define THROW_UNWINDFUNC_IB(t,ib) ((void (*)(void*))((ib) + (t).pmfnUnwind)) -#define THROW_FORWARDCOMPAT_IB(t,ib) ((int(__cdecl *)(...))((ib) + (t).pForwardCompat)) -#define THROW_CTARRAY_IB(t,ib) ((CatchableTypeArray*)((ib) + (t).pCatchableTypeArray)) -#define THROW_COUNT_IB(t,ib) (THROW_CTARRAY_IB(t,ib)->nCatchableTypes) -#define THROW_CTLIST_IB(t,ib) (THROW_CTARRAY_IB(t,ib)->arrayOfCatchableTypes) +#define THROW_UNWINDFUNC_IB(t,ib) ((void (*)(void*))((ib) + (t).pmfnUnwind)) +#define THROW_FORWARDCOMPAT_IB(t,ib) ((int(__cdecl *)(...))((ib) + (t).pForwardCompat)) +#define THROW_CTARRAY_IB(t,ib) ((CatchableTypeArray*)((ib) + (t).pCatchableTypeArray)) +#define THROW_COUNT_IB(t,ib) (THROW_CTARRAY_IB(t,ib)->nCatchableTypes) +#define THROW_CTLIST_IB(t,ib) (THROW_CTARRAY_IB(t,ib)->arrayOfCatchableTypes) #else -#define THROW_FORWARDCOMPAT(t) ((t).pForwardCompat) -#define THROW_COUNT(t) ((t).pCatchableTypeArray->nCatchableTypes) -#define THROW_CTLIST(t) ((t).pCatchableTypeArray->arrayOfCatchableTypes) +#define THROW_FORWARDCOMPAT(t) ((t).pForwardCompat) +#define THROW_COUNT(t) ((t).pCatchableTypeArray->nCatchableTypes) +#define THROW_CTLIST(t) ((t).pCatchableTypeArray->arrayOfCatchableTypes) #endif -#define THROW_UNWINDFUNC(t) ((t).pmfnUnwind) -#define THROW_PCTLIST(t) (&THROW_CTLIST(t)) -#define THROW_CT(t, n) (*THROW_CTLIST(t)[n]) -#define THROW_PCT(t, n) (THROW_CTLIST(t)[n]) +#define THROW_UNWINDFUNC(t) ((t).pmfnUnwind) +#define THROW_PCTLIST(t) (&THROW_CTLIST(t)) +#define THROW_CT(t, n) (*THROW_CTLIST(t)[n]) +#define THROW_PCT(t, n) (THROW_CTLIST(t)[n]) -#define THROW_ISCONST(t) (THROW_ATTRS(t) & TI_IsConst) -#define THROW_ISVOLATILE(t) (THROW_ATTRS(t) & TI_IsVolatile) -#define THROW_ISUNALIGNED(t) (THROW_ATTRS(t) & TI_IsUnaligned) -#define THROW_ISPURE(t) (THROW_ATTRS(t) & TI_IsPure) -#define THROW_ISWINRT(t) (THROW_ATTRS(t) & TI_IsWinRT) +#define THROW_ISCONST(t) (THROW_ATTRS(t) & TI_IsConst) +#define THROW_ISVOLATILE(t) (THROW_ATTRS(t) & TI_IsVolatile) +#define THROW_ISUNALIGNED(t) (THROW_ATTRS(t) & TI_IsUnaligned) +#define THROW_ISPURE(t) (THROW_ATTRS(t) & TI_IsPure) +#define THROW_ISWINRT(t) (THROW_ATTRS(t) & TI_IsWinRT) ///////////////////////////////////////////////////////////////////////////// // @@ -94,87 +94,87 @@ // -1 is the 'blank' state, i.e. there is nothing to unwind, no try blocks active. // -typedef int __ehstate_t; // The type of a state index +typedef int __ehstate_t; // The type of a state index // // HandlerType - description of a single 'catch' // typedef const struct _s_HandlerType { - unsigned int adjectives; // Handler Type adjectives (bitfield) + unsigned int adjectives; // Handler Type adjectives (bitfield) #if _EH_RELATIVE_FUNCINFO - int dispType; // Image relative offset of the corresponding type descriptor - int dispCatchObj; // Displacement of catch object from base - int dispOfHandler; // Image relative offset of 'catch' code + int dispType; // Image relative offset of the corresponding type descriptor + int dispCatchObj; // Displacement of catch object from base + int dispOfHandler; // Image relative offset of 'catch' code #if defined(_WIN64) || defined(_CHPE_X86_ARM64_EH_) - int dispFrame; // displacement of address of function frame wrt establisher frame + int dispFrame; // displacement of address of function frame wrt establisher frame #endif #else // _EH_RELATIVE_FUNCINFO - TypeDescriptor* pType; // Pointer to the corresponding type descriptor - ptrdiff_t dispCatchObj; // Displacement of catch object from base - void * addressOfHandler; // Address of 'catch' code + TypeDescriptor* pType; // Pointer to the corresponding type descriptor + ptrdiff_t dispCatchObj; // Displacement of catch object from base + void * addressOfHandler; // Address of 'catch' code #endif // _EH_RELATIVE_FUNCINFO } HandlerType; -#define HT_ADJECTIVES(ht) ((ht).adjectives) +#define HT_ADJECTIVES(ht) ((ht).adjectives) #if _EH_RELATIVE_FUNCINFO -#define HT_PTD_IB(ht,ib) ((TypeDescriptor*)((ib) + (ht).dispType)) -#define HT_HANDLER_IB(ht,ib) ((void*)((ib) + (ht).dispOfHandler)) +#define HT_PTD_IB(ht,ib) ((TypeDescriptor*)((ib) + (ht).dispType)) +#define HT_HANDLER_IB(ht,ib) ((void*)((ib) + (ht).dispOfHandler)) #else -#define HT_PTD(ht) ((ht).pType) -#define HT_HANDLER(ht) ((ht).addressOfHandler) +#define HT_PTD(ht) ((ht).pType) +#define HT_HANDLER(ht) ((ht).addressOfHandler) #endif -#define HT_DISPCATCH(ht) ((ht).dispCatchObj) -#define HT_NAME(ht) (TD_NAME(*HT_PTD(ht))) -#define HT_HASH(ht) (TD_HASH(*HT_PTD(ht))) -#define HT_IS_TYPE_ELLIPSIS(ht) TD_IS_TYPE_ELLIPSIS(HT_PTD(ht)) - -#define HT_ISCONST(ht) (HT_ADJECTIVES(ht) & HT_IsConst) // Is the type referenced 'const' qualified -#define HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) & HT_IsVolatile) // Is the type referenced 'volatile' qualified -#define HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) & HT_IsUnaligned) // Is the type referenced 'unaligned' qualified -#define HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) & HT_IsReference) // Is the catch type by reference -#define HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) & HT_IsResumable) // Might the catch choose to resume (Reserved) +#define HT_DISPCATCH(ht) ((ht).dispCatchObj) +#define HT_NAME(ht) (TD_NAME(*HT_PTD(ht))) +#define HT_HASH(ht) (TD_HASH(*HT_PTD(ht))) +#define HT_IS_TYPE_ELLIPSIS(ht) TD_IS_TYPE_ELLIPSIS(HT_PTD(ht)) + +#define HT_ISCONST(ht) (HT_ADJECTIVES(ht) & HT_IsConst) // Is the type referenced 'const' qualified +#define HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) & HT_IsVolatile) // Is the type referenced 'volatile' qualified +#define HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) & HT_IsUnaligned) // Is the type referenced 'unaligned' qualified +#define HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) & HT_IsReference) // Is the catch type by reference +#define HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) & HT_IsResumable) // Might the catch choose to resume (Reserved) #define HT_ISCOMPLUSEH(ht) (HT_ADJECTIVES(ht) & HT_IsComplusEh) #define HT_ISBADALLOCCOMPAT(ht) (HT_ADJECTIVES(ht) & HT_IsBadAllocCompat) #define HT_IS_STD_DOTDOT(ht) (HT_ADJECTIVES(ht) & HT_IsStdDotDot) -#define SET_HT_ISCONST(ht) (HT_ADJECTIVES(ht) |= HT_IsConst) -#define SET_HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) |= HT_IsVolatile) -#define SET_HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) |= HT_IsUnaligned) -#define SET_HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) |= HT_IsReference) -#define SET_HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) |= HT_IsResumable) -#define SET_HT_ISCOMPLUSEH(ht) (HT_ADJECTIVES(ht) |= HT_IsComplusEh) +#define SET_HT_ISCONST(ht) (HT_ADJECTIVES(ht) |= HT_IsConst) +#define SET_HT_ISVOLATILE(ht) (HT_ADJECTIVES(ht) |= HT_IsVolatile) +#define SET_HT_ISUNALIGNED(ht) (HT_ADJECTIVES(ht) |= HT_IsUnaligned) +#define SET_HT_ISREFERENCE(ht) (HT_ADJECTIVES(ht) |= HT_IsReference) +#define SET_HT_ISRESUMABLE(ht) (HT_ADJECTIVES(ht) |= HT_IsResumable) +#define SET_HT_ISCOMPLUSEH(ht) (HT_ADJECTIVES(ht) |= HT_IsComplusEh) // // HandlerMapEntry - associates a handler list (sequence of catches) with a -// range of eh-states. +// range of eh-states. // typedef const struct _s_TryBlockMapEntry { - __ehstate_t tryLow; // Lowest state index of try - __ehstate_t tryHigh; // Highest state index of try - __ehstate_t catchHigh; // Highest state index of any associated catch - int nCatches; // Number of entries in array + __ehstate_t tryLow; // Lowest state index of try + __ehstate_t tryHigh; // Highest state index of try + __ehstate_t catchHigh; // Highest state index of any associated catch + int nCatches; // Number of entries in array #if _EH_RELATIVE_FUNCINFO - int dispHandlerArray; // Image relative offset of list of handlers for this try + int dispHandlerArray; // Image relative offset of list of handlers for this try #else - HandlerType* pHandlerArray; // List of handlers for this try + HandlerType* pHandlerArray; // List of handlers for this try #endif } TryBlockMapEntry; -#define TBME_LOW(hm) ((hm).tryLow) -#define TBME_HIGH(hm) ((hm).tryHigh) -#define TBME_CATCHHIGH(hm) ((hm).catchHigh) -#define TBME_NCATCHES(hm) ((hm).nCatches) +#define TBME_LOW(hm) ((hm).tryLow) +#define TBME_HIGH(hm) ((hm).tryHigh) +#define TBME_CATCHHIGH(hm) ((hm).catchHigh) +#define TBME_NCATCHES(hm) ((hm).nCatches) #if _EH_RELATIVE_FUNCINFO -#define TBME_PLIST(hm,ib) ((HandlerType*)((ib) + (hm).dispHandlerArray)) -#define TBME_CATCH(hm,n,ib) (TBME_PLIST(hm,ib)[n]) -#define TBME_PCATCH(hm,n,ib)(&(TBME_PLIST(hm,ib)[n])) +#define TBME_PLIST(hm,ib) ((HandlerType*)((ib) + (hm).dispHandlerArray)) +#define TBME_CATCH(hm,n,ib) (TBME_PLIST(hm,ib)[n]) +#define TBME_PCATCH(hm,n,ib) (&(TBME_PLIST(hm,ib)[n])) #else -#define TBME_PLIST(hm) ((hm).pHandlerArray) -#define TBME_CATCH(hm, n) (TBME_PLIST(hm)[n]) -#define TBME_PCATCH(hm, n) (&(TBME_PLIST(hm)[n])) +#define TBME_PLIST(hm) ((hm).pHandlerArray) +#define TBME_CATCH(hm, n) (TBME_PLIST(hm)[n]) +#define TBME_PCATCH(hm, n) (&(TBME_PLIST(hm)[n])) #endif @@ -186,7 +186,7 @@ typedef const struct _s_TryBlockMapEntry { // // UnwindMapEntry - Description of each state transition for unwinding -// the stack (i.e. calling destructors). +// the stack (i.e. calling destructors). // // The unwind map is an array, indexed by current state. Each entry specifies // the state to go to during unwind, and the action required to get there. @@ -198,35 +198,35 @@ typedef const struct _s_TryBlockMapEntry { // typedef const struct _s_UnwindMapEntry { - __ehstate_t toState; // State this action takes us to + __ehstate_t toState; // State this action takes us to #if _EH_RELATIVE_FUNCINFO - int action; // Image relative offset of funclet + int action; // Image relative offset of funclet #else - void (__cdecl * action)(void); // Funclet to call to effect state change + void (__cdecl * action)(void); // Funclet to call to effect state change #endif } UnwindMapEntry; -#define UWE_TOSTATE(uwe) ((uwe).toState) +#define UWE_TOSTATE(uwe) ((uwe).toState) #if _EH_RELATIVE_FUNCINFO -#define UWE_ACTION_IB(uwe,ib) ((void (__cdecl *)(void))((ib) + (uwe).action)) +#define UWE_ACTION_IB(uwe,ib) ((void (__cdecl *)(void))((ib) + (uwe).action)) #else -#define UWE_ACTION(uwe) ((uwe).action) +#define UWE_ACTION(uwe) ((uwe).action) #endif #if defined(_M_X64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_) typedef struct IptoStateMapEntry { - unsigned int Ip; // Image relative offset of IP - __ehstate_t State; + unsigned int Ip; // Image relative offset of IP + __ehstate_t State; } IptoStateMapEntry; #endif typedef const struct _s_ESTypeList { - int nCount; // how many types are there + int nCount; // how many types are there #if _EH_RELATIVE_TYPEINFO - int dispTypeArray; // offset of list of types in exception specification + int dispTypeArray; // offset of list of types in exception specification #else - HandlerType* pTypeArray; // List of types in exception specification + HandlerType* pTypeArray; // List of types in exception specification #endif }ESTypeList; @@ -239,7 +239,7 @@ typedef const struct _s_ESTypeList // // FuncInfo - all the information that describes a function with exception -// handling information. +// handling information. // // bbtFlags values @@ -256,61 +256,61 @@ typedef const struct _s_ESTypeList */ typedef const struct _s_FuncInfo { - unsigned int magicNumber:29; // Identifies version of compiler - unsigned int bbtFlags:3; // flags that may be set by BBT processing - __ehstate_t maxState; // Highest state number plus one (thus + unsigned int magicNumber:29; // Identifies version of compiler + unsigned int bbtFlags:3; // flags that may be set by BBT processing + __ehstate_t maxState; // Highest state number plus one (thus // number of entries in unwind map) #if _EH_RELATIVE_FUNCINFO - int dispUnwindMap; // Image relative offset of the unwind map - unsigned int nTryBlocks; // Number of 'try' blocks in this function - int dispTryBlockMap; // Image relative offset of the handler map - unsigned int nIPMapEntries; // # entries in the IP-to-state map. NYI (reserved) - int dispIPtoStateMap; // Image relative offset of the IP to state map - int dispUwindHelp; // Displacement of unwind helpers from base - int dispESTypeList; // Image relative list of types for exception specifications + int dispUnwindMap; // Image relative offset of the unwind map + unsigned int nTryBlocks; // Number of 'try' blocks in this function + int dispTryBlockMap; // Image relative offset of the handler map + unsigned int nIPMapEntries; // # entries in the IP-to-state map. NYI (reserved) + int dispIPtoStateMap; // Image relative offset of the IP to state map + int dispUwindHelp; // Displacement of unwind helpers from base + int dispESTypeList; // Image relative list of types for exception specifications #else - UnwindMapEntry* pUnwindMap; // Where the unwind map is - unsigned int nTryBlocks; // Number of 'try' blocks in this function - TryBlockMapEntry* pTryBlockMap; // Where the handler map is - unsigned int nIPMapEntries; // # entries in the IP-to-state map. NYI (reserved) - void* pIPtoStateMap; // An IP to state map. NYI (reserved). - ESTypeList* pESTypeList; // List of types for exception specifications + UnwindMapEntry* pUnwindMap; // Where the unwind map is + unsigned int nTryBlocks; // Number of 'try' blocks in this function + TryBlockMapEntry* pTryBlockMap; // Where the handler map is + unsigned int nIPMapEntries; // # entries in the IP-to-state map. NYI (reserved) + void* pIPtoStateMap; // An IP to state map. NYI (reserved). + ESTypeList* pESTypeList; // List of types for exception specifications #endif - int EHFlags; // Flags for some features. + int EHFlags; // Flags for some features. } FuncInfo; -#define FUNC_MAGICNUM(fi) ((fi).magicNumber) -#define FUNC_MAXSTATE(fi) ((fi).maxState) -#define FUNC_NTRYBLOCKS(fi) ((fi).nTryBlocks) -#define FUNC_NIPMAPENT(fi) ((fi).nIPMapEntries) -#define FUNC_FLAGS(fi) ((fi).EHFlags) +#define FUNC_MAGICNUM(fi) ((fi).magicNumber) +#define FUNC_MAXSTATE(fi) ((fi).maxState) +#define FUNC_NTRYBLOCKS(fi) ((fi).nTryBlocks) +#define FUNC_NIPMAPENT(fi) ((fi).nIPMapEntries) +#define FUNC_FLAGS(fi) ((fi).EHFlags) #if _EH_RELATIVE_FUNCINFO -#define FUNC_PUNWINDMAP(fi,ib) ((UnwindMapEntry*)((ib) + (fi).dispUnwindMap)) -#define FUNC_PHANDLERMAP(fi,ib) ((TryBlockMapEntry*)((ib) + (fi).dispTryBlockMap)) -#define FUNC_IPMAP(fi,ib) ((IptoStateMapEntry*)((ib) + (fi).dispIPtoStateMap)) -#define FUNC_UNWIND(fi,st,ib) (FUNC_PUNWINDMAP(fi,ib)[st]) -#define FUNC_PUNWIND(fi,st,ib) (&FUNC_UNWIND(fi,st,ib)) -#define FUNC_TRYBLOCK(fi,n,ib) (FUNC_PHANDLERMAP(fi,ib)[n]) -#define FUNC_PTRYBLOCK(fi,n,ib) (&FUNC_TRYBLOCK(fi,n,ib)) -#define FUNC_ESTYPES_IB(fi, ib) ((ESTypeList*)((ib) + (fi).dispESTypeList)) -#define FUNC_PESTYPES_IB(fi, ib) FUNC_ESTYPES_IB((*fi), ib) +#define FUNC_PUNWINDMAP(fi,ib) ((UnwindMapEntry*)((ib) + (fi).dispUnwindMap)) +#define FUNC_PHANDLERMAP(fi,ib) ((TryBlockMapEntry*)((ib) + (fi).dispTryBlockMap)) +#define FUNC_IPMAP(fi,ib) ((IptoStateMapEntry*)((ib) + (fi).dispIPtoStateMap)) +#define FUNC_UNWIND(fi,st,ib) (FUNC_PUNWINDMAP(fi,ib)[st]) +#define FUNC_PUNWIND(fi,st,ib) (&FUNC_UNWIND(fi,st,ib)) +#define FUNC_TRYBLOCK(fi,n,ib) (FUNC_PHANDLERMAP(fi,ib)[n]) +#define FUNC_PTRYBLOCK(fi,n,ib) (&FUNC_TRYBLOCK(fi,n,ib)) +#define FUNC_ESTYPES_IB(fi, ib) ((ESTypeList*)((ib) + (fi).dispESTypeList)) +#define FUNC_PESTYPES_IB(fi, ib) FUNC_ESTYPES_IB((*fi), ib) #else -#define FUNC_PUNWINDMAP(fi) ((fi).pUnwindMap) -#define FUNC_PHANDLERMAP(fi) ((fi).pTryBlockMap) -#define FUNC_IPMAP(fi) ((fi).pIPtoStateMap) -#define FUNC_UNWIND(fi, st) ((fi).pUnwindMap[st]) -#define FUNC_PUNWIND(fi, st) (&FUNC_UNWIND(fi, st)) -#define FUNC_TRYBLOCK(fi,n) ((fi).pTryBlockMap[n]) -#define FUNC_PTRYBLOCK(fi,n) (&FUNC_TRYBLOCK(fi, n)) -#define FUNC_ESTYPES(fi) ((fi).pESTypeList) -#define FUNC_PESTYPES(fi) (FUNC_ESTYPES(*fi)) +#define FUNC_PUNWINDMAP(fi) ((fi).pUnwindMap) +#define FUNC_PHANDLERMAP(fi) ((fi).pTryBlockMap) +#define FUNC_IPMAP(fi) ((fi).pIPtoStateMap) +#define FUNC_UNWIND(fi, st) ((fi).pUnwindMap[st]) +#define FUNC_PUNWIND(fi, st) (&FUNC_UNWIND(fi, st)) +#define FUNC_TRYBLOCK(fi,n) ((fi).pTryBlockMap[n]) +#define FUNC_PTRYBLOCK(fi,n) (&FUNC_TRYBLOCK(fi, n)) +#define FUNC_ESTYPES(fi) ((fi).pESTypeList) +#define FUNC_PESTYPES(fi) (FUNC_ESTYPES(*fi)) #endif #if _EH_RELATIVE_FUNCINFO -#define FUNC_IPTOSTATE(fi,n,ib) (FUNC_IPMAP(fi,ib)[n]) -#define FUNC_PIPTOSTATE(fi,n,ib)(&FUNC_IPTOSTATE(fi,n,ib)) -#define FUNC_DISPUNWINDHELP(fi) ((fi).dispUwindHelp) +#define FUNC_IPTOSTATE(fi,n,ib) (FUNC_IPMAP(fi,ib)[n]) +#define FUNC_PIPTOSTATE(fi,n,ib) (&FUNC_IPTOSTATE(fi,n,ib)) +#define FUNC_DISPUNWINDHELP(fi) ((fi).dispUwindHelp) #else -#define FUNC_IPTOSTATE(fi,n) __ERROR_NYI__ +#define FUNC_IPTOSTATE(fi,n) __ERROR_NYI__ #endif ///////////////////////////////////////////////////////////////////////////// @@ -320,8 +320,6 @@ typedef const struct _s_FuncInfo // //--------------------------------------------------------------------------- -#define RUNTIME_FUNCTION_INDIRECT 0x1 - ///////////////////////////////////////////////////////////////////////////// // // A stack registration node (i386 only) @@ -333,31 +331,31 @@ struct EHRegistrationNode; typedef struct EHRegistrationNode EHRegistrationNode; struct EHRegistrationNode { - /* void * stackPtr */ // Stack ptr at entry to try (below address point) - EHRegistrationNode* pNext; // Next node in the chain - void * frameHandler; // The handler function for this frame - __ehstate_t state; // The current state of this function + /* void * stackPtr */ // Stack ptr at entry to try (below address point) + EHRegistrationNode* pNext; // Next node in the chain + void * frameHandler; // The handler function for this frame + __ehstate_t state; // The current state of this function }; -# define FRAME_OFFSET sizeof(EHRegistrationNode) +# define FRAME_OFFSET sizeof(EHRegistrationNode) -#define PRN_NEXT(prn) ((prn)->pNext) -#define PRN_HANDLER(prn) ((prn)->frameHandler) -#define PRN_STATE(prn) ((prn)->state) -#define PRN_STACK(prn) (((void**)(prn))[-1]) -# define PRN_FRAME(prn) ((void*)(((char*)prn) + FRAME_OFFSET)) +#define PRN_NEXT(prn) ((prn)->pNext) +#define PRN_HANDLER(prn) ((prn)->frameHandler) +#define PRN_STATE(prn) ((prn)->state) +#define PRN_STACK(prn) (((void**)(prn))[-1]) +# define PRN_FRAME(prn) ((void*)(((char*)prn) + FRAME_OFFSET)) -typedef void DispatcherContext; // Meaningless on x86 +typedef void DispatcherContext; // Meaningless on x86 #elif defined(_M_ARM) -#define PRN_NEXT(prn) __ERROR__ -#define PRN_HANDLER(prn) __ERROR__ -#define PRN_STATE(prn) __ERROR__ -#define PRN_STACK(prn) __ERROR__ -#define PRN_FRAME(prn) __ERROR__ +#define PRN_NEXT(prn) __ERROR__ +#define PRN_HANDLER(prn) __ERROR__ +#define PRN_STATE(prn) __ERROR__ +#define PRN_STACK(prn) __ERROR__ +#define PRN_FRAME(prn) __ERROR__ -#define FRAME_OFFSET 0 +#define FRAME_OFFSET 0 typedef struct _UNWIND_INFO { unsigned short Version; @@ -378,133 +376,7 @@ typedef struct _xDISPATCHER_CONTEXT { ULONG ScopeIndex; BOOLEAN ControlPcIsUnwound; PUCHAR NonVolatileRegisters; -} DispatcherContext; // changed the case of the name to conform to EH conventions - - -// -// Define unwind information flags. -// - -#define UNW_FLAG_NHANDLER 0x0 /* any handler */ -#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ -#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ - -// -// Define unwind history table structure. -// - -#define UNWIND_HISTORY_TABLE_SIZE 12 - -typedef struct _UNWIND_HISTORY_TABLE_ENTRY { - DWORD ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; -} UNWIND_HISTORY_TABLE_ENTRY, * PUNWIND_HISTORY_TABLE_ENTRY; - -typedef struct _UNWIND_HISTORY_TABLE { - DWORD Count; - BYTE LocalHint; - BYTE GlobalHint; - BYTE Search; - BYTE Once; - DWORD LowAddress; - DWORD HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; -} UNWIND_HISTORY_TABLE, * PUNWIND_HISTORY_TABLE; - -// -// Define exception dispatch context structure. -// - -typedef struct _DISPATCHER_CONTEXT { - DWORD ControlPc; - DWORD ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; - DWORD EstablisherFrame; - DWORD TargetPc; - PCONTEXT ContextRecord; - PEXCEPTION_ROUTINE LanguageHandler; - PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; - DWORD ScopeIndex; - BOOLEAN ControlPcIsUnwound; - PBYTE NonVolatileRegisters; - DWORD Reserved; -} DISPATCHER_CONTEXT, * PDISPATCHER_CONTEXT; - -// -// Define exception filter and termination handler function types. -// N.B. These functions use a custom calling convention. -// - -struct _EXCEPTION_POINTERS; -typedef -LONG -(*PEXCEPTION_FILTER) ( - struct _EXCEPTION_POINTERS* ExceptionPointers, - DWORD EstablisherFrame - ); - -typedef -VOID -(*PTERMINATION_HANDLER) ( - BOOLEAN AbnormalTermination, - DWORD EstablisherFrame - ); - -// -// Define dynamic function table entry. -// - -typedef -_Function_class_(GET_RUNTIME_FUNCTION_CALLBACK) -PIMAGE_RUNTIME_FUNCTION_ENTRY -GET_RUNTIME_FUNCTION_CALLBACK( - _In_ DWORD ControlPc, - _In_opt_ PVOID Context -); -typedef GET_RUNTIME_FUNCTION_CALLBACK* PGET_RUNTIME_FUNCTION_CALLBACK; - -typedef -_Function_class_(OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK) -DWORD -OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK( - _In_ HANDLE Process, - _In_ PVOID TableAddress, - _Out_ PDWORD Entries, - _Out_ PIMAGE_RUNTIME_FUNCTION_ENTRY* Functions -); -typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK* POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK; - -#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \ - "OutOfProcessFunctionTableCallback" - -// -// Nonvolatile context pointer record. -// - -typedef struct _KNONVOLATILE_CONTEXT_POINTERS { - - PDWORD R4; - PDWORD R5; - PDWORD R6; - PDWORD R7; - PDWORD R8; - PDWORD R9; - PDWORD R10; - PDWORD R11; - PDWORD Lr; - - PULONGLONG D8; - PULONGLONG D9; - PULONGLONG D10; - PULONGLONG D11; - PULONGLONG D12; - PULONGLONG D13; - PULONGLONG D14; - PULONGLONG D15; - -} KNONVOLATILE_CONTEXT_POINTERS, * PKNONVOLATILE_CONTEXT_POINTERS; - +} DispatcherContext; // changed the case of the name to conform to EH conventions // // On ARM we don't have a registration node, just a pointer to the stack frame base @@ -514,13 +386,13 @@ typedef ULONG EHRegistrationNode; #elif defined(_M_X64) -#define PRN_NEXT(prn) __ERROR__ -#define PRN_HANDLER(prn) __ERROR__ -#define PRN_STATE(prn) __ERROR__ -#define PRN_STACK(prn) __ERROR__ -#define PRN_FRAME(prn) __ERROR__ +#define PRN_NEXT(prn) __ERROR__ +#define PRN_HANDLER(prn) __ERROR__ +#define PRN_STATE(prn) __ERROR__ +#define PRN_STACK(prn) __ERROR__ +#define PRN_FRAME(prn) __ERROR__ -#define FRAME_OFFSET 0 +#define FRAME_OFFSET 0 #pragma warning (push) #pragma warning (disable: 4201) @@ -565,180 +437,27 @@ typedef struct _xDISPATCHER_CONTEXT { PVOID HandlerData; PUNWIND_HISTORY_TABLE HistoryTable; ULONG ScopeIndex; -} DispatcherContext; // changed the case of the name to conform to EH conventions - -// -// Define unwind information flags. -// - -#define UNW_FLAG_NHANDLER 0x0 -#define UNW_FLAG_EHANDLER 0x1 -#define UNW_FLAG_UHANDLER 0x2 -#define UNW_FLAG_CHAININFO 0x4 - -#define UNW_FLAG_NO_EPILOGUE 0x80000000UL // Software only flag - -#define UNWIND_CHAIN_LIMIT 32 - -// -// Define unwind history table structure. -// - -#define UNWIND_HISTORY_TABLE_SIZE 12 - -typedef struct _UNWIND_HISTORY_TABLE_ENTRY { - DWORD64 ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; -} UNWIND_HISTORY_TABLE_ENTRY, * PUNWIND_HISTORY_TABLE_ENTRY; - -typedef struct _UNWIND_HISTORY_TABLE { - DWORD Count; - BYTE LocalHint; - BYTE GlobalHint; - BYTE Search; - BYTE Once; - DWORD64 LowAddress; - DWORD64 HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; -} UNWIND_HISTORY_TABLE, * PUNWIND_HISTORY_TABLE; - -// -// Define dynamic function table entry. -// - -typedef -_Function_class_(GET_RUNTIME_FUNCTION_CALLBACK) -PIMAGE_RUNTIME_FUNCTION_ENTRY -GET_RUNTIME_FUNCTION_CALLBACK( - _In_ DWORD64 ControlPc, - _In_opt_ PVOID Context -); -typedef GET_RUNTIME_FUNCTION_CALLBACK* PGET_RUNTIME_FUNCTION_CALLBACK; - -typedef -_Function_class_(OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK) -DWORD -OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK( - _In_ HANDLE Process, - _In_ PVOID TableAddress, - _Out_ PDWORD Entries, - _Out_ PIMAGE_RUNTIME_FUNCTION_ENTRY* Functions -); -typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK* POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK; - -#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \ - "OutOfProcessFunctionTableCallback" - -// -// Define exception dispatch context structure. -// - -typedef struct _DISPATCHER_CONTEXT { - DWORD64 ControlPc; - DWORD64 ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; - DWORD64 EstablisherFrame; - DWORD64 TargetIp; - PCONTEXT ContextRecord; - PEXCEPTION_ROUTINE LanguageHandler; - PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; - DWORD ScopeIndex; - DWORD Fill0; -} DISPATCHER_CONTEXT, * PDISPATCHER_CONTEXT; - -// -// Define exception filter and termination handler function types. -// - -struct _EXCEPTION_POINTERS; -typedef -LONG -(*PEXCEPTION_FILTER) ( - struct _EXCEPTION_POINTERS* ExceptionPointers, - PVOID EstablisherFrame - ); - -typedef -VOID -(*PTERMINATION_HANDLER) ( - BOOLEAN AbnormalTermination, - PVOID EstablisherFrame - ); - -// -// Nonvolatile context pointer record. -// - -#pragma warning(push) -#pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union -typedef struct _KNONVOLATILE_CONTEXT_POINTERS { - union { - PM128A FloatingContext[16]; - struct { - PM128A Xmm0; - PM128A Xmm1; - PM128A Xmm2; - PM128A Xmm3; - PM128A Xmm4; - PM128A Xmm5; - PM128A Xmm6; - PM128A Xmm7; - PM128A Xmm8; - PM128A Xmm9; - PM128A Xmm10; - PM128A Xmm11; - PM128A Xmm12; - PM128A Xmm13; - PM128A Xmm14; - PM128A Xmm15; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; - - union { - PDWORD64 IntegerContext[16]; - struct { - PDWORD64 Rax; - PDWORD64 Rcx; - PDWORD64 Rdx; - PDWORD64 Rbx; - PDWORD64 Rsp; - PDWORD64 Rbp; - PDWORD64 Rsi; - PDWORD64 Rdi; - PDWORD64 R8; - PDWORD64 R9; - PDWORD64 R10; - PDWORD64 R11; - PDWORD64 R12; - PDWORD64 R13; - PDWORD64 R14; - PDWORD64 R15; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME2; - -} KNONVOLATILE_CONTEXT_POINTERS, * PKNONVOLATILE_CONTEXT_POINTERS; -#pragma warning(pop) +} DispatcherContext; // changed the case of the name to conform to EH conventions // // On P7 we don't have a registration node, just a pointer to the stack frame base // + typedef ULONG_PTR EHRegistrationNode; #elif defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_) -#define PRN_NEXT(prn) __ERROR__ -#define PRN_HANDLER(prn) __ERROR__ -#define PRN_STATE(prn) __ERROR__ -#define PRN_STACK(prn) __ERROR__ -#define PRN_FRAME(prn) __ERROR__ +#define PRN_NEXT(prn) __ERROR__ +#define PRN_HANDLER(prn) __ERROR__ +#define PRN_STATE(prn) __ERROR__ +#define PRN_STACK(prn) __ERROR__ +#define PRN_FRAME(prn) __ERROR__ -#define FRAME_OFFSET 0 +#define FRAME_OFFSET 0 #pragma warning (push) #pragma warning (disable: 4201) - typedef union _UNWIND_CODE { struct { unsigned char CodeOffset; @@ -747,8 +466,8 @@ typedef union _UNWIND_CODE { }; unsigned short FrameOffset; } UNWIND_CODE, * PUNWIND_CODE; - #pragma warning (pop) + typedef struct _UNWIND_INFO { unsigned char Version : 3; unsigned char Flags : 5; @@ -784,146 +503,10 @@ typedef struct _xDISPATCHER_CONTEXT { PUCHAR NonVolatileRegisters; } DispatcherContext; -// -// Define unwind information flags. -// - -#define UNW_FLAG_NHANDLER 0x0 /* any handler */ -#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ -#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ - -// -// Define unwind history table structure. -// - -#define UNWIND_HISTORY_TABLE_SIZE 12 - -typedef struct _UNWIND_HISTORY_TABLE_ENTRY { - DWORD64 ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; -} UNWIND_HISTORY_TABLE_ENTRY, * PUNWIND_HISTORY_TABLE_ENTRY; - -typedef struct _UNWIND_HISTORY_TABLE { - DWORD Count; - BYTE LocalHint; - BYTE GlobalHint; - BYTE Search; - BYTE Once; - DWORD64 LowAddress; - DWORD64 HighAddress; - UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; -} UNWIND_HISTORY_TABLE, * PUNWIND_HISTORY_TABLE; - -#pragma push_macro("_DISPATCHER_CONTEXT_ARM64") -#undef _DISPATCHER_CONTEXT_ARM64 -#define _DISPATCHER_CONTEXT_ARM64 _DISPATCHER_CONTEXT - -// -// Define exception dispatch context structure. -// - -typedef struct _DISPATCHER_CONTEXT_ARM64 { - ULONG_PTR ControlPc; - ULONG_PTR ImageBase; - PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry; - ULONG_PTR EstablisherFrame; - ULONG_PTR TargetPc; - PARM64_NT_CONTEXT ContextRecord; - PEXCEPTION_ROUTINE LanguageHandler; - PVOID HandlerData; - PUNWIND_HISTORY_TABLE HistoryTable; - DWORD ScopeIndex; - BOOLEAN ControlPcIsUnwound; - PBYTE NonVolatileRegisters; -} DISPATCHER_CONTEXT_ARM64, * PDISPATCHER_CONTEXT_ARM64; - -#undef _DISPATCHER_CONTEXT_ARM64 -#pragma pop_macro("_DISPATCHER_CONTEXT_ARM64") - -typedef DISPATCHER_CONTEXT_ARM64 DISPATCHER_CONTEXT, * PDISPATCHER_CONTEXT; - -// -// Define exception filter and termination handler function types. -// N.B. These functions use a custom calling convention. -// - -struct _EXCEPTION_POINTERS; -typedef -LONG -(*PEXCEPTION_FILTER) ( - struct _EXCEPTION_POINTERS* ExceptionPointers, - DWORD64 EstablisherFrame - ); - -typedef -VOID -(*PTERMINATION_HANDLER) ( - BOOLEAN AbnormalTermination, - DWORD64 EstablisherFrame - ); - -// -// Define dynamic function table entry. -// - -typedef -_Function_class_(GET_RUNTIME_FUNCTION_CALLBACK) -PIMAGE_RUNTIME_FUNCTION_ENTRY -GET_RUNTIME_FUNCTION_CALLBACK( - _In_ DWORD64 ControlPc, - _In_opt_ PVOID Context -); -typedef GET_RUNTIME_FUNCTION_CALLBACK* PGET_RUNTIME_FUNCTION_CALLBACK; - -typedef -_Function_class_(OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK) -DWORD -OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK( - _In_ HANDLE Process, - _In_ PVOID TableAddress, - _Out_ PDWORD Entries, - _Out_ PIMAGE_RUNTIME_FUNCTION_ENTRY* Functions -); -typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK* POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK; - -#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \ - "OutOfProcessFunctionTableCallback" - -// -// Nonvolatile context pointer record. -// - -typedef struct _KNONVOLATILE_CONTEXT_POINTERS_ARM64 { - - PDWORD64 X19; - PDWORD64 X20; - PDWORD64 X21; - PDWORD64 X22; - PDWORD64 X23; - PDWORD64 X24; - PDWORD64 X25; - PDWORD64 X26; - PDWORD64 X27; - PDWORD64 X28; - PDWORD64 Fp; - PDWORD64 Lr; - - PDWORD64 D8; - PDWORD64 D9; - PDWORD64 D10; - PDWORD64 D11; - PDWORD64 D12; - PDWORD64 D13; - PDWORD64 D14; - PDWORD64 D15; - -} KNONVOLATILE_CONTEXT_POINTERS_ARM64, * PKNONVOLATILE_CONTEXT_POINTERS_ARM64; - -typedef KNONVOLATILE_CONTEXT_POINTERS_ARM64 KNONVOLATILE_CONTEXT_POINTERS, * PKNONVOLATILE_CONTEXT_POINTERS; - // // On ARM64 we don't have a registration node, just a pointer to the stack frame base // + typedef ULONG_PTR EHRegistrationNode; #else @@ -942,17 +525,17 @@ typedef ULONG_PTR EHRegistrationNode; #pragma pack(push, EHExceptionRecord, 8) #endif typedef struct EHExceptionRecord { - unsigned long ExceptionCode; // The code of this exception. (= EH_EXCEPTION_NUMBER) - unsigned long ExceptionFlags; // Flags determined by NT - struct _EXCEPTION_RECORD * ExceptionRecord; // An extra exception record (not used) - void * ExceptionAddress; // Address at which exception occurred - unsigned long NumberParameters; // Number of extended parameters. (= EH_EXCEPTION_PARAMETERS) + unsigned long ExceptionCode; // The code of this exception. (= EH_EXCEPTION_NUMBER) + unsigned long ExceptionFlags; // Flags determined by NT + struct _EXCEPTION_RECORD * ExceptionRecord; // An extra exception record (not used) + void * ExceptionAddress; // Address at which exception occurred + unsigned long NumberParameters; // Number of extended parameters. (= EH_EXCEPTION_PARAMETERS) struct EHParameters { - unsigned long magicNumber; // = EH_MAGIC_NUMBER1 - void * pExceptionObject; // Pointer to the actual object thrown - ThrowInfo* pThrowInfo; // Description of thrown object + unsigned long magicNumber; // = EH_MAGIC_NUMBER1 + void * pExceptionObject; // Pointer to the actual object thrown + ThrowInfo* pThrowInfo; // Description of thrown object #if _EH_RELATIVE_TYPEINFO - void * pThrowImageBase; // Image base of thrown object + void * pThrowImageBase; // Image base of thrown object #endif } params; } EHExceptionRecord; @@ -961,45 +544,45 @@ typedef struct EHExceptionRecord { #pragma pack(pop, EHExceptionRecord) #endif -#define PER_CODE(per) ((per)->ExceptionCode) -#define PER_FLAGS(per) ((per)->ExceptionFlags) -#define PER_NEXT(per) ((per)->ExceptionRecord) -#define PER_ADDRESS(per) ((per)->ExceptionAddress) -#define PER_NPARAMS(per) ((per)->NumberParameters) -#define PER_MAGICNUM(per) ((per)->params.magicNumber) -#define PER_PEXCEPTOBJ(per) ((per)->params.pExceptionObject) -#define PER_PTHROW(per) ((per)->params.pThrowInfo) -#define PER_EXCEPTINFO(per) ((PULONG_PTR)&(PER_MAGICNUM(per))) +#define PER_CODE(per) ((per)->ExceptionCode) +#define PER_FLAGS(per) ((per)->ExceptionFlags) +#define PER_NEXT(per) ((per)->ExceptionRecord) +#define PER_ADDRESS(per) ((per)->ExceptionAddress) +#define PER_NPARAMS(per) ((per)->NumberParameters) +#define PER_MAGICNUM(per) ((per)->params.magicNumber) +#define PER_PEXCEPTOBJ(per) ((per)->params.pExceptionObject) +#define PER_PTHROW(per) ((per)->params.pThrowInfo) +#define PER_EXCEPTINFO(per) ((PULONG_PTR)&(PER_MAGICNUM(per))) #if _EH_RELATIVE_TYPEINFO -#define PER_PTHROWIB(per) ((per)->params.pThrowImageBase) +#define PER_PTHROWIB(per) ((per)->params.pThrowImageBase) #endif -#define PER_THROW(per) (*PER_PTHROW(per)) +#define PER_THROW(per) (*PER_PTHROW(per)) -#define PER_ISSIMPLETYPE(t) (PER_THROW(t).isSimpleType) -#define PER_ISREFERENCE(t) (PER_THROW(t).isReference) -#define PER_ISCONST(t) (PER_THROW(t).isConst) -#define PER_ISVOLATILE(t) (PER_THROW(t).isVolatile) -#define PER_ISUNALIGNED(t) (PER_THROW(t).isUnaligned) -#define PER_UNWINDFUNC(t) (PER_THROW(t).pmfnUnwind) -#define PER_PCTLIST(t) (PER_THROW(t).pCatchable) -#define PER_CTLIST(t) (*PER_PCTLIST(t)) +#define PER_ISSIMPLETYPE(t) (PER_THROW(t).isSimpleType) +#define PER_ISREFERENCE(t) (PER_THROW(t).isReference) +#define PER_ISCONST(t) (PER_THROW(t).isConst) +#define PER_ISVOLATILE(t) (PER_THROW(t).isVolatile) +#define PER_ISUNALIGNED(t) (PER_THROW(t).isUnaligned) +#define PER_UNWINDFUNC(t) (PER_THROW(t).pmfnUnwind) +#define PER_PCTLIST(t) (PER_THROW(t).pCatchable) +#define PER_CTLIST(t) (*PER_PCTLIST(t)) #if defined(_M_CEE_PURE) -#define PER_IS_MSVC_EH(per) ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ - (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ - ((PER_MAGICNUM(per) == EH_PURE_MAGIC_NUMBER1) || \ +#define PER_IS_MSVC_EH(per) ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ + (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ + ((PER_MAGICNUM(per) == EH_PURE_MAGIC_NUMBER1) || \ PER_PTHROW(per) == NULL)) #else -#define PER_IS_MSVC_EH(per) ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ - (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ +#define PER_IS_MSVC_EH(per) ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ + (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ ((PER_MAGICNUM(per) == EH_MAGIC_NUMBER1) || \ (PER_MAGICNUM(per) == EH_MAGIC_NUMBER2) || \ (PER_MAGICNUM(per) == EH_MAGIC_NUMBER3))) #endif #define PER_IS_MSVC_PURE_OR_NATIVE_EH(per) \ - ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ - (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ + ((PER_CODE(per) == EH_EXCEPTION_NUMBER) && \ + (PER_NPARAMS(per) == EH_EXCEPTION_PARAMETERS) && \ ((PER_MAGICNUM(per) == EH_MAGIC_NUMBER1) || \ (PER_MAGICNUM(per) == EH_MAGIC_NUMBER2) || \ (PER_MAGICNUM(per) == EH_MAGIC_NUMBER3) || \ diff --git a/src/vcruntime/ehdata_forceinclude.h b/src/vcruntime/ehdata_forceinclude.h index 889a46d..7fc55ef 100644 --- a/src/vcruntime/ehdata_forceinclude.h +++ b/src/vcruntime/ehdata_forceinclude.h @@ -62,9 +62,9 @@ // typedef struct PMD { - int mdisp; // Offset of intended data within base - int pdisp; // Displacement to virtual base pointer - int vdisp; // Index within vbTable to offset of base + int mdisp; // Offset of intended data within base + int pdisp; // Displacement to virtual base pointer + int vdisp; // Index within vbTable to offset of base } PMD; // @@ -100,7 +100,7 @@ typedef struct TypeDescriptor #if defined(_WIN64) || defined(_RTTI) || defined(BUILDING_C1XX_FORCEINCLUDE) const void * pVFTable; // Field overloaded by RTTI #else - unsigned long hash; // Hash value computed from type's decorated name + unsigned long hash; // Hash value computed from type's decorated name #endif void * spare; // reserved, possible for RTTI char name[]; // The decorated name of the type; 0 terminated. @@ -134,7 +134,7 @@ typedef struct TypeDescriptor // CatchableType - description of a type that can be caught. // // Note: although isSimpleType can be part of ThrowInfo, it is more -// convenient for the run-time to have it here. +// convenient for the run-time to have it here. // typedef const struct _s_CatchableType { unsigned int properties; // Catchable Type properties (Bit field) @@ -206,11 +206,11 @@ EXTERN_C int __cdecl __CxxExceptionFilter(void* ppExcept, void* pType, int adjec #ifdef prepifdef prepifdef _MANAGED int __clrcall ___CxxExceptionFilter(void* ppExcept, void* pType, int adjectives, void *pBuildObj); - prependif // _MANAGED + prependif // _MANAGED #else #ifdef _MANAGED int __clrcall ___CxxExceptionFilter(void* ppExcept, void* pType, int adjectives, void *pBuildObj); - #endif // _MANAGED + #endif // _MANAGED #endif // Returns true if the object is really a C++ exception diff --git a/src/vcruntime/ehhooks.h b/src/vcruntime/ehhooks.h index 59a5f30..80b7f2c 100644 --- a/src/vcruntime/ehhooks.h +++ b/src/vcruntime/ehhooks.h @@ -55,57 +55,6 @@ enum : size_t #endif }; -EXTERN_C NTSYSAPI VOID NTAPI -RtlRaiseException( - _In_ PEXCEPTION_RECORD ExceptionRecord -); - -EXTERN_C NTSYSAPI PVOID NTAPI -RtlPcToFileHeader( - _In_ PVOID PcValue, - _Out_ PVOID* BaseOfImage -); - -EXTERN_C NTSYSAPI VOID NTAPI -RtlUnwind( - PVOID TargetFrame, - PVOID TargetIp, - PEXCEPTION_RECORD ExceptionRecord, - PVOID ReturnValue -); - -#if defined(_M_AMD64) || defined(_M_ARM64) || defined(_M_ARM) -EXTERN_C NTSYSAPI PIMAGE_RUNTIME_FUNCTION_ENTRY NTAPI -RtlLookupFunctionEntry( - _In_ ULONG_PTR ControlPc, - _Out_ PULONG_PTR ImageBase, - _Inout_opt_ PUNWIND_HISTORY_TABLE HistoryTable -); - -EXTERN_C NTSYSAPI VOID NTAPI -RtlUnwindEx( - _In_opt_ PVOID TargetFrame, - _In_opt_ PVOID TargetIp, - _In_opt_ PEXCEPTION_RECORD ExceptionRecord, - _In_ PVOID ReturnValue, - _In_ PCONTEXT ContextRecord, - _In_opt_ PUNWIND_HISTORY_TABLE HistoryTable -); - -EXTERN_C NTSYSAPI -PEXCEPTION_ROUTINE NTAPI -RtlVirtualUnwind( - _In_ DWORD HandlerType, - _In_ ULONG_PTR ImageBase, - _In_ ULONG_PTR ControlPc, - _In_ PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, - _Inout_ PCONTEXT ContextRecord, - _Out_ PVOID* HandlerData, - _Out_ PULONG_PTR EstablisherFrame, - _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers -); -#endif - #if _EH_RELATIVE_FUNCINFO EXTERN_C uintptr_t __cdecl _GetImageBase(); @@ -119,17 +68,17 @@ EXTERN_C void __cdecl _SetThrowImageBase(uintptr_t NewThrowImageBase); #endif EXTERN_C _VCRTIMP FRAMEINFO * __cdecl _CreateFrameInfo( - FRAMEINFO * pFrameInfo, - PVOID pExceptionObject + FRAMEINFO * pFrameInfo, + PVOID pExceptionObject ); EXTERN_C _VCRTIMP void __cdecl _FindAndUnlinkFrame( - FRAMEINFO * pFrameInfo + FRAMEINFO * pFrameInfo ); EXTERN_C _VCRTIMP BOOL __cdecl _IsExceptionObjectToBeDestroyed( - PVOID pExceptionObject + PVOID pExceptionObject ); #ifdef _EH_RELATIVE_FUNCINFO @@ -147,28 +96,28 @@ BOOL _CallSETranslator( #if defined(_M_X64) EXTERN_C void* __cdecl _CallSettingFrame( - void* handler, - EHRegistrationNode* pEstablisher, - ULONG NLG_CODE + void* handler, + EHRegistrationNode* pEstablisher, + ULONG NLG_CODE ); EXTERN_C void* __cdecl _CallSettingFrameEncoded( - void* handler, - EHRegistrationNode pEstablisher, - void* object, - ULONG NLG_CODE + void* handler, + EHRegistrationNode pEstablisher, + void* object, + ULONG NLG_CODE ); EXTERN_C void* __cdecl _CallSettingFrame_LookupContinuationIndex( void* handler, EHRegistrationNode *pEstablisher, ULONG NLG_CODE - ); + ); EXTERN_C void* __cdecl _CallSettingFrame_NotifyContinuationAddr( void* handler, EHRegistrationNode *pEstablisher - ); + ); #elif defined(_M_ARM_NT) || defined(_M_ARM64) || defined(_CHPE_X86_ARM64_EH_) EXTERN_C void* __cdecl _CallSettingFrame( @@ -176,7 +125,7 @@ EXTERN_C void* __cdecl _CallSettingFrame( EHRegistrationNode* pRN, PULONG pNonVolatiles, ULONG NLG_CODE - ); + ); #endif #ifndef EXCEPTION_NONCONTINUABLE_EXCEPTION diff --git a/src/vcruntime/winapi_thunks.cpp b/src/vcruntime/winapi_thunks.cpp new file mode 100644 index 0000000..387db6f --- /dev/null +++ b/src/vcruntime/winapi_thunks.cpp @@ -0,0 +1,208 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: winapi_thunks.cpp + * DATA: 2022/05/22 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +// +// winapi_thunks.cpp +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// Definitions of wrappers for Windows API functions that cannot be called +// by the statically-linked CRT code because they are not part of the MSDK. +// +#include +#include "winapi_thunks.h" + +EXTERN_C NTSTATUS NTAPI RtlFindAndFormatMessage( + _In_ UINT32 Flags, + _In_opt_ LPCVOID Source, + _In_ UINT32 MessageId, + _In_ UINT32 LanguageId, + _Out_ LPWSTR Buffer, + _Inout_ UINT32* Size, + _In_opt_ va_list* Arguments +); + +_CRT_BEGIN_C_HEADER + +DWORD __vcrt_FormatMessageA( + _In_ DWORD Flags, + _In_opt_ LPCVOID Source, + _In_ DWORD MessageId, + _In_ DWORD LanguageId, + _Out_ LPSTR Buffer, + _In_ DWORD Size, + _In_opt_ va_list* Arguments +) +{ + NTSTATUS Status = STATUS_SUCCESS; + UINT32 WrittenSize = Size; + PWSTR UnicodeSource = nullptr; + PWSTR UnicodeBuffer = nullptr; + + ANSI_STRING AnsiString{}; + UNICODE_STRING UnicodeString{}; + + do + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_FROM_STRING)) + { + if (strlen((LPCSTR)Source) >= MAXSHORT) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + else + { + RtlInitAnsiString(&AnsiString, (LPCSTR)Source); + Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE); + if (!NT_SUCCESS(Status)) + { + break; + } + + UnicodeSource = UnicodeString.Buffer; + } + } + else + { + UnicodeSource = (LPWSTR)Source; + } + + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ALLOCATE_BUFFER)) + { + UnicodeBuffer = (LPWSTR)Buffer; + } + else + { + UnicodeBuffer = (LPWSTR)malloc(Size * sizeof(wchar_t)); + } + + if (UnicodeBuffer == nullptr) + { + Status = STATUS_NO_MEMORY; + break; + } + + SetFlag(Flags, FORMAT_MESSAGE_ARGUMENT_ANSI); + + Status = RtlFindAndFormatMessage( + Flags, + UnicodeSource, + MessageId, + LanguageId, + UnicodeBuffer, + &WrittenSize, + Arguments); + + RtlFreeUnicodeString(&UnicodeString); + + if (!NT_SUCCESS(Status)) + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ALLOCATE_BUFFER)) + { + UnicodeBuffer = nullptr; + } + + break; + } + + if (WrittenSize >= MAXSHORT) + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ALLOCATE_BUFFER)) + { + UnicodeBuffer = *(LPWSTR*)Buffer; + *(LPWSTR*)Buffer = nullptr; + } + + Status = STATUS_INVALID_PARAMETER; + break; + } + + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ALLOCATE_BUFFER)) + { + UnicodeBuffer = *(LPWSTR*)Buffer; + + UnicodeString.Buffer = UnicodeBuffer; + UnicodeString.Length = (USHORT)(WrittenSize * sizeof(WCHAR)); + UnicodeString.MaximumLength = (USHORT)(UnicodeString.Length + sizeof(UNICODE_NULL)); + + Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE); + if (!NT_SUCCESS(Status)) + { + *(LPSTR*)Buffer = nullptr; + break; + } + + *(LPSTR*)Buffer = AnsiString.Buffer; + } + else + { + UnicodeString.Buffer = UnicodeBuffer; + + RtlInitEmptyAnsiString(&AnsiString, Buffer, (USHORT)Size); + Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE); + if (!NT_SUCCESS(Status)) + { + break; + } + } + + WrittenSize = AnsiString.Length; + + } while (false); + + if (UnicodeBuffer) + { + free(UnicodeBuffer); + } + + _set_doserrno(Status); + return WrittenSize; +} + +DWORD __vcrt_FormatMessageW( + _In_ DWORD Flags, + _In_opt_ LPCVOID Source, + _In_ DWORD MessageId, + _In_ DWORD LanguageId, + _Out_ LPWSTR Buffer, + _In_ DWORD Size, + _In_opt_ va_list* Arguments +) +{ + NTSTATUS Status = STATUS_SUCCESS; + UINT32 WrittenSize = Size; + + do + { + if (BooleanFlagOn(Flags, FORMAT_MESSAGE_ARGUMENT_ANSI)) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + Status = RtlFindAndFormatMessage( + Flags, + Source, + MessageId, + LanguageId, + Buffer, + &WrittenSize, + Arguments); + + } while (false); + + _set_doserrno(Status); + return WrittenSize; +} + +_CRT_END_C_HEADER diff --git a/src/vcruntime/winapi_thunks.h b/src/vcruntime/winapi_thunks.h new file mode 100644 index 0000000..7812fce --- /dev/null +++ b/src/vcruntime/winapi_thunks.h @@ -0,0 +1,46 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: winapi_thunks.h + * DATA: 2022/02/27 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + + // + // winapi_thunks.cpp + // + // Copyright (c) Microsoft Corporation. All rights reserved. + // + // Definitions of wrappers for Windows API functions that cannot be called + // by the statically-linked CRT code because they are not part of the MSDK. + // + +#pragma once + +_CRT_BEGIN_C_HEADER + +DWORD __vcrt_FormatMessageA( + _In_ DWORD Flags, + _In_opt_ LPCVOID Source, + _In_ DWORD MessageId, + _In_ DWORD LanguageId, + _Out_ LPSTR Buffer, + _In_ DWORD Size, + _In_opt_ va_list* Arguments +); + +DWORD __vcrt_FormatMessageW( + _In_ DWORD Flags, + _In_opt_ LPCVOID Source, + _In_ DWORD MessageId, + _In_ DWORD LanguageId, + _Out_ LPWSTR Buffer, + _In_ DWORD Size, + _In_opt_ va_list* Arguments +); + +_CRT_END_C_HEADER diff --git a/ucxxrt.h b/ucxxrt.h index 1819a0b..31e5639 100644 --- a/ucxxrt.h +++ b/ucxxrt.h @@ -56,20 +56,15 @@ namespace ucxxrt { -#if (_MSVC_LANG < 201704L) && (__cplusplus < 201704L) - constexpr char __Version[] = u8"2.1.1"; -#else - constexpr char8_t __Version[] = u8"2.1.1"; -#endif - #ifdef _KERNEL_MODE extern ULONG DefaultPoolTag; extern POOL_TYPE DefaultPoolType; extern ULONG DefaultMdlProtection; + + extern PVOID PsSystemDllBase; #endif } - #ifndef _ByteSwap16 #define _ByteSwap16(x) ( \ ((uint16_t(x) & uint16_t(0xFF << 8)) >> 8) | \ diff --git a/ucxxrt.inl b/ucxxrt.inl index 6bcaa5b..7db1627 100644 --- a/ucxxrt.inl +++ b/ucxxrt.inl @@ -82,8 +82,7 @@ # endif #endif -#include -#include +#include #include #define _VCRT_BUILD @@ -97,7 +96,6 @@ #include #include #include -#include #include "ucxxrt.h" diff --git a/veil b/veil new file mode 160000 index 0000000..28009c5 --- /dev/null +++ b/veil @@ -0,0 +1 @@ +Subproject commit 28009c50410ae05bb8732d3d41e68b1ff94b5ad2 diff --git a/vsproject/ucxxrt.test.vcxproj b/vsproject/ucxxrt.test.vcxproj index 58c6eda..3a662be 100644 --- a/vsproject/ucxxrt.test.vcxproj +++ b/vsproject/ucxxrt.test.vcxproj @@ -50,64 +50,64 @@ true WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 false WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 true WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 false WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 true WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 false WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 true WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop Windows10 false WindowsKernelModeDriver10.0 Driver - KMDF - Universal + WDM + Desktop diff --git a/vsproject/ucxxrt.vcxproj b/vsproject/ucxxrt.vcxproj index 6b31c88..840b3eb 100644 --- a/vsproject/ucxxrt.vcxproj +++ b/vsproject/ucxxrt.vcxproj @@ -82,13 +82,17 @@ + + + + @@ -115,6 +119,7 @@ + true @@ -156,6 +161,7 @@ + diff --git a/vsproject/ucxxrt.vcxproj.filters b/vsproject/ucxxrt.vcxproj.filters index 7505a60..37999e4 100644 --- a/vsproject/ucxxrt.vcxproj.filters +++ b/vsproject/ucxxrt.vcxproj.filters @@ -178,6 +178,21 @@ ucxxrt + + ucxxrt\stl + + + ucxxrt\stl + + + ucxxrt\vcruntime + + + ucxxrt + + + ucxxrt + @@ -223,6 +238,9 @@ ucxxrt\inc + + ucxxrt\vcruntime +