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 = 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 FILE_PIPE_MESSAGE_MODE, 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, 1, &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 */ 879