summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-04-20 14:41:49 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-04-20 14:41:49 +0200
commit3d51ea5b54a55c5417236ed00212d1e3d5134dd2 (patch)
tree6b1f14b42dc6bf4d6f06bfdc1b64d018acb77c77
parentfb6917305fe5e09da02d887f7cfde916006e9c13 (diff)
Added kernel threading support.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--.gitignore1
-rw-r--r--DriverThread.cpp62
-rw-r--r--DriverThread.hpp46
-rw-r--r--Makefile9
-rw-r--r--ddk-template-cplusplus.cpp22
5 files changed, 137 insertions, 3 deletions
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.hpp>
+
+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 <ntddk.h>
+
+#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 <ntddk.h>
+#include <DriverThread.hpp>
+
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"