aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile89
-rwxr-xr-xexamples/dpp-example-cplusplus-EASTL.bat27
-rw-r--r--examples/dpp-example-cplusplus-EASTL.cpp201
-rwxr-xr-xexamples/dpp-example-cplusplus.bat27
-rw-r--r--examples/dpp-example-cplusplus.cpp237
-rwxr-xr-xexamples/dpp-example.bat27
-rw-r--r--examples/dpp-example.c155
7 files changed, 763 insertions, 0 deletions
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 0000000..abf8f2a
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,89 @@
+ifndef DPP_ROOT
+$(error DPP_ROOT is undefined, use `make DPP_ROOT=$(realpath ..)`)
+endif
+
+ifndef BUILD_NATIVE
+include $(DPP_ROOT)/Makefile.inc
+OPP_SUFFIX := kopp
+EXE_SUFFIX := sys
+else
+include $(DPP_ROOT)/Makefile.native.inc
+CFLAGS += -DBUILD_USERMODE=1
+OPP_SUFFIX := uopp
+EXE_SUFFIX := run
+endif
+
+1_DRIVER_NAME = dpp-example
+1_OBJECTS = $(1_DRIVER_NAME).o
+1_TARGET = $(1_DRIVER_NAME).$(EXE_SUFFIX)
+
+2_DRIVER_NAME = dpp-example-cplusplus
+2_OBJECTS = $(2_DRIVER_NAME).$(OPP_SUFFIX)
+2_TARGET = $(2_DRIVER_NAME).$(EXE_SUFFIX)
+
+3_DRIVER_NAME = dpp-example-cplusplus-EASTL
+3_OBJECTS = $(3_DRIVER_NAME).$(OPP_SUFFIX)
+3_TARGET = $(3_DRIVER_NAME).$(EXE_SUFFIX)
+
+ifndef BUILD_NATIVE
+all: $(1_TARGET) $(2_TARGET) $(3_TARGET)
+else
+all: $(3_TARGET)
+endif
+
+%.o: %.c
+ $(call BUILD_C_OBJECT,$<,$@)
+
+%.$(OPP_SUFFIX): %.cpp
+ $(call BUILD_CPP_OBJECT,$<,$@)
+
+ifndef BUILD_NATIVE
+# simple C driver
+$(1_TARGET): $(1_OBJECTS)
+ $(call LINK_C_KERNEL_TARGET,$(1_OBJECTS),$@)
+
+# C++ driver w/ MT
+$(2_TARGET): $(2_OBJECTS)
+ $(call LINK_CPP_KERNEL_TARGET,$(2_OBJECTS),$@)
+
+# C++ driver w/ EASTL
+$(3_TARGET): $(3_OBJECTS)
+ $(call LINK_CPP_KERNEL_TARGET,$(3_OBJECTS),$@)
+
+install: all
+ $(call INSTALL_EXEC_SIGN,$(1_TARGET))
+ $(call INSTALL_EXEC_SIGN,$(2_TARGET))
+ $(call INSTALL_EXEC_SIGN,$(3_TARGET))
+ $(INSTALL) $(1_DRIVER_NAME).bat $(DESTDIR)
+ $(INSTALL) $(2_DRIVER_NAME).bat $(DESTDIR)
+ $(INSTALL) $(3_DRIVER_NAME).bat $(DESTDIR)
+else
+$(1_TARGET):
+ $(error Target $(1_TARGET) does not support BUILD_NATIVE)
+
+# C++ driver w/ MT
+$(2_TARGET):
+ $(error Target $(2_TARGET) does not support BUILD_NATIVE)
+
+# C++ driver w/ EASTL
+$(3_TARGET): $(3_OBJECTS)
+ $(call LINK_CPP_USER_TARGET,$(3_OBJECTS),$@)
+
+install: all
+ $(call INSTALL_EXEC,$(3_TARGET))
+endif
+
+$(1_DRIVER_NAME): $(1_TARGET)
+ @echo 'Target compiled/linked: $(1_TARGET)'
+$(2_DRIVER_NAME): $(2_TARGET)
+ @echo 'Target compiled/linked: $(2_TARGET)'
+$(3_DRIVER_NAME): $(3_TARGET)
+ @echo 'Target compiled/linked: $(3_TARGET)'
+
+clean:
+ rm -f $(1_OBJECTS) $(1_TARGET) $(1_TARGET).map
+ rm -f $(2_OBJECTS) $(2_TARGET) $(2_TARGET).map
+ rm -f $(3_OBJECTS) $(3_TARGET) $(3_TARGET).map
+
+.PHONY: all install clean
+.DEFAULT_GOAL := all
diff --git a/examples/dpp-example-cplusplus-EASTL.bat b/examples/dpp-example-cplusplus-EASTL.bat
new file mode 100755
index 0000000..9793eee
--- /dev/null
+++ b/examples/dpp-example-cplusplus-EASTL.bat
@@ -0,0 +1,27 @@
+@echo off
+set SERVICE_NAME=DPP-Example-CPlusPlus-EASTL
+set DRIVER="%~dp0\dpp-example-cplusplus-EASTL.sys"
+
+net session >nul 2>&1
+if NOT %ERRORLEVEL% EQU 0 (
+ echo ERROR: This script requires Administrator privileges!
+ pause
+ exit /b 1
+)
+
+echo ---------------------------------------
+echo -- Service Name: %SERVICE_NAME%
+echo -- Driver......: %DRIVER%
+echo ---------------------------------------
+
+sc create %SERVICE_NAME% binPath= %DRIVER% type= kernel
+echo ---------------------------------------
+sc start %SERVICE_NAME%
+echo ---------------------------------------
+sc query %SERVICE_NAME%
+echo [PRESS A KEY TO STOP THE DRIVER]
+pause
+sc stop %SERVICE_NAME%
+sc delete %SERVICE_NAME%
+echo Done.
+timeout /t 3
diff --git a/examples/dpp-example-cplusplus-EASTL.cpp b/examples/dpp-example-cplusplus-EASTL.cpp
new file mode 100644
index 0000000..5c4322f
--- /dev/null
+++ b/examples/dpp-example-cplusplus-EASTL.cpp
@@ -0,0 +1,201 @@
+#ifndef BUILD_USERMODE
+#include <ntddk.h>
+#endif
+
+#include <cstdint>
+#include <stdexcept>
+
+#include <EASTL/functional.h>
+#include <EASTL/hash_map.h>
+#include <EASTL/random.h>
+#include <EASTL/scoped_ptr.h>
+#include <EASTL/set.h>
+#include <EASTL/shared_ptr.h>
+#include <EASTL/sort.h>
+#include <EASTL/string.h>
+#include <EASTL/map.h>
+#include <EASTL/unordered_map.h>
+#include <EASTL/unordered_set.h>
+#include <EASTL/vector.h>
+
+#ifdef BUILD_USERMODE
+#include <cstdio>
+
+#define DbgPrint printf
+typedef struct
+{
+} DRIVER_OBJECT;
+typedef DRIVER_OBJECT * PDRIVER_OBJECT;
+typedef struct
+{
+} UNICODE_STRING;
+typedef UNICODE_STRING * PUNICODE_STRING;
+typedef int NTSTATUS;
+#else
+extern "C" NTSTATUS NTAPI ZwQuerySystemInformation(_In_ int SystemInformationClass,
+ _Inout_ PVOID SystemInformation,
+ _In_ ULONG SystemInformationLength,
+ _Out_opt_ PULONG ReturnLength);
+extern "C" NTSTATUS NTAPI WrapperZwQuerySystemInformation(_In_ int SystemInformationClass,
+ _Inout_ PVOID SystemInformation,
+ _In_ ULONG SystemInformationLength,
+ _Out_opt_ PULONG ReturnLength);
+#endif
+
+struct GeneratorUint32
+{
+ uint32_t mValue;
+ GeneratorUint32() : mValue(0)
+ {
+ }
+ uint32_t operator()()
+ {
+ return mValue++;
+ }
+};
+
+using namespace eastl;
+
+// C&P from: https://raw.githubusercontent.com/sidyhe/dxx/ed06aba3b91fe8e101d08c33c26ba73db96acef0/README.md
+void stl_test()
+{
+ make_unique<DRIVER_OBJECT>();
+ make_shared<UNICODE_STRING>();
+ scoped_ptr<double> dptr(new double(3.6));
+
+ set<int> set_test;
+ set_test.insert(1);
+ set_test.insert(3);
+ set_test.insert(5);
+ set_test.erase(1);
+
+ map<int, int> map_test;
+ map_test[0] = 1;
+ map_test[10] = 11;
+ map_test[20] = 12;
+ map_test.erase(11);
+
+ vector<int> vec_test;
+ vec_test.push_back(2);
+ vec_test.push_back(3);
+ vec_test.push_back(1);
+ stable_sort(vec_test.begin(), vec_test.end(), less<int>());
+ for (auto e : vec_test)
+ {
+ DbgPrint("%d\n", e);
+ }
+
+ string s;
+ s = "This a string";
+ s.append(" ");
+ s.append("any");
+ DbgPrint("%s\n", s.c_str());
+
+ wstring ws;
+ ws = L"wide string";
+ ws.clear();
+
+ unordered_set<float> us_test;
+ us_test.insert(333);
+
+ unordered_map<double, string> um_test;
+ um_test.insert(make_pair(6.6, "9.9"));
+}
+
+void more_stl_test()
+{
+#ifndef BUILD_USERMODE
+ hash_map<int, string> hm;
+
+ hm[0] = "test1";
+ hm[10] = "test2";
+ hm[20] = "test3";
+ for (auto s : hm)
+ {
+ DbgPrint("%s\n", s.second.c_str());
+ }
+#endif
+
+ uniform_int_distribution<std::uint32_t> uid(1, UINT32_MAX);
+ GeneratorUint32 g;
+ DbgPrint("PRNG: %u\n", uid(g));
+
+ auto lambda = [] { DbgPrint("Hello lambda!\n"); };
+ function<void(void)> fn = lambda;
+ fn();
+
+ auto lambda2 = [](int n)
+ {
+ DbgPrint("Hello lambda2, %u!\n", n);
+ return n;
+ };
+ function<int(int)> fn2 = lambda2;
+ fn2(1337);
+
+ vector<std::uint32_t> fill_me;
+ for (auto i = UINT16_MAX; i > 0; --i)
+ {
+ fill_me.push_back(i);
+ }
+ DbgPrint("fill_me size: %zu\n", fill_me.size());
+}
+
+#ifndef BUILD_USERMODE
+static void zw_test()
+{
+ NTSTATUS ret;
+ ULONG memoryNeeded = 0;
+
+ ret = ZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded);
+ if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded)
+ {
+ DbgPrint("ZwQuerySystemInformation failed with 0x%lX (memory needed: %lu)\n", ret, memoryNeeded);
+ }
+
+ memoryNeeded = 0;
+ ret = WrapperZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded);
+ if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded)
+ {
+ DbgPrint("ZwQuerySystemInformation failed 0x%lX (memory needed: %lu)\n", ret, memoryNeeded);
+ }
+}
+#endif
+
+extern "C"
+{
+#ifndef BUILD_USERMODE
+ DRIVER_INITIALIZE DriverEntry;
+ DRIVER_UNLOAD DriverUnload;
+
+ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+ {
+ (void)DriverObject;
+ (void)RegistryPath;
+
+ DbgPrint("%s\n", "Hello ring0!");
+
+ zw_test();
+ stl_test();
+ more_stl_test();
+
+ return STATUS_SUCCESS;
+ }
+
+ void DriverUnload(PDRIVER_OBJECT DriverObject)
+ {
+ (void)DriverObject;
+
+ DbgPrint("%s\n", "Bye ring0!");
+ }
+#else
+ int main()
+ {
+ DbgPrint("%s\n", "Hello user!");
+
+ stl_test();
+ more_stl_test();
+
+ return 0;
+ }
+#endif
+}
diff --git a/examples/dpp-example-cplusplus.bat b/examples/dpp-example-cplusplus.bat
new file mode 100755
index 0000000..d19d3bf
--- /dev/null
+++ b/examples/dpp-example-cplusplus.bat
@@ -0,0 +1,27 @@
+@echo off
+set SERVICE_NAME=DPP-Example-CPlusPlus
+set DRIVER="%~dp0\dpp-example-cplusplus.sys"
+
+net session >nul 2>&1
+if NOT %ERRORLEVEL% EQU 0 (
+ echo ERROR: This script requires Administrator privileges!
+ pause
+ exit /b 1
+)
+
+echo ---------------------------------------
+echo -- Service Name: %SERVICE_NAME%
+echo -- Driver......: %DRIVER%
+echo ---------------------------------------
+
+sc create %SERVICE_NAME% binPath= %DRIVER% type= kernel
+echo ---------------------------------------
+sc start %SERVICE_NAME%
+echo ---------------------------------------
+sc query %SERVICE_NAME%
+echo [PRESS A KEY TO STOP THE DRIVER]
+pause
+sc stop %SERVICE_NAME%
+sc delete %SERVICE_NAME%
+echo Done.
+timeout /t 3
diff --git a/examples/dpp-example-cplusplus.cpp b/examples/dpp-example-cplusplus.cpp
new file mode 100644
index 0000000..215c59c
--- /dev/null
+++ b/examples/dpp-example-cplusplus.cpp
@@ -0,0 +1,237 @@
+#include <ntddk.h>
+
+#include <EASTL/string.h>
+#include <eastl_compat.hpp>
+#include <DriverThread.hpp>
+
+class TestSmth
+{
+public:
+ TestSmth()
+ {
+ DbgPrint("%s\n", "ctor");
+ }
+ ~TestSmth()
+ {
+ DbgPrint("%s\n", "dtor");
+ }
+ void doSmth(void)
+ {
+ DbgPrint("%s\n", "Hello Class!");
+
+ const auto & eastl_to_string = eastl::to_string(0xDEADC0DE);
+ DbgPrint("Using eastl::to_string should return a warning: %s\n", eastl_to_string.c_str());
+
+ eastl::wstring eastl_unicode = L"test_eastl_unicode_string";
+ DbgPrint("eastl::wstring: %S\n", eastl_unicode.c_str());
+
+ wchar_t test_unicode_str[] = L"test_unicode_string";
+ unsigned short test_unicode_strlen = sizeof(test_unicode_str);
+ const auto & eastl_from_unicode = ::from_unicode(test_unicode_str, test_unicode_strlen);
+ DbgPrint("unicode2ansi: \"%s\"\n", eastl_from_unicode.c_str());
+
+ const auto & number_ud = ::to_string(1337u);
+ DbgPrint("Value 1337u to String: %s\n", number_ud.c_str());
+ const auto & number_d = ::to_string(1337);
+ DbgPrint("Value 1337 to String: %s\n", number_d.c_str());
+ const auto & number_l = ::to_string(1337l);
+ DbgPrint("Value 1337l to String: %s\n", number_l.c_str());
+ const auto & number_lu = ::to_string(1337lu);
+ DbgPrint("Value 1337lu to String: %s\n", number_lu.c_str());
+ const auto & number_ll = ::to_string(1337ll);
+ DbgPrint("Value 1337ll to String: %s\n", number_ll.c_str());
+ const auto & number_llu = ::to_string(1337llu);
+ DbgPrint("Value 1337llu to String: %s\n", number_llu.c_str());
+ const auto & number_f = ::to_string(1337.1337f);
+ DbgPrint("Value 1337f to String: %s\n", number_f.c_str());
+ const auto & number_lf = ::to_string(1337.1337);
+ DbgPrint("Value 1337lf to String: %s\n", number_lf.c_str());
+
+ DbgPrint("Value 0x00000000DEADBEEF to Hex String: 0x%s\n", ::to_string_hex(0xdeadbeef, 16));
+ DbgPrint("Value 0xDEADC0DEDEADBEEF to Hex String: 0x%s\n", ::to_string_hex(0xdeadc0dedeadbeef));
+ }
+};
+static TestSmth * cdtor_test;
+
+class Derived : public TestSmth
+{
+public:
+ Derived()
+ {
+ }
+ ~Derived()
+ {
+ }
+ void doSmth(void)
+ {
+ DbgPrint("%s\n", "Hello Derived!");
+ }
+};
+
+class DerivedWithCDtor : public Derived
+{
+public:
+ explicit DerivedWithCDtor(unsigned int value)
+ {
+ some_value = value;
+ DbgPrint("%s\n", "DerivedWithCDtor-Ctor.");
+ }
+ ~DerivedWithCDtor()
+ {
+ DbgPrint("%s\n", "DerivedWithCDtor-Dtor.");
+ }
+ void doSmth(void)
+ {
+ DbgPrint("SomeValue: %X\n", some_value);
+ }
+
+private:
+ unsigned int some_value = 0;
+};
+
+class MyWorkItem
+{
+public:
+ MyWorkItem()
+ {
+ DbgPrint("MyWorkItem ctor\n");
+ }
+ ~MyWorkItem()
+ {
+ DbgPrint("MyWorkItem dtor\n");
+ }
+
+ UINT32 counter = 0, another_counter = 0;
+};
+
+static DriverThread::WorkQueue global_work_queue;
+static DerivedWithCDtor some_static(0xDEADC0DE);
+
+class threadContext : public DriverThread::ThreadArgs
+{
+public:
+ DriverThread::Semaphore sem;
+ DriverThread::Thread dth;
+};
+
+static NTSTATUS threadRoutine(eastl::shared_ptr<DriverThread::ThreadArgs> args)
+{
+ DbgPrint("ThreadRoutine %p, ThreadContext: %p\n", threadRoutine, args);
+ auto ctx = eastl::static_pointer_cast<threadContext>(args);
+ for (size_t i = 3; i > 0; --i)
+ {
+ DbgPrint("ThreadLoop: %zu (isRunning: %u)\n", i, ctx->dth.isRunning());
+ }
+ DbgPrint("Fin. ThreadId: %p\n", ctx->dth.GetThreadId());
+ ctx->sem.Release();
+ DbgPrint("Thread WaitForTermination: 0x%X\n", ctx->dth.WaitForTermination()); // must return STATUS_UNSUCCESSFUL;
+
+ return STATUS_SUCCESS;
+}
+
+static void test_cplusplus(void)
+{
+ TestSmth t;
+ t.doSmth();
+ Derived d;
+ d.doSmth();
+
+ auto ctx = eastl::make_shared<threadContext>();
+ ctx->dth.Start(threadRoutine, ctx);
+ ctx->sem.Wait();
+ DbgPrint("MainThread semaphore signaled.\n");
+ ctx->dth.WaitForTermination();
+ ctx->dth.WaitForTermination();
+ DbgPrint("MainThread EOF\n");
+
+ DriverThread::WorkQueue work_queue;
+ DbgPrint("WorkQueue test.\n");
+ {
+ DriverThread::WorkItem wi(eastl::make_shared<MyWorkItem>());
+
+ auto user = wi.Get<MyWorkItem>();
+ user->counter = 3;
+ user->another_counter = 1;
+ work_queue.Enqueue(wi);
+ global_work_queue.Enqueue(wi);
+ }
+ {
+ eastl::deque<DriverThread::WorkItem> items;
+
+ for (size_t i = 1; i < 3; ++i)
+ {
+ DriverThread::WorkItem wi(eastl::make_shared<MyWorkItem>());
+
+ auto user = wi.Get<MyWorkItem>();
+ user->counter = 3 + i;
+ user->another_counter = 1 + i;
+ items.emplace_back(wi);
+ }
+
+ work_queue.Enqueue(items);
+ global_work_queue.Enqueue(items);
+ }
+
+ work_queue.Start(
+ [](DriverThread::WorkItem & item)
+ {
+ DbgPrint("Worker callback.\n");
+
+ eastl::shared_ptr<MyWorkItem> wi;
+ item.Get<MyWorkItem>(wi);
+ while (wi->counter-- > 0)
+ {
+ DbgPrint("WorkItem Counter: %u\n", wi->counter);
+ }
+
+ DbgPrint("Worker finished.\n");
+ return STATUS_SUCCESS;
+ });
+ work_queue.Stop();
+
+ global_work_queue.Start(
+ [](DriverThread::WorkItem & item)
+ {
+ DbgPrint("Global Worker callback.\n");
+
+ eastl::shared_ptr<MyWorkItem> wi;
+ item.Get<MyWorkItem>(wi);
+ while (wi->another_counter-- > 0)
+ {
+ DbgPrint("WorkItem Another Counter: %u\n", wi->another_counter);
+ }
+
+ DbgPrint("Global Worker finished.\n");
+ return STATUS_SUCCESS;
+ });
+
+ some_static.doSmth();
+}
+
+extern "C"
+{
+
+ DRIVER_INITIALIZE DriverEntry;
+ DRIVER_UNLOAD DriverUnload;
+
+ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+ {
+ (void)DriverObject;
+ (void)RegistryPath;
+
+ DbgPrint("%s\n", "Hello ring0!");
+ cdtor_test = new TestSmth();
+
+ test_cplusplus();
+
+ return STATUS_SUCCESS;
+ }
+
+ VOID DriverUnload(PDRIVER_OBJECT DriverObject)
+ {
+ (void)DriverObject;
+
+ delete cdtor_test;
+ DbgPrint("%s\n", "Bye ring0!");
+ }
+}
diff --git a/examples/dpp-example.bat b/examples/dpp-example.bat
new file mode 100755
index 0000000..cada015
--- /dev/null
+++ b/examples/dpp-example.bat
@@ -0,0 +1,27 @@
+@echo off
+set SERVICE_NAME=DPP-Example
+set DRIVER="%~dp0\dpp-example.sys"
+
+net session >nul 2>&1
+if NOT %ERRORLEVEL% EQU 0 (
+ echo ERROR: This script requires Administrator privileges!
+ pause
+ exit /b 1
+)
+
+echo ---------------------------------------
+echo -- Service Name: %SERVICE_NAME%
+echo -- Driver......: %DRIVER%
+echo ---------------------------------------
+
+sc create %SERVICE_NAME% binPath= %DRIVER% type= kernel
+echo ---------------------------------------
+sc start %SERVICE_NAME%
+echo ---------------------------------------
+sc query %SERVICE_NAME%
+echo [PRESS A KEY TO STOP THE DRIVER]
+pause
+sc stop %SERVICE_NAME%
+sc delete %SERVICE_NAME%
+echo Done.
+timeout /t 3
diff --git a/examples/dpp-example.c b/examples/dpp-example.c
new file mode 100644
index 0000000..2b9f26f
--- /dev/null
+++ b/examples/dpp-example.c
@@ -0,0 +1,155 @@
+#include <ntddk.h>
+
+#include <except.h>
+
+DRIVER_INITIALIZE DriverEntry;
+DRIVER_UNLOAD DriverUnload;
+
+extern NTSTATUS NTAPI ZwProtectVirtualMemory(_In_ HANDLE ProcessHandle,
+ _In_ _Out_ PVOID * BaseAddress,
+ _In_ _Out_ PULONG NumberOfBytesToProtect,
+ _In_ ULONG NewAccessProtection,
+ _Out_ PULONG OldAccessProtection);
+extern NTSTATUS NTAPI ZwQuerySystemInformation(_In_ int SystemInformationClass,
+ _Inout_ PVOID SystemInformation,
+ _In_ ULONG SystemInformationLength,
+ _Out_opt_ PULONG ReturnLength);
+extern NTSTATUS NTAPI WrapperZwQuerySystemInformation(_In_ int SystemInformationClass,
+ _Inout_ PVOID SystemInformation,
+ _In_ ULONG SystemInformationLength,
+ _Out_opt_ PULONG ReturnLength);
+extern NTSTATUS NTAPI WrapperZwCreateFile(_Out_ PHANDLE FileHandle,
+ _In_ ACCESS_MASK DesiredAccess,
+ _In_ POBJECT_ATTRIBUTES ObjectAttributes,
+ _Out_ PIO_STATUS_BLOCK StatusBlock,
+ _In_ PLARGE_INTEGER AllocationSize,
+ _In_ ULONG FileAttributes,
+ _In_ ULONG ShareAccess,
+ _In_ ULONG CreateDisposition,
+ _In_ ULONG CreateOptions,
+ _In_ PVOID EaBuffer,
+ _In_ ULONG EaLength);
+extern NTSTATUS NTAPI WrapperZwClose(_In_ HANDLE Handle);
+extern NTSTATUS NTAPI WrapperZwWriteFile(_In_ HANDLE FileHandle,
+ _In_ HANDLE Event,
+ _In_ PIO_APC_ROUTINE ApcRoutine,
+ _In_ PVOID ApcContext,
+ _Out_ PIO_STATUS_BLOCK StatusBlock,
+ _In_ PVOID Buffer,
+ _In_ ULONG Length,
+ _In_ PLARGE_INTEGER ByteOffset,
+ _In_ PULONG Key);
+
+int example_exception_handler(_In_ EXCEPTION_POINTERS * lpEP)
+{
+ (void)lpEP;
+ DbgPrint("Exception handler called!\n");
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+static void another_seh_test()
+{
+ DbgPrint("Another SEH test..\n");
+ __dpptry(example_exception_handler, anotherseh)
+ {
+ *(int *)0 = 0;
+ }
+ __dppexcept(anotherseh)
+ {
+ DbgPrint("Success!\n");
+ }
+ __dpptryend(anotherseh);
+}
+
+static void zw_test()
+{
+ NTSTATUS ret;
+ ULONG memoryNeeded = 0;
+
+ ret = ZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded);
+ if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded)
+ {
+ DbgPrint("ZwQuerySystemInformation failed with 0x%lX (memory needed: %lu)\n", ret, memoryNeeded);
+ }
+
+ memoryNeeded = 0;
+ ret = WrapperZwQuerySystemInformation(0x5, NULL, 0, &memoryNeeded);
+ if (ret != STATUS_INFO_LENGTH_MISMATCH || !memoryNeeded)
+ {
+ DbgPrint("ZwQuerySystemInformation failed 0x%lX (memory needed: %lu)\n", ret, memoryNeeded);
+ }
+}
+
+static NTSTATUS WriteToFile()
+{
+ UNICODE_STRING fileName = RTL_CONSTANT_STRING(L"\\??\\C:\\dpp-example-text.log");
+ OBJECT_ATTRIBUTES objAttr;
+ IO_STATUS_BLOCK ioStatusBlock;
+ HANDLE fileHandle;
+ NTSTATUS status;
+
+ InitializeObjectAttributes(&objAttr, &fileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+
+ status = WrapperZwCreateFile(&fileHandle,
+ GENERIC_WRITE,
+ &objAttr,
+ &ioStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ CHAR data[] = "Test data from the kernel driver\n";
+ status = WrapperZwWriteFile(fileHandle, NULL, NULL, NULL, &ioStatusBlock, data, sizeof(data) - 1, NULL, NULL);
+
+ WrapperZwClose(fileHandle);
+ return status;
+}
+
+NTSTATUS DriverEntry(struct _DRIVER_OBJECT * DriverObject, PUNICODE_STRING RegistryPath)
+{
+ (void)DriverObject;
+ (void)RegistryPath;
+
+ DbgPrint("%s\n", "Hello ring0!");
+
+ DbgPrint("Testing SEH..\n");
+ __dpptry(example_exception_handler, testseh)
+ {
+ *(int *)0 = 0;
+ DbgPrint("You should never see this text!\n");
+ }
+ __dppexcept(testseh)
+ {
+ DbgPrint("Success! SEH seems to work.\n");
+ }
+ __dpptryend(testseh);
+
+ another_seh_test();
+ zw_test();
+
+ DbgPrint("%s\n", "Disable/Enable Interrupts!");
+ _disable();
+ _enable();
+ DbgPrint("%s\n", "Done with Disable/Enable Interrupts!");
+
+ DbgPrint("%s\n", "WriteToFile");
+ WriteToFile();
+
+ return STATUS_SUCCESS;
+}
+
+VOID DriverUnload(struct _DRIVER_OBJECT * DriverObject)
+{
+ (void)DriverObject;
+
+ DbgPrint("%s\n", "Bye ring0!");
+}