1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Kernel-Mode Test Suite test framework declarations
5 * COPYRIGHT: Copyright 2011-2018 Thomas Faber <thomas.faber@reactos.org>
6 * Copyright 2013 Nikolay Borisov <nib9@aber.ac.uk>
7 * Copyright 2014-2016 Pierre Schweitzer <pierre@reactos.org>
8 * Copyright 2017 Ged Murphy <gedmurphy@reactos.org>
9 */
10
11 /* Inspired by Wine C unit tests, Copyright (C) 2002 Alexandre Julliard
12 * Inspired by ReactOS kernel-mode regression tests,
13 * Copyright (C) Aleksey Bragin, Filip Navara
14 */
15
16 #ifndef _KMTEST_TEST_H_
17 #define _KMTEST_TEST_H_
18
19 #include <kmt_platform.h>
20
21 typedef VOID KMT_TESTFUNC(VOID);
22 typedef KMT_TESTFUNC *PKMT_TESTFUNC;
23
24 typedef struct
25 {
26 const char *TestName;
27 KMT_TESTFUNC *TestFunction;
28 } KMT_TEST, *PKMT_TEST;
29
30 typedef const KMT_TEST CKMT_TEST, *PCKMT_TEST;
31
32 extern const KMT_TEST TestList[];
33
34 typedef struct
35 {
36 volatile LONG Successes;
37 volatile LONG Failures;
38 volatile LONG Skipped;
39 volatile LONG LogBufferLength;
40 LONG LogBufferMaxLength;
41 CHAR LogBuffer[ANYSIZE_ARRAY];
42 } KMT_RESULTBUFFER, *PKMT_RESULTBUFFER;
43
44 #ifndef KMT_STANDALONE_DRIVER
45
46 /* usermode call-back mechanism */
47
48 /* list of supported operations */
49 typedef enum _KMT_CALLBACK_INFORMATION_CLASS
50 {
51 QueryVirtualMemory
52 } KMT_CALLBACK_INFORMATION_CLASS, *PKMT_CALLBACK_INFORMATION_CLASS;
53
54 /* TODO: "response" is a little generic */
55 typedef union _KMT_RESPONSE
56 {
57 MEMORY_BASIC_INFORMATION MemInfo;
58 } KMT_RESPONSE, *PKMT_RESPONSE;
59
60 /* this struct is sent from driver to usermode */
61 typedef struct _KMT_CALLBACK_REQUEST_PACKET
62 {
63 ULONG RequestId;
64 KMT_CALLBACK_INFORMATION_CLASS OperationClass;
65 PVOID Parameters;
66 } KMT_CALLBACK_REQUEST_PACKET, *PKMT_CALLBACK_REQUEST_PACKET;
67
68 PKMT_RESPONSE KmtUserModeCallback(KMT_CALLBACK_INFORMATION_CLASS Operation, PVOID Parameters);
69 VOID KmtFreeCallbackResponse(PKMT_RESPONSE Response);
70
71 //macro to simplify using the mechanism
72 #define Test_NtQueryVirtualMemory(BaseAddress, Size, AllocationType, ProtectionType) \
73 do { \
74 PKMT_RESPONSE NtQueryTest = KmtUserModeCallback(QueryVirtualMemory, BaseAddress); \
75 if (NtQueryTest != NULL) \
76 { \
77 ok_eq_hex(NtQueryTest->MemInfo.Protect, ProtectionType); \
78 ok_eq_hex(NtQueryTest->MemInfo.State, AllocationType); \
79 ok_eq_size(NtQueryTest->MemInfo.RegionSize, Size); \
80 KmtFreeCallbackResponse(NtQueryTest); \
81 } \
82 } while (0) \
83
84 #endif
85
86 #ifdef KMT_STANDALONE_DRIVER
87 #define KMT_KERNEL_MODE
88
89 typedef NTSTATUS (KMT_IRP_HANDLER)(
90 IN PDEVICE_OBJECT DeviceObject,
91 IN PIRP Irp,
92 IN PIO_STACK_LOCATION IoStackLocation);
93 typedef KMT_IRP_HANDLER *PKMT_IRP_HANDLER;
94
95 NTSTATUS KmtRegisterIrpHandler(IN UCHAR MajorFunction, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_IRP_HANDLER IrpHandler);
96 NTSTATUS KmtUnregisterIrpHandler(IN UCHAR MajorFunction, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_IRP_HANDLER IrpHandler);
97
98 typedef NTSTATUS (KMT_MESSAGE_HANDLER)(
99 IN PDEVICE_OBJECT DeviceObject,
100 IN ULONG ControlCode,
101 IN PVOID Buffer OPTIONAL,
102 IN SIZE_T InLength,
103 IN OUT PSIZE_T OutLength);
104 typedef KMT_MESSAGE_HANDLER *PKMT_MESSAGE_HANDLER;
105
106 NTSTATUS KmtRegisterMessageHandler(IN ULONG ControlCode OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_MESSAGE_HANDLER MessageHandler);
107 NTSTATUS KmtUnregisterMessageHandler(IN ULONG ControlCode OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PKMT_MESSAGE_HANDLER MessageHandler);
108
109 typedef enum
110 {
111 TESTENTRY_NO_CREATE_DEVICE = 1,
112 TESTENTRY_NO_REGISTER_DISPATCH = 2,
113 TESTENTRY_NO_REGISTER_UNLOAD = 4,
114 TESTENTRY_NO_EXCLUSIVE_DEVICE = 8,
115 TESTENTRY_NO_READONLY_DEVICE = 16,
116 TESTENTRY_BUFFERED_IO_DEVICE = 32,
117 } KMT_TESTENTRY_FLAGS;
118
119 NTSTATUS TestEntry(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath, OUT PCWSTR *DeviceName, IN OUT INT *Flags);
120 VOID TestUnload(IN PDRIVER_OBJECT DriverObject);
121 #endif /* defined KMT_STANDALONE_DRIVER */
122
123 #ifdef KMT_FILTER_DRIVER
124 #ifndef KMT_KERNEL_MODE
125 #define KMT_KERNEL_MODE
126 #endif
127
128 NTSTATUS KmtFilterRegisterCallbacks(_In_ CONST FLT_OPERATION_REGISTRATION *OperationRegistration);
129
130 typedef enum
131 {
132 TESTENTRY_NO_REGISTER_FILTER = 0x01,
133 TESTENTRY_NO_CREATE_COMMS_PORT = 0x02,
134 TESTENTRY_NO_START_FILTERING = 0x04,
135 TESTENTRY_NO_INSTANCE_SETUP = 0x08,
136 TESTENTRY_NO_QUERY_TEARDOWN = 0x10,
137 TESTENTRY_NO_ALL = 0xFF
138 } KMT_MINIFILTER_FLAGS;
139
140 VOID TestFilterUnload(_In_ ULONG Flags);
141 NTSTATUS TestInstanceSetup(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_SETUP_FLAGS Flags, _In_ DEVICE_TYPE VolumeDeviceType, _In_ FLT_FILESYSTEM_TYPE VolumeFilesystemType, _In_ PUNICODE_STRING VolumeName, _In_ ULONG RealSectorSize, _In_ ULONG SectorSize);
142 VOID TestQueryTeardown(_In_ PCFLT_RELATED_OBJECTS FltObjects, _In_ FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags);
143
144 NTSTATUS KmtFilterRegisterComms(_In_ PFLT_CONNECT_NOTIFY ConnectNotifyCallback, _In_ PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback, _In_opt_ PFLT_MESSAGE_NOTIFY MessageNotifyCallback, _In_ LONG MaxClientConnections);
145
146 #endif/* defined KMT_FILTER_DRIVER */
147
148
149 #ifdef KMT_KERNEL_MODE
150 /* Device Extension layout */
151 typedef struct
152 {
153 PKMT_RESULTBUFFER ResultBuffer;
154 PMDL Mdl;
155 } KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
156
157 extern BOOLEAN KmtIsCheckedBuild;
158 extern BOOLEAN KmtIsMultiProcessorBuild;
159 extern PCSTR KmtMajorFunctionNames[];
160 extern PDRIVER_OBJECT KmtDriverObject;
161
162 VOID KmtSetIrql(IN KIRQL NewIrql);
163 BOOLEAN KmtAreInterruptsEnabled(VOID);
164 ULONG KmtGetPoolTag(PVOID Memory);
165 USHORT KmtGetPoolType(PVOID Memory);
166 PVOID KmtGetSystemRoutineAddress(IN PCWSTR RoutineName);
167 PKTHREAD KmtStartThread(IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext OPTIONAL);
168 VOID KmtFinishThread(IN PKTHREAD Thread OPTIONAL, IN PKEVENT Event OPTIONAL);
169 #elif defined KMT_USER_MODE
170 DWORD KmtRunKernelTest(IN PCSTR TestName);
171
172 DWORD KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
173 VOID KmtUnloadDriverKeepService(VOID);
174 VOID KmtUnloadDriver(VOID);
175 DWORD KmtOpenDriver(VOID);
176 VOID KmtCloseDriver(VOID);
177 DWORD KmtLoadAndOpenDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
178
179 DWORD KmtSendToDriver(IN DWORD ControlCode);
180 DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String);
181 DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String);
182 DWORD KmtSendUlongToDriver(IN DWORD ControlCode, IN DWORD Value);
183 DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength);
184
185
186 DWORD KmtFltCreateService(_In_z_ PCWSTR ServiceName, _In_z_ PCWSTR DisplayName, _Out_ SC_HANDLE *ServiceHandle);
187 DWORD KmtFltDeleteService(_In_opt_z_ PCWSTR ServiceName, _Inout_ SC_HANDLE *ServiceHandle);
188 DWORD KmtFltAddAltitude(_In_z_ LPWSTR Altitude);
189 DWORD KmtFltLoadDriver(_In_ BOOLEAN EnableDriverLoadPrivlege, _In_ BOOLEAN RestartIfRunning, _In_ BOOLEAN ConnectComms, _Out_ HANDLE *hPort);
190 DWORD KmtFltUnloadDriver(_In_ HANDLE *hPort, _In_ BOOLEAN DisonnectComms);
191 DWORD KmtFltConnectComms(_Out_ HANDLE *hPort);
192 DWORD KmtFltDisconnectComms(_In_ HANDLE hPort);
193 DWORD KmtFltRunKernelTest(_In_ HANDLE hPort, _In_z_ PCSTR TestName);
194 DWORD KmtFltSendToDriver(_In_ HANDLE hPort, _In_ DWORD Message);
195 DWORD KmtFltSendStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCSTR String);
196 DWORD KmtFltSendWStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCWSTR String);
197 DWORD KmtFltSendUlongToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ DWORD Value);
198 DWORD KmtFltSendBufferToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_reads_bytes_(BufferSize) LPVOID Buffer, _In_ DWORD BufferSize, _Out_writes_bytes_to_opt_(dwOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, _In_ DWORD dwOutBufferSize, _Out_opt_ LPDWORD lpBytesReturned);
199
200 #else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
201 #error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined
202 #endif /* !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
203
204 extern PKMT_RESULTBUFFER ResultBuffer;
205
206 #ifdef __GNUC__
207 /* TODO: GCC doesn't understand %wZ :( */
208 #define KMT_FORMAT(type, fmt, first) /*__attribute__((__format__(type, fmt, first)))*/
209 #elif !defined __GNUC__
210 #define KMT_FORMAT(type, fmt, first)
211 #endif /* !defined __GNUC__ */
212
213 #define START_TEST(name) VOID Test_##name(VOID)
214
215 #ifndef KMT_STRINGIZE
216 #define KMT_STRINGIZE(x) #x
217 #endif /* !defined KMT_STRINGIZE */
218 #define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
219 #define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
220 #define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
221
222 #define ok_(test, file, line, ...) KmtOk(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
223 #define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line), __VA_ARGS__)
224 #define skip_(test, file, line, ...) KmtSkip(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
225
226 BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
227 BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
228 VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 2, 0);
229 VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 2, 3);
230 BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
231 BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
232 PVOID KmtAllocateGuarded(SIZE_T SizeRequested);
233 VOID KmtFreeGuarded(PVOID Pointer);
234
235 #ifdef KMT_KERNEL_MODE
236 #define ok_irql(irql) ok(KeGetCurrentIrql() == irql, "IRQL is %d, expected %d\n", KeGetCurrentIrql(), irql)
237 #endif /* defined KMT_KERNEL_MODE */
238 #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
239 #define ok_eq_pointer(value, expected) ok_eq_print(value, expected, "%p")
240 #define ok_eq_int(value, expected) ok_eq_print(value, expected, "%d")
241 #define ok_eq_uint(value, expected) ok_eq_print(value, expected, "%u")
242 #define ok_eq_long(value, expected) ok_eq_print(value, expected, "%ld")
243 #define ok_eq_ulong(value, expected) ok_eq_print(value, expected, "%lu")
244 #define ok_eq_longlong(value, expected) ok_eq_print(value, expected, "%I64d")
245 #define ok_eq_ulonglong(value, expected) ok_eq_print(value, expected, "%I64u")
246 #define ok_eq_char(value, expected) ok_eq_print(value, expected, "%c")
247 #define ok_eq_wchar(value, expected) ok_eq_print(value, expected, "%C")
248 #ifndef _WIN64
249 #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%lu")
250 #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%ld")
251 #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%lu")
252 #elif defined _WIN64
253 #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%I64u")
254 #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%I64d")
255 #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%I64u")
256 #endif /* defined _WIN64 */
257 #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
258 #define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
259 #define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
260 #define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", \
261 (value) ? "TRUE" : "FALSE", \
262 (expected) ? "TRUE" : "FALSE")
263 #define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
264 #define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
265 #define ok_eq_tag(value, expected) ok_eq_print(value, expected, "0x%08lx")
266
267 #define ok_eq_hex64(value, expected) ok_eq_print(value, expected, "%I64x")
268 #define ok_eq_xmm(value, expected) ok((value).Low == (expected).Low, #value " = %I64x'%08I64x, expected %I64x'%08I64x\n", (value).Low, (value).High, (expected).Low, (expected).High)
269
270 #define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
271 0xC00 + (ControlCode), \
272 METHOD_BUFFERED, \
273 FILE_ANY_ACCESS)
274
275 #define MICROSECOND 10
276 #define MILLISECOND (1000 * MICROSECOND)
277 #define SECOND (1000 * MILLISECOND)
278
279 /* See apitests/include/apitest.h */
280 #define KmtInvalidPointer ((PVOID)0x5555555555555555ULL)
281
282 #define KmtStartSeh() \
283 { \
284 NTSTATUS ExceptionStatus = STATUS_SUCCESS; \
285 _SEH2_TRY \
286 {
287
288 #define KmtEndSeh(ExpectedStatus) \
289 } \
290 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
291 { \
292 ExceptionStatus = _SEH2_GetExceptionCode(); \
293 } \
294 _SEH2_END; \
295 ok_eq_hex(ExceptionStatus, (ExpectedStatus)); \
296 }
297
298 #define KmtGetSystemOrEmbeddedRoutineAddress(RoutineName) \
299 p##RoutineName = KmtGetSystemRoutineAddress(L ## #RoutineName); \
300 if (!p##RoutineName) \
301 { \
302 p##RoutineName = RoutineName; \
303 trace("Using embedded routine for " #RoutineName "\n"); \
304 } \
305 else \
306 trace("Using system routine for " #RoutineName "\n");
307
308 #if defined KMT_DEFINE_TEST_FUNCTIONS
309
310 #if defined KMT_KERNEL_MODE
311 #include "kmt_test_kernel.h"
312 #elif defined KMT_USER_MODE
313 #include "kmt_test_user.h"
314 #endif /* defined KMT_USER_MODE */
315
316 PKMT_RESULTBUFFER ResultBuffer = NULL;
317
KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer,PCSTR String,SIZE_T Length)318 static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Length)
319 {
320 LONG OldLength;
321 LONG NewLength;
322
323 if (!Buffer)
324 return;
325
326 do
327 {
328 OldLength = Buffer->LogBufferLength;
329 NewLength = OldLength + (ULONG)Length;
330 if (NewLength > Buffer->LogBufferMaxLength)
331 return;
332 } while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
333
334 memcpy(&Buffer->LogBuffer[OldLength], String, Length);
335 }
336
337 KMT_FORMAT(ms_printf, 5, 0)
KmtXVSNPrintF(PSTR Buffer,SIZE_T BufferMaxLength,PCSTR FileAndLine,PCSTR Prepend,PCSTR Format,va_list Arguments)338 static SIZE_T KmtXVSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, va_list Arguments)
339 {
340 SIZE_T BufferLength = 0;
341 SIZE_T Length;
342
343 if (FileAndLine)
344 {
345 PCSTR Slash;
346 Slash = strrchr(FileAndLine, '\\');
347 if (Slash)
348 FileAndLine = Slash + 1;
349 Slash = strrchr(FileAndLine, '/');
350 if (Slash)
351 FileAndLine = Slash + 1;
352
353 Length = min(BufferMaxLength, strlen(FileAndLine));
354 memcpy(Buffer, FileAndLine, Length);
355 Buffer += Length;
356 BufferLength += Length;
357 BufferMaxLength -= Length;
358 }
359 if (Prepend)
360 {
361 Length = min(BufferMaxLength, strlen(Prepend));
362 memcpy(Buffer, Prepend, Length);
363 Buffer += Length;
364 BufferLength += Length;
365 BufferMaxLength -= Length;
366 }
367 if (Format)
368 {
369 Length = KmtVSNPrintF(Buffer, BufferMaxLength, Format, Arguments);
370 /* vsnprintf can return more than maxLength, we don't want to do that */
371 BufferLength += min(Length, BufferMaxLength);
372 }
373 return BufferLength;
374 }
375
376 KMT_FORMAT(ms_printf, 5, 6)
KmtXSNPrintF(PSTR Buffer,SIZE_T BufferMaxLength,PCSTR FileAndLine,PCSTR Prepend,PCSTR Format,...)377 static SIZE_T KmtXSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, ...)
378 {
379 SIZE_T BufferLength;
380 va_list Arguments;
381 va_start(Arguments, Format);
382 BufferLength = KmtXVSNPrintF(Buffer, BufferMaxLength, FileAndLine, Prepend, Format, Arguments);
383 va_end(Arguments);
384 return BufferLength;
385 }
386
KmtFinishTest(PCSTR TestName)387 VOID KmtFinishTest(PCSTR TestName)
388 {
389 CHAR MessageBuffer[512];
390 SIZE_T MessageLength;
391
392 if (!ResultBuffer)
393 return;
394
395 MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL,
396 "%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
397 TestName,
398 ResultBuffer->Successes + ResultBuffer->Failures,
399 ResultBuffer->Failures,
400 ResultBuffer->Skipped);
401 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
402 }
403
KmtVOk(INT Condition,PCSTR FileAndLine,PCSTR Format,va_list Arguments)404 BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
405 {
406 CHAR MessageBuffer[512];
407 SIZE_T MessageLength;
408
409 if (!ResultBuffer)
410 return Condition != 0;
411
412 if (Condition)
413 {
414 InterlockedIncrement(&ResultBuffer->Successes);
415
416 if (0/*KmtReportSuccess*/)
417 {
418 MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test succeeded\n", NULL);
419 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
420 }
421 }
422 else
423 {
424 InterlockedIncrement(&ResultBuffer->Failures);
425 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test failed: ", Format, Arguments);
426 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
427 }
428
429 return Condition != 0;
430 }
431
KmtOk(INT Condition,PCSTR FileAndLine,PCSTR Format,...)432 BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
433 {
434 BOOLEAN Ret;
435 va_list Arguments;
436 va_start(Arguments, Format);
437 Ret = KmtVOk(Condition, FileAndLine, Format, Arguments);
438 va_end(Arguments);
439 return Ret;
440 }
441
KmtVTrace(PCSTR FileAndLine,PCSTR Format,va_list Arguments)442 VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments)
443 {
444 CHAR MessageBuffer[512];
445 SIZE_T MessageLength;
446
447 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": ", Format, Arguments);
448 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
449 }
450
KmtTrace(PCSTR FileAndLine,PCSTR Format,...)451 VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...)
452 {
453 va_list Arguments;
454 va_start(Arguments, Format);
455 KmtVTrace(FileAndLine, Format, Arguments);
456 va_end(Arguments);
457 }
458
KmtVSkip(INT Condition,PCSTR FileAndLine,PCSTR Format,va_list Arguments)459 BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
460 {
461 CHAR MessageBuffer[512];
462 SIZE_T MessageLength;
463
464 if (!ResultBuffer)
465 return !Condition;
466
467 if (!Condition)
468 {
469 InterlockedIncrement(&ResultBuffer->Skipped);
470 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Tests skipped: ", Format, Arguments);
471 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
472 }
473
474 return !Condition;
475 }
476
KmtSkip(INT Condition,PCSTR FileAndLine,PCSTR Format,...)477 BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
478 {
479 BOOLEAN Ret;
480 va_list Arguments;
481 va_start(Arguments, Format);
482 Ret = KmtVSkip(Condition, FileAndLine, Format, Arguments);
483 va_end(Arguments);
484 return Ret;
485 }
486
KmtAllocateGuarded(SIZE_T SizeRequested)487 PVOID KmtAllocateGuarded(SIZE_T SizeRequested)
488 {
489 NTSTATUS Status;
490 SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
491 PVOID VirtualMemory = NULL;
492 PCHAR StartOfBuffer;
493
494 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
495
496 if (!NT_SUCCESS(Status))
497 return NULL;
498
499 Size -= PAGE_SIZE;
500 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
501 if (!NT_SUCCESS(Status))
502 {
503 Size = 0;
504 Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
505 ok_eq_hex(Status, STATUS_SUCCESS);
506 return NULL;
507 }
508
509 StartOfBuffer = VirtualMemory;
510 StartOfBuffer += Size - SizeRequested;
511
512 return StartOfBuffer;
513 }
514
KmtFreeGuarded(PVOID Pointer)515 VOID KmtFreeGuarded(PVOID Pointer)
516 {
517 NTSTATUS Status;
518 PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
519 SIZE_T Size = 0;
520
521 Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
522 ok_eq_hex(Status, STATUS_SUCCESS);
523 }
524
525 #endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
526
527 #endif /* !defined _KMTEST_TEST_H_ */
528