Sync with trunk r63502.
[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 && NamedPipeEnd == FILE_PIPE_SERVER_END)
245 {
246 Status = NpImpersonateClientContext(Ccb);
247 }
248 else
249 {
250 Status = STATUS_ILLEGAL_FUNCTION;
251 }
252
253 return Status;
254 }
255
256 NTSTATUS
257 NTAPI
258 NpDisconnect(IN PDEVICE_OBJECT DeviceObject,
259 IN PIRP Irp,
260 IN PLIST_ENTRY List)
261 {
262 ULONG NamedPipeEnd;
263 PNP_CCB Ccb;
264 NTSTATUS Status;
265 NODE_TYPE_CODE NodeTypeCode;
266 PIO_STACK_LOCATION IoStack;
267 PAGED_CODE();
268
269 IoStack = IoGetCurrentIrpStackLocation(Irp);
270
271 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
272 if (NodeTypeCode == NPFS_NTC_CCB)
273 {
274 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
275 {
276 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
277
278 Status = NpSetDisconnectedPipeState(Ccb, List);
279
280 NpUninitializeSecurity(Ccb);
281
282 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
283 }
284 else
285 {
286 Status = STATUS_ILLEGAL_FUNCTION;
287 }
288 }
289 else
290 {
291 Status = STATUS_PIPE_DISCONNECTED;
292 }
293
294 return Status;
295 }
296
297 NTSTATUS
298 NTAPI
299 NpListen(IN PDEVICE_OBJECT DeviceObject,
300 IN PIRP Irp,
301 IN PLIST_ENTRY List)
302 {
303 ULONG NamedPipeEnd;
304 PNP_CCB Ccb;
305 NTSTATUS Status;
306 NODE_TYPE_CODE NodeTypeCode;
307 PIO_STACK_LOCATION IoStack;
308 PAGED_CODE();
309
310 IoStack = IoGetCurrentIrpStackLocation(Irp);
311
312 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
313 if (NodeTypeCode == NPFS_NTC_CCB)
314 {
315 if (NamedPipeEnd == FILE_PIPE_SERVER_END)
316 {
317 ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
318
319 Status = NpSetListeningPipeState(Ccb, Irp, List);
320
321 NpUninitializeSecurity(Ccb);
322
323 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
324 }
325 else
326 {
327 Status = STATUS_ILLEGAL_FUNCTION;
328 }
329 }
330 else
331 {
332 Status = STATUS_ILLEGAL_FUNCTION;
333 }
334
335 return Status;
336 }
337
338 NTSTATUS
339 NTAPI
340 NpPeek(IN PDEVICE_OBJECT DeviceObject,
341 IN PIRP Irp,
342 IN PLIST_ENTRY List)
343 {
344 PIO_STACK_LOCATION IoStack;
345 NODE_TYPE_CODE Type;
346 ULONG OutputLength;
347 ULONG NamedPipeEnd;
348 PNP_CCB Ccb;
349 PFILE_PIPE_PEEK_BUFFER PeekBuffer;
350 PNP_DATA_QUEUE DataQueue;
351 ULONG_PTR BytesPeeked;
352 IO_STATUS_BLOCK IoStatus;
353 NTSTATUS Status;
354 PNP_DATA_QUEUE_ENTRY DataEntry;
355 PAGED_CODE();
356
357 IoStack = IoGetCurrentIrpStackLocation(Irp);
358 OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
359 Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
360
361 if (!Type)
362 {
363 return STATUS_PIPE_DISCONNECTED;
364 }
365
366 if ((Type != NPFS_NTC_CCB) &&
367 (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)))
368 {
369 return STATUS_INVALID_PARAMETER;
370 }
371
372 PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
373 if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
374 {
375 if (NamedPipeEnd != FILE_PIPE_SERVER_END)
376 {
377 NpBugCheck(NamedPipeEnd, 0, 0);
378 }
379
380 DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
381 }
382 else
383 {
384 DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
385 }
386
387 if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
388 {
389 if (Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE)
390 {
391 return STATUS_INVALID_PIPE_STATE;
392 }
393
394 if (DataQueue->QueueState != WriteEntries)
395 {
396 return STATUS_PIPE_BROKEN;
397 }
398 }
399
400 PeekBuffer->NamedPipeState = 0;
401 PeekBuffer->ReadDataAvailable = 0;
402 PeekBuffer->NumberOfMessages = 0;
403 PeekBuffer->MessageLength = 0;
404 PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
405 BytesPeeked = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data);
406
407 if (DataQueue->QueueState == WriteEntries)
408 {
409 DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
410 NP_DATA_QUEUE_ENTRY,
411 QueueEntry);
412 ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));
413
414 PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
415 if (Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
416 {
417 PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
418 PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
419 }
420
421 if (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))
422 {
423 Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
424 }
425 else
426 {
427 IoStatus = NpReadDataQueue(DataQueue,
428 TRUE,
429 FALSE,
430 PeekBuffer->Data,
431 OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data),
432 Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
433 Ccb,
434 List);
435 Status = IoStatus.Status;
436 BytesPeeked += IoStatus.Information;
437 }
438 }
439 else
440 {
441 Status = STATUS_SUCCESS;
442 }
443
444 Irp->IoStatus.Information = BytesPeeked;
445 return Status;
446 }
447
448 NTSTATUS
449 NTAPI
450 NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject,
451 IN PIRP Irp,
452 IN PVOID Context)
453 {
454 PAGED_CODE();
455
456 if (Irp->AssociatedIrp.SystemBuffer)
457 {
458 ExFreePool(Irp->AssociatedIrp.SystemBuffer);
459 }
460
461 IoFreeIrp(Irp);
462 return STATUS_MORE_PROCESSING_REQUIRED;
463 }
464
465 NTSTATUS
466 NTAPI
467 NpTransceive(IN PDEVICE_OBJECT DeviceObject,
468 IN PIRP Irp,
469 IN PLIST_ENTRY List)
470 {
471 PIO_STACK_LOCATION IoStack;
472 PVOID InBuffer, OutBuffer;
473 ULONG InLength, OutLength, BytesWritten;
474 NODE_TYPE_CODE NodeTypeCode;
475 PNP_CCB Ccb;
476 ULONG NamedPipeEnd;
477 PNP_NONPAGED_CCB NonPagedCcb;
478 PNP_DATA_QUEUE ReadQueue, WriteQueue;
479 PNP_EVENT_BUFFER EventBuffer;
480 NTSTATUS Status;
481 PIRP NewIrp;
482 PAGED_CODE();
483
484 IoStack = IoGetCurrentIrpStackLocation(Irp);
485 InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
486 InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer;
487 OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
488 OutBuffer = Irp->UserBuffer;
489
490 if (Irp->RequestorMode == UserMode)
491 {
492 _SEH2_TRY
493 {
494 ProbeForRead(InBuffer, InLength, sizeof(CHAR));
495 ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR));
496 }
497 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
498 {
499 _SEH2_YIELD(return _SEH2_GetExceptionCode());
500 }
501 _SEH2_END;
502 }
503
504 NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd);
505 if (NodeTypeCode != NPFS_NTC_CCB)
506 {
507 return STATUS_PIPE_DISCONNECTED;
508 }
509
510 NonPagedCcb = Ccb->NonPagedCcb;
511 ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
512
513 if (Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE)
514 {
515 Status = STATUS_INVALID_PIPE_STATE;
516 goto Quickie;
517 }
518
519 if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
520 {
521 if (NamedPipeEnd != FILE_PIPE_SERVER_END)
522 {
523 NpBugCheck(NamedPipeEnd, 0, 0);
524 }
525 ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
526 WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
527 }
528 else
529 {
530 ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
531 WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
532 }
533
534 EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];
535
536 if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX ||
537 Ccb->ReadMode[NamedPipeEnd] != FILE_PIPE_MESSAGE_MODE)
538 {
539 Status = STATUS_INVALID_PIPE_STATE;
540 goto Quickie;
541 }
542
543 if (ReadQueue->QueueState != Empty)
544 {
545 Status = STATUS_PIPE_BUSY;
546 goto Quickie;
547 }
548
549 Status = NpWriteDataQueue(WriteQueue,
550 1,
551 InBuffer,
552 InLength,
553 Ccb->Fcb->NamedPipeType,
554 &BytesWritten,
555 Ccb,
556 NamedPipeEnd,
557 Irp->Tail.Overlay.Thread,
558 List);
559 if (Status == STATUS_MORE_PROCESSING_REQUIRED)
560 {
561 ASSERT(WriteQueue->QueueState != ReadEntries);
562 NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
563 if (!NewIrp)
564 {
565 Status = STATUS_INSUFFICIENT_RESOURCES;
566 goto Quickie;
567 }
568
569 IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE);
570
571 if (BytesWritten)
572 {
573 NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
574 BytesWritten,
575 NPFS_WRITE_BLOCK_TAG);
576 if (!NewIrp->AssociatedIrp.SystemBuffer)
577 {
578 IoFreeIrp(NewIrp);
579 Status = STATUS_INSUFFICIENT_RESOURCES;
580 goto Quickie;
581 }
582
583 _SEH2_TRY
584 {
585 RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer,
586 (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten),
587 BytesWritten);
588 }
589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
590 {
591 Status = _SEH2_GetExceptionCode();
592 _SEH2_YIELD(goto Quickie);
593 }
594 _SEH2_END;
595 }
596 else
597 {
598 NewIrp->AssociatedIrp.SystemBuffer = NULL;
599 }
600
601 IoStack = IoGetNextIrpStackLocation(NewIrp);
602 IoSetNextIrpStackLocation(NewIrp);
603
604 NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
605 NewIrp->IoStatus.Information = BytesWritten;
606
607 IoStack->Parameters.Read.Length = BytesWritten;
608 IoStack->MajorFunction = IRP_MJ_WRITE;
609
610 if (BytesWritten > 0) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
611 NewIrp->UserIosb = &NpUserIoStatusBlock;
612
613 Status = NpAddDataQueueEntry(NamedPipeEnd,
614 Ccb,
615 WriteQueue,
616 WriteEntries,
617 Unbuffered,
618 BytesWritten,
619 NewIrp,
620 NULL,
621 0);
622 if (Status != STATUS_PENDING)
623 {
624 NewIrp->IoStatus.Status = Status;
625 InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry);
626 }
627 }
628
629 if (!NT_SUCCESS(Status)) goto Quickie;
630
631 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
632 ASSERT(ReadQueue->QueueState == Empty);
633 Status = NpAddDataQueueEntry(NamedPipeEnd,
634 Ccb,
635 ReadQueue,
636 ReadEntries,
637 Buffered,
638 OutLength,
639 Irp,
640 NULL,
641 0);
642 if (NT_SUCCESS(Status))
643 {
644 if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
645 }
646
647 Quickie:
648 ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
649 return Status;
650 }
651
652 NTSTATUS
653 NTAPI
654 NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
655 IN PIRP Irp)
656 {
657 PIO_STACK_LOCATION IoStack;
658 ULONG InLength, NameLength;
659 UNICODE_STRING SourceString, Prefix;
660 ULONG NamedPipeEnd;
661 PNP_CCB Ccb;
662 PFILE_PIPE_WAIT_FOR_BUFFER Buffer;
663 NTSTATUS Status;
664 NODE_TYPE_CODE NodeTypeCode;
665 PLIST_ENTRY NextEntry;
666 PNP_FCB Fcb;
667 PWCHAR OriginalBuffer;
668 PAGED_CODE();
669
670 IoStack = IoGetCurrentIrpStackLocation(Irp);
671 InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
672
673 SourceString.Buffer = NULL;
674
675 if (NpDecodeFileObject(IoStack->FileObject,
676 NULL,
677 &Ccb,
678 &NamedPipeEnd) != NPFS_NTC_ROOT_DCB)
679 {
680 Status = STATUS_ILLEGAL_FUNCTION;
681 goto Quickie;
682 }
683
684 Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
685 if (InLength < sizeof(*Buffer))
686 {
687 Status = STATUS_INVALID_PARAMETER;
688 goto Quickie;
689 }
690
691 NameLength = Buffer->NameLength;
692 if ((NameLength > (0xFFFF - sizeof(UNICODE_NULL))) ||
693 ((NameLength + FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name)) > InLength))
694 {
695 Status = STATUS_INVALID_PARAMETER;
696 goto Quickie;
697 }
698
699 SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
700 SourceString.Buffer = ExAllocatePoolWithTag(PagedPool,
701 SourceString.Length,
702 NPFS_WRITE_BLOCK_TAG);
703 if (!SourceString.Buffer)
704 {
705 Status = STATUS_INSUFFICIENT_RESOURCES;
706 goto Quickie;
707 }
708
709 SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
710 RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
711
712 Status = STATUS_SUCCESS;
713 OriginalBuffer = SourceString.Buffer;
714 //Status = NpTranslateAlias(&SourceString);
715 if (!NT_SUCCESS(Status)) goto Quickie;
716
717 Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix);
718 Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1);
719
720 NodeTypeCode = Fcb ? Fcb->NodeType : 0;
721 if (NodeTypeCode != NPFS_NTC_FCB)
722 {
723 Status = STATUS_OBJECT_NAME_NOT_FOUND;
724 goto Quickie;
725 }
726
727 for (NextEntry = Fcb->CcbList.Flink;
728 NextEntry != &Fcb->CcbList;
729 NextEntry = NextEntry->Flink)
730 {
731 Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
732 if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
733 }
734
735 if (NextEntry != &Fcb->CcbList)
736 {
737 Status = STATUS_SUCCESS;
738 }
739 else
740 {
741 Status = NpAddWaiter(&NpVcb->WaitQueue,
742 Fcb->Timeout,
743 Irp,
744 OriginalBuffer == SourceString.Buffer ?
745 NULL : &SourceString);
746 }
747
748 Quickie:
749 if (SourceString.Buffer) ExFreePool(SourceString.Buffer);
750 return Status;
751 }
752
753 NTSTATUS
754 NTAPI
755 NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
756 IN PIRP Irp)
757 {
758 ULONG Fsctl;
759 BOOLEAN Overflow = FALSE;
760 LIST_ENTRY DeferredList;
761 NTSTATUS Status;
762 PAGED_CODE();
763
764 InitializeListHead(&DeferredList);
765 Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode;
766
767 switch (Fsctl)
768 {
769 case FSCTL_PIPE_PEEK:
770 NpAcquireExclusiveVcb();
771 Status = NpPeek(DeviceObject, Irp, &DeferredList);
772 break;
773
774 case FSCTL_PIPE_INTERNAL_WRITE:
775 NpAcquireSharedVcb();
776 Status = NpInternalWrite(DeviceObject, Irp, &DeferredList);
777 break;
778
779 case FSCTL_PIPE_TRANSCEIVE:
780 NpAcquireSharedVcb();
781 Status = NpTransceive(DeviceObject, Irp, &DeferredList);
782 break;
783
784 case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
785 NpAcquireSharedVcb();
786 Status = NpInternalTransceive(DeviceObject, Irp, &DeferredList);
787 break;
788
789 case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
790 Overflow = TRUE;
791 // on purpose
792
793 case FSCTL_PIPE_INTERNAL_READ:
794 NpAcquireSharedVcb();
795 Status = NpInternalRead(DeviceObject, Irp, Overflow, &DeferredList);
796 break;
797
798 case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
799
800 NpAcquireSharedVcb();
801 Status = NpQueryClientProcess(DeviceObject, Irp);
802 break;
803
804 case FSCTL_PIPE_ASSIGN_EVENT:
805
806 NpAcquireExclusiveVcb();
807 Status = NpAssignEvent(DeviceObject, Irp);
808 break;
809
810 case FSCTL_PIPE_DISCONNECT:
811
812 NpAcquireExclusiveVcb();
813 Status = NpDisconnect(DeviceObject, Irp, &DeferredList);
814 break;
815
816 case FSCTL_PIPE_LISTEN:
817
818 NpAcquireSharedVcb();
819 Status = NpListen(DeviceObject, Irp, &DeferredList);
820 break;
821
822 case FSCTL_PIPE_QUERY_EVENT:
823
824 NpAcquireExclusiveVcb();
825 Status = NpQueryEvent(DeviceObject, Irp);
826 break;
827
828 case FSCTL_PIPE_WAIT:
829
830 NpAcquireExclusiveVcb();
831 Status = NpWaitForNamedPipe(DeviceObject, Irp);
832 break;
833
834 case FSCTL_PIPE_IMPERSONATE:
835
836 NpAcquireExclusiveVcb();
837 Status = NpImpersonate(DeviceObject, Irp);
838 break;
839
840 case FSCTL_PIPE_SET_CLIENT_PROCESS:
841 NpAcquireExclusiveVcb();
842 Status = NpSetClientProcess(DeviceObject, Irp);
843 break;
844
845 default:
846 return STATUS_NOT_SUPPORTED;
847 }
848
849 NpReleaseVcb();
850 NpCompleteDeferredIrps(&DeferredList);
851
852 return Status;
853 }
854
855 NTSTATUS
856 NTAPI
857 NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
858 IN PIRP Irp)
859 {
860 NTSTATUS Status;
861 PAGED_CODE();
862
863 FsRtlEnterFileSystem();
864
865 Status = NpCommonFileSystemControl(DeviceObject, Irp);
866
867 FsRtlExitFileSystem();
868
869 if (Status != STATUS_PENDING)
870 {
871 Irp->IoStatus.Status = Status;
872 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
873 }
874
875 return Status;
876 }
877
878 /* EOF */