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 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) 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) 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 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 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 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 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 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 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 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 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 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