aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format77
-rw-r--r--.gitignore5
-rw-r--r--EASTL-compat/kcrt.cpp208
-rw-r--r--EASTL/source/assert.cpp6
-rw-r--r--EASTL/source/thread_support.cpp6
-rw-r--r--Makefile51
-rw-r--r--README.md15
-rw-r--r--ddk-template-cplusplus-EASTL.cpp125
-rw-r--r--ddk-template-cplusplus.cpp44
-rw-r--r--ddk-template.c5
10 files changed, 507 insertions, 35 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..aeb942a
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,77 @@
+Language: Cpp
+BasedOnStyle : LLVM
+Standard : Cpp03
+# BasedOnStyle: LLVM
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: true
+ConstructorInitializerIndentWidth: 4
+AlignEscapedNewlinesLeft: false
+AlignTrailingComments: true
+AllowShortBlocksOnASingleLine: true
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: false
+AlwaysBreakTemplateDeclarations: true
+AlwaysBreakBeforeMultilineStrings: true
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit: 120
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+DerivePointerAlignment: false
+ExperimentalAutoDetectBinPacking: false
+IndentCaseLabels: true
+IndentWrappedFunctionNames: false
+IndentFunctionDeclarationAfterType: false
+MaxEmptyLinesToKeep: 1
+KeepEmptyLinesAtTheStartOfBlocks: true
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+
+PenaltyExcessCharacter : 500
+PenaltyReturnTypeOnItsOwnLine : 120
+PenaltyBreakBeforeFirstCallParameter : 100
+PenaltyBreakString : 20
+PenaltyBreakComment : 10
+PenaltyBreakFirstLessLess : 0
+
+SpacesBeforeTrailingComments: 1
+Cpp11BracedListStyle: true
+IndentWidth: 4
+TabWidth: 4
+UseTab: Never
+BreakBeforeBraces: Allman
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+SpacesInAngles : false
+SpaceInEmptyParentheses : false
+SpacesInCStyleCastParentheses : false
+SpaceAfterCStyleCast : false
+SpacesInContainerLiterals : true
+SpaceBeforeAssignmentOperators : true
+ContinuationIndentWidth : 4
+SpaceBeforeParens : ControlStatements
+DisableFormat : false
+AccessModifierOffset : -4
+PointerAlignment : Middle
+AlignAfterOpenBracket : Align
+AllowAllParametersOfDeclarationOnNextLine : true
+BinPackArguments : false
+BinPackParameters : false
+AlignOperands : true
+AlignConsecutiveAssignments : false
+AllowShortFunctionsOnASingleLine : None
+BreakBeforeBinaryOperators : None
+AlwaysBreakAfterReturnType : None
+SortIncludes : false
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..04fea95
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/.deps-built
+/EASTL-build
+/x86_64-w64-mingw32
+*.o
+*.opp
diff --git a/EASTL-compat/kcrt.cpp b/EASTL-compat/kcrt.cpp
new file mode 100644
index 0000000..7a8fc52
--- /dev/null
+++ b/EASTL-compat/kcrt.cpp
@@ -0,0 +1,208 @@
+/*
+ * Shameless copy pasta from: https://github.com/sidyhe/dxx
+ */
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <ntddk.h>
+
+#define KCRT_POOL_DEFAULT_TAG 0xDEADBEEF
+
+typedef struct _MALLOC_HEADER
+{
+ ULONG32 Tags;
+ ULONG32 _Resv0;
+ ULONG_PTR Size;
+} MALLOC_HEADER, *PMALLOC_HEADER;
+C_ASSERT(sizeof(MALLOC_HEADER) % sizeof(void *) == 0);
+
+// dynamic memory mgmt
+
+PMALLOC_HEADER GET_MALLOC_HEADER(PVOID ptr)
+{
+ return (MALLOC_HEADER *)((PUCHAR)ptr - sizeof(MALLOC_HEADER));
+}
+
+PVOID GET_MALLOC_ADDRESS(PMALLOC_HEADER header)
+{
+ return (PVOID)((PUCHAR)header + sizeof(MALLOC_HEADER));
+}
+
+ULONG_PTR GET_MALLOC_SIZE(PVOID ptr)
+{
+ PMALLOC_HEADER header = GET_MALLOC_HEADER(ptr);
+
+ if (header->Tags != KCRT_POOL_DEFAULT_TAG)
+ KeBugCheckEx(BAD_POOL_HEADER, 0, 0, 0, 0);
+
+ return header->Size;
+}
+
+// c runtime
+
+void __cdecl free(void * ptr)
+{
+ if (ptr)
+ {
+ MALLOC_HEADER * mhdr = GET_MALLOC_HEADER(ptr);
+
+ if (mhdr->Tags != KCRT_POOL_DEFAULT_TAG)
+ KeBugCheckEx(BAD_POOL_HEADER, 0, 0, 0, 0);
+
+ ExFreePool(mhdr);
+ }
+}
+
+void * __cdecl malloc(size_t size)
+{
+ PMALLOC_HEADER mhdr = NULL;
+ const size_t new_size = size + sizeof(MALLOC_HEADER);
+
+ mhdr = (PMALLOC_HEADER)ExAllocatePoolWithTag(NonPagedPool, new_size, KCRT_POOL_DEFAULT_TAG);
+ if (mhdr)
+ {
+ RtlZeroMemory(mhdr, new_size);
+
+ mhdr->Tags = KCRT_POOL_DEFAULT_TAG;
+ mhdr->Size = size;
+ return GET_MALLOC_ADDRESS(mhdr);
+ }
+
+ return NULL;
+}
+
+void * __cdecl realloc(void * ptr, size_t new_size)
+{
+ if (!ptr)
+ {
+ return malloc(new_size);
+ }
+ else if (new_size == 0)
+ {
+ free(ptr);
+ return NULL;
+ }
+ else
+ {
+ size_t old_size = GET_MALLOC_SIZE(ptr);
+
+ if (new_size <= old_size)
+ {
+ return ptr;
+ }
+ else
+ {
+ void * new_ptr = malloc(new_size);
+
+ if (new_ptr)
+ {
+ memcpy(new_ptr, ptr, old_size);
+ free(ptr);
+ return new_ptr;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// new & delete
+
+void * __cdecl operator new(std::size_t size)
+{
+ return malloc(size);
+}
+
+void * __cdecl operator new[](size_t size)
+{
+ return malloc(size);
+}
+
+void __cdecl operator delete(void * ptr)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete(void * ptr, size_t)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete[](void * ptr, long long unsigned int)
+{
+ free(ptr);
+}
+
+void __cdecl operator delete[](void * ptr)
+{
+ free(ptr);
+}
+
+// EASTL
+
+void * operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+void * operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+
+extern "C" void __cxa_pure_virtual(void)
+{
+}
+
+// stolen from musl: https://elixir.bootlin.com/musl/v1.1.9/source/src/math/ceilf.c
+#define FORCE_EVAL(x) \
+ do \
+ { \
+ if (sizeof(x) == sizeof(float)) \
+ { \
+ volatile float __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ else if (sizeof(x) == sizeof(double)) \
+ { \
+ volatile double __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ else \
+ { \
+ volatile long double __x __attribute__((unused)); \
+ __x = (x); \
+ } \
+ } while (0)
+
+extern "C" float ceilf(float x)
+{
+ union {
+ float f;
+ UINT32 i;
+ } u = {x};
+ int e = (int)(u.i >> 23 & 0xff) - 0x7f;
+ UINT32 m;
+
+ if (e >= 23)
+ return x;
+ if (e >= 0)
+ {
+ m = 0x007fffff >> e;
+ if ((u.i & m) == 0)
+ return x;
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31 == 0)
+ u.i += m;
+ u.i &= ~m;
+ }
+ else
+ {
+ FORCE_EVAL(x + 0x1p120f);
+ if (u.i >> 31)
+ u.f = -0.0;
+ else if (u.i << 1)
+ u.f = 1.0;
+ }
+ return u.f;
+}
diff --git a/EASTL/source/assert.cpp b/EASTL/source/assert.cpp
index 7d32d5e..a4734af 100644
--- a/EASTL/source/assert.cpp
+++ b/EASTL/source/assert.cpp
@@ -15,7 +15,11 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
- #include <Windows.h>
+ #ifdef __MINGW64__
+ #include <windows.h>
+ #else
+ #include <Windows.h>
+ #endif
EA_RESTORE_ALL_VC_WARNINGS();
#elif defined(EA_PLATFORM_ANDROID)
#include <android/log.h>
diff --git a/EASTL/source/thread_support.cpp b/EASTL/source/thread_support.cpp
index 1b03629..3b8550e 100644
--- a/EASTL/source/thread_support.cpp
+++ b/EASTL/source/thread_support.cpp
@@ -13,7 +13,11 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
- #include <Windows.h>
+ #ifdef __MINGW64__
+ #include <windows.h>
+ #else
+ #include <Windows.h>
+ #endif
EA_RESTORE_ALL_VC_WARNINGS();
#endif
diff --git a/Makefile b/Makefile
index e4011a6..eb6feb8 100644
--- a/Makefile
+++ b/Makefile
@@ -3,13 +3,26 @@ LOCAL_MINGW64_BUILD_DIR := ./x86_64-w64-mingw32
LOCAL_MINGW64_CC := $(LOCAL_MINGW64_BUILD_DIR)/bin/x86_64-w64-mingw32-gcc
LOCAL_MINGW64_DDK_INCLUDE_DIR := $(LOCAL_MINGW64_BUILD_DIR)/x86_64-w64-mingw32/include/ddk
+CMAKE = cmake
CC = $(LOCAL_MINGW64_CC)
CXX = $(dir $(CC))/x86_64-w64-mingw32-g++
DDK_INCLUDE_DIR = $(LOCAL_MINGW64_DDK_INCLUDE_DIR)
-CFLAGS = -Wall -m64 -shared \
+CFLAGS := -Wall -Wextra -m64 -shared \
-I$(DDK_INCLUDE_DIR) \
-D__INTRINSIC_DEFINED_InterlockedBitTestAndSet \
-D__INTRINSIC_DEFINED_InterlockedBitTestAndReset
+CXXFLAGS := -fno-exceptions -fno-rtti
+EASTL_CXXFLAGS := -IEASTL/include -IEASTL/test/packages/EABase/include/Common \
+ -DEASTL_THREAD_SUPPORT_AVAILABLE=0 \
+ -DEASTL_EXCEPTIONS_ENABLED=0 \
+ -DEASTL_ASSERT_ENABLED=0 \
+ -DEA_COMPILER_NO_EXCEPTIONS=1 \
+ -DEA_COMPILER_MANAGED_CPP=1 \
+ -Wno-unknown-pragmas \
+ -Wno-deprecated-copy \
+ -Wl,--gc-sections
+EASTL_STATIC_LIB := EASTL-build/libEASTL.a
+EASTL_COMPAT := EASTL-compat/kcrt.opp
1_DRIVER_NAME = ddk-template
1_OBJECTS = $(1_DRIVER_NAME).o
@@ -19,9 +32,13 @@ CFLAGS = -Wall -m64 -shared \
2_OBJECTS = $(2_DRIVER_NAME).opp
2_TARGET = $(2_DRIVER_NAME).sys
-all: deps-print-local-notice check-vars $(1_TARGET) $(2_TARGET)
+3_DRIVER_NAME = ddk-template-cplusplus-EASTL
+3_OBJECTS = $(3_DRIVER_NAME).opp
+3_TARGET = $(3_DRIVER_NAME).sys
-deps-print-local-notice:
+all: deps-print-local-notice check-vars $(1_TARGET) $(2_TARGET) $(3_TARGET)
+
+deps-print-local-notice: $(CC)
ifeq ($(CC),$(LOCAL_MINGW64_CC))
ifeq ($(DDK_INCLUDE_DIR),$(LOCAL_MINGW64_DDK_INCLUDE_DIR))
@echo
@@ -80,15 +97,31 @@ endif
deps: .deps-built
+$(EASTL_STATIC_LIB): .deps-built
+ mkdir -p EASTL-build
+ cd EASTL-build && \
+ $(CMAKE) ../EASTL \
+ -DCMAKE_CXX_COMPILER="$(realpath $(CXX))" \
+ -DCMAKE_SYSTEM_NAME="Windows" \
+ -DCMAKE_CXX_FLAGS='-ffunction-sections -fdata-sections $(CXXFLAGS) $(EASTL_CXXFLAGS)' && \
+ $(MAKE) VERBOSE=1
+
+distclean: clean
+ rm -f .deps-built
+ rm -rf $(LOCAL_MINGW64_BUILD_DIR)
+
clean:
rm -f $(1_OBJECTS) $(1_TARGET)
rm -f $(2_OBJECTS) $(2_TARGET)
+ rm -f $(3_OBJECTS) $(3_TARGET)
+ rm -f $(EASTL_COMPAT) $(EASTL_STATIC_LIB)
+ $(MAKE) -C EASTL-build clean
-%.o: %.c
+%.o: %.c .deps-built
$(CC) $(CFLAGS) -c $< -o $@
-%.opp: %.cpp
- $(CXX) $(CFLAGS) -c $< -o $@
+%.opp: %.cpp .deps-built
+ $(CXX) $(CFLAGS) $(CXXFLAGS) $(EASTL_CXXFLAGS) -c $< -o $@
$(1_TARGET): .deps-built $(1_OBJECTS)
$(CC) -std=c99 $(CFLAGS) -Wl,--subsystem,native -Wl,--image-base,0x140000000 -Wl,--dynamicbase -Wl,--nxcompat \
@@ -101,3 +134,9 @@ $(2_TARGET): .deps-built $(2_OBJECTS)
-Wl,--file-alignment,0x200 -Wl,--section-alignment,0x1000 -Wl,--stack,0x100000 \
-Wl,--entry,DriverEntry@8 -nostartfiles -nostdlib -o $(2_TARGET) \
$(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 \
+ -Wl,--file-alignment,0x200 -Wl,--section-alignment,0x1000 -Wl,--stack,0x100000 \
+ -Wl,--entry,DriverEntry@8 -nostartfiles -nostdlib -o $(3_TARGET) \
+ $(3_OBJECTS) $(EASTL_COMPAT) $(EASTL_STATIC_LIB) -lntoskrnl -lhal
diff --git a/README.md b/README.md
index 980494c..b7d4644 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
-# Mingw64 [D]river [D]evelopment [K]it - Template
+# Mingw64 Driver Plus Plus
A demonstration on how to compile Windows kernel drivers using Mingw64.
-## How?
+It provides also an example with a feature complete STL including your
+beloved containers.
You will need an modern Mingw64-GCC toolchain.
Do not use any broken toolchains like the one shipped with debian-10.
@@ -10,8 +11,9 @@ Instead either use Zeranoe's build script with `make deps` or use your own.
## What?
-1. ddk-template: plain and stupid ddk example
-2. ddk-template-cplusplus: same, but in C++, including a very complex class
+1. ddk-template: plain and stupid ddk C example
+2. ddk-template-cplusplus: same, but written in C++, including a very complex class
+3. ddk-template-cplusplus: C++ example w/ (EA)STL integration, everything usable except for Threads
## Build and Test
@@ -32,3 +34,8 @@ Build Mingw64 only:
``
make deps
``
+
+## Thanks!
+
+- [Zeranoe](https://github.com/Zeranoe/mingw-w64-build) for the Mingw64 build script
+- [sidhye](https://github.com/sidhye/dxx) for some copy paste ready CRT code ;)
diff --git a/ddk-template-cplusplus-EASTL.cpp b/ddk-template-cplusplus-EASTL.cpp
new file mode 100644
index 0000000..e099488
--- /dev/null
+++ b/ddk-template-cplusplus-EASTL.cpp
@@ -0,0 +1,125 @@
+#include <ntddk.h>
+
+#include <cstdint>
+
+#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>
+
+// C&P from: https://raw.githubusercontent.com/sidyhe/dxx/ed06aba3b91fe8e101d08c33c26ba73db96acef0/README.md
+void stl_test()
+{
+ eastl::make_unique<DRIVER_OBJECT>();
+ eastl::make_shared<UNICODE_STRING>();
+ eastl::scoped_ptr<double> dptr(new double(3.6));
+
+ eastl::set<int> set_test;
+ set_test.insert(1);
+ set_test.insert(3);
+ set_test.insert(5);
+ set_test.erase(1);
+
+ eastl::map<int, int> map_test;
+ map_test[0] = 1;
+ map_test[10] = 11;
+ map_test[20] = 12;
+ map_test.erase(11);
+
+ eastl::vector<int> vec_test;
+ vec_test.push_back(2);
+ vec_test.push_back(3);
+ vec_test.push_back(1);
+ eastl::stable_sort(vec_test.begin(), vec_test.end(), eastl::less<int>());
+ for (auto e : vec_test)
+ {
+ DbgPrint("%d\n", e);
+ }
+
+ eastl::string s;
+ s = "This a string";
+ s.append("any");
+ DbgPrint("%s\n", s.c_str());
+
+ eastl::wstring ws;
+ ws = L"wide string";
+ ws.clear();
+
+ eastl::unordered_set<float> us_test;
+ us_test.insert(333);
+
+ eastl::unordered_map<double, eastl::string> um_test;
+ um_test.insert(eastl::make_pair(6.6, "9.9"));
+}
+
+void more_stl_test()
+{
+ eastl::hash_map<int, eastl::string> hm;
+
+ hm[0] = "test1";
+ hm[10] = "test2";
+ hm[20] = "test3";
+ for (auto s : hm)
+ {
+ DbgPrint("%s\n", s.second.c_str());
+ }
+
+ eastl::uniform_int_distribution<std::uint32_t> uid(1, UINT32_MAX);
+ DbgPrint("PRNG: %u\n", uid);
+
+ auto lambda = [] { DbgPrint("Hello lambda!\n"); };
+ eastl::function<void(void)> fn = lambda;
+ fn();
+
+ auto lambda2 = [](int n) {
+ DbgPrint("Hello lambda2, %u!\n", n);
+ return n;
+ };
+ eastl::function<int(int)> fn2 = lambda2;
+ fn2(1337);
+
+ eastl::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());
+}
+
+extern "C"
+{
+
+ DRIVER_INITIALIZE DriverEntry;
+ DRIVER_UNLOAD DriverUnload;
+
+ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT * DriverObject, _In_ PUNICODE_STRING RegistryPath)
+ {
+ (void)DriverObject;
+ (void)RegistryPath;
+
+ DbgPrint("%s\n", "Hello ring0!");
+
+ /* support for service stopping */
+ DriverObject->DriverUnload = DriverUnload;
+
+ stl_test();
+ more_stl_test();
+
+ return STATUS_SUCCESS;
+ }
+
+ VOID DriverUnload(_In_ struct _DRIVER_OBJECT * DriverObject)
+ {
+ (void)DriverObject;
+
+ DbgPrint("%s\n", "Bye ring0!");
+ }
+}
diff --git a/ddk-template-cplusplus.cpp b/ddk-template-cplusplus.cpp
index 3ab6257..f4e3ce4 100644
--- a/ddk-template-cplusplus.cpp
+++ b/ddk-template-cplusplus.cpp
@@ -1,11 +1,11 @@
#include <ntddk.h>
-#include <vector>
-
class TestSmth
{
public:
- TestSmth() {}
+ TestSmth()
+ {
+ }
void doSmth(void)
{
DbgPrint("%s\n", "Hello Class!");
@@ -21,30 +21,28 @@ static void test_cplusplus(void)
extern "C"
{
-DRIVER_INITIALIZE DriverEntry;
-DRIVER_UNLOAD DriverUnload;
+ DRIVER_INITIALIZE DriverEntry;
+ DRIVER_UNLOAD DriverUnload;
-NTSTATUS DriverEntry(
- _In_ struct _DRIVER_OBJECT *DriverObject,
- _In_ PUNICODE_STRING RegistryPath
-)
-{
- DbgPrint("%s\n", "Hello ring0!");
+ NTSTATUS DriverEntry(_In_ struct _DRIVER_OBJECT * DriverObject, _In_ PUNICODE_STRING RegistryPath)
+ {
+ (void)DriverObject;
+ (void)RegistryPath;
- /* support for service stopping */
- DriverObject->DriverUnload = DriverUnload;
+ DbgPrint("%s\n", "Hello ring0!");
- test_cplusplus();
+ /* support for service stopping */
+ DriverObject->DriverUnload = DriverUnload;
- return STATUS_SUCCESS;
-}
+ test_cplusplus();
-VOID
-DriverUnload(
- _In_ struct _DRIVER_OBJECT *DriverObject
-)
-{
- DbgPrint("%s\n", "Bye ring0!");
-}
+ return STATUS_SUCCESS;
+ }
+ VOID DriverUnload(_In_ struct _DRIVER_OBJECT * DriverObject)
+ {
+ (void)DriverObject;
+
+ DbgPrint("%s\n", "Bye ring0!");
+ }
}
diff --git a/ddk-template.c b/ddk-template.c
index 9374b1f..9667b18 100644
--- a/ddk-template.c
+++ b/ddk-template.c
@@ -8,6 +8,9 @@ NTSTATUS DriverEntry(
_In_ PUNICODE_STRING RegistryPath
)
{
+ (void)DriverObject;
+ (void)RegistryPath;
+
DbgPrint("%s\n", "Hello ring0!");
/* support for service stopping */
@@ -21,5 +24,7 @@ DriverUnload(
_In_ struct _DRIVER_OBJECT *DriverObject
)
{
+ (void)DriverObject;
+
DbgPrint("%s\n", "Bye ring0!");
}