blob: 6413b1a2cb72e48cf0a24cf80a35899f8150b52c [file] [log] [blame]
tandasat45e5eab2016-05-11 21:48:32 -07001/* Capstone Disassembly Engine */
2/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
Satoshi Tanda565b6c32016-09-27 07:39:51 -07003
tandasat45e5eab2016-05-11 21:48:32 -07004#include <ntddk.h>
5
6#include <capstone/platform.h>
7#include <capstone/capstone.h>
8
9#ifdef __cplusplus
10extern "C" {
11#endif
12
13#include "../utils.h" // for cs_snprintf
14
15#ifdef __cplusplus
16}
17#endif
18
19EXTERN_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
Satoshi Tanda565b6c32016-09-27 07:39:51 -070025// Drivers must protect floating point hardware state. See use of float.
tandasat45e5eab2016-05-11 21:48:32 -070026// 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
35namespace basic {
36#include "test_basic.c"
37} // namespace basic
38
39namespace detail {
40#include "test_detail.c"
41} // namespace detail
42
43namespace skipdata {
44#include "test_skipdata.c"
45} // namespace skipdata
46
47namespace iter {
48#include "test_iter.c"
49} // namespace iter
50
51namespace customized_mnem_ {
52#include "test_customized_mnem.c"
53} // namespace customized_mnem_
54
55namespace arm {
56#include "test_arm.c"
57} // namespace arm
58
59namespace arm64 {
60#include "test_arm64.c"
61} // namespace arm64
62
63namespace mips {
64#include "test_mips.c"
65} // namespace mips
66
67namespace m68k {
68#include "test_m68k.c"
69} // namespace m68k
70
71namespace ppc {
72#include "test_ppc.c"
73} // namespace ppc
74
75namespace sparc {
76#include "test_sparc.c"
77} // namespace sparc
78
79namespace systemz {
80#include "test_systemz.c"
81} // namespace systemz
82
83namespace x86 {
84#include "test_x86.c"
85} // namespace x86
86
87namespace xcore {
88#include "test_xcore.c"
89} // namespace xcore
90
91#pragma warning(pop)
92
93// Exercises all existing regression tests
94static 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
Satoshi Tanda565b6c32016-09-27 07:39:51 -0700107 // KeRestoreFloatingPointState() after accessing them. See "Using Floating
tandasat45e5eab2016-05-11 21:48:32 -0700108 // 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()
135static 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
151EXTERN_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_
163int __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}