1 /* Capstone Disassembly Engine */
2 /* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
3
4 #include <ntddk.h>
5
6 #include <capstone/platform.h>
7 #include <capstone/capstone.h>
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12
13 #include "../utils.h" // for cs_snprintf
14
15 #ifdef __cplusplus
16 }
17 #endif
18
19 EXTERN_C DRIVER_INITIALIZE DriverEntry;
20
21 #pragma warning(push)
22 #pragma warning(disable : 4005) // 'identifier' : macro redefinition
23 #pragma warning(disable : 4007) // 'main': must be '__cdecl'
24
25 // Drivers must protect floating point hardware state. See use of float.
26 // Use KeSaveFloatingPointState/KeRestoreFloatingPointState around floating
27 // point operations. Display Drivers should use the corresponding Eng... routines.
28 #pragma warning(disable : 28110) // Suppress this, as it is false positive.
29
30 // "Import" existing tests into this file. All code is encaptured into unique
31 // namespace so that the same name does not conflict. Beware that those code
32 // is going to be compiled as C++ source file and not C files because this file
33 // is C++.
34
35 namespace basic {
36 #include "test_basic.c"
37 } // namespace basic
38
39 namespace detail {
40 #include "test_detail.c"
41 } // namespace detail
42
43 namespace skipdata {
44 #include "test_skipdata.c"
45 } // namespace skipdata
46
47 namespace iter {
48 #include "test_iter.c"
49 } // namespace iter
50
51 namespace customized_mnem_ {
52 #include "test_customized_mnem.c"
53 } // namespace customized_mnem_
54
55 namespace arm {
56 #include "test_arm.c"
57 } // namespace arm
58
59 namespace arm64 {
60 #include "test_arm64.c"
61 } // namespace arm64
62
63 namespace mips {
64 #include "test_mips.c"
65 } // namespace mips
66
67 namespace m68k {
68 #include "test_m68k.c"
69 } // namespace m68k
70
71 namespace ppc {
72 #include "test_ppc.c"
73 } // namespace ppc
74
75 namespace sparc {
76 #include "test_sparc.c"
77 } // namespace sparc
78
79 namespace systemz {
80 #include "test_systemz.c"
81 } // namespace systemz
82
83 namespace x86 {
84 #include "test_x86.c"
85 } // namespace x86
86
87 namespace xcore {
88 #include "test_xcore.c"
89 } // namespace xcore
90
91 #pragma warning(pop)
92
93 // Exercises all existing regression tests
test()94 static void test()
95 {
96 KFLOATING_SAVE float_save;
97 NTSTATUS status;
98
99 // Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
100 // since our malloc implementation using ExAllocatePoolWithTag() is able to
101 // allocate memory only up to the DISPATCH_LEVEL level.
102 NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
103
104 // On a 32bit driver, KeSaveFloatingPointState() is required before using any
105 // Capstone function because Capstone can access to the MMX/x87 registers and
106 // 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
107 // KeRestoreFloatingPointState() after accessing them. See "Using Floating
108 // Point or MMX in a WDM Driver" on MSDN for more details.
109 status = KeSaveFloatingPointState(&float_save);
110 if (!NT_SUCCESS(status)) {
111 printf("ERROR: Failed to save floating point state!\n");
112 return;
113 }
114
115 basic::test();
116 detail::test();
117 skipdata::test();
118 iter::test();
119 customized_mnem_::test();
120 arm::test();
121 arm64::test();
122 mips::test();
123 m68k::test();
124 ppc::test();
125 sparc::test();
126 systemz::test();
127 x86::test();
128 xcore::test();
129
130 // Restores the nonvolatile floating-point context.
131 KeRestoreFloatingPointState(&float_save);
132 }
133
134 // Functional test for cs_winkernel_vsnprintf()
cs_winkernel_vsnprintf_test()135 static void cs_winkernel_vsnprintf_test()
136 {
137 char buf[10];
138 bool ok = true;
139 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0);
140 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0);
141 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0);
142 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0);
143 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0);
144 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0);
145 if (!ok) {
146 printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n");
147 }
148 }
149
150 // Driver entry point
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)151 EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
152 {
153 UNREFERENCED_PARAMETER(DriverObject);
154 UNREFERENCED_PARAMETER(RegistryPath);
155 cs_winkernel_vsnprintf_test();
156 test();
157 return STATUS_CANCELLED;
158 }
159
160 // This functions mimics printf() but does not return the same value as printf()
161 // would do. printf() is required to exercise regression tests.
162 _Use_decl_annotations_
printf(const char * format,...)163 int __cdecl printf(const char * format, ...)
164 {
165 NTSTATUS status;
166 va_list args;
167
168 va_start(args, format);
169 status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args);
170 va_end(args);
171 return NT_SUCCESS(status);
172 }
173