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