[KMTESTS:NPFS]
[reactos.git] / rostests / kmtests / npfs / NpfsHelpers.c
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 KeResetEvent(&Context->WorkCompleteEvent);
713 KeSetEvent(&Context->StartWorkEvent, IO_NO_INCREMENT, TRUE);
714 return WaitForWork(Context, MilliSeconds);
715 }