From 003bac21681c776f683ffd23423f6e242e0ff285 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 1 Aug 2023 09:39:39 -0700 Subject: [PATCH 1/4] WIP Signed-off-by: Dave Thaler --- inc/TraceLoggingProvider.h | 3 +++ src/platform_user.cpp | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/inc/TraceLoggingProvider.h b/inc/TraceLoggingProvider.h index a4536d6..435112a 100644 --- a/inc/TraceLoggingProvider.h +++ b/inc/TraceLoggingProvider.h @@ -121,6 +121,9 @@ extern "C" #define _tlgWriteTransfer_EtwWriteTransfer(...) + USERSIM_API void + EtwWriteTransfer(_In_ const TraceLoggingHProvider hProvider, _In_z_ const char* eventName, size_t argc, ...); + #ifdef __cplusplus } #endif diff --git a/src/platform_user.cpp b/src/platform_user.cpp index 7ff0a61..055d182 100644 --- a/src/platform_user.cpp +++ b/src/platform_user.cpp @@ -1156,4 +1156,10 @@ usersim_trace_logging_write(_In_ const TraceLoggingHProvider hProvider, _In_z_ c va_end(valist); printf("}\n"); +} + +void +EtwWriteTransfer(_In_ const TraceLoggingHProvider hProvider, _In_z_ const char* eventName, size_t argc, ...) +{ + usersim_trace_logging_write(hProvider, eventName, argc, nullptr); } \ No newline at end of file From 8696ab5abd88e12f26b9c98c49b98d896e678a5d Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 1 Aug 2023 17:14:14 -0700 Subject: [PATCH 2/4] Clean up unused function Signed-off-by: Dave Thaler --- tests/mm_test.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/mm_test.cpp b/tests/mm_test.cpp index 09e5c0e..5197c85 100644 --- a/tests/mm_test.cpp +++ b/tests/mm_test.cpp @@ -52,12 +52,6 @@ TEST_CASE("IoAllocateMdl", "[mm]") ExFreePoolWithTag(buffer, tag); } -int -test_probe_for_read_exception_filter(ULONG code, _In_ struct _EXCEPTION_POINTERS *ep) -{ - return EXCEPTION_EXECUTE_HANDLER; -} - ULONG test_probe_for_read(_In_ const volatile void* address, SIZE_T length, ULONG alignment) { @@ -116,4 +110,4 @@ TEST_CASE("ProbeForWrite", "[mm]") // Verify a write past end of memory results in STATUS_ACCESS_VIOLATION. REQUIRE(test_probe_for_write(&x, 65536, 8) == STATUS_ACCESS_VIOLATION); -} \ No newline at end of file +} From efc4be8a978cc8d86017bbbd6294d1ca6b0852cb Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Tue, 1 Aug 2023 17:24:53 -0700 Subject: [PATCH 3/4] Add KfRaiseIrql The DDK just defines KeRaiseIrql as inline wrapper around KfRaiseIrql so we need to expose KfRaiseIrql when linking. Addresses part of #69 Signed-off-by: Dave Thaler --- inc/usersim/ke.h | 4 ++++ src/ke.cpp | 12 ++++++++++-- tests/ke_test.cpp | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/inc/usersim/ke.h b/inc/usersim/ke.h index 3f4ca95..ea36440 100644 --- a/inc/usersim/ke.h +++ b/inc/usersim/ke.h @@ -67,6 +67,10 @@ extern "C" VOID KeRaiseIrql(_In_ KIRQL new_irql, _Out_ PKIRQL old_irql); + USERSIM_API + _IRQL_requires_max_(HIGH_LEVEL) _IRQL_raises_(new_irql) _IRQL_saves_ KIRQL + KfRaiseIrql(_In_ KIRQL new_irql); + USERSIM_API KIRQL KeRaiseIrqlToDpcLevel(); diff --git a/src/ke.cpp b/src/ke.cpp index a3d8ce0..0767864 100644 --- a/src/ke.cpp +++ b/src/ke.cpp @@ -68,12 +68,18 @@ KeGetCurrentIrql() { return _usersim_current_irql; } VOID KeRaiseIrql(_In_ KIRQL new_irql, _Out_ PKIRQL old_irql) { - *old_irql = KeGetCurrentIrql(); + *old_irql = KfRaiseIrql(new_irql); +} + +KIRQL +KfRaiseIrql(_In_ KIRQL new_irql) +{ + KIRQL old_irql = KeGetCurrentIrql(); _usersim_current_irql = new_irql; BOOL result = SetThreadPriority(GetCurrentThread(), new_irql); ASSERT(result); - if (new_irql >= DISPATCH_LEVEL && *old_irql < DISPATCH_LEVEL) { + if (new_irql >= DISPATCH_LEVEL && old_irql < DISPATCH_LEVEL) { PROCESSOR_NUMBER processor; uint32_t processor_index = KeGetCurrentProcessorNumberEx(&processor); @@ -85,6 +91,8 @@ KeRaiseIrql(_In_ KIRQL new_irql, _Out_ PKIRQL old_irql) _usersim_dispatch_locks[processor_index].lock(); } + + return old_irql; } KIRQL diff --git a/tests/ke_test.cpp b/tests/ke_test.cpp index d4d6bb7..81dc260 100644 --- a/tests/ke_test.cpp +++ b/tests/ke_test.cpp @@ -36,6 +36,23 @@ TEST_CASE("irql", "[ke]") REQUIRE(KeGetCurrentIrql() == PASSIVE_LEVEL); } +TEST_CASE("KfRaiseIrql", "[ke]") +{ + REQUIRE(KeGetCurrentIrql() == PASSIVE_LEVEL); + + KIRQL old_irql; + old_irql = KfRaiseIrql(DISPATCH_LEVEL); + REQUIRE(old_irql == PASSIVE_LEVEL); + REQUIRE(KeGetCurrentIrql() == DISPATCH_LEVEL); + + old_irql = KfRaiseIrql(DISPATCH_LEVEL); + REQUIRE(old_irql == DISPATCH_LEVEL); + REQUIRE(KeGetCurrentIrql() == DISPATCH_LEVEL); + + KeLowerIrql(PASSIVE_LEVEL); + REQUIRE(KeGetCurrentIrql() == PASSIVE_LEVEL); +} + TEST_CASE("spin lock", "[ke]") { KSPIN_LOCK lock; From 762640aa4c9e699d30b2b275f04abd29606858f5 Mon Sep 17 00:00:00 2001 From: Dave Thaler Date: Wed, 2 Aug 2023 10:26:59 -0700 Subject: [PATCH 4/4] Add stubs for ETW apis Addresses part of #70 Signed-off-by: Dave Thaler --- inc/TraceLoggingProvider.h | 3 -- inc/usersim/etw.h | 47 ++++++++++++++++++++++++++ inc/usersim/ke.h | 3 +- src/CMakeLists.txt | 1 + src/etw.cpp | 67 +++++++++++++++++++++++++++++++++++++ src/platform_user.cpp | 6 ---- src/usersim.vcxproj | 2 ++ src/usersim.vcxproj.filters | 6 ++++ tests/CMakeLists.txt | 1 + tests/etw_test.cpp | 17 ++++++++++ tests/tests.vcxproj | 1 + tests/tests.vcxproj.filters | 3 ++ 12 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 inc/usersim/etw.h create mode 100644 src/etw.cpp create mode 100644 tests/etw_test.cpp diff --git a/inc/TraceLoggingProvider.h b/inc/TraceLoggingProvider.h index 435112a..a4536d6 100644 --- a/inc/TraceLoggingProvider.h +++ b/inc/TraceLoggingProvider.h @@ -121,9 +121,6 @@ extern "C" #define _tlgWriteTransfer_EtwWriteTransfer(...) - USERSIM_API void - EtwWriteTransfer(_In_ const TraceLoggingHProvider hProvider, _In_z_ const char* eventName, size_t argc, ...); - #ifdef __cplusplus } #endif diff --git a/inc/usersim/etw.h b/inc/usersim/etw.h new file mode 100644 index 0000000..db79731 --- /dev/null +++ b/inc/usersim/etw.h @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +#pragma once +#include "usersim/ke.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ VOID NTAPI ETWENABLECALLBACK( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext); + +typedef ETWENABLECALLBACK* PETWENABLECALLBACK; + +_IRQL_requires_max_(PASSIVE_LEVEL) USERSIM_API NTSTATUS EtwRegister( + _In_ LPCGUID provider_id, + _In_opt_ PETWENABLECALLBACK enable_callback, + _In_opt_ PVOID callback_context, + _Out_ PREGHANDLE reg_handle); + +_IRQL_requires_max_(PASSIVE_LEVEL) USERSIM_API NTSTATUS EtwUnregister(_In_ REGHANDLE reg_handle); + +_IRQL_requires_max_(HIGH_LEVEL) USERSIM_API NTSTATUS EtwWriteTransfer( + REGHANDLE reg_handle, + _In_ EVENT_DESCRIPTOR const* descriptor, + _In_opt_ LPCGUID activity_id, + _In_opt_ LPCGUID related_activity_id, + _In_range_(2, 128) UINT32 data_size, + _Inout_cap_(cData) EVENT_DATA_DESCRIPTOR* data); + +USERSIM_API NTSTATUS +EtwSetInformation( + REGHANDLE reg_handle, + EVENT_INFO_CLASS information_class, + _In_opt_ PVOID information, + UINT16 const information_size); + +#ifdef __cplusplus +} +#endif diff --git a/inc/usersim/ke.h b/inc/usersim/ke.h index ea36440..0091579 100644 --- a/inc/usersim/ke.h +++ b/inc/usersim/ke.h @@ -3,9 +3,10 @@ #pragma once #include "..\src\platform.h" -#include #if defined(__cplusplus) +#include + extern "C" { #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ccdfc15..e35aac2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(usersim SHARED dllmain.cpp + etw.cpp ex.cpp fault_injection.cpp fault_injection.h diff --git a/src/etw.cpp b/src/etw.cpp new file mode 100644 index 0000000..3a7ad1b --- /dev/null +++ b/src/etw.cpp @@ -0,0 +1,67 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT + +#include "platform.h" +#include "usersim/etw.h" + +typedef struct +{ + GUID provider_id; + PETWENABLECALLBACK enable_callback; + PVOID callback_context; +} usersim_etw_provider_t; + +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS EtwRegister( + _In_ LPCGUID provider_id, + _In_opt_ PETWENABLECALLBACK enable_callback, + _In_opt_ PVOID callback_context, + _Out_ PREGHANDLE reg_handle) +{ + usersim_etw_provider_t* provider = (usersim_etw_provider_t*)usersim_allocate(sizeof(*provider)); + if (provider == nullptr) { + return STATUS_NO_MEMORY; + } + provider->provider_id = *provider_id; + provider->enable_callback = enable_callback; + provider->callback_context = callback_context; + *reg_handle = (uintptr_t)provider; + return STATUS_SUCCESS; +} + +_IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS EtwUnregister(_In_ REGHANDLE reg_handle) +{ + usersim_free((void*)(uintptr_t)reg_handle); + return STATUS_SUCCESS; +} + +NTSTATUS +EtwWriteTransfer( + REGHANDLE reg_handle, + _In_ EVENT_DESCRIPTOR const* desc, + _In_opt_ LPCGUID activity_id, + _In_opt_ LPCGUID related_activity_id, + _In_range_(2, 128) UINT32 data_size, + _Inout_cap_(cData) EVENT_DATA_DESCRIPTOR* data) +{ + usersim_etw_provider_t* provider = (usersim_etw_provider_t*)reg_handle; + + // TODO(#70): implement similar to usersim_trace_logging_write(). + UNREFERENCED_PARAMETER(provider); + UNREFERENCED_PARAMETER(desc); + UNREFERENCED_PARAMETER(activity_id); + UNREFERENCED_PARAMETER(related_activity_id); + UNREFERENCED_PARAMETER(data_size); + UNREFERENCED_PARAMETER(data); + return STATUS_SUCCESS; +} + +NTSTATUS +EtwSetInformation( + REGHANDLE reg_handle, EVENT_INFO_CLASS information_class, _In_opt_ PVOID information, UINT16 const information_size) +{ + UNREFERENCED_PARAMETER(reg_handle); + UNREFERENCED_PARAMETER(information_class); + UNREFERENCED_PARAMETER(information); + UNREFERENCED_PARAMETER(information_size); + return STATUS_SUCCESS; +} diff --git a/src/platform_user.cpp b/src/platform_user.cpp index 055d182..304ff2c 100644 --- a/src/platform_user.cpp +++ b/src/platform_user.cpp @@ -1157,9 +1157,3 @@ usersim_trace_logging_write(_In_ const TraceLoggingHProvider hProvider, _In_z_ c printf("}\n"); } - -void -EtwWriteTransfer(_In_ const TraceLoggingHProvider hProvider, _In_z_ const char* eventName, size_t argc, ...) -{ - usersim_trace_logging_write(hProvider, eventName, argc, nullptr); -} \ No newline at end of file diff --git a/src/usersim.vcxproj b/src/usersim.vcxproj index a340b42..3fe590b 100644 --- a/src/usersim.vcxproj +++ b/src/usersim.vcxproj @@ -193,6 +193,7 @@ + @@ -214,6 +215,7 @@ + diff --git a/src/usersim.vcxproj.filters b/src/usersim.vcxproj.filters index 65ad466..55ba329 100644 --- a/src/usersim.vcxproj.filters +++ b/src/usersim.vcxproj.filters @@ -69,6 +69,9 @@ Source Files + + Source Files + @@ -134,6 +137,9 @@ Header Files + + Header Files + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a9ece13..37f46f5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,7 @@ FetchContent_Declare( FetchContent_MakeAvailable(Catch2) add_executable(usersim_tests + etw_test.cpp ex_test.cpp ke_test.cpp mm_test.cpp diff --git a/tests/etw_test.cpp b/tests/etw_test.cpp new file mode 100644 index 0000000..6456660 --- /dev/null +++ b/tests/etw_test.cpp @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT + +#if !defined(CMAKE_NUGET) +#include +#else +#include +#endif +#include "usersim/etw.h" + +TEST_CASE("EtwRegister", "[etw]") +{ + GUID guid = {}; + REGHANDLE reg_handle; + REQUIRE(EtwRegister(&guid, nullptr, nullptr, ®_handle) == STATUS_SUCCESS); + REQUIRE(EtwUnregister(reg_handle) == STATUS_SUCCESS); +} \ No newline at end of file diff --git a/tests/tests.vcxproj b/tests/tests.vcxproj index 05c60af..e31a8b8 100644 --- a/tests/tests.vcxproj +++ b/tests/tests.vcxproj @@ -152,6 +152,7 @@ + diff --git a/tests/tests.vcxproj.filters b/tests/tests.vcxproj.filters index db21f2c..ffba78a 100644 --- a/tests/tests.vcxproj.filters +++ b/tests/tests.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files +