1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite Helper functions for NPFS tests 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #include "npfs.h" 10 11 NTSTATUS 12 NpCreatePipeEx( 13 OUT PHANDLE ServerHandle, 14 IN PCWSTR PipePath, 15 IN ULONG ReadMode, 16 IN ULONG CompletionMode, 17 IN ULONG NamedPipeType, 18 IN ULONG ShareAccess, 19 IN ULONG MaximumInstances, 20 IN ULONG InboundQuota, 21 IN ULONG OutboundQuota, 22 IN ACCESS_MASK DesiredAccess, 23 IN ULONG Disposition, 24 IN ULONG CreateOptions, 25 IN PLARGE_INTEGER DefaultTimeout OPTIONAL) 26 { 27 UNICODE_STRING ObjectName; 28 OBJECT_ATTRIBUTES ObjectAttributes; 29 NAMED_PIPE_CREATE_PARAMETERS Params; 30 IO_STATUS_BLOCK IoStatusBlock; 31 NTSTATUS Status; 32 33 RtlInitUnicodeString(&ObjectName, PipePath); 34 InitializeObjectAttributes(&ObjectAttributes, 35 &ObjectName, 36 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 37 NULL, 38 NULL); 39 40 Params.NamedPipeType = NamedPipeType; 41 Params.ReadMode = ReadMode; 42 Params.CompletionMode = CompletionMode; 43 Params.MaximumInstances = MaximumInstances; 44 Params.InboundQuota = InboundQuota; 45 Params.OutboundQuota = OutboundQuota; 46 if (DefaultTimeout) 47 { 48 Params.DefaultTimeout.QuadPart = DefaultTimeout->QuadPart; 49 Params.TimeoutSpecified = TRUE; 50 } 51 else 52 { 53 Params.DefaultTimeout.QuadPart = 0; 54 Params.TimeoutSpecified = FALSE; 55 } 56 57 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 58 Status = IoCreateFile(ServerHandle, 59 DesiredAccess, 60 &ObjectAttributes, 61 &IoStatusBlock, 62 NULL, /* AllocationSize */ 63 0, /* FileAttributes */ 64 ShareAccess, 65 Disposition, 66 CreateOptions, 67 NULL, /* EaBuffer */ 68 0, /* EaLength */ 69 CreateFileTypeNamedPipe, 70 &Params, 71 0); 72 if (NT_SUCCESS(Status)) 73 { 74 ok_eq_hex(IoStatusBlock.Status, Status); 75 ok_eq_ulongptr(IoStatusBlock.Information, FILE_CREATED); 76 } 77 else 78 { 79 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 80 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 81 } 82 return Status; 83 } 84 85 NTSTATUS 86 NpCreatePipe( 87 OUT PHANDLE ServerHandle, 88 PCWSTR PipePath, 89 ULONG ReadMode, 90 ULONG CompletionMode, 91 ULONG NamedPipeType, 92 ULONG NamedPipeConfiguration, 93 ULONG MaximumInstances, 94 ULONG InboundQuota, 95 ULONG OutboundQuota) 96 { 97 ULONG ShareAccess; 98 LARGE_INTEGER DefaultTimeout; 99 100 if (NamedPipeConfiguration == FILE_PIPE_INBOUND) 101 ShareAccess = FILE_SHARE_WRITE; 102 else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) 103 ShareAccess = FILE_SHARE_READ; 104 else if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) 105 ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; 106 107 DefaultTimeout.QuadPart = -50 * 1000 * 10; 108 109 return NpCreatePipeEx(ServerHandle, 110 PipePath, 111 ReadMode, 112 CompletionMode, 113 NamedPipeType, 114 ShareAccess, 115 MaximumInstances, 116 InboundQuota, 117 OutboundQuota, 118 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, 119 FILE_OPEN_IF, 120 FILE_SYNCHRONOUS_IO_NONALERT, 121 &DefaultTimeout); 122 } 123 124 NTSTATUS 125 NpOpenPipeEx( 126 OUT PHANDLE ClientHandle, 127 IN PCWSTR PipePath, 128 IN ACCESS_MASK DesiredAccess, 129 IN ULONG ShareAccess, 130 IN ULONG Disposition, 131 IN ULONG CreateOptions) 132 { 133 UNICODE_STRING ObjectName; 134 OBJECT_ATTRIBUTES ObjectAttributes; 135 NTSTATUS Status; 136 IO_STATUS_BLOCK IoStatusBlock; 137 138 RtlInitUnicodeString(&ObjectName, PipePath); 139 InitializeObjectAttributes(&ObjectAttributes, 140 &ObjectName, 141 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 142 NULL, 143 NULL); 144 145 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 146 Status = IoCreateFile(ClientHandle, 147 DesiredAccess, 148 &ObjectAttributes, 149 &IoStatusBlock, 150 NULL, /* AllocationSize */ 151 0, /* FileAttributes */ 152 ShareAccess, 153 Disposition, 154 CreateOptions, 155 NULL, /* EaBuffer */ 156 0, /* EaLength */ 157 CreateFileTypeNone, 158 NULL, 159 0); 160 if (NT_SUCCESS(Status)) 161 { 162 ok(Status != STATUS_PENDING, "IoCreateFile returned pending\n"); 163 ok_eq_hex(IoStatusBlock.Status, Status); 164 ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED); 165 } 166 else 167 { 168 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 169 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 170 } 171 return Status; 172 } 173 174 NTSTATUS 175 NpOpenPipe( 176 OUT PHANDLE ClientHandle, 177 IN PCWSTR PipePath, 178 IN ULONG NamedPipeConfiguration) 179 { 180 ULONG ShareAccess; 181 182 if (NamedPipeConfiguration == FILE_PIPE_INBOUND) 183 ShareAccess = FILE_SHARE_WRITE; 184 else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) 185 ShareAccess = FILE_SHARE_READ; 186 else if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) 187 ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; 188 189 return NpOpenPipeEx(ClientHandle, 190 PipePath, 191 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, 192 ShareAccess, 193 FILE_OPEN, 194 FILE_SYNCHRONOUS_IO_NONALERT); 195 } 196 197 NTSTATUS 198 NpControlPipe( 199 IN HANDLE ServerHandle, 200 IN ULONG FsControlCode, 201 IN PVOID InputBuffer, 202 IN ULONG InputBufferLength) 203 { 204 NTSTATUS Status; 205 IO_STATUS_BLOCK IoStatusBlock; 206 207 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 208 Status = ZwFsControlFile(ServerHandle, 209 NULL, 210 NULL, 211 NULL, 212 &IoStatusBlock, 213 FsControlCode, 214 InputBuffer, 215 InputBufferLength, 216 NULL, 217 0); 218 if (Status == STATUS_PENDING) 219 { 220 Status = ZwWaitForSingleObject(ServerHandle, 221 FALSE, 222 NULL); 223 ok_eq_hex(Status, STATUS_SUCCESS); 224 Status = IoStatusBlock.Status; 225 } 226 if (NT_SUCCESS(Status)) 227 { 228 ok_eq_hex(IoStatusBlock.Status, Status); 229 ok_eq_ulongptr(IoStatusBlock.Information, 0); 230 } 231 else 232 { 233 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 234 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 235 } 236 return Status; 237 } 238 239 NTSTATUS 240 NpWaitPipe( 241 IN PCWSTR PipeName, 242 IN PLARGE_INTEGER Timeout) 243 { 244 NTSTATUS Status; 245 HANDLE RootHandle; 246 UNICODE_STRING RootDirectoryName = RTL_CONSTANT_STRING(DEVICE_NAMED_PIPE); 247 OBJECT_ATTRIBUTES ObjectAttributes; 248 IO_STATUS_BLOCK IoStatusBlock; 249 PFILE_PIPE_WAIT_FOR_BUFFER WaitForBuffer; 250 ULONG NameLength; 251 ULONG BufferSize; 252 253 InitializeObjectAttributes(&ObjectAttributes, 254 &RootDirectoryName, 255 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 256 NULL, 257 NULL); 258 259 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 260 Status = IoCreateFile(&RootHandle, 261 FILE_READ_ATTRIBUTES | SYNCHRONIZE, 262 &ObjectAttributes, 263 &IoStatusBlock, 264 NULL, 265 0, 266 FILE_SHARE_READ | FILE_SHARE_WRITE, 267 FILE_OPEN, 268 FILE_SYNCHRONOUS_IO_NONALERT, 269 NULL, 270 0, 271 CreateFileTypeNone, 272 NULL, 273 0); 274 if (!NT_SUCCESS(Status)) 275 { 276 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 277 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 278 return Status; 279 } 280 ok(Status != STATUS_PENDING, "IoCreateFile returned pending\n"); 281 ok_eq_hex(IoStatusBlock.Status, Status); 282 ok_eq_ulongptr(IoStatusBlock.Information, FILE_OPENED); 283 284 NameLength = wcslen(PipeName) * sizeof(WCHAR); 285 BufferSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, 286 Name[NameLength / sizeof(WCHAR)]); 287 WaitForBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, 'WPmK'); 288 if (WaitForBuffer == NULL) 289 return STATUS_INSUFFICIENT_RESOURCES; 290 291 if (Timeout) 292 { 293 WaitForBuffer->Timeout.QuadPart = Timeout->QuadPart; 294 WaitForBuffer->TimeoutSpecified = TRUE; 295 } 296 else 297 { 298 WaitForBuffer->Timeout.QuadPart = 0; 299 WaitForBuffer->TimeoutSpecified = FALSE; 300 } 301 WaitForBuffer->NameLength = NameLength; 302 RtlCopyMemory(WaitForBuffer->Name, PipeName, NameLength); 303 Status = NpControlPipe(RootHandle, 304 FSCTL_PIPE_WAIT, 305 WaitForBuffer, 306 BufferSize); 307 ExFreePoolWithTag(WaitForBuffer, 'WPmK'); 308 return Status; 309 } 310 311 NTSTATUS 312 NpReadPipe( 313 IN HANDLE PipeHandle, 314 OUT PVOID Buffer, 315 IN ULONG BufferSize, 316 OUT PULONG_PTR BytesRead) 317 { 318 NTSTATUS Status; 319 IO_STATUS_BLOCK IoStatusBlock; 320 BOOLEAN PendingReturned = FALSE; 321 322 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 323 Status = ZwReadFile(PipeHandle, 324 NULL, 325 NULL, 326 NULL, 327 &IoStatusBlock, 328 Buffer, 329 BufferSize, 330 NULL, 331 NULL); 332 if (Status == STATUS_PENDING) 333 { 334 Status = ZwWaitForSingleObject(PipeHandle, 335 FALSE, 336 NULL); 337 ok_eq_hex(Status, STATUS_SUCCESS); 338 Status = IoStatusBlock.Status; 339 PendingReturned = TRUE; 340 } 341 if (NT_SUCCESS(Status)) 342 { 343 ok_eq_hex(IoStatusBlock.Status, Status); 344 *BytesRead = IoStatusBlock.Information; 345 } 346 else 347 { 348 if (PendingReturned) 349 { 350 ok_eq_hex(IoStatusBlock.Status, Status); 351 ok_eq_ulongptr(IoStatusBlock.Information, 0); 352 } 353 else 354 { 355 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 356 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 357 } 358 *BytesRead = 0; 359 } 360 return Status; 361 } 362 363 NTSTATUS 364 NpWritePipe( 365 IN HANDLE PipeHandle, 366 IN const VOID *Buffer, 367 IN ULONG BufferSize, 368 OUT PULONG_PTR BytesWritten) 369 { 370 NTSTATUS Status; 371 IO_STATUS_BLOCK IoStatusBlock; 372 373 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 374 Status = ZwWriteFile(PipeHandle, 375 NULL, 376 NULL, 377 NULL, 378 &IoStatusBlock, 379 (PVOID)Buffer, 380 BufferSize, 381 NULL, 382 NULL); 383 if (Status == STATUS_PENDING) 384 { 385 Status = ZwWaitForSingleObject(PipeHandle, 386 FALSE, 387 NULL); 388 ok_eq_hex(Status, STATUS_SUCCESS); 389 Status = IoStatusBlock.Status; 390 } 391 if (NT_SUCCESS(Status)) 392 { 393 ok_eq_hex(IoStatusBlock.Status, Status); 394 *BytesWritten = IoStatusBlock.Information; 395 } 396 else 397 { 398 ok_eq_hex(IoStatusBlock.Status, 0x55555555UL); 399 ok_eq_ulongptr(IoStatusBlock.Information, 0x5555555555555555ULL); 400 *BytesWritten = 0; 401 } 402 return Status; 403 } 404 405 static 406 BOOLEAN 407 CheckBuffer( 408 PVOID Buffer, 409 SIZE_T Size, 410 UCHAR Value) 411 { 412 PUCHAR Array = Buffer; 413 SIZE_T i; 414 415 for (i = 0; i < Size; i++) 416 if (Array[i] != Value) 417 { 418 trace("Expected %x, found %x at offset %lu\n", Value, Array[i], (ULONG)i); 419 return FALSE; 420 } 421 return TRUE; 422 } 423 424 #define ok_eq_print_(value, expected, spec, FileAndLine) \ 425 KmtOk((value) == (expected), FileAndLine, #value " = " spec ", expected " spec "\n", value, expected) 426 #define ok_eq_ulong_(value, expected) ok_eq_print_(value, expected, "%lu", FileAndLine) 427 #define ok_eq_ulonglong_(value, expected) ok_eq_print_(value, expected, "%I64u", FileAndLine) 428 #ifndef _WIN64 429 #define ok_eq_ulongptr_(value, expected) ok_eq_print_(value, (ULONG_PTR)(expected), "%lu", FileAndLine) 430 #elif defined _WIN64 431 #define ok_eq_ulongptr_(value, expected) ok_eq_print_(value, (ULONG_PTR)(expected), "%I64u", FileAndLine) 432 #endif 433 #define ok_eq_hex_(value, expected) ok_eq_print_(value, expected, "0x%08lx", FileAndLine) 434 435 VOID 436 NpCheckServerPipe_( 437 IN HANDLE ServerHandle, 438 /* PipeInformation */ 439 IN ULONG ReadMode, 440 IN ULONG CompletionMode, 441 /* PipeLocalInformation */ 442 IN ULONG NamedPipeType, 443 IN ULONG NamedPipeConfiguration, 444 IN ULONG MaximumInstances, 445 IN ULONG CurrentInstances, 446 IN ULONG InboundQuota, 447 IN ULONG ReadDataAvailable, 448 IN ULONG OutboundQuota, 449 IN ULONG WriteQuotaAvailable, 450 IN ULONG NamedPipeState, 451 /* PipeRemoteInformation */ 452 /* */ 453 IN PCSTR FileAndLine) 454 { 455 NTSTATUS Status; 456 IO_STATUS_BLOCK IoStatusBlock; 457 FILE_PIPE_INFORMATION PipeInfo; 458 FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo; 459 FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo; 460 461 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 462 RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55); 463 Status = ZwQueryInformationFile(ServerHandle, 464 &IoStatusBlock, 465 &PipeInfo, 466 sizeof(PipeInfo), 467 FilePipeInformation); 468 ok_eq_hex_(Status, STATUS_SUCCESS); 469 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 470 ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeInfo)); 471 ok_eq_ulong_(PipeInfo.ReadMode, ReadMode); 472 ok_eq_ulong_(PipeInfo.CompletionMode, CompletionMode); 473 474 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 475 RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55); 476 Status = ZwQueryInformationFile(ServerHandle, 477 &IoStatusBlock, 478 &PipeLocalInfo, 479 sizeof(PipeLocalInfo), 480 FilePipeLocalInformation); 481 ok_eq_hex_(Status, STATUS_SUCCESS); 482 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 483 ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeLocalInfo)); 484 ok_eq_ulong_(PipeLocalInfo.NamedPipeType, NamedPipeType); 485 ok_eq_ulong_(PipeLocalInfo.NamedPipeConfiguration, NamedPipeConfiguration); 486 ok_eq_ulong_(PipeLocalInfo.MaximumInstances, MaximumInstances); 487 ok_eq_ulong_(PipeLocalInfo.CurrentInstances, CurrentInstances); 488 ok_eq_ulong_(PipeLocalInfo.InboundQuota, InboundQuota); 489 ok_eq_ulong_(PipeLocalInfo.ReadDataAvailable, ReadDataAvailable); 490 ok_eq_ulong_(PipeLocalInfo.OutboundQuota, OutboundQuota); 491 ok_eq_ulong_(PipeLocalInfo.WriteQuotaAvailable, WriteQuotaAvailable); 492 ok_eq_ulong_(PipeLocalInfo.NamedPipeState, NamedPipeState); 493 ok_eq_ulong_(PipeLocalInfo.NamedPipeEnd, (ULONG)FILE_PIPE_SERVER_END); 494 495 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 496 RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55); 497 Status = ZwQueryInformationFile(ServerHandle, 498 &IoStatusBlock, 499 &PipeRemoteInfo, 500 sizeof(PipeRemoteInfo), 501 FilePipeInformation); 502 ok_eq_hex_(Status, STATUS_SUCCESS); 503 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 504 ok_eq_ulongptr_(IoStatusBlock.Information, RTL_SIZEOF_THROUGH_FIELD(FILE_PIPE_REMOTE_INFORMATION, CollectDataTime)); 505 ok_eq_ulonglong_(PipeRemoteInfo.CollectDataTime.QuadPart, 0ULL); 506 ok_eq_ulong_(PipeRemoteInfo.MaximumCollectionCount, 0x55555555UL); 507 } 508 509 VOID 510 NpCheckClientPipe_( 511 IN HANDLE ClientHandle, 512 /* PipeInformation */ 513 IN ULONG ReadMode, 514 IN ULONG CompletionMode, 515 /* PipeLocalInformation */ 516 IN ULONG NamedPipeType, 517 IN ULONG NamedPipeConfiguration, 518 IN ULONG MaximumInstances, 519 IN ULONG CurrentInstances, 520 IN ULONG InboundQuota, 521 IN ULONG ReadDataAvailable, 522 IN ULONG OutboundQuota, 523 IN ULONG WriteQuotaAvailable, 524 IN ULONG NamedPipeState, 525 /* PipeRemoteInformation */ 526 /* */ 527 IN PCSTR FileAndLine) 528 { 529 NTSTATUS Status; 530 IO_STATUS_BLOCK IoStatusBlock; 531 FILE_PIPE_INFORMATION PipeInfo; 532 FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo; 533 FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo; 534 535 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 536 RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55); 537 Status = ZwQueryInformationFile(ClientHandle, 538 &IoStatusBlock, 539 &PipeInfo, 540 sizeof(PipeInfo), 541 FilePipeInformation); 542 ok_eq_hex_(Status, STATUS_SUCCESS); 543 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 544 ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeInfo)); 545 ok_eq_ulong_(PipeInfo.ReadMode, ReadMode); 546 ok_eq_ulong_(PipeInfo.CompletionMode, CompletionMode); 547 548 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 549 RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55); 550 Status = ZwQueryInformationFile(ClientHandle, 551 &IoStatusBlock, 552 &PipeLocalInfo, 553 sizeof(PipeLocalInfo), 554 FilePipeLocalInformation); 555 ok_eq_hex_(Status, STATUS_SUCCESS); 556 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 557 ok_eq_ulongptr_(IoStatusBlock.Information, sizeof(PipeLocalInfo)); 558 ok_eq_ulong_(PipeLocalInfo.NamedPipeType, NamedPipeType); 559 ok_eq_ulong_(PipeLocalInfo.NamedPipeConfiguration, NamedPipeConfiguration); 560 ok_eq_ulong_(PipeLocalInfo.MaximumInstances, MaximumInstances); 561 ok_eq_ulong_(PipeLocalInfo.CurrentInstances, CurrentInstances); 562 ok_eq_ulong_(PipeLocalInfo.InboundQuota, InboundQuota); 563 ok_eq_ulong_(PipeLocalInfo.ReadDataAvailable, ReadDataAvailable); 564 ok_eq_ulong_(PipeLocalInfo.OutboundQuota, OutboundQuota); 565 ok_eq_ulong_(PipeLocalInfo.WriteQuotaAvailable, WriteQuotaAvailable); 566 ok_eq_ulong_(PipeLocalInfo.NamedPipeState, NamedPipeState); 567 ok_eq_ulong_(PipeLocalInfo.NamedPipeEnd, (ULONG)FILE_PIPE_CLIENT_END); 568 569 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 570 RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55); 571 Status = ZwQueryInformationFile(ClientHandle, 572 &IoStatusBlock, 573 &PipeRemoteInfo, 574 sizeof(PipeRemoteInfo), 575 FilePipeInformation); 576 ok_eq_hex_(Status, STATUS_SUCCESS); 577 ok_eq_hex_(IoStatusBlock.Status, STATUS_SUCCESS); 578 ok_eq_ulongptr_(IoStatusBlock.Information, RTL_SIZEOF_THROUGH_FIELD(FILE_PIPE_REMOTE_INFORMATION, CollectDataTime)); 579 ok_eq_ulonglong_(PipeRemoteInfo.CollectDataTime.QuadPart, 0ULL); 580 ok_eq_ulong_(PipeRemoteInfo.MaximumCollectionCount, 0x55555555UL); 581 } 582 583 VOID 584 NpQueryPipe_( 585 IN HANDLE PipeHandle, 586 IN NTSTATUS ExpectedStatus, 587 IN PCSTR FileAndLine) 588 { 589 NTSTATUS Status; 590 IO_STATUS_BLOCK IoStatusBlock; 591 FILE_PIPE_INFORMATION PipeInfo; 592 FILE_PIPE_LOCAL_INFORMATION PipeLocalInfo; 593 FILE_PIPE_REMOTE_INFORMATION PipeRemoteInfo; 594 595 ASSERT(!NT_SUCCESS(ExpectedStatus)); 596 597 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 598 RtlFillMemory(&PipeInfo, sizeof(PipeInfo), 0x55); 599 Status = ZwQueryInformationFile(PipeHandle, 600 &IoStatusBlock, 601 &PipeInfo, 602 sizeof(PipeInfo), 603 FilePipeInformation); 604 ok_eq_hex_(Status, ExpectedStatus); 605 ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55), "CheckBuffer returned"); 606 ok_bool_true(CheckBuffer(&PipeInfo, sizeof(PipeInfo), 0x55), "CheckBuffer returned"); 607 608 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 609 RtlFillMemory(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55); 610 Status = ZwQueryInformationFile(PipeHandle, 611 &IoStatusBlock, 612 &PipeLocalInfo, 613 sizeof(PipeLocalInfo), 614 FilePipeLocalInformation); 615 ok_eq_hex_(Status, ExpectedStatus); 616 ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55), "CheckBuffer returned"); 617 ok_bool_true(CheckBuffer(&PipeLocalInfo, sizeof(PipeLocalInfo), 0x55), "CheckBuffer returned"); 618 619 RtlFillMemory(&IoStatusBlock, sizeof(IoStatusBlock), 0x55); 620 RtlFillMemory(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55); 621 Status = ZwQueryInformationFile(PipeHandle, 622 &IoStatusBlock, 623 &PipeRemoteInfo, 624 sizeof(PipeRemoteInfo), 625 FilePipeInformation); 626 ok_eq_hex_(Status, ExpectedStatus); 627 ok_bool_true(CheckBuffer(&IoStatusBlock, sizeof(IoStatusBlock), 0x55), "CheckBuffer returned"); 628 ok_bool_true(CheckBuffer(&PipeRemoteInfo, sizeof(PipeRemoteInfo), 0x55), "CheckBuffer returned"); 629 } 630 631 static KSTART_ROUTINE PipeWorkerThread; 632 static 633 VOID 634 NTAPI 635 PipeWorkerThread( 636 IN PVOID ThreadContext) 637 { 638 PTHREAD_CONTEXT Context = ThreadContext; 639 PVOID WaitEvents[2] = { &Context->ThreadDoneEvent, 640 &Context->StartWorkEvent }; 641 NTSTATUS Status; 642 643 while (TRUE) 644 { 645 Status = KeWaitForMultipleObjects(RTL_NUMBER_OF(WaitEvents), 646 WaitEvents, 647 WaitAny, 648 Executive, 649 KernelMode, 650 FALSE, 651 NULL, 652 NULL); 653 if (Status == STATUS_WAIT_0) 654 break; 655 ASSERT(Status == STATUS_WAIT_1); 656 657 Context->Work(Context); 658 659 KeSetEvent(&Context->WorkCompleteEvent, IO_NO_INCREMENT, TRUE); 660 } 661 } 662 663 VOID 664 StartWorkerThread( 665 OUT PTHREAD_CONTEXT Context) 666 { 667 KeInitializeEvent(&Context->ThreadDoneEvent, NotificationEvent, FALSE); 668 KeInitializeEvent(&Context->StartWorkEvent, SynchronizationEvent, FALSE); 669 KeInitializeEvent(&Context->WorkCompleteEvent, NotificationEvent, TRUE); 670 671 Context->Thread = KmtStartThread(PipeWorkerThread, Context); 672 } 673 674 VOID 675 FinishWorkerThread( 676 IN PTHREAD_CONTEXT Context) 677 { 678 KmtFinishThread(Context->Thread, &Context->ThreadDoneEvent); 679 } 680 681 BOOLEAN 682 WaitForWork( 683 IN PTHREAD_CONTEXT Context, 684 IN ULONG MilliSeconds) 685 { 686 LARGE_INTEGER Timeout; 687 NTSTATUS Status; 688 689 Timeout.QuadPart = -10 * 1000 * (LONGLONG)MilliSeconds; 690 Status = KeWaitForSingleObject(&Context->WorkCompleteEvent, 691 Executive, 692 KernelMode, 693 FALSE, 694 &Timeout); 695 ok(Status == STATUS_SUCCESS || Status == STATUS_TIMEOUT, "Wait status %lx\n", Status); 696 return Status != STATUS_TIMEOUT; 697 } 698 699 BOOLEAN 700 TriggerWork( 701 IN PTHREAD_CONTEXT Context, 702 IN ULONG MilliSeconds) 703 { 704 NTSTATUS Status; 705 706 Status = KeWaitForSingleObject(&Context->WorkCompleteEvent, 707 Executive, 708 KernelMode, 709 FALSE, 710 NULL); 711 ok_eq_hex(Status, STATUS_SUCCESS); 712 KeClearEvent(&Context->WorkCompleteEvent); 713 KeSetEvent(&Context->StartWorkEvent, IO_NO_INCREMENT, TRUE); 714 return WaitForWork(Context, MilliSeconds); 715 } 716