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