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