From 3d51ea5b54a55c5417236ed00212d1e3d5134dd2 Mon Sep 17 00:00:00 2001 From: Toni Uhlig Date: Tue, 20 Apr 2021 14:41:49 +0200 Subject: Added kernel threading support. Signed-off-by: Toni Uhlig --- .gitignore | 1 + DriverThread.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++ DriverThread.hpp | 46 ++++++++++++++++++++++++++++++++++ Makefile | 9 ++++--- ddk-template-cplusplus.cpp | 22 ++++++++++++++++ 5 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 DriverThread.cpp create mode 100644 DriverThread.hpp diff --git a/.gitignore b/.gitignore index 04fea95..624579b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/codesign-* /.deps-built /EASTL-build /x86_64-w64-mingw32 diff --git a/DriverThread.cpp b/DriverThread.cpp new file mode 100644 index 0000000..2eb7c6d --- /dev/null +++ b/DriverThread.cpp @@ -0,0 +1,62 @@ +#include + +DriverThread::Thread::Thread(void) +{ +} + +NTSTATUS DriverThread::Thread::Start(PKSTART_ROUTINE threadRoutine, PVOID threadContext) +{ + HANDLE threadHandle; + NTSTATUS status; + + status = PsCreateSystemThread(&threadHandle, (ACCESS_MASK)0, NULL, (HANDLE)0, NULL, threadRoutine, threadContext); + + if (!NT_SUCCESS(status)) + { + return status; + } + + ObReferenceObjectByHandle(threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *)&m_threadObject, NULL); + return ZwClose(threadHandle); +} + +NTSTATUS DriverThread::Thread::WaitForTermination(LONGLONG timeout) +{ + LARGE_INTEGER li_timeout = {.QuadPart = timeout}; + NTSTATUS status = + KeWaitForSingleObject(m_threadObject, Executive, KernelMode, FALSE, (timeout == 0 ? NULL : &li_timeout)); + + ObDereferenceObject(m_threadObject); + return status; +} + +DriverThread::Spinlock::Spinlock(void) +{ + KeInitializeSpinLock(&m_spinLock); +} + +NTSTATUS DriverThread::Spinlock::Acquire(KIRQL * const oldIrql) +{ + return KeAcquireSpinLock(&m_spinLock, oldIrql); +} + +void DriverThread::Spinlock::Release(KIRQL * const oldIrql) +{ + KeReleaseSpinLock(&m_spinLock, *oldIrql); +} + +DriverThread::Semaphore::Semaphore(LONG initialValue, LONG maxValue) +{ + KeInitializeSemaphore(&m_semaphore, initialValue, maxValue); +} + +NTSTATUS DriverThread::Semaphore::Wait(LONGLONG timeout) +{ + LARGE_INTEGER li_timeout = {.QuadPart = timeout}; + return KeWaitForSingleObject(&m_semaphore, Executive, KernelMode, FALSE, (timeout == 0 ? NULL : &li_timeout)); +} + +LONG DriverThread::Semaphore::Release(LONG adjustment) +{ + return KeReleaseSemaphore(&m_semaphore, 0, adjustment, FALSE); +} diff --git a/DriverThread.hpp b/DriverThread.hpp new file mode 100644 index 0000000..39f5a89 --- /dev/null +++ b/DriverThread.hpp @@ -0,0 +1,46 @@ +#ifndef DDK_THREAD +#define DDK_THREAD 1 + +#include + +#define TERMINATE_MYSELF(ntstatus) PsTerminateSystemThread(ntstatus); + +namespace DriverThread +{ + +class Thread +{ +public: + Thread(); + NTSTATUS Start(PKSTART_ROUTINE threadRoutine, PVOID threadContext); + NTSTATUS WaitForTermination(LONGLONG timeout = 0); + +private: + PETHREAD m_threadObject; +}; + +class Spinlock +{ +public: + Spinlock(void); + NTSTATUS Acquire(KIRQL * const oldIrql); + void Release(KIRQL * const oldIrql); + +private: + KSPIN_LOCK m_spinLock; +}; + +class Semaphore +{ +public: + explicit Semaphore(LONG initialValue = 0, LONG maxValue = MAXLONG); + NTSTATUS Wait(LONGLONG timeout = 0); + LONG Release(LONG adjustment = 1); + +private: + KSEMAPHORE m_semaphore; +}; + +}; // namespace DriverThread + +#endif diff --git a/Makefile b/Makefile index 5f20b8a..92cb391 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ CC = $(LOCAL_MINGW64_CC) CXX = $(dir $(CC))/x86_64-w64-mingw32-g++ DDK_INCLUDE_DIR = $(LOCAL_MINGW64_DDK_INCLUDE_DIR) CFLAGS := -Wall -Wextra -m64 -shared \ - -I$(DDK_INCLUDE_DIR) \ + -I. -I$(DDK_INCLUDE_DIR) \ -D__INTRINSIC_DEFINED_InterlockedBitTestAndSet \ -D__INTRINSIC_DEFINED_InterlockedBitTestAndReset CXXFLAGS := -fno-exceptions -fno-rtti @@ -23,6 +23,8 @@ EASTL_CXXFLAGS := -IEASTL/include -IEASTL/test/packages/EABase/include/Common \ -Wno-unknown-pragmas \ -Wno-deprecated-copy \ -Wl,--gc-sections +ADDITIONAL_OBJS := DriverThread.opp +ADDITIONAL_HDRS := DriverThread.hpp EASTL_STATIC_LIB := EASTL-build/libEASTL.a EASTL_COMPAT := EASTL-compat/kcrt.opp @@ -136,6 +138,7 @@ clean: rm -f $(2_OBJECTS) $(2_TARGET) rm -f $(3_OBJECTS) $(3_TARGET) rm -f $(EASTL_COMPAT) $(EASTL_STATIC_LIB) + rm -f $(ADDITIONAL_OBJS) $(MAKE) -C EASTL-build clean %.o: %.c .deps-built @@ -150,11 +153,11 @@ $(1_TARGET): .deps-built $(1_OBJECTS) -Wl,--entry,DriverEntry -nostartfiles -nostdlib -o $(1_TARGET) \ $(1_OBJECTS) -lntoskrnl -lhal -$(2_TARGET): .deps-built $(2_OBJECTS) +$(2_TARGET): .deps-built $(ADDITIONAL_HDRS) $(ADDITIONAL_OBJS) $(2_OBJECTS) $(CXX) $(CFLAGS) -Wl,--subsystem,native -Wl,--image-base,0x140000000 -Wl,--dynamicbase -Wl,--nxcompat \ -Wl,--file-alignment,0x200 -Wl,--section-alignment,0x1000 -Wl,--stack,0x100000 \ -Wl,--entry,DriverEntry@8 -nostartfiles -nostdlib -o $(2_TARGET) \ - $(2_OBJECTS) -lntoskrnl -lhal + $(ADDITIONAL_OBJS) $(2_OBJECTS) -lntoskrnl -lhal $(3_TARGET): .deps-built $(EASTL_STATIC_LIB) $(EASTL_COMPAT) $(3_OBJECTS) $(CXX) $(CFLAGS) $(CXXFLAGS) $(EASTL_CXXFLAGS) -Wl,--subsystem,native -Wl,--image-base,0x140000000 -Wl,--dynamicbase -Wl,--nxcompat \ diff --git a/ddk-template-cplusplus.cpp b/ddk-template-cplusplus.cpp index f4e3ce4..aafe492 100644 --- a/ddk-template-cplusplus.cpp +++ b/ddk-template-cplusplus.cpp @@ -1,5 +1,7 @@ #include +#include + class TestSmth { public: @@ -12,10 +14,30 @@ public: } }; +static void threadRoutine(PVOID threadContext) +{ + DbgPrint("ThreadRoutine %p, ThreadContext: %p\n", threadRoutine, threadContext); + for (size_t i = 3; i > 0; --i) + { + DbgPrint("ThreadLoop: %zu\n", i); + } + DbgPrint("Fin.\n"); + DriverThread::Semaphore * const sem = (DriverThread::Semaphore *)threadContext; + sem->Release(); + TERMINATE_MYSELF(STATUS_SUCCESS); +} + static void test_cplusplus(void) { TestSmth t; t.doSmth(); + + DriverThread::Semaphore sem; + DriverThread::Thread dt; + dt.Start(threadRoutine, (PVOID)&sem); + sem.Wait(); + DbgPrint("Thread signaled semaphore.\n"); + dt.WaitForTermination(); } extern "C" -- cgit v1.2.3