Sync with trunk rev.61910 to get latest improvements and bugfixes.
[reactos.git] / drivers / filesystems / npfs / fsctrl.c
1 /*
2 * PROJECT: ReactOS Named Pipe FileSystem
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/filesystems/npfs/fsctrl.c
5 * PURPOSE: Named Pipe FileSystem I/O Controls
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "npfs.h"
12
13 // File ID number for NPFS bugchecking support
14 #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FSCTRL)
15
16 /* GLOBALS ********************************************************************/
17
18 IO_STATUS_BLOCK NpUserIoStatusBlock;
19
20 /* FUNCTIONS ******************************************************************/
21
22 NTSTATUS
23 NTAPI
24 NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject,
25 IN PIRP Irp,
26 IN PLIST_ENTRY List)
27 {
28 UNIMPLEMENTED;
29 return STATUS_NOT_IMPLEMENTED;
30 }
31
32 NTSTATUS
33 NTAPI
34 NpInternalRead(IN PDEVICE_OBJECT DeviceObject,
35 IN PIRP Irp,
36 IN BOOLEAN Overflow,
37 IN PLIST_ENTRY List)
38 {
39 UNIMPLEMENTED;
40 return STATUS_NOT_IMPLEMENTED;
41 }
42
43 NTSTATUS
44 NTAPI
45 NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
46 IN PIRP Irp,
47 IN PLIST_ENTRY List)
48 {
49 UNIMPLEMENTED;
50 return STATUS_NOT_IMPLEMENTED;
51 }
52
53 NTSTATUS
54 NTAPI
55 NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
56 IN PIRP Irp)
57 {
58 PIO_STACK_LOCATION IoStackLocation;
59 NODE_TYPE_CODE NodeTypeCode;
60 PNP_CCB Ccb;
61 PNP_CLIENT_PROCESS ClientSession, QueryBuffer;
62 ULONG Length;
63 PAGED_CODE();
64
65 /* Get the current stack location */
66 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
67
68 /* Decode the file object and check the node type */
69 NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0);
70 if (NodeTypeCode != NPFS_NTC_CCB)
71 {
72 return STATUS_PIPE_DISCONNECTED;
73 }
74
75 /* Get the length of the query buffer */
76 Length = IoStackLocation->Parameters.QueryFile.Length;
77 if (Length < 8)
78 {
79 return STATUS_INVALID_PARAMETER;
80 }
81
82 QueryBuffer = Irp->AssociatedIrp.SystemBuffer;
83
84 /* Lock the Ccb */
85 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
86
87 /* Get the CCBs client session and check if it's set */
88 ClientSession = Ccb->ClientSession;
89 if (ClientSession != NULL)
90 {
91 /* Copy first 2 fields */
92 QueryBuffer->Unknown = ClientSession->Unknown;
93 QueryBuffer->Process = ClientSession->Process;
94 }
95 else
96 {
97 /* Copy the process from the CCB */
98 QueryBuffer->Unknown = NULL;
99 QueryBuffer->Process = Ccb->Process;
100 }
101
102 /* Does the caller provide a large enough buffer for the full data? */
103 if (Length >= sizeof(NP_CLIENT_PROCESS))
104 {
105 Irp->IoStatus.Information = sizeof(NP_CLIENT_PROCESS);
106
107 /* Do we have a ClientSession structure? */
108 if (ClientSession != NULL)
109 {
110 /* Copy length and the data */
111 QueryBuffer->DataLength = ClientSession->DataLength;
112 RtlCopyMemory(QueryBuffer->Buffer,
113 ClientSession->Buffer,
114 ClientSession->DataLength);
115
116 /* NULL terminate the buffer */
117 NT_ASSERT(QueryBuffer->DataLength <= 30);
118 QueryBuffer->Buffer[QueryBuffer->DataLength / sizeof(WCHAR)] = 0;
119 }
120 else
121 {
122 /* No data */
123 QueryBuffer->DataLength = 0;
124 QueryBuffer->Buffer[0] = 0;
125 }
126 }
127 else
128 {
129 Irp->IoStatus.Information = FIELD_OFFSET(NP_CLIENT_PROCESS, DataLength);
130 }
131
132 /* Unlock the Ccb */
133 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
134
135 return STATUS_SUCCESS;
136 }
137
138 NTSTATUS
139 NTAPI
140 NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
141 IN PIRP Irp)
142 {
143 PIO_STACK_LOCATION IoStackLocation;
144 NODE_TYPE_CODE NodeTypeCode;
145 PNP_CCB Ccb;
146 ULONG Length;
147 PNP_CLIENT_PROCESS InputBuffer, ClientSession, OldClientSession;
148 PAGED_CODE();
149
150 /* Get the current stack location */
151 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
152
153 /* Only kernel calls are allowed! */
154 if (IoStackLocation->MinorFunction != IRP_MN_KERNEL_CALL)
155 {
156 return STATUS_ACCESS_DENIED;
157 }
158
159 /* Decode the file object and check the node type */
160 NodeTypeCode = NpDecodeFileObject(IoStackLocation->FileObject, 0, &Ccb, 0);
161 if (NodeTypeCode != NPFS_NTC_CCB)
162 {
163 return STATUS_PIPE_DISCONNECTED;
164 }
165
166 /* Get the length of the query buffer and check if it's valid */
167 Length = IoStackLocation->Parameters.QueryFile.Length;
168 if (Length != sizeof(NP_CLIENT_PROCESS))
169 {
170 return STATUS_INVALID_PARAMETER;
171 }
172
173 /* Get the buffer and check if the data Length is valid */
174 InputBuffer = Irp->AssociatedIrp.SystemBuffer;
175 if (InputBuffer->DataLength > 30)
176 {
177 return STATUS_INVALID_PARAMETER;
178 }
179
180 /* Allocate a new structure */
181 ClientSession = ExAllocatePoolWithQuotaTag(PagedPool,
182 sizeof(NP_CLIENT_PROCESS),
183 'iFpN');
184
185 /* Copy the full input buffer */
186 RtlCopyMemory(ClientSession, InputBuffer, sizeof(NP_CLIENT_PROCESS));
187
188 /* Lock the Ccb */
189 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
190
191 /* Get the old ClientSession and set the new */
192 OldClientSession = Ccb->ClientSession;
193 Ccb->ClientSession = ClientSession;
194
195 /* Copy the process to the CCB */
196 Ccb->Process = ClientSession->Process;
197
198 /* Unlock the Ccb */
199 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
200
201 /* Check if there was already a ClientSession */
202 if (OldClientSession != NULL)
203 {
204 /* Free it */
205 ExFreePoolWithTag(OldClientSession, 'iFpN');
206 }
207
208 return STATUS_SUCCESS;
209 }
210
211 NTSTATUS
212 NTAPI
213 NpAssignEvent(IN PDEVICE_OBJECT DeviceObject,
214 IN PIRP Irp)
215 {
216 UNIMPLEMENTED;
217 return STATUS_NOT_IMPLEMENTED;
218 }
219
220 NTSTATUS
221 NTAPI
222 NpQueryEvent(IN PDEVICE_OBJECT DeviceObject,
223 IN PIRP Irp)
224 {
225 UNIMPLEMENTED;
226 return STATUS_NOT_IMPLEMENTED;
227 }
228
229 NTSTATUS
230 NTAPI
231 NpImpersonate(IN PDEVICE_OBJECT DeviceObject,
232 IN PIRP Irp)
233 {
234 ULONG NamedPipeEnd;
235 PNP_CCB Ccb;
236 NTSTATUS Status;
237 NODE_TYPE_CODE NodeTypeCode;
238 PIO_STACK_LOCATION IoStack;
239 PAGED_CODE();
240
241 IoStack = IoGetCurrentIrpStackLocation(Irp);
242
243 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
244 if (NodeTypeCode == NPFS_NTC_CCB)
245 {
246 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
247 {
248 Status = NpImpersonateClientContext(Ccb);
249 }
250 else
251 {
252 Status = STATUS_ILLEGAL_FUNCTION;
253 }
254 }
255
256 return Status;
257 }
258
259 NTSTATUS
260 NTAPI
261 NpDisconnect(IN PDEVICE_OBJECT DeviceObject,
262 IN PIRP Irp,
263 IN PLIST_ENTRY List)
264 {
265 ULONG NamedPipeEnd;
266 PNP_CCB Ccb;
267 NTSTATUS Status;
268 NODE_TYPE_CODE NodeTypeCode;
269 PIO_STACK_LOCATION IoStack;
270 PAGED_CODE();
271
272 IoStack = IoGetCurrentIrpStackLocation(Irp);
273
274 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
275 if (NodeTypeCode == NPFS_NTC_CCB)
276 {
277 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
278 {
279 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
280
281 Status = NpSetDisconnectedPipeState(Ccb, List);
282
283 NpUninitializeSecurity(Ccb);
284
285 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
286 }
287 else
288 {
289 Status = STATUS_ILLEGAL_FUNCTION;
290 }
291 }
292 else
293 {
294 Status = STATUS_PIPE_DISCONNECTED;
295 }
296
297 return Status;
298 }
299
300 NTSTATUS
301 NTAPI
302 NpListen(IN PDEVICE_OBJECT DeviceObject,
303 IN PIRP Irp,
304 IN PLIST_ENTRY List)
305 {
306 ULONG NamedPipeEnd;
307 PNP_CCB Ccb;
308 NTSTATUS Status;
309 NODE_TYPE_CODE NodeTypeCode;
310 PIO_STACK_LOCATION IoStack;
311 PAGED_CODE();
312
313 IoStack = IoGetCurrentIrpStackLocation(Irp);
314
315 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
316 if (NodeTypeCode == NPFS_NTC_CCB)
317 {
318 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
319 {
320 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
321
322 Status = NpSetListeningPipeState(Ccb, Irp, List);
323
324 NpUninitializeSecurity(Ccb);
325
326 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
327 }
328 else
329 {
330 Status = STATUS_ILLEGAL_FUNCTION;
331 }
332 }
333 else
334 {
335 Status = STATUS_ILLEGAL_FUNCTION;
336 }
337
338 return Status;
339 }
340
341 NTSTATUS
342 NTAPI
343 NpPeek(IN PDEVICE_OBJECT DeviceObject,
344 IN PIRP Irp,
345 IN PLIST_ENTRY List)
346 {
347 PIO_STACK_LOCATION IoStack;
348 NODE_TYPE_CODE Type;
349 ULONG OutputLength;
350 ULONG NamedPipeEnd;
351 PNP_CCB Ccb;
352 PFILE_PIPE_PEEK_BUFFER PeekBuffer;
353 PNP_DATA_QUEUE DataQueue;
354 ULONG_PTR BytesPeeked;
355 IO_STATUS_BLOCK IoStatus;
356 NTSTATUS Status;
357 PNP_DATA_QUEUE_ENTRY DataEntry;
358 PAGED_CODE();
359
360 IoStack = IoGetCurrentIrpStackLocation(Irp);
361 OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
362 Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
363
364 if (!Type)
365 {
366 return STATUS_PIPE_DISCONNECTED;
367 }
368
369 if ((Type != NPFS_NTC_CCB) &&
370 (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)))
371 {
372 return STATUS_INVALID_PARAMETER;
373 }
374
375 PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
376 if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
377 {
378 if (NamedPipeEnd != FILE_PIPE_SERVER_END)
379 {
380 NpBugCheck(NamedPipeEnd, 0, 0);
381 }
382
383 DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
384 }
385 else
386 {
387 DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
388 }
389
390 if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
391 {
392 if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE)
393 {
394 return STATUS_INVALID_PIPE_STATE;
395 }
396
397 if (DataQueue->QueueState != WriteEntries)
398 {
399 return STATUS_PIPE_BROKEN;
400 }
401 }
402
403 PeekBuffer->NamedPipeState = 0;
404 PeekBuffer->ReadDataAvailable = 0;
405 PeekBuffer->NumberOfMessages = 0;
406 PeekBuffer->MessageLength = 0;
407 PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
408 BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data);
409
410 if (DataQueue->QueueState == WriteEntries)
411 {
412 DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
413 NP_DATA_QUEUE_ENTRY,
414 QueueEntry);
415 ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));
416
417 PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
418 if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
419 {
420 PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
421 PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
422 }
423
424 if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))
425 {
426 Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
427 }
428 else
429 {
430 IoStatus = NpReadDataQueue(DataQueue,
431 TRUE,
432 FALSE,
433 PeekBuffer->Data,
434 OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data),
435 Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
436 Ccb,
437 List);
438 Status = IoStatus.Status;
439 BytesPeeked += IoStatus.Information;
440 }
441 }
442 else
443 {
444 Status = STATUS_SUCCESS;
445 }
446
447 Irp->IoStatus.Information = BytesPeeked;
448 return Status;
449 }
450
451 NTSTATUS
452 NTAPI
453 NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject,
454 IN PIRP Irp,
455 IN PVOID Context)
456 {
457 PAGED_CODE();
458
459 if (Irp->AssociatedIrp.SystemBuffer)
460 {
461 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
462 }
463
464 IoFreeIrp(Irp);
465 return STATUS_MORE_PROCESSING_REQUIRED;
466 }
467
468 NTSTATUS
469 NTAPI
470 NpTransceive(IN PDEVICE_OBJECT DeviceObject,
471 IN PIRP Irp,
472 IN PLIST_ENTRY List)
473 {
474 PIO_STACK_LOCATION IoStack;
475 PVOID InBuffer, OutBuffer;
476 ULONG InLength, OutLength, BytesWritten;
477 NODE_TYPE_CODE NodeTypeCode;
478 PNP_CCB Ccb;
479 ULONG NamedPipeEnd;
480 PNP_NONPAGED_CCB NonPagedCcb;
481 PNP_DATA_QUEUE ReadQueue, WriteQueue;
482 PNP_EVENT_BUFFER EventBuffer;
483 NTSTATUS Status;
484 PIRP NewIrp;
485 PAGED_CODE();
486
487 IoStack = IoGetCurrentIrpStackLocation(Irp);
488 InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
489 InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer;
490 OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
491 OutBuffer = Irp->UserBuffer;
492
493 if (Irp->RequestorMode == UserMode)
494 {
495 _SEH2_TRY
496 {
497 ProbeForRead(InBuffer, InLength, sizeof(CHAR));
498 ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR));
499 }
500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
501 {
502 _SEH2_YIELD(return _SEH2_GetExceptionCode());
503 }
504 _SEH2_END;
505 }
506
507 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
508 if (NodeTypeCode != NPFS_NTC_CCB)
509 {
510 return STATUS_PIPE_DISCONNECTED;
511 }
512
513 NonPagedCcb = Ccb->NonPagedCcb;
514 ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
515
516 if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
517 {
518 Status = STATUS_INVALID_PIPE_STATE;
519 goto Quickie;
520 }
521
522 if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
523 {
524 if (NamedPipeEnd != FILE_PIPE_SERVER_END)
525 {
526 NpBugCheck(NamedPipeEnd, 0, 0);
527 }
528 ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
529 WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
530 }
531 else
532 {
533 ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
534 WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
535 }
536
537 EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
538
539 if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX ||
540 Ccb->ReadMode[NamedPipeEnd] != FILE_PIPE_MESSAGE_MODE)
541 {
542 Status = STATUS_INVALID_PIPE_STATE;
543 goto Quickie;
544 }
545
546 if (ReadQueue->QueueState != Empty)
547 {
548 Status = STATUS_PIPE_BUSY;
549 goto Quickie;
550 }
551
552 Status = NpWriteDataQueue(WriteQueue,
553 1,
554 InBuffer,
555 InLength,
556 Ccb->Fcb->NamedPipeType,
557 &BytesWritten,
558 Ccb,
559 NamedPipeEnd,
560 Irp->Tail.Overlay.Thread,
561 List);
562 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
563 {
564 ASSERT(WriteQueue->QueueState != ReadEntries);
565 NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
566 if (!NewIrp)
567 {
568 Status = STATUS_INSUFFICIENT_RESOURCES;
569 goto Quickie;
570 }
571
572 IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE);
573
574 if (BytesWritten)
575 {
576 NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
577 BytesWritten,
578 NPFS_WRITE_BLOCK_TAG);
579 if (!NewIrp->AssociatedIrp.SystemBuffer)
580 {
581 IoFreeIrp(NewIrp);
582 Status = STATUS_INSUFFICIENT_RESOURCES;
583 goto Quickie;
584 }
585
586 _SEH2_TRY
587 {
588 RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer,
589 (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten),
590 BytesWritten);
591 }
592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
593 {
594 Status = _SEH2_GetExceptionCode();
595 _SEH2_YIELD(goto Quickie);
596 }
597 _SEH2_END;
598 }
599 else
600 {
601 NewIrp->AssociatedIrp.SystemBuffer = NULL;
602 }
603
604 IoStack = IoGetNextIrpStackLocation(NewIrp);
605 IoSetNextIrpStackLocation(NewIrp);
606
607 NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
608 NewIrp->IoStatus.Information = BytesWritten;
609
610 IoStack->Parameters.Read.Length = BytesWritten;
611 IoStack->MajorFunction = IRP_MJ_WRITE;
612
613 if (BytesWritten > 0) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
614 NewIrp->UserIosb = &NpUserIoStatusBlock;
615
616 Status = NpAddDataQueueEntry(NamedPipeEnd,
617 Ccb,
618 WriteQueue,
619 WriteEntries,
620 Unbuffered,
621 BytesWritten,
622 NewIrp,
623 NULL,
624 0);
625 if (Status != STATUS_PENDING)
626 {
627 NewIrp->IoStatus.Status = Status;
628 InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry);
629 }
630 }
631
632 if (!NT_SUCCESS(Status)) goto Quickie;
633
634 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
635 ASSERT(ReadQueue->QueueState == Empty);
636 Status = NpAddDataQueueEntry(NamedPipeEnd,
637 Ccb,
638 ReadQueue,
639 ReadEntries,
640 Buffered,
641 OutLength,
642 Irp,
643 NULL,
644 0);
645 if (NT_SUCCESS(Status))
646 {
647 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
648 }
649
650 Quickie:
651 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
652 return Status;
653 }
654
655 NTSTATUS
656 NTAPI
657 NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
658 IN PIRP Irp)
659 {
660 PIO_STACK_LOCATION IoStack;
661 ULONG InLength, NameLength;
662 UNICODE_STRING SourceString, Prefix;
663 ULONG NamedPipeEnd;
664 PNP_CCB Ccb;
665 PFILE_PIPE_WAIT_FOR_BUFFER Buffer;
666 NTSTATUS Status;
667 NODE_TYPE_CODE NodeTypeCode;
668 PLIST_ENTRY NextEntry;
669 PNP_FCB Fcb;
670 PWCHAR OriginalBuffer;
671 PAGED_CODE();
672
673 IoStack = IoGetCurrentIrpStackLocation(Irp);
674 InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
675
676 SourceString.Buffer = NULL;
677
678 if (NpDecodeFileObject(IoStack->FileObject,
679 NULL,
680 &Ccb,
681 &NamedPipeEnd) != NPFS_NTC_ROOT_DCB)
682 {
683 Status = STATUS_ILLEGAL_FUNCTION;
684 goto Quickie;
685 }
686
687 Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
688 if (InLength < sizeof(*Buffer))
689 {
690 Status = STATUS_INVALID_PARAMETER;
691 goto Quickie;
692 }
693
694 NameLength = Buffer->NameLength;
695 if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) ||
696 ((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength))
697 {
698 Status = STATUS_INVALID_PARAMETER;
699 goto Quickie;
700 }
701
702 SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
703 SourceString.Buffer = ExAllocatePoolWithTag(PagedPool,
704 SourceString.Length,
705 NPFS_WRITE_BLOCK_TAG);
706 if (!SourceString.Buffer)
707 {
708 Status = STATUS_INSUFFICIENT_RESOURCES;
709 goto Quickie;
710 }
711
712 SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
713 RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
714
715 Status = STATUS_SUCCESS;
716 OriginalBuffer = SourceString.Buffer;
717 //Status = NpTranslateAlias(&SourceString);
718 if (!NT_SUCCESS(Status)) goto Quickie;
719
720 Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix);
721 Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1);
722
723 NodeTypeCode = Fcb ? Fcb->NodeType : 0;
724 if (NodeTypeCode != NPFS_NTC_FCB)
725 {
726 Status = STATUS_OBJECT_NAME_NOT_FOUND;
727 goto Quickie;
728 }
729
730 for (NextEntry = Fcb->CcbList.Flink;
731 NextEntry != &Fcb->CcbList;
732 NextEntry = NextEntry->Flink)
733 {
734 Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
735 if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
736 }
737
738 if (NextEntry != &Fcb->CcbList)
739 {
740 Status = STATUS_SUCCESS;
741 }
742 else
743 {
744 Status = NpAddWaiter(&NpVcb->WaitQueue,
745 Fcb->Timeout,
746 Irp,
747 OriginalBuffer == SourceString.Buffer ?
748 NULL : &SourceString);
749 }
750
751 Quickie:
752 if (SourceString.Buffer) ExFreePool(SourceString.Buffer);
753 return Status;
754 }
755
756 NTSTATUS
757 NTAPI
758 NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
759 IN PIRP Irp)
760 {
761 ULONG Fsctl;
762 BOOLEAN Overflow = FALSE;
763 LIST_ENTRY DeferredList;
764 NTSTATUS Status;
765 PAGED_CODE();
766
767 InitializeListHead(&DeferredList);
768 Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode;
769
770 switch (Fsctl)
771 {
772 case FSCTL_PIPE_PEEK:
773 NpAcquireExclusiveVcb();
774 Status = NpPeek(DeviceObject, Irp, &DeferredList);
775 break;
776
777 case FSCTL_PIPE_INTERNAL_WRITE:
778 NpAcquireSharedVcb();
779 Status = NpInternalWrite(DeviceObject, Irp, &DeferredList);
780 break;
781
782 case FSCTL_PIPE_TRANSCEIVE:
783 NpAcquireSharedVcb();
784 Status = NpTransceive(DeviceObject, Irp, &DeferredList);
785 break;
786
787 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
788 NpAcquireSharedVcb();
789 Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList);
790 break;
791
792 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
793 Overflow = TRUE;
794 // on purpose
795
796 case FSCTL_PIPE_INTERNAL_READ:
797 NpAcquireSharedVcb();
798 Status = NpInternalRead(DeviceObject, Irp, Overflow, &DeferredList);
799 break;
800
801 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
802
803 NpAcquireSharedVcb();
804 Status = NpQueryClientProcess(DeviceObject, Irp);
805 break;
806
807 case FSCTL_PIPE_ASSIGN_EVENT:
808
809 NpAcquireExclusiveVcb();
810 Status = NpAssignEvent(DeviceObject, Irp);
811 break;
812
813 case FSCTL_PIPE_DISCONNECT:
814
815 NpAcquireExclusiveVcb();
816 Status = NpDisconnect(DeviceObject, Irp, &DeferredList);
817 break;
818
819 case FSCTL_PIPE_LISTEN:
820
821 NpAcquireSharedVcb();
822 Status = NpListen(DeviceObject, Irp, &DeferredList);
823 break;
824
825 case FSCTL_PIPE_QUERY_EVENT:
826
827 NpAcquireExclusiveVcb();
828 Status = NpQueryEvent(DeviceObject, Irp);
829 break;
830
831 case FSCTL_PIPE_WAIT:
832
833 NpAcquireExclusiveVcb();
834 Status = NpWaitForNamedPipe(DeviceObject, Irp);
835 break;
836
837 case FSCTL_PIPE_IMPERSONATE:
838
839 NpAcquireExclusiveVcb();
840 Status = NpImpersonate(DeviceObject, Irp);
841 break;
842
843 case FSCTL_PIPE_SET_CLIENT_PROCESS:
844 NpAcquireExclusiveVcb();
845 Status = NpSetClientProcess(DeviceObject, Irp);
846 break;
847
848 default:
849 return STATUS_NOT_SUPPORTED;
850 }
851
852 NpReleaseVcb();
853 NpCompleteDeferredIrps(&DeferredList);
854
855 return Status;
856 }
857
858 NTSTATUS
859 NTAPI
860 NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
861 IN PIRP Irp)
862 {
863 NTSTATUS Status;
864 PAGED_CODE();
865
866 FsRtlEnterFileSystem();
867
868 Status = NpCommonFileSystemControl(DeviceObject, Irp);
869
870 FsRtlExitFileSystem();
871
872 if (Status != STATUS_PENDING)
873 {
874 Irp->IoStatus.Status = Status;
875 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
876 }
877
878 return Status;
879 }
880
881 /* EOF */