[NPFS] Magic--;
[reactos.git] / drivers / filesystems / npfs / create.c
index abdfe5e..8efcd77 100644 (file)
 /*
-* COPYRIGHT:  See COPYING in the top level directory
-* PROJECT:    ReactOS kernel
-* FILE:       drivers/filesystems/npfs/create.c
-* PURPOSE:    Named pipe filesystem
-* PROGRAMMER: David Welch <welch@cwcom.net>
-*/
+ * 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 ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "npfs.h"
 
-#define NDEBUG
-#include <debug.h>
+// File ID number for NPFS bugchecking support
+#define NPFS_BUGCHECK_FILE_ID   (NPFS_BUGCHECK_CREATE)
 
-//#define USING_PROPER_NPFS_WAIT_SEMANTICS
-
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 VOID
-NpfsDereferenceFcb(PNPFS_FCB Fcb)
+NTAPI
+NpCheckForNotify(IN PNP_DCB Dcb,
+                 IN BOOLEAN SecondList,
+                 IN PLIST_ENTRY List)
 {
-    PNPFS_VCB Vcb = Fcb->Vcb;
-
-    KeLockMutex(&Vcb->PipeListLock);
-    if (InterlockedDecrement(&Fcb->RefCount) == 0)
-    {
-        DPRINT("NpfsDereferenceFcb. Deleting %p\n", Fcb);
-        RemoveEntryList(&Fcb->PipeListEntry);
-        RtlFreeUnicodeString(&Fcb->PipeName);
-        ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
-    }
-    KeUnlockMutex(&Vcb->PipeListLock);
-}
-
-static
-PNPFS_CCB
-NpfsAllocateCcb(CCB_TYPE Type, PNPFS_FCB Fcb)
-{
-    PNPFS_CCB Ccb;
+    PLIST_ENTRY NextEntry, ListHead;
+    PIRP Irp;
+    ULONG i;
+    PAGED_CODE();
 
-    Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB);
-    if (!Ccb)
+    ListHead = &Dcb->NotifyList;
+    for (i = 0; i < 2; i++)
     {
-        return NULL;
-    }
-
-    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
+        ASSERT(IsListEmpty(ListHead));
+        while (!IsListEmpty(ListHead))
+        {
+            NextEntry = RemoveHeadList(ListHead);
 
-    Ccb->RefCount = 1;
-    Ccb->Type = Type;
-    // FIXME: why does this function not reference Fcb?
-    Ccb->Fcb = Fcb;
-    Ccb->OtherSide = NULL;
+            Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
 
-    return Ccb;
-}
-
-static
-VOID
-NpfsReferenceCcb(PNPFS_CCB Ccb)
-{
-    ASSERT(Ccb->RefCount > 0);
-    InterlockedIncrement(&Ccb->RefCount);
-}
+            if (IoSetCancelRoutine(Irp, NULL))
+            {
+                Irp->IoStatus.Status = STATUS_SUCCESS;
+                InsertTailList(List, NextEntry);
+            }
+            else
+            {
+                InitializeListHead(NextEntry);
+            }
+        }
 
-static
-VOID
-NpfsDereferenceCcb(PNPFS_CCB Ccb)
-{
-    /* Decrement reference count */
-    ASSERT(Ccb->RefCount > 0);
-    if (InterlockedDecrement(&Ccb->RefCount) == 0)
-    {
-        /* Its zero, delete CCB */
-        ExFreePoolWithTag(Ccb, TAG_NPFS_CCB);
+        if (!SecondList) break;
+        ListHead = &Dcb->NotifyList2;
     }
 }
 
-static
-VOID
-NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide)
+IO_STATUS_BLOCK
+NTAPI
+NpOpenNamedPipeFileSystem(IN PFILE_OBJECT FileObject,
+                          IN ACCESS_MASK DesiredAccess)
 {
-    /* Dereference old other side */
-    if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide);
+    IO_STATUS_BLOCK Status;
+    PAGED_CODE();
+    TRACE("Entered\n");
 
-    /* Reference the new other side */
-    if (OtherSide) NpfsReferenceCcb(OtherSide);
+    NpSetFileObject(FileObject, NpVcb, NULL, FALSE);
+    ++NpVcb->ReferenceCount;
 
-    /* Set new value */
-    Ccb->OtherSide = OtherSide;
+    Status.Information = FILE_OPENED;
+    Status.Status = STATUS_SUCCESS;
+    TRACE("Leaving, Status.Status = %lx\n", Status.Status);
+    return Status;
 }
 
-PNPFS_FCB
-NpfsFindPipe(PNPFS_VCB Vcb,
-             PUNICODE_STRING PipeName)
+IO_STATUS_BLOCK
+NTAPI
+NpOpenNamedPipeRootDirectory(IN PNP_DCB Dcb,
+                             IN PFILE_OBJECT FileObject,
+                             IN ACCESS_MASK DesiredAccess,
+                             IN PLIST_ENTRY List)
 {
-    PLIST_ENTRY CurrentEntry;
-    PNPFS_FCB Fcb;
+    IO_STATUS_BLOCK IoStatus;
+    PNP_ROOT_DCB_FCB Ccb;
+    PAGED_CODE();
+    TRACE("Entered\n");
 
-    CurrentEntry = Vcb->PipeListHead.Flink;
-    while (CurrentEntry != &Vcb->PipeListHead)
+    IoStatus.Status = NpCreateRootDcbCcb(&Ccb);
+    if (NT_SUCCESS(IoStatus.Status))
     {
-        Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
-        if (RtlCompareUnicodeString(PipeName,
-            &Fcb->PipeName,
-            TRUE) == 0)
-        {
-            DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
-            (VOID)InterlockedIncrement(&Fcb->RefCount);
-            return Fcb;
-        }
+        NpSetFileObject(FileObject, Dcb, Ccb, FALSE);
+        ++Dcb->CurrentInstances;
 
-        CurrentEntry = CurrentEntry->Flink;
+        IoStatus.Information = FILE_OPENED;
+        IoStatus.Status = STATUS_SUCCESS;
     }
-
-    return NULL;
-}
-
-
-static PNPFS_CCB
-NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
-{
-    PLIST_ENTRY CurrentEntry;
-    PNPFS_WAITER_ENTRY Waiter;
-    KIRQL oldIrql;
-    PIRP Irp;
-
-    CurrentEntry = Fcb->WaiterListHead.Flink;
-    while (CurrentEntry != &Fcb->WaiterListHead)
+    else
     {
-        Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
-        Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
-        if (Waiter->Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
-        {
-            DPRINT("Server found! CCB %p\n", Waiter->Ccb);
-
-            IoAcquireCancelSpinLock(&oldIrql);
-            if (!Irp->Cancel)
-            {
-                if (IoSetCancelRoutine(Irp, NULL) != NULL)
-                {
-                    IoReleaseCancelSpinLock(oldIrql);
-                    return Waiter->Ccb;
-                }
-            }
-            IoReleaseCancelSpinLock(oldIrql);
-        }
-
-        CurrentEntry = CurrentEntry->Flink;
+        IoStatus.Information = 0;
     }
 
-    return NULL;
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+    return IoStatus;
 }
 
-
-static VOID
-NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
-                                           PNPFS_CCB Ccb)
+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)
 {
-    PLIST_ENTRY CurrentEntry;
-    PNPFS_WAITER_ENTRY Waiter;
-    PIRP Irp;
-
-    CurrentEntry = Fcb->WaiterListHead.Flink;
-    while (CurrentEntry != &Fcb->WaiterListHead)
-    {
-        Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
-        if (Waiter->Ccb == Ccb)
-        {
-            DPRINT("Server found! CCB %p\n", Waiter->Ccb);
+    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");
 
-            RemoveEntryList(&Waiter->Entry);
-            Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
-            Irp->IoStatus.Status = STATUS_SUCCESS;
-            Irp->IoStatus.Information = 0;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            break;
-        }
-        CurrentEntry = CurrentEntry->Flink;
-    }
-}
+    IoStatus.Information = 0;
+    Privileges = NULL;
 
+    NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
 
-static VOID
-NpfsOpenFileSystem(PNPFS_FCB Fcb,
-                   PFILE_OBJECT FileObject,
-                   PIO_STATUS_BLOCK IoStatus)
-{
-    PNPFS_CCB Ccb;
+    SubjectSecurityContext = &AccessState->SubjectSecurityContext;
+    SeLockSubjectContext(SubjectSecurityContext);
 
-    DPRINT("NpfsOpenFileSystem()\n");
+    AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
+                                  SubjectSecurityContext,
+                                  TRUE,
+                                  DesiredAccess & ~4,
+                                  0,
+                                  &Privileges,
+                                  IoGetFileObjectGenericMapping(),
+                                  PreviousMode,
+                                  &GrantedAccess,
+                                  &IoStatus.Status);
 
-    Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb);
-    if (Ccb == NULL)
+    if (Privileges)
     {
-        IoStatus->Status = STATUS_NO_MEMORY;
-        return;
+        SeAppendPrivileges(AccessState, Privileges);
+        SeFreePrivileges(Privileges);
     }
 
-    Ccb->FileObject = FileObject;
-
-    FileObject->FsContext = Fcb;
-    FileObject->FsContext2 = Ccb;
+    if (AccessGranted)
+    {
+        AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+        AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
+    }
 
-    IoStatus->Information = FILE_OPENED;
-    IoStatus->Status = STATUS_SUCCESS;
+    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;
 
-    return;
-}
+    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;
 
-static VOID
-NpfsOpenRootDirectory(PNPFS_FCB Fcb,
-                      PFILE_OBJECT FileObject,
-                      PIO_STATUS_BLOCK IoStatus)
-{
-    PNPFS_CCB Ccb;
+    ListHead = &Fcb->CcbList;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
+        Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
+        if (Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE) break;
 
-    DPRINT("NpfsOpenRootDirectory()\n");
+        NextEntry = NextEntry->Flink;
+    }
 
-    Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb);
-    if (Ccb == NULL)
+    if (NextEntry == ListHead)
     {
-        IoStatus->Status = STATUS_NO_MEMORY;
-        return;
+        IoStatus.Status = STATUS_PIPE_NOT_AVAILABLE;
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
     }
 
-    Ccb->FileObject = FileObject;
+    IoStatus.Status = NpInitializeSecurity(Ccb, SecurityQos, Thread);
+    if (!NT_SUCCESS(IoStatus.Status)) return IoStatus;
 
-    FileObject->FsContext = Fcb;
-    FileObject->FsContext2 = Ccb;
+    IoStatus.Status = NpSetConnectedPipeState(Ccb, FileObject, List);
+    if (!NT_SUCCESS(IoStatus.Status))
+    {
+        NpUninitializeSecurity(Ccb);
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
+    }
 
-    IoStatus->Information = FILE_OPENED;
-    IoStatus->Status = STATUS_SUCCESS;
+    Ccb->ClientSession = NULL;
+    Ccb->Process = IoThreadToProcess(Thread);
 
-    return;
+    IoStatus.Information = FILE_OPENED;
+    IoStatus.Status = STATUS_SUCCESS;
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+    return IoStatus;
 }
 
-
-NTSTATUS NTAPI
-NpfsCreate(PDEVICE_OBJECT DeviceObject,
-           PIRP Irp)
+NTSTATUS
+NTAPI
+NpTranslateAlias(
+    PUNICODE_STRING PipeName)
 {
-    PEXTENDED_IO_STACK_LOCATION IoStack;
-    PUNICODE_STRING FileName;
-    PFILE_OBJECT FileObject;
-    PFILE_OBJECT RelatedFileObject;
-    PNPFS_FCB Fcb;
-    PNPFS_CCB ClientCcb;
-    PNPFS_CCB ServerCcb = NULL;
-    PNPFS_VCB Vcb;
+    WCHAR UpcaseBuffer[MAX_INDEXED_LENGTH + 1];
+    UNICODE_STRING UpcaseString;
+    ULONG Length;
+    PNPFS_ALIAS CurrentAlias;
     NTSTATUS Status;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    ACCESS_MASK DesiredAccess;
-    BOOLEAN SpecialAccess;
-#endif
-
-    DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
-
-    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
-    IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
-    FileObject = IoStack->FileObject;
-    RelatedFileObject = FileObject->RelatedFileObject;
-    FileName = &FileObject->FileName;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
-#endif
-
-    DPRINT("FileObject %p\n", FileObject);
-    DPRINT("FileName %wZ\n", &FileObject->FileName);
+    BOOLEAN BufferAllocated, BackSlash;
+    LONG Result;
+    PAGED_CODE();
 
-    Irp->IoStatus.Information = 0;
-
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
-    if (SpecialAccess)
+    /* Get the pipe name length and check for empty string */
+    Length = PipeName->Length;
+    if (Length == 0)
     {
-        DPRINT("NpfsCreate() open client end for special use!\n");
+        return STATUS_SUCCESS;
     }
-#endif
 
-    DPRINT("FileName->Length: %hu  RelatedFileObject: %p\n", FileName->Length, RelatedFileObject);
-
-    /* Open the file system */
-    if (FileName->Length == 0 &&
-        (RelatedFileObject == NULL || ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DEVICE))
+    /* Check if the name starts with a path separator */
+    BackSlash = (PipeName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR);
+    if (BackSlash)
     {
-        DPRINT("Open the file system\n");
-
-        NpfsOpenFileSystem(Vcb->DeviceFcb,
-                           FileObject,
-                           &Irp->IoStatus);
-
-        Status = Irp->IoStatus.Status;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return Status;
+        /* We are only interested in the part after the backslash */
+        Length -= sizeof(WCHAR);
     }
 
-    /* Open the root directory */
-    if ((FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL) ||
-        (FileName->Length == 0 && ((PNPFS_CCB)RelatedFileObject->FsContext2)->Type == CCB_DIRECTORY))
+    /* Check if the length is within our indexed list bounds */
+    if ((Length >= MIN_INDEXED_LENGTH * sizeof(WCHAR)) &&
+        (Length <= MAX_INDEXED_LENGTH * sizeof(WCHAR)))
     {
-        DPRINT("Open the root directory\n");
-
-        NpfsOpenRootDirectory(Vcb->RootFcb,
-                              FileObject,
-                              &Irp->IoStatus);
-
-        Status = Irp->IoStatus.Status;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return Status;
+        /* Length is within bounds, use the list by length */
+        CurrentAlias = NpAliasListByLength[(Length / sizeof(WCHAR)) - MIN_INDEXED_LENGTH];
     }
-
-
-    /*
-    * Step 1. Find the pipe we're trying to open.
-    */
-    KeLockMutex(&Vcb->PipeListLock);
-    Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
-    if (Fcb == NULL)
+    else
     {
-        /* Not found, bail out with error. */
-        DPRINT("No pipe found!\n");
-        KeUnlockMutex(&Vcb->PipeListLock);
-        Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_OBJECT_NAME_NOT_FOUND;
-    }
-
-    KeUnlockMutex(&Vcb->PipeListLock);
+        /* 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;
+            }
 
-    /*
-    * Acquire the lock for CCB lists. From now on no modifications to the
-    * CCB lists are allowed, because it can cause various misconsistencies.
-    */
-    KeLockMutex(&Fcb->CcbListLock);
+            /* Go to the next alias in the list */
+            CurrentAlias = CurrentAlias->Next;
+        }
+    }
 
-    /*
-    * Step 2. Create the client CCB.
-    */
-    ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb);
-    if (ClientCcb == NULL)
+    /* Did we find any alias? */
+    if (CurrentAlias == NULL)
     {
-        DPRINT("No memory!\n");
-        KeUnlockMutex(&Fcb->CcbListLock);
-        NpfsDereferenceFcb(Fcb);
-        Irp->IoStatus.Status = STATUS_NO_MEMORY;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_NO_MEMORY;
+        /* Nothing found, no matching alias */
+        return STATUS_SUCCESS;
     }
 
-    ClientCcb->FileObject = FileObject;
-    ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
-    ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
-#else
-    ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
-#endif
-    InitializeListHead(&ClientCcb->ReadRequestListHead);
-
-    DPRINT("CCB: %p\n", ClientCcb);
+    /* 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);
 
-    /* Initialize data list. */
-    if (Fcb->OutboundQuota)
+        /* Upcase the pipe name */
+        Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, FALSE);
+        NT_ASSERT(NT_SUCCESS(Status));
+        BufferAllocated = FALSE;
+    }
+    else
     {
-        ClientCcb->Data = ExAllocatePoolWithTag(PagedPool,
-                                                Fcb->OutboundQuota,
-                                                TAG_NPFS_CCB_DATA);
-        if (ClientCcb->Data == NULL)
+        /* Upcase the pipe name, allocate the string buffer */
+        Status = RtlUpcaseUnicodeString(&UpcaseString, PipeName, TRUE);
+        if (!NT_SUCCESS(Status))
         {
-            DPRINT("No memory!\n");
-            NpfsDereferenceCcb(ClientCcb);
-            KeUnlockMutex(&Fcb->CcbListLock);
-            NpfsDereferenceFcb(Fcb);
-            Irp->IoStatus.Status = STATUS_NO_MEMORY;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_NO_MEMORY;
+            return Status;
         }
+
+        BufferAllocated = TRUE;
     }
-    else
+
+    /* Did the original name start with a backslash? */
+    if (BackSlash)
     {
-        ClientCcb->Data = NULL;
+        /* Skip it for the comparison */
+        UpcaseString.Buffer++;
+        UpcaseString.Length -= sizeof(WCHAR);
     }
 
-    ClientCcb->ReadPtr = ClientCcb->Data;
-    ClientCcb->WritePtr = ClientCcb->Data;
-    ClientCcb->ReadDataAvailable = 0;
-    ClientCcb->WriteQuotaAvailable = Fcb->OutboundQuota;
-    ClientCcb->MaxDataLength = Fcb->OutboundQuota;
-    ExInitializeFastMutex(&ClientCcb->DataListLock);
-    KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE);
-    KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE);
-
-
-    /*
-    * Step 3. Search for listening server CCB.
-    */
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    if (!SpecialAccess)
+    /* 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
     {
-#endif
-        /*
-        * WARNING: Point of no return! Once we get the server CCB it's
-        * possible that we completed a wait request and so we have to
-        * complete even this request.
-        */
-
-        ServerCcb = NpfsFindListeningServerInstance(Fcb);
-        if (ServerCcb == NULL)
+        /* Compare the names and check if they match */
+        Result = NpCompareAliasNames(&UpcaseString, &CurrentAlias->Name);
+        if (Result == 0)
         {
-            PLIST_ENTRY CurrentEntry;
-            PNPFS_CCB Ccb;
-
-            /*
-            * If no waiting server CCB was found then try to pick
-            * one of the listing server CCB on the pipe.
-            */
+            /* The names match, use the target name */
+            *PipeName = *CurrentAlias->TargetName;
 
-            CurrentEntry = Fcb->ServerCcbListHead.Flink;
-            while (CurrentEntry != &Fcb->ServerCcbListHead)
+            /* Did the original name start with a backslash? */
+            if (!BackSlash)
             {
-                Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
-                if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
-                {
-                    ServerCcb = Ccb;
-                    break;
-                }
-                CurrentEntry = CurrentEntry->Flink;
+                /* It didn't, so skip it in the target name as well */
+                PipeName->Buffer++;
+                PipeName->Length -= sizeof(WCHAR);
             }
-
-            /*
-            * No one is listening to me?! I'm so lonely... :(
-            */
-
-            if (ServerCcb == NULL)
-            {
-                /* Not found, bail out with error for FILE_OPEN requests. */
-                DPRINT("No listening server CCB found!\n");
-                if (ClientCcb->Data)
-                {
-                    ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
-                }
-
-                NpfsDereferenceCcb(ClientCcb);
-                KeUnlockMutex(&Fcb->CcbListLock);
-                NpfsDereferenceFcb(Fcb);
-                Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
-                IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                return STATUS_OBJECT_NAME_NOT_FOUND;
-            }
-        }
-        else
-        {
-            /* Signal the server thread and remove it from the waiter list */
-            /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
-            NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
+            break;
         }
-#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
-    }
-    else if (IsListEmpty(&Fcb->ServerCcbListHead))
-    {
-        DPRINT("No server fcb found!\n");
 
-        if (ClientCcb->Data)
+        /* Check if we went past all string candidates */
+        if (Result < 0)
         {
-            ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
+            /* Nothing found, we're done */
+            break;
         }
 
-        NpfsDereferenceCcb(ClientCcb);
-        KeUnlockMutex(&Fcb->CcbListLock);
-        NpfsDereferenceFcb(Fcb);
-        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_UNSUCCESSFUL;
-    }
-#endif
-
-    /*
-    * Step 4. Add the client CCB to a list and connect it if possible.
-    */
+        /* Go to the next alias */
+        CurrentAlias = CurrentAlias->Next;
 
-    /* Add the client CCB to the pipe CCB list. */
-    InsertTailList(&Fcb->ClientCcbListHead, &ClientCcb->CcbListEntry);
+        /* Keep looping while we have aliases of the right length */
+    } while ((CurrentAlias != NULL) && (CurrentAlias->Name.Length == Length));
 
-    /* Connect to listening server side */
-    if (ServerCcb)
+    /* Did we allocate a buffer? */
+    if (BufferAllocated)
     {
-        NpfsCcbSetOtherSide(ClientCcb, ServerCcb);
-        NpfsCcbSetOtherSide(ServerCcb, ClientCcb);
-        ClientCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
-        ServerCcb->PipeState = FILE_PIPE_CONNECTED_STATE;
-        KeSetEvent(&ServerCcb->ConnectEvent, IO_NO_INCREMENT, FALSE);
+        /* Free the allocated buffer */
+        ASSERT(UpcaseString.Buffer != UpcaseBuffer);
+        RtlFreeUnicodeString(&UpcaseString);
     }
 
-    KeUnlockMutex(&Fcb->CcbListLock);
-
-    FileObject->FsContext = Fcb;
-    FileObject->FsContext2 = ClientCcb;
-    FileObject->Flags |= FO_NAMED_PIPE;
-
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    DPRINT("Success!\n");
-
     return STATUS_SUCCESS;
 }
 
-
-NTSTATUS NTAPI
-NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
-                    PIRP Irp)
+NTSTATUS
+NTAPI
+NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
+            IN PIRP Irp)
 {
-    PEXTENDED_IO_STACK_LOCATION IoStack;
+    IO_STATUS_BLOCK IoStatus;
+    PIO_STACK_LOCATION IoStack;
+    UNICODE_STRING FileName;
     PFILE_OBJECT FileObject;
-    PNPFS_VCB Vcb;
-    PNPFS_FCB Fcb;
-    PNPFS_CCB Ccb;
-    ULONG Disposition;
-    ULONG ShareAccess;
-    PNAMED_PIPE_CREATE_PARAMETERS Parameters;
-
-    DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+    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");
 
-    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
-    IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
+    InitializeListHead(&DeferredList);
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
     FileObject = IoStack->FileObject;
-    DPRINT("FileObject %p\n", FileObject);
-    DPRINT("Pipe name %wZ\n", &FileObject->FileName);
+    RelatedFileObject = FileObject->RelatedFileObject;
+    FileName = FileObject->FileName;
+    DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
 
-    Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
-    ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess;
-    Parameters = IoStack->Parameters.CreatePipe.Parameters;
+    IoStatus.Information = 0;
 
-    Irp->IoStatus.Information = 0;
+    FsRtlEnterFileSystem();
+    NpAcquireExclusiveVcb();
 
-    if ((Disposition == FILE_OVERWRITE) ||
-        (Disposition == FILE_OVERWRITE_IF) ||
-        !(ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
-        (ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
+    if (RelatedFileObject)
     {
-        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_INVALID_PARAMETER;
+        Type = NpDecodeFileObject(RelatedFileObject, (PVOID*)&Fcb, &Ccb, FALSE);
     }
-
-    KeLockMutex(&Vcb->PipeListLock);
-
-    /*
-    * First search for existing Pipe with the same name.
-    */
-    Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
-    if (Fcb != NULL)
+    else
     {
-        /*
-        * Found Pipe with the same name. Check if we are
-        * allowed to use it.
-        */
-        KeUnlockMutex(&Vcb->PipeListLock);
-
-        if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
-        {
-            DPRINT("Out of instances.\n");
-            NpfsDereferenceFcb(Fcb);
-            Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_INSTANCE_NOT_AVAILABLE;
-        }
+        Type = 0;
+        Fcb = NULL;
+        Ccb = NULL;
+    }
 
-        if (Disposition == FILE_CREATE ||
-            Fcb->MaximumInstances != Parameters->MaximumInstances ||
-            Fcb->TimeOut.QuadPart != Parameters->DefaultTimeout.QuadPart ||
-            Fcb->PipeType != Parameters->NamedPipeType)
+    if (FileName.Length)
+    {
+        if ((FileName.Length == sizeof(OBJ_NAME_PATH_SEPARATOR)) &&
+            (FileName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
+            !(RelatedFileObject))
         {
-            DPRINT("Asked for invalid pipe mode.\n");
-            NpfsDereferenceFcb(Fcb);
-            Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_ACCESS_DENIED;
+            IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
+                                                    FileObject,
+                                                    DesiredAccess,
+                                                    &DeferredList);
+            goto Quickie;
         }
     }
-    else
+    else if (!(RelatedFileObject) || (Type == NPFS_NTC_VCB))
     {
-        Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB);
-        if (Fcb == NULL)
-        {
-            KeUnlockMutex(&Vcb->PipeListLock);
-            Irp->IoStatus.Status = STATUS_NO_MEMORY;
-            Irp->IoStatus.Information = 0;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_NO_MEMORY;
-        }
-
-        Fcb->Type = FCB_PIPE;
-        Fcb->Vcb = Vcb;
-        Fcb->RefCount = 1;
-        Fcb->PipeName.Length = FileObject->FileName.Length;
-        Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL);
-        Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
-                                                     Fcb->PipeName.MaximumLength,
-                                                     TAG_NPFS_NAMEBLOCK);
-        if (Fcb->PipeName.Buffer == NULL)
-        {
-            KeUnlockMutex(&Vcb->PipeListLock);
-            ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
-            Irp->IoStatus.Status = STATUS_NO_MEMORY;
-            Irp->IoStatus.Information = 0;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_NO_MEMORY;
-        }
-
-        RtlCopyUnicodeString(&Fcb->PipeName, &FileObject->FileName);
-
-        InitializeListHead(&Fcb->ServerCcbListHead);
-        InitializeListHead(&Fcb->ClientCcbListHead);
-        InitializeListHead(&Fcb->WaiterListHead);
-        KeInitializeMutex(&Fcb->CcbListLock, 0);
+        IoStatus = NpOpenNamedPipeFileSystem(FileObject,
+                                             DesiredAccess);
+        goto Quickie;
+    }
+    else if (Type == NPFS_NTC_ROOT_DCB)
+    {
+        IoStatus = NpOpenNamedPipeRootDirectory(NpVcb->RootDcb,
+                                                FileObject,
+                                                DesiredAccess,
+                                                &DeferredList);
+        goto Quickie;
+    }
 
-        Fcb->PipeType = Parameters->NamedPipeType;
-        Fcb->ServerReadMode = Parameters->ReadMode;
-        /* MSDN documentation reads that clients always start off in byte mode */
-        Fcb->ClientReadMode = FILE_PIPE_BYTE_STREAM_MODE;
+    IoStatus.Status = NpTranslateAlias(&FileName);
+    if (!NT_SUCCESS(IoStatus.Status)) goto Quickie;
 
-        Fcb->CompletionMode = Parameters->CompletionMode;
-        switch (ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
-        {
-        case FILE_SHARE_READ:
-            Fcb->PipeConfiguration = FILE_PIPE_OUTBOUND;
-            break;
-        case FILE_SHARE_WRITE:
-            Fcb->PipeConfiguration = FILE_PIPE_INBOUND;
-            break;
-        case FILE_SHARE_READ|FILE_SHARE_WRITE:
-            Fcb->PipeConfiguration = FILE_PIPE_FULL_DUPLEX;
-            break;
-        }
-        Fcb->MaximumInstances = Parameters->MaximumInstances;
-        Fcb->CurrentInstances = 0;
-        Fcb->TimeOut = Parameters->DefaultTimeout;
-        if (!(Fcb->PipeConfiguration & FILE_PIPE_OUTBOUND) ||
-            Fcb->PipeConfiguration & FILE_PIPE_FULL_DUPLEX)
+    if (RelatedFileObject)
+    {
+        if (Type == NPFS_NTC_ROOT_DCB)
         {
-            if (Parameters->InboundQuota == 0)
+            Dcb = (PNP_DCB)Ccb;
+            IoStatus.Status = NpFindRelativePrefix(Dcb,
+                                                   &FileName,
+                                                   1,
+                                                   &Prefix,
+                                                   &Fcb);
+            if (!NT_SUCCESS(IoStatus.Status))
             {
-                Fcb->InboundQuota = Vcb->DefaultQuota;
-            }
-            else
-            {
-                Fcb->InboundQuota = PAGE_ROUND_UP(Parameters->InboundQuota);
-                if (Fcb->InboundQuota < Vcb->MinQuota)
-                {
-                    Fcb->InboundQuota = Vcb->MinQuota;
-                }
-                else if (Fcb->InboundQuota > Vcb->MaxQuota)
-                {
-                    Fcb->InboundQuota = Vcb->MaxQuota;
-                }
+                goto Quickie;
             }
         }
-        else
+        else if ((Type != NPFS_NTC_CCB) || (FileName.Length))
         {
-            Fcb->InboundQuota = 0;
+            IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+            goto Quickie;
         }
-
-        if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
+        else
         {
-            if (Parameters->OutboundQuota == 0)
-            {
-                Fcb->OutboundQuota = Vcb->DefaultQuota;
-            }
-            else
-            {
-                Fcb->OutboundQuota = PAGE_ROUND_UP(Parameters->OutboundQuota);
-                if (Fcb->OutboundQuota < Vcb->MinQuota)
-                {
-                    Fcb->OutboundQuota = Vcb->MinQuota;
-                }
-                else if (Fcb->OutboundQuota > Vcb->MaxQuota)
-                {
-                    Fcb->OutboundQuota = Vcb->MaxQuota;
-                }
-            }
+            Prefix.Length = 0;
         }
-        else
+    }
+    else
+    {
+        if ((FileName.Length <= sizeof(OBJ_NAME_PATH_SEPARATOR)) ||
+            (FileName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
         {
-            Fcb->OutboundQuota = 0;
+            IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+            goto Quickie;
         }
 
-        InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry);
-        KeUnlockMutex(&Vcb->PipeListLock);
+        Fcb = NpFindPrefix(&FileName, 1, &Prefix);
     }
 
-    Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb);
-    if (Ccb == NULL)
+    if (Prefix.Length)
     {
-        NpfsDereferenceFcb(Fcb);
-        Irp->IoStatus.Status = STATUS_NO_MEMORY;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_NO_MEMORY;
+        IoStatus.Status = Fcb->NodeType != NPFS_NTC_FCB ?
+                           STATUS_OBJECT_NAME_NOT_FOUND :
+                           STATUS_OBJECT_NAME_INVALID;
+        goto Quickie;
     }
 
-    Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
-
-    if (Fcb->InboundQuota)
+    if (Fcb->NodeType != NPFS_NTC_FCB)
     {
-        Ccb->Data = ExAllocatePoolWithTag(PagedPool,
-                                          Fcb->InboundQuota,
-                                          TAG_NPFS_CCB_DATA);
-        if (Ccb->Data == NULL)
-        {
-            NpfsDereferenceCcb(Ccb);
-            NpfsDereferenceFcb(Fcb);
-
-            Irp->IoStatus.Status = STATUS_NO_MEMORY;
-            IoCompleteRequest(Irp, IO_NO_INCREMENT);
-            return STATUS_NO_MEMORY;
-        }
+        IoStatus.Status = STATUS_OBJECT_NAME_INVALID;
+        goto Quickie;
     }
-    else
+
+    if (!Fcb->ServerOpenCount)
     {
-        Ccb->Data = NULL;
+        IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+        goto Quickie;
     }
 
-    Ccb->ReadPtr = Ccb->Data;
-    Ccb->WritePtr = Ccb->Data;
-    Ccb->ReadDataAvailable = 0;
-    Ccb->WriteQuotaAvailable = Fcb->InboundQuota;
-    Ccb->MaxDataLength = Fcb->InboundQuota;
-    InitializeListHead(&Ccb->ReadRequestListHead);
-    ExInitializeFastMutex(&Ccb->DataListLock);
+    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();
 
-    Fcb->CurrentInstances++;
+    Irp->IoStatus = IoStatus;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+    return IoStatus.Status;
+}
 
-    Ccb->Fcb = Fcb;
-    Ccb->FileObject = FileObject;
-    Ccb->PipeEnd = FILE_PIPE_SERVER_END;
-    Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
+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");
 
-    DPRINT("CCB: %p\n", Ccb);
+    Privileges = NULL;
 
-    KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE);
-    KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE);
+    NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
 
-    KeLockMutex(&Fcb->CcbListLock);
-    InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry);
-    KeUnlockMutex(&Fcb->CcbListLock);
+    SubjectSecurityContext = &AccessState->SubjectSecurityContext;
+    SeLockSubjectContext(SubjectSecurityContext);
 
-    FileObject->FsContext = Fcb;
-    FileObject->FsContext2 = Ccb;
-    FileObject->Flags |= FO_NAMED_PIPE;
+    IoStatus.Information = 0;
 
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    AccessGranted = SeAccessCheck(Fcb->SecurityDescriptor,
+                                  SubjectSecurityContext,
+                                  TRUE,
+                                  DesiredAccess | 4,
+                                  0,
+                                  &Privileges,
+                                  IoGetFileObjectGenericMapping(),
+                                  PreviousMode,
+                                  &GrantedAccess,
+                                  &IoStatus.Status);
 
-    DPRINT("Success!\n");
+    if (Privileges)
+    {
+        SeAppendPrivileges(AccessState, Privileges);
+        SeFreePrivileges(Privileges);
+    }
 
-    return STATUS_SUCCESS;
-}
+    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);
 
-NTSTATUS NTAPI
-NpfsCleanup(PDEVICE_OBJECT DeviceObject,
-            PIRP Irp)
-{
-    //PNPFS_VCB Vcb;
-    PIO_STACK_LOCATION IoStack;
-    PFILE_OBJECT FileObject;
-    PNPFS_CCB Ccb, OtherSide;
-    PNPFS_FCB Fcb;
-    BOOLEAN Server;
+    SeUnlockSubjectContext(SubjectSecurityContext);
+    if (!AccessGranted)
+    {
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
+    }
 
-    DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+    if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
+    {
+        IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
+    }
 
-    IoStack = IoGetCurrentIrpStackLocation(Irp);
-    //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
-    FileObject = IoStack->FileObject;
-    Ccb = FileObject->FsContext2;
+    if (Disposition == FILE_CREATE)
+    {
+        IoStatus.Status = STATUS_ACCESS_DENIED;
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
+    }
 
-    if (Ccb == NULL)
+    CheckShareAccess = 0;
+    if (NamedPipeConfiguration == FILE_PIPE_FULL_DUPLEX)
     {
-        DPRINT("Success!\n");
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
+        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 (Ccb->Type == CCB_DEVICE)
+    if (CheckShareAccess != ShareAccess)
     {
-        DPRINT("Cleanup the file system!\n");
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
+        IoStatus.Status = STATUS_ACCESS_DENIED;
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
     }
 
-    if (Ccb->Type == CCB_DIRECTORY)
+    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))
     {
-        DPRINT("Cleanup the root directory!\n");
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
+        --Ccb->Fcb->CurrentInstances;
+        NpDeleteCcb(Ccb, List);
+        TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+        return IoStatus;
     }
 
-    DPRINT("CCB %p\n", Ccb);
-    Fcb = Ccb->Fcb;
+    NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
+    Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
+    NpCheckForNotify(Fcb->ParentDcb, 0, List);
 
-    DPRINT("Cleaning pipe %wZ\n", &Fcb->PipeName);
+    IoStatus.Status = STATUS_SUCCESS;
+    IoStatus.Information = FILE_OPENED;
+    TRACE("Leaving, IoStatus.Status = %lx\n", IoStatus.Status);
+    return IoStatus;
+}
 
-    KeLockMutex(&Fcb->CcbListLock);
+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");
 
-    Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
+    if (!(Parameters->TimeoutSpecified) ||
+        !(Parameters->MaximumInstances) ||
+        (Parameters->DefaultTimeout.QuadPart >= 0))
+    {
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
+    }
 
-    if (Server)
+    if (Disposition == FILE_OPEN)
     {
-        /* FIXME: Clean up existing connections here ?? */
-        DPRINT("Server\n");
+        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
     {
-        DPRINT("Client\n");
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
     }
-    if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide))
+
+    if (Parameters->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
+        Parameters->ReadMode == FILE_PIPE_MESSAGE_MODE)
     {
-        OtherSide = Ccb->OtherSide;
-        ASSERT(OtherSide->OtherSide == Ccb);
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
+    }
 
-        /* Lock the server first */
-        if (Server)
-        {
-            ExAcquireFastMutex(&Ccb->DataListLock);
-            ExAcquireFastMutex(&OtherSide->DataListLock);
-        }
-        else
-        {
-            ExAcquireFastMutex(&OtherSide->DataListLock);
-            ExAcquireFastMutex(&Ccb->DataListLock);
-        }
+    Status = NpCreateFcb(Dcb,
+                         &PipeName,
+                         Parameters->MaximumInstances,
+                         Parameters->DefaultTimeout,
+                         NamedPipeConfiguration,
+                         Parameters->NamedPipeType & 0xFFFF,
+                         &Fcb);
+    if (!NT_SUCCESS(Status)) goto Quickie;
 
-        /* Unlink FCBs */
-        NpfsCcbSetOtherSide(OtherSide, NULL);
-        NpfsCcbSetOtherSide(Ccb, NULL);
-
-        /*
-        * Signaling the write event. If is possible that an other
-        * thread waits for an empty buffer.
-        */
-        KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
-        KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
-        if (Server)
-        {
-            ExReleaseFastMutex(&OtherSide->DataListLock);
-            ExReleaseFastMutex(&Ccb->DataListLock);
-        }
-        else
-        {
-            ExReleaseFastMutex(&Ccb->DataListLock);
-            ExReleaseFastMutex(&OtherSide->DataListLock);
-        }
-    }
-    else if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
+    Status = NpCreateCcb(Fcb,
+                         FileObject,
+                         FILE_PIPE_LISTENING_STATE,
+                         Parameters->ReadMode & 0xFF,
+                         Parameters->CompletionMode & 0xFF,
+                         Parameters->InboundQuota,
+                         Parameters->OutboundQuota,
+                         &Ccb);
+    if (!NT_SUCCESS(Status))
     {
-        PLIST_ENTRY Entry;
-        PNPFS_WAITER_ENTRY WaitEntry = NULL;
-        BOOLEAN Complete = FALSE;
-        KIRQL oldIrql;
-        PIRP tmpIrp;
-
-        Entry = Ccb->Fcb->WaiterListHead.Flink;
-        while (Entry != &Ccb->Fcb->WaiterListHead)
-        {
-            WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
-            if (WaitEntry->Ccb == Ccb)
-            {
-                RemoveEntryList(Entry);
-                tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
-                IoAcquireCancelSpinLock(&oldIrql);
-                Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL));
-                IoReleaseCancelSpinLock(oldIrql);
-                if (Complete)
-                {
-                    tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
-                    tmpIrp->IoStatus.Information = 0;
-                    IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
-                }
-                break;
-            }
-            Entry = Entry->Flink;
-        }
+        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;
     }
-    Ccb->PipeState = FILE_PIPE_CLOSING_STATE;
 
-    KeUnlockMutex(&Fcb->CcbListLock);
+    Status = ObLogSecurityDescriptor(SecurityDescriptor,
+                                     &CachedSecurityDescriptor,
+                                     1);
+    ExFreePoolWithTag(SecurityDescriptor, 0);
 
-    ExAcquireFastMutex(&Ccb->DataListLock);
-    if (Ccb->Data)
+    if (!NT_SUCCESS(Status))
     {
-        ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA);
-        Ccb->Data = NULL;
-        Ccb->ReadPtr = NULL;
-        Ccb->WritePtr = NULL;
+        NpDeleteCcb(Ccb, List);
+        NpDeleteFcb(Fcb, List);
+        goto Quickie;
     }
-    ExReleaseFastMutex(&Ccb->DataListLock);
 
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    Irp->IoStatus.Information = 0;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    Fcb->SecurityDescriptor = CachedSecurityDescriptor;
+
+    NpSetFileObject(FileObject, Ccb, Ccb->NonPagedCcb, TRUE);
+    Ccb->FileObject[FILE_PIPE_SERVER_END] = FileObject;
 
-    DPRINT("Success!\n");
+    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
-NpfsClose(PDEVICE_OBJECT DeviceObject,
-          PIRP Irp)
+NTSTATUS
+NTAPI
+NpFsdCreateNamedPipe(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
 {
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
-    //PNPFS_VCB Vcb;
-    PNPFS_FCB Fcb;
-    PNPFS_CCB Ccb;
-    BOOLEAN Server;
+    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");
 
-    DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
+    InitializeListHead(&DeferredList);
+    Process = IoGetRequestorProcess(Irp);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     FileObject = IoStack->FileObject;
-    Ccb = FileObject->FsContext2;
+    RelatedFileObject = FileObject->RelatedFileObject;
 
-    if (Ccb == NULL)
-    {
-        DPRINT("Success!\n");
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
-    }
+    Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
+    ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess & 0xFFFF;
+    Parameters = IoStack->Parameters.CreatePipe.Parameters;
 
-    if (Ccb->Type == CCB_DEVICE)
-    {
-        DPRINT("Closing the file system!\n");
+    FileName = FileObject->FileName;
 
-        NpfsDereferenceCcb(Ccb);
-        FileObject->FsContext = NULL;
-        FileObject->FsContext2 = NULL;
+    IoStatus.Information = 0;
 
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
-    }
+    FsRtlEnterFileSystem();
+    NpAcquireExclusiveVcb();
 
-    if (Ccb->Type == CCB_DIRECTORY)
+    if (RelatedFileObject)
     {
-        DPRINT("Closing the root directory!\n");
-
-        if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
-            ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer,
-                              TAG_NPFS_NAMEBLOCK);
-
-        NpfsDereferenceCcb(Ccb);
-        FileObject->FsContext = NULL;
-        FileObject->FsContext2 = NULL;
-
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
-    }
-
-    DPRINT("CCB %p\n", Ccb);
-    Fcb = Ccb->Fcb;
-
-    DPRINT("Closing pipe %wZ\n", &Fcb->PipeName);
-
-    KeLockMutex(&Fcb->CcbListLock);
-
-    Server = (Ccb->PipeEnd == FILE_PIPE_SERVER_END);
+        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;
+        }
 
-    if (Server)
-    {
-        DPRINT("Server\n");
-        Fcb->CurrentInstances--;
+        IoStatus.Status = NpFindRelativePrefix(RelatedFileObject->FsContext,
+                                               &FileName,
+                                               TRUE,
+                                               &Prefix,
+                                               &Fcb);
+        if (!NT_SUCCESS(IoStatus.Status))
+        {
+            goto Quickie;
+        }
     }
     else
     {
-        DPRINT("Client\n");
+        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);
     }
 
-    /* Disconnect the pipes */
-    if (Ccb->OtherSide)
+    if (Prefix.Length)
     {
-        /* FIXME: Timo wants it rewritten */
-        /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
-        NpfsCcbSetOtherSide(Ccb->OtherSide, NULL);
-        NpfsCcbSetOtherSide(Ccb, NULL);
+        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;
+        }
     }
 
-    ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
-
-    FileObject->FsContext2 = NULL;
-
-    RemoveEntryList(&Ccb->CcbListEntry);
-
-    NpfsDereferenceCcb(Ccb);
-
-    KeUnlockMutex(&Fcb->CcbListLock);
-
-    NpfsDereferenceFcb(Fcb);
-    FileObject->FsContext = NULL;
-
-    Irp->IoStatus.Status = STATUS_SUCCESS;
-    Irp->IoStatus.Information = 0;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    DPRINT("Success!\n");
-
-    return STATUS_SUCCESS;
+    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 */