[KMTESTS:KE]
[reactos.git] / 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 } KMT_TESTENTRY_FLAGS;
113
114 NTSTATUS TestEntry(IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath, OUT PCWSTR *DeviceName, IN OUT INT *Flags);
115 VOID TestUnload(IN PDRIVER_OBJECT DriverObject);
116 #endif /* defined KMT_STANDALONE_DRIVER */
117
118 #ifdef KMT_KERNEL_MODE
119 /* Device Extension layout */
120 typedef struct
121 {
122 PKMT_RESULTBUFFER ResultBuffer;
123 PMDL Mdl;
124 } KMT_DEVICE_EXTENSION, *PKMT_DEVICE_EXTENSION;
125
126 extern BOOLEAN KmtIsCheckedBuild;
127 extern BOOLEAN KmtIsMultiProcessorBuild;
128 extern PCSTR KmtMajorFunctionNames[];
129 extern PDRIVER_OBJECT KmtDriverObject;
130
131 VOID KmtSetIrql(IN KIRQL NewIrql);
132 BOOLEAN KmtAreInterruptsEnabled(VOID);
133 ULONG KmtGetPoolTag(PVOID Memory);
134 USHORT KmtGetPoolType(PVOID Memory);
135 #elif defined KMT_USER_MODE
136 DWORD KmtRunKernelTest(IN PCSTR TestName);
137
138 VOID KmtLoadDriver(IN PCWSTR ServiceName, IN BOOLEAN RestartIfRunning);
139 VOID KmtUnloadDriver(VOID);
140 VOID KmtOpenDriver(VOID);
141 VOID KmtCloseDriver(VOID);
142
143 DWORD KmtSendToDriver(IN DWORD ControlCode);
144 DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String);
145 DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String);
146 DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength);
147 #else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
148 #error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined
149 #endif /* !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
150
151 extern PKMT_RESULTBUFFER ResultBuffer;
152
153 #ifdef __GNUC__
154 /* TODO: GCC doesn't understand %wZ :( */
155 #define KMT_FORMAT(type, fmt, first) /*__attribute__((__format__(type, fmt, first)))*/
156 #elif !defined __GNUC__
157 #define KMT_FORMAT(type, fmt, first)
158 #endif /* !defined __GNUC__ */
159
160 #define START_TEST(name) VOID Test_##name(VOID)
161
162 #ifndef KMT_STRINGIZE
163 #define KMT_STRINGIZE(x) #x
164 #endif /* !defined KMT_STRINGIZE */
165 #define ok(test, ...) ok_(test, __FILE__, __LINE__, __VA_ARGS__)
166 #define trace(...) trace_( __FILE__, __LINE__, __VA_ARGS__)
167 #define skip(test, ...) skip_(test, __FILE__, __LINE__, __VA_ARGS__)
168
169 #define ok_(test, file, line, ...) KmtOk(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
170 #define trace_(file, line, ...) KmtTrace( file ":" KMT_STRINGIZE(line), __VA_ARGS__)
171 #define skip_(test, file, line, ...) KmtSkip(test, file ":" KMT_STRINGIZE(line), __VA_ARGS__)
172
173 BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
174 BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
175 VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 2, 0);
176 VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 2, 3);
177 BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
178 BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...) KMT_FORMAT(ms_printf, 3, 4);
179 PVOID KmtAllocateGuarded(SIZE_T SizeRequested);
180 VOID KmtFreeGuarded(PVOID Pointer);
181
182 #ifdef KMT_KERNEL_MODE
183 #define ok_irql(irql) ok(KeGetCurrentIrql() == irql, "IRQL is %d, expected %d\n", KeGetCurrentIrql(), irql)
184 #endif /* defined KMT_KERNEL_MODE */
185 #define ok_eq_print(value, expected, spec) ok((value) == (expected), #value " = " spec ", expected " spec "\n", value, expected)
186 #define ok_eq_pointer(value, expected) ok_eq_print(value, expected, "%p")
187 #define ok_eq_int(value, expected) ok_eq_print(value, expected, "%d")
188 #define ok_eq_uint(value, expected) ok_eq_print(value, expected, "%u")
189 #define ok_eq_long(value, expected) ok_eq_print(value, expected, "%ld")
190 #define ok_eq_ulong(value, expected) ok_eq_print(value, expected, "%lu")
191 #define ok_eq_longlong(value, expected) ok_eq_print(value, expected, "%I64d")
192 #define ok_eq_ulonglong(value, expected) ok_eq_print(value, expected, "%I64u")
193 #define ok_eq_char(value, expected) ok_eq_print(value, expected, "%c")
194 #define ok_eq_wchar(value, expected) ok_eq_print(value, expected, "%C")
195 #ifndef _WIN64
196 #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%lu")
197 #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%ld")
198 #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%lu")
199 #elif defined _WIN64
200 #define ok_eq_size(value, expected) ok_eq_print(value, (SIZE_T)(expected), "%I64u")
201 #define ok_eq_longptr(value, expected) ok_eq_print(value, (LONG_PTR)(expected), "%I64d")
202 #define ok_eq_ulongptr(value, expected) ok_eq_print(value, (ULONG_PTR)(expected), "%I64u")
203 #endif /* defined _WIN64 */
204 #define ok_eq_hex(value, expected) ok_eq_print(value, expected, "0x%08lx")
205 #define ok_bool_true(value, desc) ok((value) == TRUE, desc " FALSE, expected TRUE\n")
206 #define ok_bool_false(value, desc) ok((value) == FALSE, desc " TRUE, expected FALSE\n")
207 #define ok_eq_bool(value, expected) ok((value) == (expected), #value " = %s, expected %s\n", \
208 (value) ? "TRUE" : "FALSE", \
209 (expected) ? "TRUE" : "FALSE")
210 #define ok_eq_str(value, expected) ok(!strcmp(value, expected), #value " = \"%s\", expected \"%s\"\n", value, expected)
211 #define ok_eq_wstr(value, expected) ok(!wcscmp(value, expected), #value " = \"%ls\", expected \"%ls\"\n", value, expected)
212 #define ok_eq_tag(value, expected) ok_eq_print(value, expected, "0x%08lx")
213
214 #define KMT_MAKE_CODE(ControlCode) CTL_CODE(FILE_DEVICE_UNKNOWN, \
215 0xC00 + (ControlCode), \
216 METHOD_BUFFERED, \
217 FILE_ANY_ACCESS)
218
219 #define MICROSECOND 10
220 #define MILLISECOND (1000 * MICROSECOND)
221 #define SECOND (1000 * MILLISECOND)
222
223 /* See apitests/include/apitest.h */
224 #define KmtInvalidPointer ((PVOID)0x5555555555555555ULL)
225
226 #define KmtStartSeh() \
227 { \
228 NTSTATUS ExceptionStatus = STATUS_SUCCESS; \
229 _SEH2_TRY \
230 {
231
232 #define KmtEndSeh(ExpectedStatus) \
233 } \
234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) \
235 { \
236 ExceptionStatus = _SEH2_GetExceptionCode(); \
237 } \
238 _SEH2_END; \
239 ok_eq_hex(ExceptionStatus, (ExpectedStatus)); \
240 }
241
242 #if defined KMT_DEFINE_TEST_FUNCTIONS
243
244 #if defined KMT_KERNEL_MODE
245 BOOLEAN KmtIsCheckedBuild;
246 BOOLEAN KmtIsMultiProcessorBuild;
247 PCSTR KmtMajorFunctionNames[] =
248 {
249 "Create",
250 "CreateNamedPipe",
251 "Close",
252 "Read",
253 "Write",
254 "QueryInformation",
255 "SetInformation",
256 "QueryEa",
257 "SetEa",
258 "FlushBuffers",
259 "QueryVolumeInformation",
260 "SetVolumeInformation",
261 "DirectoryControl",
262 "FileSystemControl",
263 "DeviceControl",
264 "InternalDeviceControl/Scsi",
265 "Shutdown",
266 "LockControl",
267 "Cleanup",
268 "CreateMailslot",
269 "QuerySecurity",
270 "SetSecurity",
271 "Power",
272 "SystemControl",
273 "DeviceChange",
274 "QueryQuota",
275 "SetQuota",
276 "Pnp/PnpPower"
277 };
278
279 VOID KmtSetIrql(IN KIRQL NewIrql)
280 {
281 KIRQL Irql = KeGetCurrentIrql();
282 if (Irql > NewIrql)
283 KeLowerIrql(NewIrql);
284 else if (Irql < NewIrql)
285 KeRaiseIrql(NewIrql, &Irql);
286 }
287
288 BOOLEAN KmtAreInterruptsEnabled(VOID)
289 {
290 return (__readeflags() & (1 << 9)) != 0;
291 }
292
293 typedef struct _POOL_HEADER
294 {
295 union
296 {
297 struct
298 {
299 #ifdef _M_AMD64
300 USHORT PreviousSize:8;
301 USHORT PoolIndex:8;
302 USHORT BlockSize:8;
303 USHORT PoolType:8;
304 #else
305 USHORT PreviousSize:9;
306 USHORT PoolIndex:7;
307 USHORT BlockSize:9;
308 USHORT PoolType:7;
309 #endif
310 };
311 ULONG Ulong1;
312 };
313 #ifdef _M_AMD64
314 ULONG PoolTag;
315 #endif
316 union
317 {
318 #ifdef _M_AMD64
319 PEPROCESS ProcessBilled;
320 #else
321 ULONG PoolTag;
322 #endif
323 struct
324 {
325 USHORT AllocatorBackTraceIndex;
326 USHORT PoolTagHash;
327 };
328 };
329 } POOL_HEADER, *PPOOL_HEADER;
330
331 ULONG KmtGetPoolTag(PVOID Memory)
332 {
333 PPOOL_HEADER Header;
334
335 /* it's not so easy for allocations of PAGE_SIZE */
336 if (((ULONG_PTR)Memory & (PAGE_SIZE - 1)) == 0)
337 return 'TooL';
338
339 Header = Memory;
340 Header--;
341
342 return Header->PoolTag;
343 }
344
345 USHORT KmtGetPoolType(PVOID Memory)
346 {
347 PPOOL_HEADER Header;
348
349 /* it's not so easy for allocations of PAGE_SIZE */
350 if (((ULONG_PTR)Memory & (PAGE_SIZE - 1)) == 0)
351 return 0;
352
353 Header = Memory;
354 Header--;
355
356 return Header->PoolType;
357 }
358
359 INT __cdecl KmtVSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR Format, va_list Arguments) KMT_FORMAT(ms_printf, 3, 0);
360 #elif defined KMT_USER_MODE
361 static PKMT_RESULTBUFFER KmtAllocateResultBuffer(SIZE_T ResultBufferSize)
362 {
363 PKMT_RESULTBUFFER Buffer = HeapAlloc(GetProcessHeap(), 0, ResultBufferSize);
364 if (!Buffer)
365 return NULL;
366
367 Buffer->Successes = 0;
368 Buffer->Failures = 0;
369 Buffer->Skipped = 0;
370 Buffer->LogBufferLength = 0;
371 Buffer->LogBufferMaxLength = (ULONG)ResultBufferSize - FIELD_OFFSET(KMT_RESULTBUFFER, LogBuffer);
372
373 return Buffer;
374 }
375
376 static VOID KmtFreeResultBuffer(PKMT_RESULTBUFFER Buffer)
377 {
378 HeapFree(GetProcessHeap(), 0, Buffer);
379 }
380
381 #define KmtVSNPrintF vsnprintf
382 #endif /* defined KMT_USER_MODE */
383
384 PKMT_RESULTBUFFER ResultBuffer = NULL;
385
386 static VOID KmtAddToLogBuffer(PKMT_RESULTBUFFER Buffer, PCSTR String, SIZE_T Length)
387 {
388 LONG OldLength;
389 LONG NewLength;
390
391 if (!Buffer)
392 return;
393
394 do
395 {
396 OldLength = Buffer->LogBufferLength;
397 NewLength = OldLength + (ULONG)Length;
398 if (NewLength > Buffer->LogBufferMaxLength)
399 return;
400 } while (InterlockedCompareExchange(&Buffer->LogBufferLength, NewLength, OldLength) != OldLength);
401
402 memcpy(&Buffer->LogBuffer[OldLength], String, Length);
403 }
404
405 KMT_FORMAT(ms_printf, 5, 0)
406 static SIZE_T KmtXVSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, va_list Arguments)
407 {
408 SIZE_T BufferLength = 0;
409 SIZE_T Length;
410
411 if (FileAndLine)
412 {
413 PCSTR Slash;
414 Slash = strrchr(FileAndLine, '\\');
415 if (Slash)
416 FileAndLine = Slash + 1;
417 Slash = strrchr(FileAndLine, '/');
418 if (Slash)
419 FileAndLine = Slash + 1;
420
421 Length = min(BufferMaxLength, strlen(FileAndLine));
422 memcpy(Buffer, FileAndLine, Length);
423 Buffer += Length;
424 BufferLength += Length;
425 BufferMaxLength -= Length;
426 }
427 if (Prepend)
428 {
429 Length = min(BufferMaxLength, strlen(Prepend));
430 memcpy(Buffer, Prepend, Length);
431 Buffer += Length;
432 BufferLength += Length;
433 BufferMaxLength -= Length;
434 }
435 if (Format)
436 {
437 Length = KmtVSNPrintF(Buffer, BufferMaxLength, Format, Arguments);
438 /* vsnprintf can return more than maxLength, we don't want to do that */
439 BufferLength += min(Length, BufferMaxLength);
440 }
441 return BufferLength;
442 }
443
444 KMT_FORMAT(ms_printf, 5, 6)
445 static SIZE_T KmtXSNPrintF(PSTR Buffer, SIZE_T BufferMaxLength, PCSTR FileAndLine, PCSTR Prepend, PCSTR Format, ...)
446 {
447 SIZE_T BufferLength;
448 va_list Arguments;
449 va_start(Arguments, Format);
450 BufferLength = KmtXVSNPrintF(Buffer, BufferMaxLength, FileAndLine, Prepend, Format, Arguments);
451 va_end(Arguments);
452 return BufferLength;
453 }
454
455 VOID KmtFinishTest(PCSTR TestName)
456 {
457 CHAR MessageBuffer[512];
458 SIZE_T MessageLength;
459
460 if (!ResultBuffer)
461 return;
462
463 MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, NULL, NULL,
464 "%s: %ld tests executed (0 marked as todo, %ld failures), %ld skipped.\n",
465 TestName,
466 ResultBuffer->Successes + ResultBuffer->Failures,
467 ResultBuffer->Failures,
468 ResultBuffer->Skipped);
469 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
470 }
471
472 BOOLEAN KmtVOk(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
473 {
474 CHAR MessageBuffer[512];
475 SIZE_T MessageLength;
476
477 if (!ResultBuffer)
478 return Condition != 0;
479
480 if (Condition)
481 {
482 InterlockedIncrement(&ResultBuffer->Successes);
483
484 if (0/*KmtReportSuccess*/)
485 {
486 MessageLength = KmtXSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test succeeded\n", NULL);
487 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
488 }
489 }
490 else
491 {
492 InterlockedIncrement(&ResultBuffer->Failures);
493 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Test failed: ", Format, Arguments);
494 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
495 }
496
497 return Condition != 0;
498 }
499
500 BOOLEAN KmtOk(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
501 {
502 BOOLEAN Ret;
503 va_list Arguments;
504 va_start(Arguments, Format);
505 Ret = KmtVOk(Condition, FileAndLine, Format, Arguments);
506 va_end(Arguments);
507 return Ret;
508 }
509
510 VOID KmtVTrace(PCSTR FileAndLine, PCSTR Format, va_list Arguments)
511 {
512 CHAR MessageBuffer[512];
513 SIZE_T MessageLength;
514
515 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": ", Format, Arguments);
516 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
517 }
518
519 VOID KmtTrace(PCSTR FileAndLine, PCSTR Format, ...)
520 {
521 va_list Arguments;
522 va_start(Arguments, Format);
523 KmtVTrace(FileAndLine, Format, Arguments);
524 va_end(Arguments);
525 }
526
527 BOOLEAN KmtVSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, va_list Arguments)
528 {
529 CHAR MessageBuffer[512];
530 SIZE_T MessageLength;
531
532 if (!ResultBuffer)
533 return !Condition;
534
535 if (!Condition)
536 {
537 InterlockedIncrement(&ResultBuffer->Skipped);
538 MessageLength = KmtXVSNPrintF(MessageBuffer, sizeof MessageBuffer, FileAndLine, ": Tests skipped: ", Format, Arguments);
539 KmtAddToLogBuffer(ResultBuffer, MessageBuffer, MessageLength);
540 }
541
542 return !Condition;
543 }
544
545 BOOLEAN KmtSkip(INT Condition, PCSTR FileAndLine, PCSTR Format, ...)
546 {
547 BOOLEAN Ret;
548 va_list Arguments;
549 va_start(Arguments, Format);
550 Ret = KmtVSkip(Condition, FileAndLine, Format, Arguments);
551 va_end(Arguments);
552 return Ret;
553 }
554
555 PVOID KmtAllocateGuarded(SIZE_T SizeRequested)
556 {
557 NTSTATUS Status;
558 SIZE_T Size = PAGE_ROUND_UP(SizeRequested + PAGE_SIZE);
559 PVOID VirtualMemory = NULL;
560 PCHAR StartOfBuffer;
561
562 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_RESERVE, PAGE_NOACCESS);
563
564 if (!NT_SUCCESS(Status))
565 return NULL;
566
567 Size -= PAGE_SIZE;
568 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(), &VirtualMemory, 0, &Size, MEM_COMMIT, PAGE_READWRITE);
569 if (!NT_SUCCESS(Status))
570 {
571 Size = 0;
572 Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
573 ok_eq_hex(Status, STATUS_SUCCESS);
574 return NULL;
575 }
576
577 StartOfBuffer = VirtualMemory;
578 StartOfBuffer += Size - SizeRequested;
579
580 return StartOfBuffer;
581 }
582
583 VOID KmtFreeGuarded(PVOID Pointer)
584 {
585 NTSTATUS Status;
586 PVOID VirtualMemory = (PVOID)PAGE_ROUND_DOWN((SIZE_T)Pointer);
587 SIZE_T Size = 0;
588
589 Status = ZwFreeVirtualMemory(ZwCurrentProcess(), &VirtualMemory, &Size, MEM_RELEASE);
590 ok_eq_hex(Status, STATUS_SUCCESS);
591 }
592
593 #endif /* defined KMT_DEFINE_TEST_FUNCTIONS */
594
595 #endif /* !defined _KMTEST_TEST_H_ */