/* * PROJECT: ReactOS Named Pipe FileSystem * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: drivers/filesystems/npfs/create.c * PURPOSE: Pipes Creation * PROGRAMMERS: ReactOS Portable Systems Group */ /* INCLUDES *******************************************************************/ #include "npfs.h" // File ID number for NPFS bugchecking support #define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_CREATE) /* FUNCTIONS ******************************************************************/ VOID NTAPI NpCheckForNotify(IN PNP_DCB Dcb, IN BOOLEAN SecondList, IN PLIST_ENTRY List) { PLIST_ENTRY NextEntry, ListHead; PIRP Irp; ULONG i; PAGED_CODE(); ListHead = &Dcb->NotifyList; for (i = 0; i < 2; i++) { ASSERT(IsListEmpty(ListHead)); while (!IsListEmpty(ListHead)) { NextEntry = RemoveHeadList(ListHead); Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry); if (IoSetCancelRoutine(Irp, NULL)) { Irp->IoStatus.Status = STATUS_SUCCESS; InsertTailList(List, NextEntry); } else { InitializeListHead(NextEntry); } } if (!SecondList) break; ListHead = &Dcb->NotifyList2; } } IO_STATUS_BLOCK NTAPI NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess) { IO_STATUS_BLOCK Status; PAGED_CODE(); TRACE("Entered\n"); NpSetFileObject(FileObject, NpVcb, NULL, FALSE); ++NpVcb->ReferenceCount; Status.Information = FILE_OPENED; Status.Status = STATUS_SUCCESS; TRACE("Leaving, Status.Status = %lx\n", Status.Status); return Status; } IO_STATUS_BLOCK NTAPI NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN PLIST_ENTRY List) { IO_STATUS_BLOCK IoStatus; PNP_ROOT_DCB_FCB Ccb; PAGED_CODE(); TRACE("Entered\n"); IoStatus.Status = NpCreateRootDcbCcb(&Ccb); if (NT_SUCCESS(IoStatus.Status)) { NpSetFileObject(FileObject, Dcb, Ccb, FALSE); ++Dcb->CurrentInstances; IoStatus.Information = FILE_OPENED; IoStatus.Status = STATUS_SUCCESS; } else { IoStatus.Information = 0; } TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } IO_STATUS_BLOCK NTAPI NpCreateClientEnd(IN PNP_FCB Fcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE PreviousMode, IN PETHREAD Thread, IN PLIST_ENTRY List) { PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; BOOLEAN AccessGranted; ACCESS_MASK GrantedAccess; PPRIVILEGE_SET Privileges; UNICODE_STRING ObjectTypeName; IO_STATUS_BLOCK IoStatus; USHORT NamedPipeConfiguration; PLIST_ENTRY NextEntry, ListHead; PNP_CCB Ccb = NULL; TRACE("Entered\n"); IoStatus.Information = 0; Privileges = NULL; NamedPipeConfiguration = Fcb->NamedPipeConfiguration; SubjectSecurityContext = &AccessState->SubjectSecurityContext; SeLockSubjectContext(SubjectSecurityContext); AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, SubjectSecurityContext, TRUE, DesiredAccess & ~4, 0, &Privileges, IoGetFileObjectGenericMapping(), PreviousMode, &GrantedAccess, &IoStatus.Status); if (Privileges) { SeAppendPrivileges(AccessState, Privileges); SeFreePrivileges(Privileges); } if (AccessGranted) { AccessState->PreviouslyGrantedAccess |= GrantedAccess; AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); } ObjectTypeName.Buffer = L"NamedPipe"; ObjectTypeName.Length = 18; SeOpenObjectAuditAlarm(&ObjectTypeName, NULL, &FileObject->FileName, Fcb->SecurityDescriptor, AccessState, FALSE, AccessGranted, PreviousMode, &AccessState->GenerateOnClose); SeUnlockSubjectContext(SubjectSecurityContext); if (!AccessGranted) return IoStatus; if (((GrantedAccess & FILE_READ_DATA) && (NamedPipeConfiguration == FILE_PIPE_INBOUND)) || ((GrantedAccess & FILE_WRITE_DATA) && (NamedPipeConfiguration == FILE_PIPE_OUTBOUND))) { IoStatus.Status = STATUS_ACCESS_DENIED; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } if (!(GrantedAccess & (FILE_READ_DATA | FILE_WRITE_DATA))) SecurityQos = NULL; ListHead = &Fcb->CcbList; NextEntry = ListHead->Flink; while (NextEntry != ListHead) { Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry); if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break; NextEntry = NextEntry->Flink; } if (NextEntry == ListHead) { IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread); if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List); if (!NT_SUCCESS(IoStatus.Status)) { NpUninitializeSecurity(Ccb); TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } Ccb->ClientSession = NULL; Ccb->Process = IoThreadToProcess(Thread); IoStatus.Information = FILE_OPENED; IoStatus.Status = STATUS_SUCCESS; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } NTSTATUS NTAPI NpTranslateAlias( PUNICODE_STRING PipeName) { WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1]; UNICODE_STRING UpcaseString; ULONG Length; PNPFS_ALIAS CurrentAlias; NTSTATUS Status; BOOLEAN BufferAllocated, BackSlash; LONG Result; PAGED_CODE(); /* Get the pipe name length and check for empty string */ Length = PipeName->Length; if (Length == 0) { return STATUS_SUCCESS; } /* Check if the name starts with a path separator */ BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR); if (BackSlash) { /* We are only interested in the part after the backslash */ Length -= sizeof(WCHAR); } /* Check if the length is within our indexed list bounds */ if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) && (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR))) { /* Length is within bounds, use the list by length */ CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH]; } else { /* We use the generic list, search for an entry of the right size */ CurrentAlias = NpAliasList; while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length != Length)) { /* Check if we went past the desired length */ if (CurrentAlias->Name.Length > Length) { /* In this case there is no matching alias, return success */ return STATUS_SUCCESS; } /* Go to the next alias in the list */ CurrentAlias = CurrentAlias->Next; } } /* Did we find any alias? */ if (CurrentAlias == NULL) { /* Nothing found, no matching alias */ return STATUS_SUCCESS; } /* Check whether we can use our stack buffer */ if (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)) { /* Initialize the upcased string */ UpcaseString.Buffer = UpcaseBuffer; UpcaseString.MaximumLength = sizeof(UpcaseBuffer); /* Upcase the pipe name */ Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE); NT_ASSERT(NT_SUCCESS(Status)); BufferAllocated = FALSE; } else { /* Upcase the pipe name, allocate the string buffer */ Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE); if (!NT_SUCCESS(Status)) { return Status; } BufferAllocated = TRUE; } /* Did the original name start with a backslash? */ if (BackSlash) { /* Skip it for the comparison */ UpcaseString.Buffer++; UpcaseString.Length -= sizeof(WCHAR); } /* Make sure the length matches the "raw" length */ NT_ASSERT(UpcaseString.Length == Length); NT_ASSERT(CurrentAlias->Name.Length == Length); /* Loop while we have aliases */ do { /* Compare the names and check if they match */ Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name); if (Result == 0) { /* The names match, use the target name */ *PipeName = *CurrentAlias->TargetName; /* Did the original name start with a backslash? */ if (!BackSlash) { /* It didn't, so skip it in the target name as well */ PipeName->Buffer++; PipeName->Length -= sizeof(WCHAR); } break; } /* Check if we went past all string candidates */ if (Result < 0) { /* Nothing found, we're done */ break; } /* Go to the next alias */ CurrentAlias = CurrentAlias->Next; /* Keep looping while we have aliases of the right length */ } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length)); /* Did we allocate a buffer? */ if (BufferAllocated) { /* Free the allocated buffer */ ASSERT(UpcaseString.Buffer != UpcaseBuffer); RtlFreeUnicodeString(&UpcaseString); } return STATUS_SUCCESS; } NTSTATUS NTAPI NpFsdCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { IO_STATUS_BLOCK IoStatus; PIO_STACK_LOCATION IoStack; UNICODE_STRING FileName; PFILE_OBJECT FileObject; PFILE_OBJECT RelatedFileObject; NODE_TYPE_CODE Type; PNP_CCB Ccb; PNP_FCB Fcb; PNP_DCB Dcb; ACCESS_MASK DesiredAccess; LIST_ENTRY DeferredList; UNICODE_STRING Prefix; TRACE("Entered\n"); InitializeListHead(&DeferredList); IoStack = IoGetCurrentIrpStackLocation(Irp); FileObject = IoStack->FileObject; RelatedFileObject = FileObject->RelatedFileObject; FileName = FileObject->FileName; DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess; IoStatus.Information = 0; FsRtlEnterFileSystem(); NpAcquireExclusiveVcb(); if (RelatedFileObject) { Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE); } else { Type = 0; Fcb = NULL; Ccb = NULL; } if (FileName.Length) { if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) && (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) && !(RelatedFileObject)) { IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, FileObject, DesiredAccess, &DeferredList); goto Quickie; } } else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB)) { IoStatus = NpOpenNamedPipeFileSystem(FileObject, DesiredAccess); goto Quickie; } else if (Type == NPFS_NTC_ROOT_DCB) { IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb, FileObject, DesiredAccess, &DeferredList); goto Quickie; } IoStatus.Status = NpTranslateAlias(&FileName); if (!NT_SUCCESS(IoStatus.Status)) goto Quickie; if (RelatedFileObject) { if (Type == NPFS_NTC_ROOT_DCB) { Dcb = (PNP_DCB)Ccb; IoStatus.Status = NpFindRelativePrefix(Dcb, &FileName, 1, &Prefix, &Fcb); if (!NT_SUCCESS(IoStatus.Status)) { goto Quickie; } } else if ((Type != NPFS_NTC_CCB) || (FileName.Length)) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } else { Prefix.Length = 0; } } else { if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) || (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } Fcb = NpFindPrefix(&FileName, 1, &Prefix); } if (Prefix.Length) { IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ? STATUS_OBJECT_NAME_NOT_FOUND : STATUS_OBJECT_NAME_INVALID; goto Quickie; } if (Fcb->NodeType != NPFS_NTC_FCB) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } if (!Fcb->ServerOpenCount) { IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND; goto Quickie; } IoStatus = NpCreateClientEnd(Fcb, FileObject, DesiredAccess, IoStack->Parameters.CreatePipe. SecurityContext->SecurityQos, IoStack->Parameters.CreatePipe. SecurityContext->AccessState, IoStack->Flags & SL_FORCE_ACCESS_CHECK ? UserMode : Irp->RequestorMode, Irp->Tail.Overlay.Thread, &DeferredList); Quickie: NpReleaseVcb(); NpCompleteDeferredIrps(&DeferredList); FsRtlExitFileSystem(); Irp->IoStatus = IoStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus.Status; } IO_STATUS_BLOCK NTAPI NpCreateExistingNamedPipe(IN PNP_FCB Fcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE PreviousMode, IN ULONG Disposition, IN ULONG ShareAccess, IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, IN PEPROCESS Process, OUT PLIST_ENTRY List) { PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext; IO_STATUS_BLOCK IoStatus; UNICODE_STRING ObjectTypeName; ACCESS_MASK GrantedAccess; PNP_CCB Ccb; PPRIVILEGE_SET Privileges; USHORT NamedPipeConfiguration, CheckShareAccess; BOOLEAN AccessGranted; PAGED_CODE(); TRACE("Entered\n"); Privileges = NULL; NamedPipeConfiguration = Fcb->NamedPipeConfiguration; SubjectSecurityContext = &AccessState->SubjectSecurityContext; SeLockSubjectContext(SubjectSecurityContext); IoStatus.Information = 0; AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor, SubjectSecurityContext, TRUE, DesiredAccess | 4, 0, &Privileges, IoGetFileObjectGenericMapping(), PreviousMode, &GrantedAccess, &IoStatus.Status); if (Privileges) { SeAppendPrivileges(AccessState, Privileges); SeFreePrivileges(Privileges); } if (AccessGranted) { AccessState->PreviouslyGrantedAccess |= GrantedAccess; AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED); } ObjectTypeName.Buffer = L"NamedPipe"; ObjectTypeName.Length = 18; SeOpenObjectAuditAlarm(&ObjectTypeName, NULL, &FileObject->FileName, Fcb->SecurityDescriptor, AccessState, FALSE, AccessGranted, PreviousMode, &AccessState->GenerateOnClose); SeUnlockSubjectContext(SubjectSecurityContext); if (!AccessGranted) { TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } if (Fcb->CurrentInstances >= Fcb->MaximumInstances) { IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } if (Disposition == FILE_CREATE) { IoStatus.Status = STATUS_ACCESS_DENIED; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } CheckShareAccess = 0; if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX) { CheckShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; } else if (NamedPipeConfiguration == FILE_PIPE_OUTBOUND) { CheckShareAccess = FILE_SHARE_READ; } else if (NamedPipeConfiguration == FILE_PIPE_INBOUND) { CheckShareAccess = FILE_SHARE_WRITE; } if (CheckShareAccess != ShareAccess) { IoStatus.Status = STATUS_ACCESS_DENIED; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } IoStatus.Status = NpCreateCcb(Fcb, FileObject, FILE_PIPE_LISTENING_STATE, Parameters->ReadMode & 0xFF, Parameters->CompletionMode & 0xFF, Parameters->InboundQuota, Parameters->OutboundQuota, &Ccb); if (!NT_SUCCESS(IoStatus.Status)) return IoStatus; IoStatus.Status = NpCancelWaiter(&NpVcb->WaitQueue, &Fcb->FullName, FALSE, List); if (!NT_SUCCESS(IoStatus.Status)) { --Ccb->Fcb->CurrentInstances; NpDeleteCcb(Ccb, List); TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; NpCheckForNotify(Fcb->ParentDcb, 0, List); IoStatus.Status = STATUS_SUCCESS; IoStatus.Information = FILE_OPENED; TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); return IoStatus; } NTSTATUS NTAPI NpCreateNewNamedPipe(IN PNP_DCB Dcb, IN PFILE_OBJECT FileObject, IN UNICODE_STRING PipeName, IN ACCESS_MASK DesiredAccess, IN PACCESS_STATE AccessState, IN USHORT Disposition, IN USHORT ShareAccess, IN PNAMED_PIPE_CREATE_PARAMETERS Parameters, IN PEPROCESS Process, IN PLIST_ENTRY List, OUT PIO_STATUS_BLOCK IoStatus) { NTSTATUS Status; USHORT NamedPipeConfiguration; PSECURITY_SUBJECT_CONTEXT SecurityContext; PSECURITY_DESCRIPTOR SecurityDescriptor, CachedSecurityDescriptor; PNP_CCB Ccb; PNP_FCB Fcb; PAGED_CODE(); TRACE("Entered\n"); if (!(Parameters->TimeoutSpecified) || !(Parameters->MaximumInstances) || (Parameters->DefaultTimeout.QuadPart >= 0)) { Status = STATUS_INVALID_PARAMETER; goto Quickie; } if (Disposition == FILE_OPEN) { Status = STATUS_OBJECT_NAME_NOT_FOUND; goto Quickie; } if (ShareAccess == (FILE_SHARE_READ | FILE_SHARE_WRITE)) { NamedPipeConfiguration = FILE_PIPE_FULL_DUPLEX; } else if (ShareAccess == FILE_SHARE_READ) { NamedPipeConfiguration = FILE_PIPE_OUTBOUND; } else if (ShareAccess == FILE_SHARE_WRITE) { NamedPipeConfiguration = FILE_PIPE_INBOUND; } else { Status = STATUS_INVALID_PARAMETER; goto Quickie; } if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE && Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE) { Status = STATUS_INVALID_PARAMETER; goto Quickie; } Status = NpCreateFcb(Dcb, &PipeName, Parameters->MaximumInstances, Parameters->DefaultTimeout, NamedPipeConfiguration, Parameters->NamedPipeType & 0xFFFF, &Fcb); if (!NT_SUCCESS(Status)) goto Quickie; Status = NpCreateCcb(Fcb, FileObject, FILE_PIPE_LISTENING_STATE, Parameters->ReadMode & 0xFF, Parameters->CompletionMode & 0xFF, Parameters->InboundQuota, Parameters->OutboundQuota, &Ccb); if (!NT_SUCCESS(Status)) { NpDeleteFcb(Fcb, List); goto Quickie; } SecurityContext = &AccessState->SubjectSecurityContext; SeLockSubjectContext(SecurityContext); Status = SeAssignSecurity(NULL, AccessState->SecurityDescriptor, &SecurityDescriptor, FALSE, SecurityContext, IoGetFileObjectGenericMapping(), PagedPool); SeUnlockSubjectContext(SecurityContext); if (!NT_SUCCESS(Status)) { NpDeleteCcb(Ccb, List); NpDeleteFcb(Fcb, List); goto Quickie; } Status = ObLogSecurityDescriptor(SecurityDescriptor, &CachedSecurityDescriptor, 1); ExFreePoolWithTag(SecurityDescriptor, 0); if (!NT_SUCCESS(Status)) { NpDeleteCcb(Ccb, List); NpDeleteFcb(Fcb, List); goto Quickie; } Fcb->SecurityDescriptor = CachedSecurityDescriptor; NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE); Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject; NpCheckForNotify(Dcb, TRUE, List); IoStatus->Status = STATUS_SUCCESS; IoStatus->Information = FILE_CREATED; TRACE("Leaving, STATUS_SUCCESS\n"); return STATUS_SUCCESS; Quickie: TRACE("Leaving, Status = %lx\n", Status); IoStatus->Information = 0; IoStatus->Status = Status; return Status; } NTSTATUS NTAPI NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION IoStack; PFILE_OBJECT FileObject; PFILE_OBJECT RelatedFileObject; USHORT Disposition, ShareAccess; PEPROCESS Process; LIST_ENTRY DeferredList; UNICODE_STRING FileName; PNP_FCB Fcb; UNICODE_STRING Prefix; PNAMED_PIPE_CREATE_PARAMETERS Parameters; IO_STATUS_BLOCK IoStatus; TRACE("Entered\n"); InitializeListHead(&DeferredList); Process = IoGetRequestorProcess(Irp); IoStack = IoGetCurrentIrpStackLocation(Irp); FileObject = IoStack->FileObject; RelatedFileObject = FileObject->RelatedFileObject; Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF; ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF; Parameters = IoStack->Parameters.CreatePipe.Parameters; FileName = FileObject->FileName; IoStatus.Information = 0; FsRtlEnterFileSystem(); NpAcquireExclusiveVcb(); if (RelatedFileObject) { Fcb = (PNP_FCB)((ULONG_PTR)RelatedFileObject->FsContext & ~1); if (!(Fcb) || (Fcb->NodeType != NPFS_NTC_ROOT_DCB) || (FileName.Length < sizeof(WCHAR)) || (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext, &FileName, TRUE, &Prefix, &Fcb); if (!NT_SUCCESS(IoStatus.Status)) { goto Quickie; } } else { if (FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR) || FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } Fcb = NpFindPrefix(&FileName, 1, &Prefix); } if (Prefix.Length) { if (Fcb->NodeType == NPFS_NTC_ROOT_DCB) { IoStatus.Status = NpCreateNewNamedPipe((PNP_DCB)Fcb, FileObject, FileName, IoStack->Parameters.CreatePipe. SecurityContext->DesiredAccess, IoStack->Parameters.CreatePipe. SecurityContext->AccessState, Disposition, ShareAccess, Parameters, Process, &DeferredList, &IoStatus); goto Quickie; } else { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } } if (Fcb->NodeType != NPFS_NTC_FCB) { IoStatus.Status = STATUS_OBJECT_NAME_INVALID; goto Quickie; } IoStatus = NpCreateExistingNamedPipe(Fcb, FileObject, IoStack->Parameters.CreatePipe. SecurityContext->DesiredAccess, IoStack->Parameters.CreatePipe. SecurityContext->AccessState, IoStack->Flags & SL_FORCE_ACCESS_CHECK ? UserMode : Irp->RequestorMode, Disposition, ShareAccess, Parameters, Process, &DeferredList); Quickie: NpReleaseVcb(); NpCompleteDeferredIrps(&DeferredList); FsRtlExitFileSystem(); TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status); Irp->IoStatus = IoStatus; IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT); return IoStatus.Status; } /* EOF */