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