From b38328460537267b8fe49f2644100c333c4c5c00 Mon Sep 17 00:00:00 2001 From: Jung-Kwang Lee Date: Tue, 23 Aug 2022 21:47:59 +0900 Subject: [PATCH 1/4] Add ntl::Irql. Add ntl::spin_lock. Add ntl::resource. --- README.md | 23 ++- docs/ko-kr.md | 25 +++- include/.internal/version | 2 +- include/ntl/irql | 73 ++++++++++ include/ntl/resource | 285 ++++++++++++++++++++++++++++++++++++++ include/ntl/spin_lock | 141 +++++++++++++++++++ src/main.cpp | 23 +++ test/driver/src/all.cpp | 16 ++- test/driver/src/main.cpp | 2 +- test/driver/src/ntl.cpp | 239 +++++++++++++++++++++++++++++++- 10 files changed, 819 insertions(+), 10 deletions(-) create mode 100644 include/ntl/irql create mode 100644 include/ntl/resource create mode 100644 include/ntl/spin_lock diff --git a/README.md b/README.md index 8d50bb8..80a5b94 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,25 @@ Provides features to support a better development environment in the kernel. * ntl::rpc::client [(tested)](./test/app/src/main.cpp#L4) [(tested)](./test/common/rpc.hpp) * I did not have enough time to implement the data serialization part myself, so I referred to the contents of the project below. thank you! :-) * [Eyal Z/zpp serializer](https://github.com/eyalz800/serializer) +* ntl::irql + * Class for KIRQL + * Classes + * ntl::irql [(tested)](./test/driver/src/ntl.cpp#L46) + * Functions + * ntl::raise_irql [(tested)](./test/driver/src/ntl.cpp#L49) + * raise_irql_to_dpc_level [(tested)](./test/driver/src/ntl.cpp#L62) + * raise_irql_to_synch_level [(tested)](./test/driver/src/ntl.cpp#L71) +* ntl::spin_lock + * Class for KSPIN_LOCK + * Classes + * ntl::spin_lock [(tested)](./test/driver/src/ntl.cpp#L80) + * ntl::unique_lock [(tested)](./test/driver/src/ntl.cpp#L99) +* ntl::resource + * Class for ERESOURCE + * Classes + * ntl::resource [(tested)](./test/driver/src/ntl.cpp#L117) + * ntl::unique_lock [(tested)](./test/driver/src/ntl.cpp#L156) + * ntl::shared_lock [(tested)](./test/driver/src/ntl.cpp#L179) ## Requirements @@ -187,7 +206,7 @@ Provides features to support a better development environment in the kernel. * 14.26.28801 * 14.29.30133 * 14.31.31103 -* Windows Kit (SDK, WDK) +* Windows Kits (SDK, WDK) * 10.0.17763.0 * 10.0.18362.0 * 10.0.22000.0 @@ -281,7 +300,7 @@ If the SDK and WDK versions are different, builds are more likely to fail. **If include(cmake/CPM.cmake) set(CRTSYS_NTL_MAIN ON) # use ntl::main - CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.8") + CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.9") include(${crtsys_SOURCE_DIR}/cmake/CrtSys.cmake) # add driver diff --git a/docs/ko-kr.md b/docs/ko-kr.md index d9fda34..2fc8a01 100644 --- a/docs/ko-kr.md +++ b/docs/ko-kr.md @@ -147,7 +147,7 @@ crtsys의 장점은 아래와 같습니다. * [x] Create device [(tested)](../test/driver/src/main.cpp#L44) * ntl::device * DEVICE_OBJECT에 대한 클래스 - * Features + * 기능 * [x] Device Extension [(tested)](../test/driver/src/main.cpp#L33) * [ ] IRP_MJ_CREATE * [ ] IRP_MJ_CLOSE @@ -161,6 +161,25 @@ crtsys의 장점은 아래와 같습니다. * ntl::rpc::client [(tested)](../test/app/src/main.cpp#L4) [(tested)](../test/common/rpc.hpp) * 데이터 직렬화 부분을 직접 구현하기에는 시간이 부족하여 아래 프로젝트 내용을 참고했습니다. 감사합니다! :-) * [Eyal Z/zpp serializer](https://github.com/eyalz800/serializer) +* ntl::irql + * KIRQL에 대한 클래스 + * 클래스 + * ntl::irql [(tested)](../test/driver/src/ntl.cpp#L46) + * 함수 + * ntl::raise_irql [(tested)](../test/driver/src/ntl.cpp#L49) + * raise_irql_to_dpc_level [(tested)](../test/driver/src/ntl.cpp#L62) + * raise_irql_to_synch_level [(tested)](../test/driver/src/ntl.cpp#L71) +* ntl::spin_lock + * KSPIN_LOCK에 대한 클래스 + * 클래스 + * ntl::spin_lock [(tested)](../test/driver/src/ntl.cpp#L80) + * ntl::unique_lock [(tested)](../test/driver/src/ntl.cpp#L99) +* ntl::resource + * ERESOURCE에 대한 클래스 + * 클래스 + * ntl::resource [(tested)](../test/driver/src/ntl.cpp#L117) + * ntl::unique_lock [(tested)](../test/driver/src/ntl.cpp#L156) + * ntl::shared_lock [(tested)](../test/driver/src/ntl.cpp#L179) ## Requirements @@ -187,7 +206,7 @@ crtsys의 장점은 아래와 같습니다. * 14.26.28801 * 14.29.30133 * 14.31.31103 -* Windows Kit (SDK, WDK) +* Windows Kits (SDK, WDK) * 10.0.17763.0 * 10.0.18362.0 * 10.0.22000.0 @@ -281,7 +300,7 @@ SDK와 WDK의 버전이 다르면 빌드가 실패할 가능성이 높으므로 include(cmake/CPM.cmake) set(CRTSYS_NTL_MAIN ON) # use ntl::main - CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.8") + CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.9") include(${crtsys_SOURCE_DIR}/cmake/CrtSys.cmake) # add driver diff --git a/include/.internal/version b/include/.internal/version index dbd8899..3e61032 100644 --- a/include/.internal/version +++ b/include/.internal/version @@ -26,6 +26,6 @@ Environment: #define CRTSYS_VERSION_MAJOR 0 #define CRTSYS_VERSION_MINOR 1 -#define CRTSYS_VERSION_PATCH 8 +#define CRTSYS_VERSION_PATCH 9 #endif // _CRTSYS_VERSION_ \ No newline at end of file diff --git a/include/ntl/irql b/include/ntl/irql new file mode 100644 index 0000000..db0dadb --- /dev/null +++ b/include/ntl/irql @@ -0,0 +1,73 @@ +/** + * @file irql + * @author jungkwang.lee (ntoskrnl7@google.com) + * @brief KIRQL Helper features. + * + * @copyright Copyright (c) 2022 NT Template Library Authoers. + * + */ + +#ifndef _NTDDK_ +#include +#endif + +namespace ntl { +enum irql : KIRQL { + passive = PASSIVE_LEVEL, + low = passive, + apc = APC_LEVEL, + dispatch = DISPATCH_LEVEL, + dpc = dispatch, +#if defined(_X86_) || defined(_AMD64_) + cmci = CMCI_LEVEL, +#endif + clock = CLOCK_LEVEL, + ipi = IPI_LEVEL, + drs = DRS_LEVEL, + power = POWER_LEVEL, + profile = PROFILE_LEVEL, +#if defined(_X86_) + clock1 = CLOCK1_LEVEL, + clock2 = CLOCK2_LEVEL, +#endif + high = HIGH_LEVEL +}; + +struct to_dpc_level_t { + explicit to_dpc_level_t() = default; +}; + +struct to_synch_level_t { + explicit to_synch_level_t() = default; +}; + +_INLINE_VAR constexpr to_dpc_level_t to_dpc_level{}; +_INLINE_VAR constexpr to_synch_level_t to_synch_level{}; + +class raised_irql { +public: + raised_irql(to_dpc_level_t) : old_irql_(KeRaiseIrqlToDpcLevel()) {} + raised_irql(to_synch_level_t) : old_irql_(KeRaiseIrqlToSynchLevel()) {} + raised_irql(irql irql) { KeRaiseIrql(static_cast(irql), &old_irql_); } + + ~raised_irql() { KeLowerIrql(old_irql_); } + + raised_irql(const raised_irql &) = delete; + raised_irql &operator=(const raised_irql &) = delete; + + irql old() const { return static_cast(old_irql_); } + +private: + KIRQL old_irql_; +}; + +raised_irql raise_irql(KIRQL irql) { + return raised_irql{static_cast(irql)}; +} + +raised_irql raise_irql_to_dpc_level() { return raised_irql{to_dpc_level}; } + +raised_irql raise_irql_to_synch_level() { return raised_irql{to_synch_level}; } + +ntl::irql current_irql() { return static_cast(KeGetCurrentIrql()); } +} // namespace ntl \ No newline at end of file diff --git a/include/ntl/resource b/include/ntl/resource new file mode 100644 index 0000000..9985dfa --- /dev/null +++ b/include/ntl/resource @@ -0,0 +1,285 @@ + +/** + * @file resource + * @author jungkwang.lee (ntoskrnl7@google.com) + * @brief ERESOURCE Helper features. + * + * @copyright Copyright (c) 2022 NT Template Library Authoers. + * + */ + +#ifndef _NTDDK_ +#include +#endif + +#include + +namespace ntl { +namespace detail { +namespace resource { +extern NPAGED_LOOKASIDE_LIST lookaside; +} // namespace resource +} // namespace detail + +class resource { + friend class unique_lock; + +public: + resource() { + res_ = reinterpret_cast( + ExAllocateFromNPagedLookasideList(&detail::resource::lookaside)); + if (res_) + ExInitializeResourceLite(res_); + } + + ~resource() { + if (res_) { + ExDeleteResourceLite(res_); + ExFreeToNPagedLookasideList(&detail::resource::lookaside, res_); + } + } + + resource(const resource &) = delete; + resource &operator=(const resource &) = delete; + + _NODISCARD bool try_lock() { + if (res_ == NULL) + return false; + KeEnterCriticalRegion(); + bool locked = ExAcquireResourceExclusiveLite(res_, FALSE) == TRUE; + if (!locked) + KeLeaveCriticalRegion(); + return locked; + } + + _NODISCARD bool try_lock_shared() { + if (res_ == NULL) + return false; + KeEnterCriticalRegion(); + bool locked = ExAcquireResourceSharedLite(res_, FALSE) == TRUE; + if (!locked) + KeLeaveCriticalRegion(); + return locked; + } + + void lock() { + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(res_, TRUE); + } + + void unlock() { + ExReleaseResourceLite(res_); + KeLeaveCriticalRegion(); + } + + void lock_shared() { + KeEnterCriticalRegion(); + ExAcquireResourceSharedLite(res_, TRUE); + } + + void unlock_shared() { unlock(); } + + bool locked() const { return ExIsResourceAcquiredSharedLite(res_) == TRUE; } + + bool locked_exclusive() const { + return ExIsResourceAcquiredExclusiveLite(res_) == TRUE; + } + + bool locked_shared() const { return (!locked_exclusive()) && locked(); } + + void lock_no_critical_region(bool wait = true) { + ExAcquireResourceExclusiveLite(res_, wait ? TRUE : FALSE); + } + void lock_shared_no_critical_region(bool wait = true) { + ExAcquireResourceSharedLite(res_, wait ? TRUE : FALSE); + } + void unlock_no_critical_region() { ExReleaseResourceLite(res_); } + void unlock_shared_no_critical_region() { unlock_no_critical_region(); } + + void convert_to_shared() { + if (!locked_exclusive()) + throw std::runtime_error(""); + ExConvertExclusiveToSharedLite(res_); + } + + size_t waiter_count() const { + return static_cast(ExGetExclusiveWaiterCount(res_)); + } + + size_t shared_waiter_count() const { + return static_cast(ExGetSharedWaiterCount(res_)); + } + + using native_handle_type = PERESOURCE; + + _NODISCARD native_handle_type native_handle() { return res_; } + +private: + PERESOURCE res_; +}; + +struct adopt_critical_region_t { + explicit adopt_critical_region_t() = default; +}; + +_INLINE_VAR constexpr adopt_critical_region_t adopt_critical_region{}; + +template class unique_lock; +template class shared_lock; + +template <> class unique_lock : public std::unique_lock { + friend class shared_lock; + +public: + using lock_type = resource; + using type = std::unique_lock; + using type::type; + + unique_lock() noexcept : lockable_(nullptr), owns_(false) {} + + _NODISCARD_CTOR unique_lock(lock_type &lockable, std::adopt_lock_t) + : std::unique_lock(lockable, std::adopt_lock), + lockable_(nullptr), owns_(false) { + } // construct and assume already locked + + unique_lock(lock_type &lockable, std::defer_lock_t) noexcept + : std::unique_lock(lockable, std::defer_lock), + lockable_(nullptr), owns_(false) {} // construct but don't lock + + _NODISCARD_CTOR unique_lock(lock_type &lockable, std::try_to_lock_t) + : std::unique_lock(lockable, std::try_to_lock), + lockable_(nullptr), owns_(false) {} // construct and try to lock + + _NODISCARD_CTOR unique_lock(lock_type &lockable, adopt_critical_region_t) + : std::unique_lock(lockable, std::defer_lock), + lockable_(std::addressof(lockable)), owns_(false) { + lockable.lock_no_critical_region(); + owns_ = true; + } // construct but don't enter critical region + + unique_lock &operator=(unique_lock &&other) { + if (this != _STD addressof(other)) { + if (owns_) + lockable_->unlock_no_critical_region(); + else if (std::unique_lock::owns_lock()) + std::unique_lock::unlock(); + lockable_ = other.lockable_; + owns_ = other.owns_; + other.lockable_ = nullptr; + other.owns_ = false; + std::unique_lock::operator=( + std::forward>(other)); + } + return *this; + } + + ~unique_lock() noexcept { + if (owns_) + lockable_->unlock_no_critical_region(); + } + + unique_lock(const unique_lock &) = delete; + unique_lock &operator=(const unique_lock &) = delete; + + _NODISCARD bool owns_lock() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + + explicit operator bool() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + +protected: + bool owns_; + lock_type *lockable_; +}; + +template <> class shared_lock : public std::shared_lock { +public: + using lock_type = resource; + using type = std::shared_lock; + using type::type; + + shared_lock() noexcept : lockable_(nullptr), owns_(false) {} + + _NODISCARD_CTOR explicit shared_lock(lock_type &lockable) + : lockable_(_STD addressof(lockable)), + owns_(true) { // construct with mutex and lock shared + lockable.lock_shared(); + } + + shared_lock(lock_type &lockable, std::defer_lock_t) noexcept + : std::shared_lock(lockable, std::defer_lock), + lockable_(_STD addressof(lockable)), owns_(false) { + } // construct with unlocked mutex + + _NODISCARD_CTOR shared_lock(lock_type &lockable, std::try_to_lock_t) + : std::shared_lock(lockable, std::try_to_lock), + lockable_(_STD addressof(lockable)), owns_(lockable.try_lock_shared()) { + } // construct with mutex and try to lock shared + + _NODISCARD_CTOR shared_lock(lock_type &lockable, std::adopt_lock_t) + : std::shared_lock(lockable, std::adopt_lock), + lockable_(_STD addressof(lockable)), owns_(true) { + } // construct with mutex and adopt ownership + + _NODISCARD_CTOR shared_lock(lock_type &lockable, adopt_critical_region_t) + : std::shared_lock(lockable, std::defer_lock), + lockable_(std::addressof(lockable)), owns_(false) { + lockable.lock_shared_no_critical_region(); + owns_ = true; + } // construct but don't enter critical region + + _NODISCARD_CTOR shared_lock(unique_lock &lock) + : std::shared_lock(*lock.mutex(), std::defer_lock), + lockable_(lock.mutex()), owns_(false) { + lock.mutex()->convert_to_shared(); + lock.owns_ = false; + owns_ = true; + } // construct with convert lock exclusive to lock shared + + shared_lock &operator=(shared_lock &&other) { + if (this != _STD addressof(other)) { + if (owns_) + lockable_->unlock_no_critical_region(); + else if (std::shared_lock::owns_lock()) + std::shared_lock::unlock(); + lockable_ = other.lockable_; + owns_ = other.owns_; + other.lockable_ = nullptr; + other.owns_ = false; + std::shared_lock::operator=( + std::forward>(other)); + } + return *this; + } + + ~shared_lock() noexcept { + if (owns_) + lockable_->unlock_shared_no_critical_region(); + } + + shared_lock(const shared_lock &) = delete; + shared_lock &operator=(const shared_lock &) = delete; + + _NODISCARD bool owns_lock() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + + explicit operator bool() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + +private: + bool owns_; + lock_type *lockable_; +}; +} // namespace ntl \ No newline at end of file diff --git a/include/ntl/spin_lock b/include/ntl/spin_lock new file mode 100644 index 0000000..18f9965 --- /dev/null +++ b/include/ntl/spin_lock @@ -0,0 +1,141 @@ +/** + * @file spin_lock + * @author jungkwang.lee (ntoskrnl7@google.com) + * @brief KSPIN_LOCK Helper features. + * + * @copyright Copyright (c) 2022 NT Template Library Authoers. + * + */ + +#ifndef _NTDDK_ +#include +#endif + +#include + +namespace ntl { +namespace detail { +namespace spin_lock { +extern NPAGED_LOOKASIDE_LIST lookaside; +} +} // namespace detail + +class spin_lock { +public: + spin_lock() { + lock_ = reinterpret_cast( + ExAllocateFromNPagedLookasideList(&ntl::detail::spin_lock::lookaside)); + KeInitializeSpinLock(lock_); + } + ~spin_lock() { + if (lock_) + ExFreeToNPagedLookasideList(&ntl::detail::spin_lock::lookaside, lock_); + } + spin_lock(const spin_lock &) = delete; + spin_lock &operator=(const spin_lock &) = delete; + + _NODISCARD bool try_lock() { + return KeTryToAcquireSpinLockAtDpcLevel(lock_) == TRUE; + } + + void lock() { KeAcquireSpinLock(lock_, &old_irql_); } + void unlock() { KeReleaseSpinLock(lock_, old_irql_); } + + void lock_at_dpc_level() { KeAcquireSpinLockAtDpcLevel(lock_); } + void unlock_from_dpc_level() { KeReleaseSpinLockFromDpcLevel(lock_); } + + bool test() { return KeTestSpinLock(lock_); } + + using native_handle_type = PKSPIN_LOCK; + + _NODISCARD native_handle_type native_handle() { return lock_; } + +private: + PKSPIN_LOCK lock_; + KIRQL old_irql_; +}; + +struct at_dpc_level_lock_t { + explicit at_dpc_level_lock_t() = default; +}; + +_INLINE_VAR constexpr at_dpc_level_lock_t at_dpc_level_lock{}; + +template class unique_lock; + +template <> class unique_lock : public std::unique_lock { +public: + using lock_type = spin_lock; + using type = std::unique_lock; + using type::type; + + unique_lock() noexcept : lockable_(nullptr), owns_(false) {} + + _NODISCARD_CTOR explicit unique_lock(spin_lock &lockable) + : lockable_(_STD addressof(lockable)), + owns_(false) { // construct and lock + lockable_->lock(); + owns_ = true; + } + + _NODISCARD_CTOR unique_lock(lock_type &lockable, std::adopt_lock_t) + : std::unique_lock(lockable, std::adopt_lock), + lockable_(nullptr), owns_(false) { + } // construct and assume already locked + + unique_lock(lock_type &lockable, std::defer_lock_t) noexcept + : std::unique_lock(lockable, std::defer_lock), + lockable_(nullptr), owns_(false) {} // construct but don't lock + + _NODISCARD_CTOR unique_lock(lock_type &lockable, std::try_to_lock_t) + : std::unique_lock(lockable, std::try_to_lock), + lockable_(nullptr), owns_(false) {} // construct and try to lock + + _NODISCARD_CTOR unique_lock(lock_type &lockable, at_dpc_level_lock_t) + : std::unique_lock(lockable, std::defer_lock), + lockable_(std::addressof(lockable)), owns_(false) { + lockable.lock_at_dpc_level(); + owns_ = true; + } // construct and lock at dpc + + unique_lock &operator=(unique_lock &&other) { + if (this != _STD addressof(other)) { + if (owns_) + lockable_->unlock(); + else if (std::unique_lock::owns_lock()) + std::unique_lock::unlock(); + lockable_ = other.lockable_; + owns_ = other.owns_; + other.lockable_ = nullptr; + other.owns_ = false; + std::unique_lock::operator=( + std::forward>(other)); + } + return *this; + } + + ~unique_lock() noexcept { + if (owns_) + lockable_->unlock_from_dpc_level(); + } + + unique_lock(const unique_lock &) = delete; + unique_lock &operator=(const unique_lock &) = delete; + + _NODISCARD bool owns_lock() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + + explicit operator bool() const noexcept { + if (owns_) + return true; + return type::owns_lock(); + } + +private: + bool owns_; + lock_type *lockable_; +}; +} // namespace ntl \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index b639171..f1015d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -242,6 +242,17 @@ class driver_initializer { }; } // namespace ntl +namespace ntl { +namespace detail { +namespace resource { +NPAGED_LOOKASIDE_LIST lookaside; +} +namespace spin_lock { +NPAGED_LOOKASIDE_LIST lookaside; +} +} // namespace detail +} // namespace ntl + EXTERN_C NTSTATUS CrtSysDriverEntry(_In_ PDRIVER_OBJECT DriverObject, @@ -274,14 +285,23 @@ CrtSysDriverEntry(_In_ PDRIVER_OBJECT DriverObject, return status; } #endif + + ExInitializeNPagedLookasideList(&ntl::detail::resource::lookaside, NULL, NULL, + 0, sizeof(ERESOURCE), 'srsc', 0); + ExInitializeNPagedLookasideList(&ntl::detail::spin_lock::lookaside, NULL, + NULL, 0, sizeof(KSPIN_LOCK), 'lpsc', 0); if (!__scrt_initialize_onexit_tables(__scrt_module_type::exe)) { KdBreakPoint(); + ExDeleteNPagedLookasideList(&ntl::detail::resource::lookaside); + ExDeleteNPagedLookasideList(&ntl::detail::spin_lock::lookaside); LdkTerminate(); return STATUS_FAILED_DRIVER_ENTRY; } if (!__scrt_initialize_crt(__scrt_module_type::exe)) { KdBreakPoint(); + ExDeleteNPagedLookasideList(&ntl::detail::resource::lookaside); + ExDeleteNPagedLookasideList(&ntl::detail::spin_lock::lookaside); LdkTerminate(); return STATUS_FAILED_DRIVER_ENTRY; } @@ -310,6 +330,7 @@ CrtSysDriverEntry(_In_ PDRIVER_OBJECT DriverObject, ntl::status s = ntl::expand_stack(ntl::main, std::ref(*driver.get()), std::wstring(RegistryPath->Buffer)); if (!s.is_ok()) { + driver.release(); CrtSysDriverUnload(DriverObject); return s; } @@ -385,5 +406,7 @@ CrtSysDriverUnload ( ); CrtSyspUninitializeForLibcntpr(); #endif + ExDeleteNPagedLookasideList(&ntl::detail::resource::lookaside); + ExDeleteNPagedLookasideList(&ntl::detail::spin_lock::lookaside); LdkTerminate(); } \ No newline at end of file diff --git a/test/driver/src/all.cpp b/test/driver/src/all.cpp index c3f8f44..08757c4 100644 --- a/test/driver/src/all.cpp +++ b/test/driver/src/all.cpp @@ -61,7 +61,11 @@ void run(); // bool ntl_expand_stack_test(); -bool ntl_rpc(); +bool ntl_irql_test(); + +bool ntl_spin_lock_test(); + +bool ntl_resource_test(); // // C Standard tests. @@ -118,10 +122,18 @@ void ntl_test() { if (!ntl_expand_stack_test()) { std::cerr << "ntl_expand_stack_test failed\n"; } + if (!ntl_irql_test()) { + std::cerr << "ntl_irql_test failed\n"; + } + if (!ntl_spin_lock_test()) { + std::cerr << "ntl_spin_lock_test failed\n"; + } + if (!ntl_resource_test()) { + std::cerr << "ntl_resource_test failed\n"; + } } void test_all() { - ntl_test(); c_std_tests(); diff --git a/test/driver/src/main.cpp b/test/driver/src/main.cpp index 289b537..e21a9df 100644 --- a/test/driver/src/main.cpp +++ b/test/driver/src/main.cpp @@ -46,7 +46,6 @@ ntl::status ntl::main(ntl::driver &driver, const std::wstring ®istry_path) { .name(TEST_DEVICE_NAME) .type(FILE_DEVICE_UNKNOWN) .exclusive()); - if (test_dev) { test_dev->extension().val = 100; test_dev->extension().inc(); @@ -70,6 +69,7 @@ ntl::status ntl::main(ntl::driver &driver, const std::wstring ®istry_path) { } }); } + driver.on_unload([registry_path, test_dev, rpc_svr = test_rpc::init(driver)]() mutable { if (test_dev) diff --git a/test/driver/src/ntl.cpp b/test/driver/src/ntl.cpp index 565eb3e..9d93565 100644 --- a/test/driver/src/ntl.cpp +++ b/test/driver/src/ntl.cpp @@ -41,9 +41,246 @@ bool ntl_expand_stack_test() { return !(t1.empty() || t2.empty() || t3.empty()); } +#include + +bool ntl_irql_test() { + auto old_irql = ntl::current_irql(); + { + auto raised_irql = ntl::raise_irql(ntl::irql::apc); + + if (old_irql != raised_irql.old()) + return false; + + if (ntl::current_irql() != ntl::irql::apc) + return false; + } + if (ntl::current_irql() != old_irql) + return false; + + old_irql = ntl::current_irql(); + { + auto raised_irql = ntl::raise_irql_to_dpc_level(); + if (old_irql != raised_irql.old()) + return false; + + if (ntl::current_irql() != ntl::irql::dispatch) + return false; + } + return (ntl::current_irql() == old_irql); +} + +#include + +bool ntl_spin_lock_test() { + ntl::spin_lock lock; + ntl::spin_lock lock2; + + if (!lock.test()) + return false; + + if (!lock2.test()) + return false; + + std::unique_lock lk(lock); + if (!lk.owns_lock()) + return false; + + std::unique_lock lk2(lock, std::try_to_lock); + if (lk2.owns_lock()) + return false; + + { + ntl::unique_lock nlk(lock2, ntl::at_dpc_level_lock); + if (!nlk.owns_lock()) + return false; + if (lock2.test()) + return false; + + ntl::unique_lock nlk2(lock2, std::try_to_lock); + if (nlk2.owns_lock()) + return false; + } + if (!lock2.test()) + return false; + + return KeTestSpinLock(lock.native_handle()) == FALSE; +} + +#include + +bool ntl_resource_test() { + ntl::resource res; + { + std::shared_lock lk(res); + if (!lk.owns_lock()) + return false; + if (!res.locked_shared()) + return false; + + std::unique_lock lk2(res, std::try_to_lock); + if (lk2.owns_lock()) + return false; + if (res.locked_exclusive()) + return false; + } + if (res.locked_exclusive()) + return false; + + if (res.locked_shared()) + return false; + + ntl::resource res2; + std::unique_lock lk3(res); + if (!lk3.owns_lock()) + return false; + if (!res.locked_exclusive()) + return false; + + std::shared_lock lk4(res, std::try_to_lock); + if (!lk4.owns_lock()) + return false; + if (res.locked_shared()) + return false; + + std::shared_lock lk5(res2); + if (!lk5.owns_lock()) + return false; + if (!res2.locked_shared()) + return false; + + ntl::resource res3; + ntl::shared_lock lk6(res3, ntl::adopt_critical_region); + if (!lk6.owns_lock()) + return false; + return res3.locked_shared(); +} + // // Google Test. // #include -TEST(ntl_test, ntl_expand_stack_test) { EXPECT_TRUE(ntl_expand_stack_test()); } \ No newline at end of file +TEST(ntl_test, ntl_expand_stack_test) { + long result = 0; + ntl::expand_stack( + [&result](int i, long l, double d) { result = (long)(i + l + d); }, 1, 2, + 3.0); + EXPECT_EQ(result, 6); + + result = ntl::expand_stack( + [](int i, long l, double d) -> long { return (long)(i + l + d); }, 1, 2, + 3.0); + EXPECT_EQ(result, 6); + + std::string t1; + std::string t2; + std::string t3; + + ntl::expand_stack([&] { + try { + throw std::bad_alloc(); + } catch (const std::exception &e) { + try { + t1 = e.what(); + throw std::bad_array_new_length(); + } catch (const std::exception &e) { + try { + t2 = e.what(); + throw std::runtime_error("test"); + } catch (const std::runtime_error &e) { + t3 = e.what(); + } catch (const std::exception &) { + } + } + } + }); + EXPECT_FALSE(t1.empty() && t2.empty() && t3.empty()); +} + +TEST(ntl_test, ntl_irql_test) { + auto old_irql = ntl::current_irql(); + { + auto raised_irql = ntl::raise_irql(ntl::irql::apc); + EXPECT_EQ(old_irql, raised_irql.old()); + EXPECT_EQ(ntl::current_irql(), ntl::irql::apc); + } + EXPECT_EQ(ntl::current_irql(), old_irql); + + old_irql = ntl::current_irql(); + { + auto raised_irql = ntl::raise_irql_to_dpc_level(); + EXPECT_EQ(old_irql, raised_irql.old()); + + EXPECT_EQ(ntl::current_irql(), ntl::irql::dispatch); + } + + EXPECT_EQ(ntl::current_irql(), old_irql); +} + +TEST(ntl_test, ntl_spin_lock_test) { + ntl::spin_lock lock; + ntl::spin_lock lock2; + { + EXPECT_TRUE(lock.test()); + + std::unique_lock lk(lock); + EXPECT_FALSE(lock.test()); + EXPECT_TRUE(lk.owns_lock()); + + std::unique_lock lk2(lock, std::try_to_lock); + EXPECT_FALSE(lock.test()); + EXPECT_FALSE(lk2.owns_lock()); + + ntl::unique_lock lk3(lock2, ntl::at_dpc_level_lock); + EXPECT_FALSE(lock2.test()); + EXPECT_TRUE(lk3.owns_lock()); + } + EXPECT_TRUE(lock.test()); + EXPECT_TRUE(KeTestSpinLock(lock.native_handle())); +} + +TEST(ntl_test, ntl_resource_test) { + ntl::resource res; + { + std::shared_lock lk(res); + EXPECT_TRUE(lk.owns_lock()); + EXPECT_TRUE(res.locked()); + EXPECT_TRUE(res.locked_shared()); + + std::unique_lock lk2(res, std::try_to_lock); + EXPECT_FALSE(lk2.owns_lock()); + EXPECT_FALSE(res.locked_exclusive()); + } + EXPECT_FALSE(res.locked()); + EXPECT_FALSE(res.locked_exclusive()); + EXPECT_FALSE(res.locked_shared()); + + ntl::resource res2; + std::unique_lock lk3(res); + EXPECT_TRUE(lk3.owns_lock()); + EXPECT_TRUE(res.locked()); + EXPECT_TRUE(res.locked_exclusive()); + + std::shared_lock lk4(res, std::try_to_lock); + EXPECT_TRUE(lk4.owns_lock()); + EXPECT_FALSE(res.locked_shared()); + + ntl::unique_lock lk5(res2, ntl::adopt_critical_region); + EXPECT_TRUE(lk5.owns_lock()); + EXPECT_TRUE(res2.locked()); + EXPECT_TRUE(res2.locked_exclusive()); + EXPECT_FALSE(res2.locked_shared()); + + ntl::shared_lock lk7(lk5); + EXPECT_FALSE(lk5.owns_lock()); + EXPECT_TRUE(lk7.owns_lock()); + EXPECT_TRUE(res2.locked()); + EXPECT_TRUE(res2.locked_shared()); + EXPECT_FALSE(res2.locked_exclusive()); + + ntl::resource res3; + ntl::shared_lock lk6(res3, ntl::adopt_critical_region); + EXPECT_TRUE(lk6.owns_lock()); + EXPECT_TRUE(res3.locked()); + EXPECT_TRUE(res3.locked_shared()); +} \ No newline at end of file From 43ce703b5b1a6e9e3d670c947f0b945fc664c76a Mon Sep 17 00:00:00 2001 From: Jung-Kwang Lee Date: Tue, 23 Aug 2022 21:56:54 +0900 Subject: [PATCH 2/4] Fix code --- include/ntl/irql | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ntl/irql b/include/ntl/irql index db0dadb..5f8cce5 100644 --- a/include/ntl/irql +++ b/include/ntl/irql @@ -23,7 +23,9 @@ enum irql : KIRQL { #endif clock = CLOCK_LEVEL, ipi = IPI_LEVEL, +#if !defined(_X86_) drs = DRS_LEVEL, +#endif power = POWER_LEVEL, profile = PROFILE_LEVEL, #if defined(_X86_) From 91b57fa89beb404b2e258e17c0599125bde15f3e Mon Sep 17 00:00:00 2001 From: Jung-Kwang Lee Date: Wed, 24 Aug 2022 17:23:26 +0900 Subject: [PATCH 3/4] WDK 10.0.22621.0 MSVC 14.33.31629 --- CMakeLists.txt | 2 +- README.md | 4 +- docs/ko-kr.md | 4 +- include/.internal/version | 2 +- src/custom/crt/fenv/fenv.c | 2 + src/custom/misc/winapi.cpp | 108 +++++++++++++++++- .../143/crt/src/vcruntime/frame_redirect.cpp | 9 +- src/custom/msvc/crt.props | 2 +- .../inc/corecrt_internal_state_isolation.h | 83 ++++++++++++++ src/custom/ucrt/10.0.22621.0/inc/nt.h | 5 + src/custom/ucrt/10.0.22621.0/inc/ntrtl.h | 0 src/custom/ucrt/10.0.22621.0/inc/nturtl.h | 0 src/custom/winsdk/include/um/crtsys/Windows.h | 1 + .../winsdk/include/um/crtsys/combaseapi.h | 10 ++ src/custom/winsdk/include/um/crtsys/fileapi.h | 36 ++++++ .../winsdk/include/um/crtsys/synchapi.h | 33 ++++++ src/main.cpp | 3 +- src/ucrt.props | 5 +- src/vcruntime.props | 11 +- test/driver/src/main.cpp | 4 +- test/driver/src/ntl.cpp | 45 ++++++-- 21 files changed, 344 insertions(+), 25 deletions(-) create mode 100644 src/custom/ucrt/10.0.22621.0/inc/corecrt_internal_state_isolation.h create mode 100644 src/custom/ucrt/10.0.22621.0/inc/nt.h create mode 100644 src/custom/ucrt/10.0.22621.0/inc/ntrtl.h create mode 100644 src/custom/ucrt/10.0.22621.0/inc/nturtl.h create mode 100644 src/custom/winsdk/include/um/crtsys/combaseapi.h create mode 100644 src/custom/winsdk/include/um/crtsys/synchapi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index afec782..df4f3ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ else() set(LDK_USE_RAISE_EXCEPTION OFF) set(LDK_USE_RTL_RAISE_EXCEPTION OFF) endif() -CPMAddPackage("gh:ntoskrnl7/Ldk@0.7.4") +CPMAddPackage("gh:ntoskrnl7/Ldk@0.7.5") CPMAddPackage("gh:ntoskrnl7/FindWDK#master") list(APPEND CMAKE_MODULE_PATH "${FindWDK_SOURCE_DIR}/cmake") diff --git a/README.md b/README.md index 80a5b94..9a00d40 100644 --- a/README.md +++ b/README.md @@ -206,10 +206,12 @@ Provides features to support a better development environment in the kernel. * 14.26.28801 * 14.29.30133 * 14.31.31103 + * 14.33.31629 * Windows Kits (SDK, WDK) * 10.0.17763.0 * 10.0.18362.0 * 10.0.22000.0 + * 10.0.22621.0 If the SDK and WDK versions are different, builds are more likely to fail. **If possible, it is recommended to build in the same environment as the SDK and WDK versions.** @@ -300,7 +302,7 @@ If the SDK and WDK versions are different, builds are more likely to fail. **If include(cmake/CPM.cmake) set(CRTSYS_NTL_MAIN ON) # use ntl::main - CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.9") + CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.10") include(${crtsys_SOURCE_DIR}/cmake/CrtSys.cmake) # add driver diff --git a/docs/ko-kr.md b/docs/ko-kr.md index 2fc8a01..9a4d198 100644 --- a/docs/ko-kr.md +++ b/docs/ko-kr.md @@ -206,10 +206,12 @@ crtsys의 장점은 아래와 같습니다. * 14.26.28801 * 14.29.30133 * 14.31.31103 + * 14.33.31629 * Windows Kits (SDK, WDK) * 10.0.17763.0 * 10.0.18362.0 * 10.0.22000.0 + * 10.0.22621.0 SDK와 WDK의 버전이 다르면 빌드가 실패할 가능성이 높으므로 **가능하다면 SDK와 WDK의 버전이 같은 환경에서 빌드하는것을 권장합니다.** @@ -300,7 +302,7 @@ SDK와 WDK의 버전이 다르면 빌드가 실패할 가능성이 높으므로 include(cmake/CPM.cmake) set(CRTSYS_NTL_MAIN ON) # use ntl::main - CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.9") + CPMAddPackage("gh:ntoskrnl7/crtsys@0.1.10") include(${crtsys_SOURCE_DIR}/cmake/CrtSys.cmake) # add driver diff --git a/include/.internal/version b/include/.internal/version index 3e61032..8efd130 100644 --- a/include/.internal/version +++ b/include/.internal/version @@ -26,6 +26,6 @@ Environment: #define CRTSYS_VERSION_MAJOR 0 #define CRTSYS_VERSION_MINOR 1 -#define CRTSYS_VERSION_PATCH 9 +#define CRTSYS_VERSION_PATCH 10 #endif // _CRTSYS_VERSION_ \ No newline at end of file diff --git a/src/custom/crt/fenv/fenv.c b/src/custom/crt/fenv/fenv.c index b41dc5c..da1e085 100644 --- a/src/custom/crt/fenv/fenv.c +++ b/src/custom/crt/fenv/fenv.c @@ -56,9 +56,11 @@ CrtSyspSaveXState ( { PXSTATE_SAVE StateSave = (PXSTATE_SAVE)FlsGetValue( CrtSyspFlsXStateSaveIndex ); if (StateSave == NULL) { +#pragma warning(disable:4996) StateSave = ExAllocatePoolWithTag( NonPagedPool, sizeof(XSTATE_SAVE), 'ttsX' ); +#pragma warning(default:4996) if (StateSave == NULL) { return NULL; } diff --git a/src/custom/misc/winapi.cpp b/src/custom/misc/winapi.cpp index 188735f..7f2a481 100644 --- a/src/custom/misc/winapi.cpp +++ b/src/custom/misc/winapi.cpp @@ -220,4 +220,110 @@ EnumSystemLocalesW ( return FALSE; } -EXTERN_C_END \ No newline at end of file +// +// https://github.com/ntoskrnl7/crtsys/issues/23 +// +// Windows Kits\10\Include\10.0.22621.0\winrt\wrl\wrappers\corewrappers.h +// Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.34.31721\crt\src\stl\ppltasks.cpp +// +// MutexTraits::Lock, SemaphoreTraits::Lock +// +WINBASEAPI +BOOL +WINAPI +ReleaseSemaphore ( + _In_ HANDLE hSemaphore, + _In_ LONG lReleaseCount, + _Out_opt_ LPLONG lpPreviousCount + ) +{ + KdBreakPoint(); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} + +WINBASEAPI +BOOL +WINAPI +ReleaseMutex ( + _In_ HANDLE hMutex + ) +{ + KdBreakPoint(); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} + +#ifdef WINOLEAPI +#undef WINOLEAPI +#endif +#ifdef WINOLEAPI_ +#undef WINOLEAPI_ +#endif + +#ifdef _OLE32_ +#define WINOLEAPI STDAPI +#define WINOLEAPI_(type) STDAPI_(type) +#else + +#ifdef _68K_ +#ifndef REQUIRESAPPLEPASCAL +#define WINOLEAPI EXTERN_C HRESULT PASCAL +#define WINOLEAPI_(type) EXTERN_C type PASCAL +#else +#define WINOLEAPI EXTERN_C PASCAL HRESULT +#define WINOLEAPI_(type) EXTERN_C PASCAL type +#endif +#else +#define WINOLEAPI EXTERN_C HRESULT STDAPICALLTYPE +#define WINOLEAPI_(type) EXTERN_C type STDAPICALLTYPE +#endif + +#endif + +_Check_return_ +WINOLEAPI +CoGetObjectContext( + _In_ REFIID riid, + _Outptr_ LPVOID FAR * ppv + ) +{ + KdBreakPoint(); + return E_NOTIMPL; +} + +typedef +enum _APTTYPEQUALIFIER + { + APTTYPEQUALIFIER_NONE = 0, + APTTYPEQUALIFIER_IMPLICIT_MTA = 1, + APTTYPEQUALIFIER_NA_ON_MTA = 2, + APTTYPEQUALIFIER_NA_ON_STA = 3, + APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 4, + APTTYPEQUALIFIER_NA_ON_MAINSTA = 5, + APTTYPEQUALIFIER_APPLICATION_STA = 6, + APTTYPEQUALIFIER_RESERVED_1 = 7 + } APTTYPEQUALIFIER; + +typedef +enum _APTTYPE + { + APTTYPE_CURRENT = -1, + APTTYPE_STA = 0, + APTTYPE_MTA = 1, + APTTYPE_NA = 2, + APTTYPE_MAINSTA = 3 + } APTTYPE; + +_Check_return_ +WINOLEAPI +CoGetApartmentType( + _Out_ APTTYPE* pAptType, + _Out_ APTTYPEQUALIFIER* pAptQualifier + ) +{ + KdBreakPoint(); + return E_NOTIMPL; +} + +EXTERN_C_END diff --git a/src/custom/msvc/143/crt/src/vcruntime/frame_redirect.cpp b/src/custom/msvc/143/crt/src/vcruntime/frame_redirect.cpp index a180924..7a285ce 100644 --- a/src/custom/msvc/143/crt/src/vcruntime/frame_redirect.cpp +++ b/src/custom/msvc/143/crt/src/vcruntime/frame_redirect.cpp @@ -1,4 +1,11 @@ -#include +// +// MSVC\14.33.31629\include\eh.h +// _VCRT_COMPILER_PREPROCESSOR가 1이면서 _VCRT_BUILD가 정의되어있어야 unexpected 함수가 정의됩니다. +// +#define _VCRT_COMPILER_PREPROCESSOR 1 +#define _VCRT_BUILD + +#include #include #include #include diff --git a/src/custom/msvc/crt.props b/src/custom/msvc/crt.props index 4d3b0d9..acfef42 100644 --- a/src/custom/msvc/crt.props +++ b/src/custom/msvc/crt.props @@ -18,7 +18,7 @@ Cdecl - + Cdecl diff --git a/src/custom/ucrt/10.0.22621.0/inc/corecrt_internal_state_isolation.h b/src/custom/ucrt/10.0.22621.0/inc/corecrt_internal_state_isolation.h new file mode 100644 index 0000000..fec7738 --- /dev/null +++ b/src/custom/ucrt/10.0.22621.0/inc/corecrt_internal_state_isolation.h @@ -0,0 +1,83 @@ +#pragma once + +#define __acrt_select_exit_lock() __acrt_exit_lock + +#pragma warning(disable : 4101) +#ifdef __cplusplus + +extern "C++" +{ + namespace __crt_state_management + { + struct scoped_global_state_reset + { + }; + + const size_t state_index_count = 2; + + inline bool initialize_global_state_isolation() + { + return true; + } + + inline void uninitialize_global_state_isolation(bool const terminating) + { + terminating; + } + + inline int get_current_state_index() + { + return 0; + } + + inline int get_current_state_index(__crt_scoped_get_last_error_reset const &last_error_reset) + { + last_error_reset; + return 0; + } + + template class dual_state_global + { + public: + T &value() + { + return _value[0]; + } + + T &value_explicit(size_t const current_global_state_index) + { + return _value[current_global_state_index]; + } + + T &value(__crt_cached_ptd_host &ptd) throw(); + + T const &value(__crt_cached_ptd_host &ptd) const throw(); + + void initialize(const T &value) + { + for (size_t i = 0; i != state_index_count; i++) + _value[i] = value; + } + + template void initialize_from_array(Ta (&arr)[2]) + { + for (size_t i = 0; i != state_index_count; i++) + _value[i] = arr[i]; + } + + template void uninitialize(Fn &&fn) + { + for (size_t i = 0; i != state_index_count; i++) + fn(_value[i]); + } + + T *const dangerous_get_state_array() + { + return reinterpret_cast(&_value); + } + + T _value[state_index_count]; + }; + } // namespace __crt_state_management +} +#endif \ No newline at end of file diff --git a/src/custom/ucrt/10.0.22621.0/inc/nt.h b/src/custom/ucrt/10.0.22621.0/inc/nt.h new file mode 100644 index 0000000..02e4abf --- /dev/null +++ b/src/custom/ucrt/10.0.22621.0/inc/nt.h @@ -0,0 +1,5 @@ +#pragma once + +#include +#include +#include \ No newline at end of file diff --git a/src/custom/ucrt/10.0.22621.0/inc/ntrtl.h b/src/custom/ucrt/10.0.22621.0/inc/ntrtl.h new file mode 100644 index 0000000..e69de29 diff --git a/src/custom/ucrt/10.0.22621.0/inc/nturtl.h b/src/custom/ucrt/10.0.22621.0/inc/nturtl.h new file mode 100644 index 0000000..e69de29 diff --git a/src/custom/winsdk/include/um/crtsys/Windows.h b/src/custom/winsdk/include/um/crtsys/Windows.h index 4e9c4e3..d68fb67 100644 --- a/src/custom/winsdk/include/um/crtsys/Windows.h +++ b/src/custom/winsdk/include/um/crtsys/Windows.h @@ -11,6 +11,7 @@ // winbase.h #include // consoleapi.h #include "fileapi.h" +#include "synchapi.h" #include "processthreadsapi.h" // winbase.h diff --git a/src/custom/winsdk/include/um/crtsys/combaseapi.h b/src/custom/winsdk/include/um/crtsys/combaseapi.h new file mode 100644 index 0000000..7a626a3 --- /dev/null +++ b/src/custom/winsdk/include/um/crtsys/combaseapi.h @@ -0,0 +1,10 @@ +#ifndef _CRTSYS_COMBASEAPI +#define _CRTSYS_COMBASEAPI + +#pragma once + +#undef DECLSPEC_IMPORT +#define DECLSPEC_IMPORT +#include <../um/combaseapi.h> + +#endif // _CRTSYS_COMBASEAPI \ No newline at end of file diff --git a/src/custom/winsdk/include/um/crtsys/fileapi.h b/src/custom/winsdk/include/um/crtsys/fileapi.h index 7d7f3d6..ead414e 100644 --- a/src/custom/winsdk/include/um/crtsys/fileapi.h +++ b/src/custom/winsdk/include/um/crtsys/fileapi.h @@ -8,6 +8,42 @@ EXTERN_C_START +WINBASEAPI +DWORD +WINAPI +GetTempPathA( + _In_ DWORD nBufferLength, + _Out_writes_to_opt_(nBufferLength,return + 1) LPSTR lpBuffer + ); + +WINBASEAPI +DWORD +WINAPI +GetTempPathW( + _In_ DWORD nBufferLength, + _Out_writes_to_opt_(nBufferLength,return + 1) LPWSTR lpBuffer + ); + +WINBASEAPI +UINT +WINAPI +GetTempFileNameA( + _In_ LPCSTR lpPathName, + _In_ LPCSTR lpPrefixString, + _In_ UINT uUnique, + _Out_writes_(MAX_PATH) LPSTR lpTempFileName + ); + +WINBASEAPI +UINT +WINAPI +GetTempFileNameW( + _In_ LPCWSTR lpPathName, + _In_ LPCWSTR lpPrefixString, + _In_ UINT uUnique, + _Out_writes_(MAX_PATH) LPWSTR lpTempFileName + ); + // ucrt/inc/corecrt_internal.h WINBASEAPI BOOL diff --git a/src/custom/winsdk/include/um/crtsys/synchapi.h b/src/custom/winsdk/include/um/crtsys/synchapi.h new file mode 100644 index 0000000..dbceb98 --- /dev/null +++ b/src/custom/winsdk/include/um/crtsys/synchapi.h @@ -0,0 +1,33 @@ +#ifndef _CRTSYS_SYNCHAPI_H_ +#define _CRTSYS_SYNCHAPI_H_ + +#pragma once + +#include +#include +#include +#include + +EXTERN_C_START + +WINBASEAPI +BOOL +WINAPI +ReleaseSemaphore ( + _In_ HANDLE hSemaphore, + _In_ LONG lReleaseCount, + _Out_opt_ LPLONG lpPreviousCount + ); + +WINBASEAPI +BOOL +WINAPI +ReleaseMutex ( + _In_ HANDLE hMutex + ); + +EXTERN_C_END + +#include <../Ldk/synchapi.h> + +#endif // _CRTSYS_SYNCHAPI_H_ \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f1015d4..88000bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -165,10 +165,11 @@ CrtSysInitializeTebThreadLocalStoragePointer ( CrtSysSetTebThreadLocalStoragePointer(&CrtSyspTlsSlots); return STATUS_SUCCESS; } - +#pragma warning(disable:4996) PKDPC dpcs = (PKDPC)ExAllocatePoolWithTag( NonPagedPool, sizeof(KDPC) * ((SIZE_T)KeNumberProcessors - 1), 'pmeT' ); +#pragma warning(default:4996) if (dpcs == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } diff --git a/src/ucrt.props b/src/ucrt.props index 351309f..b6e0c6f 100644 --- a/src/ucrt.props +++ b/src/ucrt.props @@ -224,7 +224,10 @@ $(IntDir)ucrt\%(FileName).obj Cdecl - + + %(PreprocessorDefinitions);_STL_COMPILER_PREPROCESSOR=0;_CORECRT_BUILD;_CRT_GLOBAL_STATE_ISOLATION;_CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY;__WARNING_UNUSED_ASSIGNMENT=28931 + Cdecl + %(PreprocessorDefinitions);_STL_COMPILER_PREPROCESSOR=0;_CORECRT_BUILD;_CRT_GLOBAL_STATE_ISOLATION;_CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY;__WARNING_UNUSED_ASSIGNMENT=28931 diff --git a/src/vcruntime.props b/src/vcruntime.props index 9954c57..303c8d1 100644 --- a/src/vcruntime.props +++ b/src/vcruntime.props @@ -165,12 +165,6 @@ - - Cdecl - - true - true @@ -234,7 +228,10 @@ - + + _VCRT_BUILD;%(PreprocessorDefinitions) + + diff --git a/test/driver/src/main.cpp b/test/driver/src/main.cpp index e21a9df..2b65831 100644 --- a/test/driver/src/main.cpp +++ b/test/driver/src/main.cpp @@ -1,4 +1,6 @@ -#include +#define _SILENCE_CXX23_ALIGNED_STORAGE_DEPRECATION_WARNING + +#include EXTERN_C DRIVER_INITIALIZE DriverEntry; EXTERN_C DRIVER_UNLOAD DriverUnload; diff --git a/test/driver/src/ntl.cpp b/test/driver/src/ntl.cpp index 9d93565..fa6bbff 100644 --- a/test/driver/src/ntl.cpp +++ b/test/driver/src/ntl.cpp @@ -66,6 +66,12 @@ bool ntl_irql_test() { if (ntl::current_irql() != ntl::irql::dispatch) return false; } + old_irql = ntl::current_irql(); + { + auto raised_irql = ntl::raise_irql_to_synch_level(); + if (old_irql != raised_irql.old()) + return false; + } return (ntl::current_irql() == old_irql); } @@ -114,6 +120,8 @@ bool ntl_resource_test() { std::shared_lock lk(res); if (!lk.owns_lock()) return false; + if (!res.locked()) + return false; if (!res.locked_shared()) return false; @@ -123,9 +131,10 @@ bool ntl_resource_test() { if (res.locked_exclusive()) return false; } + if (res.locked()) + return false; if (res.locked_exclusive()) return false; - if (res.locked_shared()) return false; @@ -133,6 +142,8 @@ bool ntl_resource_test() { std::unique_lock lk3(res); if (!lk3.owns_lock()) return false; + if (!res.locked()) + return false; if (!res.locked_exclusive()) return false; @@ -142,15 +153,33 @@ bool ntl_resource_test() { if (res.locked_shared()) return false; - std::shared_lock lk5(res2); + ntl::unique_lock lk5(res2, ntl::adopt_critical_region); if (!lk5.owns_lock()) return false; + if (!res2.locked()) + return false; + if (!res2.locked_exclusive()) + return false; + if (res2.locked_shared()) + return false; + + ntl::shared_lock lk6(lk5); + if (lk5.owns_lock()) + return false; + if (!lk6.owns_lock()) + return false; + if (!res2.locked()) + return false; if (!res2.locked_shared()) return false; + if (res2.locked_exclusive()) + return false; ntl::resource res3; - ntl::shared_lock lk6(res3, ntl::adopt_critical_region); - if (!lk6.owns_lock()) + ntl::shared_lock lk7(res3, ntl::adopt_critical_region); + if (!lk7.owns_lock()) + return false; + if (!res3.locked()) return false; return res3.locked_shared(); } @@ -271,16 +300,16 @@ TEST(ntl_test, ntl_resource_test) { EXPECT_TRUE(res2.locked_exclusive()); EXPECT_FALSE(res2.locked_shared()); - ntl::shared_lock lk7(lk5); + ntl::shared_lock lk6(lk5); EXPECT_FALSE(lk5.owns_lock()); - EXPECT_TRUE(lk7.owns_lock()); + EXPECT_TRUE(lk6.owns_lock()); EXPECT_TRUE(res2.locked()); EXPECT_TRUE(res2.locked_shared()); EXPECT_FALSE(res2.locked_exclusive()); ntl::resource res3; - ntl::shared_lock lk6(res3, ntl::adopt_critical_region); - EXPECT_TRUE(lk6.owns_lock()); + ntl::shared_lock lk7(res3, ntl::adopt_critical_region); + EXPECT_TRUE(lk7.owns_lock()); EXPECT_TRUE(res3.locked()); EXPECT_TRUE(res3.locked_shared()); } \ No newline at end of file From 64236c269f27098a34fa70ee0679316d0fc4512e Mon Sep 17 00:00:00 2001 From: Jung-Kwang Lee Date: Wed, 24 Aug 2022 17:55:15 +0900 Subject: [PATCH 4/4] Fix code (for VS2017, VS2019) --- include/ntl/resource | 16 ++++++++-------- include/ntl/spin_lock | 8 ++++---- test/common/rpc.hpp | 6 +++++- test/driver/src/ntl.cpp | 12 ++++++------ 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/include/ntl/resource b/include/ntl/resource index 9985dfa..17a4122 100644 --- a/include/ntl/resource +++ b/include/ntl/resource @@ -137,7 +137,7 @@ public: unique_lock() noexcept : lockable_(nullptr), owns_(false) {} - _NODISCARD_CTOR unique_lock(lock_type &lockable, std::adopt_lock_t) + unique_lock(lock_type &lockable, std::adopt_lock_t) : std::unique_lock(lockable, std::adopt_lock), lockable_(nullptr), owns_(false) { } // construct and assume already locked @@ -146,11 +146,11 @@ public: : std::unique_lock(lockable, std::defer_lock), lockable_(nullptr), owns_(false) {} // construct but don't lock - _NODISCARD_CTOR unique_lock(lock_type &lockable, std::try_to_lock_t) + unique_lock(lock_type &lockable, std::try_to_lock_t) : std::unique_lock(lockable, std::try_to_lock), lockable_(nullptr), owns_(false) {} // construct and try to lock - _NODISCARD_CTOR unique_lock(lock_type &lockable, adopt_critical_region_t) + unique_lock(lock_type &lockable, adopt_critical_region_t) : std::unique_lock(lockable, std::defer_lock), lockable_(std::addressof(lockable)), owns_(false) { lockable.lock_no_critical_region(); @@ -206,7 +206,7 @@ public: shared_lock() noexcept : lockable_(nullptr), owns_(false) {} - _NODISCARD_CTOR explicit shared_lock(lock_type &lockable) + explicit shared_lock(lock_type &lockable) : lockable_(_STD addressof(lockable)), owns_(true) { // construct with mutex and lock shared lockable.lock_shared(); @@ -217,24 +217,24 @@ public: lockable_(_STD addressof(lockable)), owns_(false) { } // construct with unlocked mutex - _NODISCARD_CTOR shared_lock(lock_type &lockable, std::try_to_lock_t) + shared_lock(lock_type &lockable, std::try_to_lock_t) : std::shared_lock(lockable, std::try_to_lock), lockable_(_STD addressof(lockable)), owns_(lockable.try_lock_shared()) { } // construct with mutex and try to lock shared - _NODISCARD_CTOR shared_lock(lock_type &lockable, std::adopt_lock_t) + shared_lock(lock_type &lockable, std::adopt_lock_t) : std::shared_lock(lockable, std::adopt_lock), lockable_(_STD addressof(lockable)), owns_(true) { } // construct with mutex and adopt ownership - _NODISCARD_CTOR shared_lock(lock_type &lockable, adopt_critical_region_t) + shared_lock(lock_type &lockable, adopt_critical_region_t) : std::shared_lock(lockable, std::defer_lock), lockable_(std::addressof(lockable)), owns_(false) { lockable.lock_shared_no_critical_region(); owns_ = true; } // construct but don't enter critical region - _NODISCARD_CTOR shared_lock(unique_lock &lock) + shared_lock(unique_lock &lock) : std::shared_lock(*lock.mutex(), std::defer_lock), lockable_(lock.mutex()), owns_(false) { lock.mutex()->convert_to_shared(); diff --git a/include/ntl/spin_lock b/include/ntl/spin_lock index 18f9965..1bfb889 100644 --- a/include/ntl/spin_lock +++ b/include/ntl/spin_lock @@ -71,14 +71,14 @@ public: unique_lock() noexcept : lockable_(nullptr), owns_(false) {} - _NODISCARD_CTOR explicit unique_lock(spin_lock &lockable) + explicit unique_lock(lock_type &lockable) : lockable_(_STD addressof(lockable)), owns_(false) { // construct and lock lockable_->lock(); owns_ = true; } - _NODISCARD_CTOR unique_lock(lock_type &lockable, std::adopt_lock_t) + unique_lock(lock_type &lockable, std::adopt_lock_t) : std::unique_lock(lockable, std::adopt_lock), lockable_(nullptr), owns_(false) { } // construct and assume already locked @@ -87,11 +87,11 @@ public: : std::unique_lock(lockable, std::defer_lock), lockable_(nullptr), owns_(false) {} // construct but don't lock - _NODISCARD_CTOR unique_lock(lock_type &lockable, std::try_to_lock_t) + unique_lock(lock_type &lockable, std::try_to_lock_t) : std::unique_lock(lockable, std::try_to_lock), lockable_(nullptr), owns_(false) {} // construct and try to lock - _NODISCARD_CTOR unique_lock(lock_type &lockable, at_dpc_level_lock_t) + unique_lock(lock_type &lockable, at_dpc_level_lock_t) : std::unique_lock(lockable, std::defer_lock), lockable_(std::addressof(lockable)), owns_(false) { lockable.lock_at_dpc_level(); diff --git a/test/common/rpc.hpp b/test/common/rpc.hpp index 9e6d266..bfdb9e2 100644 --- a/test/common/rpc.hpp +++ b/test/common/rpc.hpp @@ -40,7 +40,11 @@ NTL_ADD_CALLBACK_4(test_rpc, int, test_sum, int, a, int, b, int, c, int, d, NTL_ADD_CALLBACK_5(test_rpc, int, test_sum, int, a, int, b, int, c, int, d, int, e, { return a + b + c + d + e; }) +#if _MSC_VER <= 1916 +NTL_ADD_CALLBACK_0(test_rpc, int, test_void, { return 0; }) +#else NTL_ADD_CALLBACK_0(test_rpc, void, test_void, { return; }) +#endif NTL_ADD_CALLBACK_1(test_rpc, bool, test_vec, const std::vector &, vec, { return vec.empty(); }) @@ -75,4 +79,4 @@ NTL_ADD_CALLBACK_2(test_rpc, point, test_point_class, const point &, p1, const point &, p2, { return p1.get_x() > p2.get_x() ? p1 : p2; }) -NTL_RPC_END(test_rpc) \ No newline at end of file +NTL_RPC_END(test_rpc) diff --git a/test/driver/src/ntl.cpp b/test/driver/src/ntl.cpp index fa6bbff..77028bd 100644 --- a/test/driver/src/ntl.cpp +++ b/test/driver/src/ntl.cpp @@ -87,11 +87,11 @@ bool ntl_spin_lock_test() { if (!lock2.test()) return false; - std::unique_lock lk(lock); + std::unique_lock lk(lock); if (!lk.owns_lock()) return false; - std::unique_lock lk2(lock, std::try_to_lock); + std::unique_lock lk2(lock, std::try_to_lock); if (lk2.owns_lock()) return false; @@ -117,7 +117,7 @@ bool ntl_spin_lock_test() { bool ntl_resource_test() { ntl::resource res; { - std::shared_lock lk(res); + std::shared_lock lk(res); if (!lk.owns_lock()) return false; if (!res.locked()) @@ -125,7 +125,7 @@ bool ntl_resource_test() { if (!res.locked_shared()) return false; - std::unique_lock lk2(res, std::try_to_lock); + std::unique_lock lk2(res, std::try_to_lock); if (lk2.owns_lock()) return false; if (res.locked_exclusive()) @@ -139,7 +139,7 @@ bool ntl_resource_test() { return false; ntl::resource res2; - std::unique_lock lk3(res); + std::unique_lock lk3(res); if (!lk3.owns_lock()) return false; if (!res.locked()) @@ -147,7 +147,7 @@ bool ntl_resource_test() { if (!res.locked_exclusive()) return false; - std::shared_lock lk4(res, std::try_to_lock); + std::shared_lock lk4(res, std::try_to_lock); if (!lk4.owns_lock()) return false; if (res.locked_shared())