1 /* 2 * PROJECT: ReactOS Named Pipe FileSystem 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: drivers/filesystems/npfs/create.c 5 * PURPOSE: Pipes Creation 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_CREATE) 15 16 /* FUNCTIONS ******************************************************************/ 17 18 VOID 19 NTAPI 20 NpCheckForNotify(IN PNP_DCB Dcb, 21 IN BOOLEAN SecondList, 22 IN PLIST_ENTRY List) 23 { 24 PLIST_ENTRY NextEntry, ListHead; 25 PIRP Irp; 26 ULONG i; 27 PAGED_CODE(); 28 29 ListHead = &Dcb->NotifyList; 30 for (i = 0; i < 2; i++) 31 { 32 ASSERT(IsListEmpty(ListHead)); 33 while (!IsListEmpty(ListHead)) 34 { 35 NextEntry = RemoveHeadList(ListHead); 36 37 Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); 38 39 if (IoSetCancelRoutine(Irp, NULL)) 40 { 41 Irp->IoStatus.Status = STATUS_SUCCESS; 42 InsertTailList(List, NextEntry); 43 } 44 else 45 { 46 InitializeListHead(NextEntry); 47 } 48 } 49 50 if (!SecondList) break; 51 ListHead = &Dcb->NotifyList2; 52 } 53 } 54 55 IO_STATUS_BLOCK 56 NTAPI 57 NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject, 58 IN ACCESS_MASK DesiredAccess) 59 { 60 IO_STATUS_BLOCK Status; 61 PAGED_CODE(); 62 TRACE("Entered\n"); 63 64 NpSetFileObject(FileObject, NpVcb, NULL, FALSE); 65 ++NpVcb->ReferenceCount; 66 67 Status.Information = FILE_OPENED; 68 Status.Status = STATUS_SUCCESS; 69 TRACE("Leaving, Status.Status = %lx\n", Status.Status); 70 return Status; 71 } 72 73 IO_STATUS_BLOCK 74 NTAPI 75 NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb, 76 IN PFILE_OBJECT FileObject, 77 IN ACCESS_MASK DesiredAccess, 78 IN PLIST_ENTRY List) 79 { 80 IO_STATUS_BLOCK IoStatus; 81 PNP_ROOT_DCB_FCB Ccb; 82 PAGED_CODE(); 83 TRACE("Entered\n"); 84 85 IoStatus.Status = NpCreateRootDcbCcb(&Ccb); 86 if (NT_SUCCESS(IoStatus.Status)) 87 { 88 NpSetFileObject(FileObject, Dcb, Ccb, FALSE); 89 ++Dcb->CurrentInstances; 90 91 IoStatus.Information = FILE_OPENED; 92 IoStatus.Status = STATUS_SUCCESS; 93 } 94 else 95 { 96 IoStatus.Information = 0; 97 } 98 99 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 100 return IoStatus; 101 } 102 103 IO_STATUS_BLOCK 104 NTAPI 105 NpCreateClientEnd(IN PNP_FCB Fcb, 106 IN PFILE_OBJECT FileObject, 107 IN ACCESS_MASK DesiredAccess, 108 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, 109 IN PACCESS_STATE AccessState, 110 IN KPROCESSOR_MODE PreviousMode, 111 IN PETHREAD Thread, 112 IN PLIST_ENTRY List) 113 { 114 PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; 115 BOOLEAN AccessGranted; 116 ACCESS_MASK GrantedAccess; 117 PPRIVILEGE_SET Privileges; 118 UNICODE_STRING ObjectTypeName; 119 IO_STATUS_BLOCK IoStatus; 120 USHORT NamedPipeConfiguration; 121 PLIST_ENTRY NextEntry, ListHead; 122 PNP_CCB Ccb = NULL; 123 TRACE("Entered\n"); 124 125 IoStatus.Information = 0; 126 Privileges = NULL; 127 128 NamedPipeConfiguration = Fcb->NamedPipeConfiguration; 129 130 SubjectSecurityContext = &AccessState->SubjectSecurityContext; 131 SeLockSubjectContext(SubjectSecurityContext); 132 133 AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, 134 SubjectSecurityContext, 135 TRUE, 136 DesiredAccess & ~4, 137 0, 138 &Privileges, 139 IoGetFileObjectGenericMapping(), 140 PreviousMode, 141 &GrantedAccess, 142 &IoStatus.Status); 143 144 if (Privileges) 145 { 146 SeAppendPrivileges(AccessState, Privileges); 147 SeFreePrivileges(Privileges); 148 } 149 150 if (AccessGranted) 151 { 152 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 153 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); 154 } 155 156 ObjectTypeName.Buffer = L"NamedPipe"; 157 ObjectTypeName.Length = 18; 158 SeOpenObjectAuditAlarm(&ObjectTypeName, 159 NULL, 160 &FileObject->FileName, 161 Fcb->SecurityDescriptor, 162 AccessState, 163 FALSE, 164 AccessGranted, 165 PreviousMode, 166 &AccessState->GenerateOnClose); 167 SeUnlockSubjectContext(SubjectSecurityContext); 168 if (!AccessGranted) return IoStatus; 169 170 if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) || 171 ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND))) 172 { 173 IoStatus.Status = STATUS_ACCESS_DENIED; 174 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 175 return IoStatus; 176 } 177 178 if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL; 179 180 ListHead = &Fcb->CcbList; 181 NextEntry = ListHead->Flink; 182 while (NextEntry != ListHead) 183 { 184 Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); 185 if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; 186 187 NextEntry = NextEntry->Flink; 188 } 189 190 if (NextEntry == ListHead) 191 { 192 IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE; 193 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 194 return IoStatus; 195 } 196 197 IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread); 198 if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; 199 200 IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List); 201 if (!NT_SUCCESS(IoStatus.Status)) 202 { 203 NpUninitializeSecurity(Ccb); 204 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 205 return IoStatus; 206 } 207 208 Ccb->ClientSession = NULL; 209 Ccb->Process = IoThreadToProcess(Thread); 210 211 IoStatus.Information = FILE_OPENED; 212 IoStatus.Status = STATUS_SUCCESS; 213 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 214 return IoStatus; 215 } 216 217 NTSTATUS 218 NTAPI 219 NpTranslateAlias( 220 PUNICODE_STRING PipeName) 221 { 222 WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1]; 223 UNICODE_STRING UpcaseString; 224 ULONG Length; 225 PNPFS_ALIAS CurrentAlias; 226 NTSTATUS Status; 227 BOOLEAN BufferAllocated, BackSlash; 228 LONG Result; 229 PAGED_CODE(); 230 231 /* Get the pipe name length and check for empty string */ 232 Length = PipeName->Length; 233 if (Length == 0) 234 { 235 return STATUS_SUCCESS; 236 } 237 238 /* Check if the name starts with a path separator */ 239 BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR); 240 if (BackSlash) 241 { 242 /* We are only interested in the part after the backslash */ 243 Length -= sizeof(WCHAR); 244 } 245 246 /* Check if the length is within our indexed list bounds */ 247 if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) && 248 (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))) 249 { 250 /* Length is within bounds, use the list by length */ 251 CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH]; 252 } 253 else 254 { 255 /* We use the generic list, search for an entry of the right size */ 256 CurrentAlias = NpAliasList; 257 while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length)) 258 { 259 /* Check if we went past the desired length */ 260 if (CurrentAlias->Name.Length > Length) 261 { 262 /* In this case there is no matching alias, return success */ 263 return STATUS_SUCCESS; 264 } 265 266 /* Go to the next alias in the list */ 267 CurrentAlias = CurrentAlias->Next; 268 } 269 } 270 271 /* Did we find any alias? */ 272 if (CurrentAlias == NULL) 273 { 274 /* Nothing found, no matching alias */ 275 return STATUS_SUCCESS; 276 } 277 278 /* Check whether we can use our stack buffer */ 279 if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)) 280 { 281 /* Initialize the upcased string */ 282 UpcaseString.Buffer = UpcaseBuffer; 283 UpcaseString.MaximumLength = sizeof(UpcaseBuffer); 284 285 /* Upcase the pipe name */ 286 Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE); 287 NT_ASSERT(NT_SUCCESS(Status)); 288 BufferAllocated = FALSE; 289 } 290 else 291 { 292 /* Upcase the pipe name, allocate the string buffer */ 293 Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE); 294 if (!NT_SUCCESS(Status)) 295 { 296 return Status; 297 } 298 299 BufferAllocated = TRUE; 300 } 301 302 /* Did the original name start with a backslash? */ 303 if (BackSlash) 304 { 305 /* Skip it for the comparison */ 306 UpcaseString.Buffer++; 307 UpcaseString.Length -= sizeof(WCHAR); 308 } 309 310 /* Make sure the length matches the "raw" length */ 311 NT_ASSERT(UpcaseString.Length == Length); 312 NT_ASSERT(CurrentAlias->Name.Length == Length); 313 314 /* Loop while we have aliases */ 315 do 316 { 317 /* Compare the names and check if they match */ 318 Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name); 319 if (Result == 0) 320 { 321 /* The names match, use the target name */ 322 *PipeName = *CurrentAlias->TargetName; 323 324 /* Did the original name start with a backslash? */ 325 if (!BackSlash) 326 { 327 /* It didn't, so skip it in the target name as well */ 328 PipeName->Buffer++; 329 PipeName->Length -= sizeof(WCHAR); 330 } 331 break; 332 } 333 334 /* Check if we went past all string candidates */ 335 if (Result < 0) 336 { 337 /* Nothing found, we're done */ 338 break; 339 } 340 341 /* Go to the next alias */ 342 CurrentAlias = CurrentAlias->Next; 343 344 /* Keep looping while we have aliases of the right length */ 345 } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length)); 346 347 /* Did we allocate a buffer? */ 348 if (BufferAllocated) 349 { 350 /* Free the allocated buffer */ 351 ASSERT(UpcaseString.Buffer != UpcaseBuffer); 352 RtlFreeUnicodeString(&UpcaseString); 353 } 354 355 return STATUS_SUCCESS; 356 } 357 358 NTSTATUS 359 NTAPI 360 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, 361 IN PIRP Irp) 362 { 363 IO_STATUS_BLOCK IoStatus; 364 PIO_STACK_LOCATION IoStack; 365 UNICODE_STRING FileName; 366 PFILE_OBJECT FileObject; 367 PFILE_OBJECT RelatedFileObject; 368 NODE_TYPE_CODE Type; 369 PNP_CCB Ccb; 370 PNP_FCB Fcb; 371 PNP_DCB Dcb; 372 ACCESS_MASK DesiredAccess; 373 LIST_ENTRY DeferredList; 374 UNICODE_STRING Prefix; 375 TRACE("Entered\n"); 376 377 InitializeListHead(&DeferredList); 378 IoStack = IoGetCurrentIrpStackLocation(Irp); 379 FileObject = IoStack->FileObject; 380 RelatedFileObject = FileObject->RelatedFileObject; 381 FileName = FileObject->FileName; 382 DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess; 383 384 IoStatus.Information = 0; 385 386 FsRtlEnterFileSystem(); 387 NpAcquireExclusiveVcb(); 388 389 if (RelatedFileObject) 390 { 391 Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE); 392 } 393 else 394 { 395 Type = 0; 396 Fcb = NULL; 397 Ccb = NULL; 398 } 399 400 if (FileName.Length) 401 { 402 if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) && 403 (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && 404 !(RelatedFileObject)) 405 { 406 IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, 407 FileObject, 408 DesiredAccess, 409 &DeferredList); 410 goto Quickie; 411 } 412 } 413 else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB)) 414 { 415 IoStatus = NpOpenNamedPipeFileSystem(FileObject, 416 DesiredAccess); 417 goto Quickie; 418 } 419 else if (Type == NPFS_NTC_ROOT_DCB) 420 { 421 IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, 422 FileObject, 423 DesiredAccess, 424 &DeferredList); 425 goto Quickie; 426 } 427 428 IoStatus.Status = NpTranslateAlias(&FileName); 429 if (!NT_SUCCESS(IoStatus.Status)) goto Quickie; 430 431 if (RelatedFileObject) 432 { 433 if (Type == NPFS_NTC_ROOT_DCB) 434 { 435 Dcb = (PNP_DCB)Ccb; 436 IoStatus.Status = NpFindRelativePrefix(Dcb, 437 &FileName, 438 1, 439 &Prefix, 440 &Fcb); 441 if (!NT_SUCCESS(IoStatus.Status)) 442 { 443 goto Quickie; 444 } 445 } 446 else if ((Type != NPFS_NTC_CCB) || (FileName.Length)) 447 { 448 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 449 goto Quickie; 450 } 451 else 452 { 453 Prefix.Length = 0; 454 } 455 } 456 else 457 { 458 if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) || 459 (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) 460 { 461 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 462 goto Quickie; 463 } 464 465 Fcb = NpFindPrefix(&FileName, 1, &Prefix); 466 } 467 468 if (Prefix.Length) 469 { 470 IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ? 471 STATUS_OBJECT_NAME_NOT_FOUND : 472 STATUS_OBJECT_NAME_INVALID; 473 goto Quickie; 474 } 475 476 if (Fcb->NodeType != NPFS_NTC_FCB) 477 { 478 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 479 goto Quickie; 480 } 481 482 if (!Fcb->ServerOpenCount) 483 { 484 IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; 485 goto Quickie; 486 } 487 488 IoStatus = NpCreateClientEnd(Fcb, 489 FileObject, 490 DesiredAccess, 491 IoStack->Parameters.CreatePipe. 492 SecurityContext->SecurityQos, 493 IoStack->Parameters.CreatePipe. 494 SecurityContext->AccessState, 495 IoStack->Flags & 496 SL_FORCE_ACCESS_CHECK ? 497 UserMode : Irp->RequestorMode, 498 Irp->Tail.Overlay.Thread, 499 &DeferredList); 500 501 Quickie: 502 NpReleaseVcb(); 503 NpCompleteDeferredIrps(&DeferredList); 504 FsRtlExitFileSystem(); 505 506 Irp->IoStatus = IoStatus; 507 IoCompleteRequest(Irp, IO_NO_INCREMENT); 508 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 509 return IoStatus.Status; 510 } 511 512 IO_STATUS_BLOCK 513 NTAPI 514 NpCreateExistingNamedPipe(IN PNP_FCB Fcb, 515 IN PFILE_OBJECT FileObject, 516 IN ACCESS_MASK DesiredAccess, 517 IN PACCESS_STATE AccessState, 518 IN KPROCESSOR_MODE PreviousMode, 519 IN ULONG Disposition, 520 IN ULONG ShareAccess, 521 IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, 522 IN PEPROCESS Process, 523 OUT PLIST_ENTRY List) 524 { 525 PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; 526 IO_STATUS_BLOCK IoStatus; 527 UNICODE_STRING ObjectTypeName; 528 ACCESS_MASK GrantedAccess; 529 PNP_CCB Ccb; 530 PPRIVILEGE_SET Privileges; 531 USHORT NamedPipeConfiguration, CheckShareAccess; 532 BOOLEAN AccessGranted; 533 PAGED_CODE(); 534 TRACE("Entered\n"); 535 536 Privileges = NULL; 537 538 NamedPipeConfiguration = Fcb->NamedPipeConfiguration; 539 540 SubjectSecurityContext = &AccessState->SubjectSecurityContext; 541 SeLockSubjectContext(SubjectSecurityContext); 542 543 IoStatus.Information = 0; 544 545 AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, 546 SubjectSecurityContext, 547 TRUE, 548 DesiredAccess | 4, 549 0, 550 &Privileges, 551 IoGetFileObjectGenericMapping(), 552 PreviousMode, 553 &GrantedAccess, 554 &IoStatus.Status); 555 556 if (Privileges) 557 { 558 SeAppendPrivileges(AccessState, Privileges); 559 SeFreePrivileges(Privileges); 560 } 561 562 if (AccessGranted) 563 { 564 AccessState->PreviouslyGrantedAccess |= GrantedAccess; 565 AccessState->RemainingDesiredAccess &= ~(GrantedAccess | 0x2000000); 566 } 567 568 ObjectTypeName.Buffer = L"NamedPipe"; 569 ObjectTypeName.Length = 18; 570 SeOpenObjectAuditAlarm(&ObjectTypeName, 571 NULL, 572 &FileObject->FileName, 573 Fcb->SecurityDescriptor, 574 AccessState, 575 FALSE, 576 AccessGranted, 577 PreviousMode, 578 &AccessState->GenerateOnClose); 579 580 SeUnlockSubjectContext(SubjectSecurityContext); 581 if (!AccessGranted) 582 { 583 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 584 return IoStatus; 585 } 586 587 if (Fcb->CurrentInstances >= Fcb->MaximumInstances) 588 { 589 IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; 590 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 591 return IoStatus; 592 } 593 594 if (Disposition == FILE_CREATE) 595 { 596 IoStatus.Status = STATUS_ACCESS_DENIED; 597 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 598 return IoStatus; 599 } 600 601 CheckShareAccess = 0; 602 if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) 603 { 604 CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; 605 } 606 else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) 607 { 608 CheckShareAccess = FILE_SHARE_READ; 609 } 610 else if (NamedPipeConfiguration == FILE_PIPE_INBOUND) 611 { 612 CheckShareAccess = FILE_SHARE_WRITE; 613 } 614 615 if (CheckShareAccess != ShareAccess) 616 { 617 IoStatus.Status = STATUS_ACCESS_DENIED; 618 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 619 return IoStatus; 620 } 621 622 IoStatus.Status = NpCreateCcb(Fcb, 623 FileObject, 624 FILE_PIPE_LISTENING_STATE, 625 Parameters->ReadMode & 0xFF, 626 Parameters->CompletionMode & 0xFF, 627 Parameters->InboundQuota, 628 Parameters->OutboundQuota, 629 &Ccb); 630 if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; 631 632 IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue, 633 &Fcb->FullName, 634 FALSE, 635 List); 636 if (!NT_SUCCESS(IoStatus.Status)) 637 { 638 --Ccb->Fcb->CurrentInstances; 639 NpDeleteCcb(Ccb, List); 640 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 641 return IoStatus; 642 } 643 644 NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); 645 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; 646 NpCheckForNotify(Fcb->ParentDcb, 0, List); 647 648 IoStatus.Status = STATUS_SUCCESS; 649 IoStatus.Information = FILE_OPENED; 650 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 651 return IoStatus; 652 } 653 654 NTSTATUS 655 NTAPI 656 NpCreateNewNamedPipe(IN PNP_DCB Dcb, 657 IN PFILE_OBJECT FileObject, 658 IN UNICODE_STRING PipeName, 659 IN ACCESS_MASK DesiredAccess, 660 IN PACCESS_STATE AccessState, 661 IN USHORT Disposition, 662 IN USHORT ShareAccess, 663 IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, 664 IN PEPROCESS Process, 665 IN PLIST_ENTRY List, 666 OUT PIO_STATUS_BLOCK IoStatus) 667 { 668 NTSTATUS Status; 669 USHORT NamedPipeConfiguration; 670 PSECURITY_SUBJECT_CONTEXT SecurityContext; 671 PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor; 672 PNP_CCB Ccb; 673 PNP_FCB Fcb; 674 PAGED_CODE(); 675 TRACE("Entered\n"); 676 677 if (!(Parameters->TimeoutSpecified) || 678 !(Parameters->MaximumInstances) || 679 (Parameters->DefaultTimeout.QuadPart >= 0)) 680 { 681 Status = STATUS_INVALID_PARAMETER; 682 goto Quickie; 683 } 684 685 if (Disposition == FILE_OPEN) 686 { 687 Status = STATUS_OBJECT_NAME_NOT_FOUND; 688 goto Quickie; 689 } 690 691 if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE)) 692 { 693 NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX; 694 } 695 else if (ShareAccess == FILE_SHARE_READ) 696 { 697 NamedPipeConfiguration = FILE_PIPE_OUTBOUND; 698 } 699 else if (ShareAccess == FILE_SHARE_WRITE) 700 { 701 NamedPipeConfiguration = FILE_PIPE_INBOUND; 702 } 703 else 704 { 705 Status = STATUS_INVALID_PARAMETER; 706 goto Quickie; 707 } 708 709 if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE && 710 Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE) 711 { 712 Status = STATUS_INVALID_PARAMETER; 713 goto Quickie; 714 } 715 716 Status = NpCreateFcb(Dcb, 717 &PipeName, 718 Parameters->MaximumInstances, 719 Parameters->DefaultTimeout, 720 NamedPipeConfiguration, 721 Parameters->NamedPipeType & 0xFFFF, 722 &Fcb); 723 if (!NT_SUCCESS(Status)) goto Quickie; 724 725 Status = NpCreateCcb(Fcb, 726 FileObject, 727 FILE_PIPE_LISTENING_STATE, 728 Parameters->ReadMode & 0xFF, 729 Parameters->CompletionMode & 0xFF, 730 Parameters->InboundQuota, 731 Parameters->OutboundQuota, 732 &Ccb); 733 if (!NT_SUCCESS(Status)) 734 { 735 NpDeleteFcb(Fcb, List); 736 goto Quickie; 737 } 738 739 SecurityContext = &AccessState->SubjectSecurityContext; 740 SeLockSubjectContext(SecurityContext); 741 742 Status = SeAssignSecurity(NULL, 743 AccessState->SecurityDescriptor, 744 &SecurityDescriptor, 745 FALSE, 746 SecurityContext, 747 IoGetFileObjectGenericMapping(), 748 PagedPool); 749 SeUnlockSubjectContext(SecurityContext); 750 if (!NT_SUCCESS(Status)) 751 { 752 NpDeleteCcb(Ccb, List); 753 NpDeleteFcb(Fcb, List); 754 goto Quickie; 755 } 756 757 Status = ObLogSecurityDescriptor(SecurityDescriptor, 758 &CachedSecurityDescriptor, 759 1); 760 ExFreePoolWithTag(SecurityDescriptor, 0); 761 762 if (!NT_SUCCESS(Status)) 763 { 764 NpDeleteCcb(Ccb, List); 765 NpDeleteFcb(Fcb, List); 766 goto Quickie; 767 } 768 769 Fcb->SecurityDescriptor = CachedSecurityDescriptor; 770 771 NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); 772 Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; 773 774 NpCheckForNotify(Dcb, TRUE, List); 775 776 IoStatus->Status = STATUS_SUCCESS; 777 IoStatus->Information = FILE_CREATED; 778 779 TRACE("Leaving, STATUS_SUCCESS\n"); 780 return STATUS_SUCCESS; 781 782 Quickie: 783 TRACE("Leaving, Status = %lx\n", Status); 784 IoStatus->Information = 0; 785 IoStatus->Status = Status; 786 return Status; 787 } 788 789 NTSTATUS 790 NTAPI 791 NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, 792 IN PIRP Irp) 793 { 794 PIO_STACK_LOCATION IoStack; 795 PFILE_OBJECT FileObject; 796 PFILE_OBJECT RelatedFileObject; 797 USHORT Disposition, ShareAccess; 798 PEPROCESS Process; 799 LIST_ENTRY DeferredList; 800 UNICODE_STRING FileName; 801 PNP_FCB Fcb; 802 UNICODE_STRING Prefix; 803 PNAMED_PIPE_CREATE_PARAMETERS Parameters; 804 IO_STATUS_BLOCK IoStatus; 805 TRACE("Entered\n"); 806 807 InitializeListHead(&DeferredList); 808 Process = IoGetRequestorProcess(Irp); 809 810 IoStack = IoGetCurrentIrpStackLocation(Irp); 811 FileObject = IoStack->FileObject; 812 RelatedFileObject = FileObject->RelatedFileObject; 813 814 Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF; 815 ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF; 816 Parameters = IoStack->Parameters.CreatePipe.Parameters; 817 818 FileName = FileObject->FileName; 819 820 IoStatus.Information = 0; 821 822 FsRtlEnterFileSystem(); 823 NpAcquireExclusiveVcb(); 824 825 if (RelatedFileObject) 826 { 827 Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1); 828 if (!(Fcb) || 829 (Fcb->NodeType != NPFS_NTC_ROOT_DCB) || 830 (FileName.Length < sizeof(WCHAR)) || 831 (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) 832 { 833 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 834 goto Quickie; 835 } 836 837 IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext, 838 &FileName, 839 TRUE, 840 &Prefix, 841 &Fcb); 842 if (!NT_SUCCESS(IoStatus.Status)) 843 { 844 goto Quickie; 845 } 846 } 847 else 848 { 849 if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) || 850 FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR) 851 { 852 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 853 goto Quickie; 854 } 855 856 Fcb = NpFindPrefix(&FileName, 1, &Prefix); 857 } 858 859 if (Prefix.Length) 860 { 861 if (Fcb->NodeType == NPFS_NTC_ROOT_DCB) 862 { 863 IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb, 864 FileObject, 865 FileName, 866 IoStack->Parameters.CreatePipe. 867 SecurityContext->DesiredAccess, 868 IoStack->Parameters.CreatePipe. 869 SecurityContext->AccessState, 870 Disposition, 871 ShareAccess, 872 Parameters, 873 Process, 874 &DeferredList, 875 &IoStatus); 876 goto Quickie; 877 } 878 else 879 { 880 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 881 goto Quickie; 882 } 883 } 884 885 if (Fcb->NodeType != NPFS_NTC_FCB) 886 { 887 IoStatus.Status = STATUS_OBJECT_NAME_INVALID; 888 goto Quickie; 889 } 890 891 IoStatus = NpCreateExistingNamedPipe(Fcb, 892 FileObject, 893 IoStack->Parameters.CreatePipe. 894 SecurityContext->DesiredAccess, 895 IoStack->Parameters.CreatePipe. 896 SecurityContext->AccessState, 897 IoStack->Flags & 898 SL_FORCE_ACCESS_CHECK ? 899 UserMode : Irp->RequestorMode, 900 Disposition, 901 ShareAccess, 902 Parameters, 903 Process, 904 &DeferredList); 905 906 Quickie: 907 NpReleaseVcb(); 908 NpCompleteDeferredIrps(&DeferredList); 909 FsRtlExitFileSystem(); 910 911 TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); 912 Irp->IoStatus = IoStatus; 913 IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); 914 return IoStatus.Status; 915 } 916 917 /* EOF */ 918