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