Rizin
unix-like reverse engineering framework and cli tools
test_winkernel.cpp
Go to the documentation of this file.
1 /* Capstone Disassembly Engine */
2 /* By Satoshi Tanda <tanda.sat@gmail.com>, 2016-2019 */
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
94 static void test()
95 {
96  KFLOATING_SAVE float_save;
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();
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()
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
151 EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
152 {
153  UNREFERENCED_PARAMETER(DriverObject);
154  UNREFERENCED_PARAMETER(RegistryPath);
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_
163 int __cdecl printf(const char * const format, ...)
164 {
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 }
voidpf void * buf
Definition: ioapi.h:138
KeRestoreFloatingPointState
Definition: kernel.h:142
KeSaveFloatingPointState
Definition: kernel.h:145
KeGetCurrentIrql
Definition: kernel.h:106
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
@ ok
Definition: lz4.c:1706
int args
Definition: mipsasm.c:18
int cs_snprintf(char *buffer, size_t size, const char *fmt,...)
Definition: utils.c:104
static void cs_winkernel_vsnprintf_test()
_Use_decl_annotations_ int __cdecl printf(const char *const format,...)
static void test()
EXTERN_C DRIVER_INITIALIZE DriverEntry
LONG NTSTATUS
Definition: win.h:198
#define NT_SUCCESS(status)
Definition: winapi.h:52
#define STATUS_CANCELLED
Definition: winapi.h:1824