[NPFS/KERNEL32]
[reactos.git] / reactos / drivers / filesystems / npfs / create.c
index fe6834a..abdfe5e 100644 (file)
@@ -1,7 +1,7 @@
 /*
 * COPYRIGHT:  See COPYING in the top level directory
 * PROJECT:    ReactOS kernel
-* FILE:       drivers/fs/np/create.c
+* FILE:       drivers/filesystems/npfs/create.c
 * PURPOSE:    Named pipe filesystem
 * PROGRAMMER: David Welch <welch@cwcom.net>
 */
 
 /* FUNCTIONS *****************************************************************/
 
+VOID
+NpfsDereferenceFcb(PNPFS_FCB Fcb)
+{
+    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;
+
+    Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_CCB), TAG_NPFS_CCB);
+    if (!Ccb)
+    {
+        return NULL;
+    }
+
+    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
+
+    Ccb->RefCount = 1;
+    Ccb->Type = Type;
+    // FIXME: why does this function not reference Fcb?
+    Ccb->Fcb = Fcb;
+    Ccb->OtherSide = NULL;
+
+    return Ccb;
+}
+
+static
+VOID
+NpfsReferenceCcb(PNPFS_CCB Ccb)
+{
+    ASSERT(Ccb->RefCount > 0);
+    InterlockedIncrement(&Ccb->RefCount);
+}
+
+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);
+    }
+}
+
+static
+VOID
+NpfsCcbSetOtherSide(PNPFS_CCB Ccb, PNPFS_CCB OtherSide)
+{
+    /* Dereference old other side */
+    if (Ccb->OtherSide) NpfsDereferenceCcb(Ccb->OtherSide);
+
+    /* Reference the new other side */
+    if (OtherSide) NpfsReferenceCcb(OtherSide);
+
+    /* Set new value */
+    Ccb->OtherSide = OtherSide;
+}
+
 PNPFS_FCB
 NpfsFindPipe(PNPFS_VCB Vcb,
              PUNICODE_STRING PipeName)
@@ -33,6 +107,7 @@ NpfsFindPipe(PNPFS_VCB Vcb,
             TRUE) == 0)
         {
             DPRINT("<%wZ> = <%wZ>\n", PipeName, &Fcb->PipeName);
+            (VOID)InterlockedIncrement(&Fcb->RefCount);
             return Fcb;
         }
 
@@ -63,9 +138,11 @@ NpfsFindListeningServerInstance(PNPFS_FCB Fcb)
             IoAcquireCancelSpinLock(&oldIrql);
             if (!Irp->Cancel)
             {
-                (void)IoSetCancelRoutine(Irp, NULL);
-                IoReleaseCancelSpinLock(oldIrql);
-                return Waiter->Ccb;
+                if (IoSetCancelRoutine(Irp, NULL) != NULL)
+                {
+                    IoReleaseCancelSpinLock(oldIrql);
+                    return Waiter->Ccb;
+                }
             }
             IoReleaseCancelSpinLock(oldIrql);
         }
@@ -114,17 +191,14 @@ NpfsOpenFileSystem(PNPFS_FCB Fcb,
 
     DPRINT("NpfsOpenFileSystem()\n");
 
-    Ccb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
+    Ccb = NpfsAllocateCcb(CCB_DEVICE, Fcb);
     if (Ccb == NULL)
     {
         IoStatus->Status = STATUS_NO_MEMORY;
         return;
     }
 
-    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
-
-    Ccb->Type = CCB_DEVICE;
-    Ccb->Fcb = Fcb;
+    Ccb->FileObject = FileObject;
 
     FileObject->FsContext = Fcb;
     FileObject->FsContext2 = Ccb;
@@ -145,17 +219,14 @@ NpfsOpenRootDirectory(PNPFS_FCB Fcb,
 
     DPRINT("NpfsOpenRootDirectory()\n");
 
-    Ccb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
+    Ccb = NpfsAllocateCcb(CCB_DIRECTORY, Fcb);
     if (Ccb == NULL)
     {
         IoStatus->Status = STATUS_NO_MEMORY;
         return;
     }
 
-    RtlZeroMemory(Ccb, sizeof(NPFS_CCB));
-
-    Ccb->Type = CCB_DIRECTORY;
-    Ccb->Fcb = Fcb;
+    Ccb->FileObject = FileObject;
 
     FileObject->FsContext = Fcb;
     FileObject->FsContext2 = Ccb;
@@ -179,9 +250,9 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     PNPFS_CCB ClientCcb;
     PNPFS_CCB ServerCcb = NULL;
     PNPFS_VCB Vcb;
-    ACCESS_MASK DesiredAccess;
     NTSTATUS Status;
 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
+    ACCESS_MASK DesiredAccess;
     BOOLEAN SpecialAccess;
 #endif
 
@@ -192,7 +263,9 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     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);
@@ -244,8 +317,7 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     * Step 1. Find the pipe we're trying to open.
     */
     KeLockMutex(&Vcb->PipeListLock);
-    Fcb = NpfsFindPipe(Vcb,
-        &FileObject->FileName);
+    Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
     if (Fcb == NULL)
     {
         /* Not found, bail out with error. */
@@ -267,21 +339,20 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     /*
     * Step 2. Create the client CCB.
     */
-    ClientCcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
+    ClientCcb = NpfsAllocateCcb(CCB_PIPE, Fcb);
     if (ClientCcb == 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;
     }
 
-    ClientCcb->Type = CCB_PIPE;
+    ClientCcb->FileObject = FileObject;
     ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
-    ClientCcb->Fcb = Fcb;
     ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
-    ClientCcb->OtherSide = NULL;
 #ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
     ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
 #else
@@ -294,12 +365,15 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     /* Initialize data list. */
     if (Fcb->OutboundQuota)
     {
-        ClientCcb->Data = ExAllocatePool(PagedPool, Fcb->OutboundQuota);
+        ClientCcb->Data = ExAllocatePoolWithTag(PagedPool,
+                                                Fcb->OutboundQuota,
+                                                TAG_NPFS_CCB_DATA);
         if (ClientCcb->Data == NULL)
         {
             DPRINT("No memory!\n");
-            ExFreePool(ClientCcb);
+            NpfsDereferenceCcb(ClientCcb);
             KeUnlockMutex(&Fcb->CcbListLock);
+            NpfsDereferenceFcb(Fcb);
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return STATUS_NO_MEMORY;
@@ -367,14 +441,15 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
                 DPRINT("No listening server CCB found!\n");
                 if (ClientCcb->Data)
                 {
-                    ExFreePool(ClientCcb->Data);
+                    ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
                 }
 
-                ExFreePool(ClientCcb);
+                NpfsDereferenceCcb(ClientCcb);
                 KeUnlockMutex(&Fcb->CcbListLock);
-                Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
+                NpfsDereferenceFcb(Fcb);
+                Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                return STATUS_OBJECT_PATH_NOT_FOUND;
+                return STATUS_OBJECT_NAME_NOT_FOUND;
             }
         }
         else
@@ -391,12 +466,12 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
 
         if (ClientCcb->Data)
         {
-            ExFreePool(ClientCcb->Data);
+            ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
         }
 
-        ExFreePool(ClientCcb);
-
+        NpfsDereferenceCcb(ClientCcb);
         KeUnlockMutex(&Fcb->CcbListLock);
+        NpfsDereferenceFcb(Fcb);
         Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_UNSUCCESSFUL;
@@ -413,8 +488,8 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     /* Connect to listening server side */
     if (ServerCcb)
     {
-        ClientCcb->OtherSide = ServerCcb;
-        ServerCcb->OtherSide = ClientCcb;
+        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);
@@ -444,8 +519,9 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
     PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
-    PNAMED_PIPE_CREATE_PARAMETERS Buffer;
-    BOOLEAN NewPipe = FALSE;
+    ULONG Disposition;
+    ULONG ShareAccess;
+    PNAMED_PIPE_CREATE_PARAMETERS Parameters;
 
     DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
@@ -455,35 +531,28 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
     DPRINT("FileObject %p\n", FileObject);
     DPRINT("Pipe name %wZ\n", &FileObject->FileName);
 
-    Buffer = IoStack->Parameters.CreatePipe.Parameters;
+    Disposition = (IoStack->Parameters.CreatePipe.Options >> 24) & 0xFF;
+    ShareAccess = IoStack->Parameters.CreatePipe.ShareAccess;
+    Parameters = IoStack->Parameters.CreatePipe.Parameters;
 
     Irp->IoStatus.Information = 0;
 
-    if (!(IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
-        (IoStack->Parameters.CreatePipe.ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
+    if ((Disposition == FILE_OVERWRITE) ||
+        (Disposition == FILE_OVERWRITE_IF) ||
+        !(ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE)) ||
+        (ShareAccess & ~(FILE_SHARE_READ|FILE_SHARE_WRITE)))
     {
         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_INVALID_PARAMETER;
     }
 
-    Ccb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
-    if (Ccb == NULL)
-    {
-        Irp->IoStatus.Status = STATUS_NO_MEMORY;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_NO_MEMORY;
-    }
-
-    Ccb->Type = CCB_PIPE;
-    Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
     KeLockMutex(&Vcb->PipeListLock);
 
     /*
     * First search for existing Pipe with the same name.
     */
-    Fcb = NpfsFindPipe(Vcb,
-        &FileObject->FileName);
+    Fcb = NpfsFindPipe(Vcb, &FileObject->FileName);
     if (Fcb != NULL)
     {
         /*
@@ -495,18 +564,19 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
         {
             DPRINT("Out of instances.\n");
-            ExFreePool(Ccb);
+            NpfsDereferenceFcb(Fcb);
             Irp->IoStatus.Status = STATUS_INSTANCE_NOT_AVAILABLE;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return STATUS_INSTANCE_NOT_AVAILABLE;
         }
 
-        if (Fcb->MaximumInstances != Buffer->MaximumInstances ||
-            Fcb->TimeOut.QuadPart != Buffer->DefaultTimeout.QuadPart ||
-            Fcb->PipeType != Buffer->NamedPipeType)
+        if (Disposition == FILE_CREATE ||
+            Fcb->MaximumInstances != Parameters->MaximumInstances ||
+            Fcb->TimeOut.QuadPart != Parameters->DefaultTimeout.QuadPart ||
+            Fcb->PipeType != Parameters->NamedPipeType)
         {
             DPRINT("Asked for invalid pipe mode.\n");
-            ExFreePool(Ccb);
+            NpfsDereferenceFcb(Fcb);
             Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
             return STATUS_ACCESS_DENIED;
@@ -514,12 +584,10 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
     }
     else
     {
-        NewPipe = TRUE;
-        Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
+        Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NPFS_FCB), TAG_NPFS_FCB);
         if (Fcb == NULL)
         {
             KeUnlockMutex(&Vcb->PipeListLock);
-            ExFreePool(Ccb);
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
             Irp->IoStatus.Information = 0;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -528,14 +596,16 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
 
         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 = ExAllocatePool(NonPagedPool, Fcb->PipeName.MaximumLength);
+        Fcb->PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                                     Fcb->PipeName.MaximumLength,
+                                                     TAG_NPFS_NAMEBLOCK);
         if (Fcb->PipeName.Buffer == NULL)
         {
             KeUnlockMutex(&Vcb->PipeListLock);
-            ExFreePool(Fcb);
-            ExFreePool(Ccb);
+            ExFreePoolWithTag(Fcb, TAG_NPFS_FCB);
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
             Irp->IoStatus.Information = 0;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -549,13 +619,13 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         InitializeListHead(&Fcb->WaiterListHead);
         KeInitializeMutex(&Fcb->CcbListLock, 0);
 
-        Fcb->PipeType = Buffer->NamedPipeType;
-        Fcb->ServerReadMode = Buffer->ReadMode;
+        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;
 
-        Fcb->CompletionMode = Buffer->CompletionMode;
-        switch (IoStack->Parameters.CreatePipe.ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
+        Fcb->CompletionMode = Parameters->CompletionMode;
+        switch (ShareAccess & (FILE_SHARE_READ|FILE_SHARE_WRITE))
         {
         case FILE_SHARE_READ:
             Fcb->PipeConfiguration = FILE_PIPE_OUTBOUND;
@@ -567,19 +637,19 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
             Fcb->PipeConfiguration = FILE_PIPE_FULL_DUPLEX;
             break;
         }
-        Fcb->MaximumInstances = Buffer->MaximumInstances;
+        Fcb->MaximumInstances = Parameters->MaximumInstances;
         Fcb->CurrentInstances = 0;
-        Fcb->TimeOut = Buffer->DefaultTimeout;
+        Fcb->TimeOut = Parameters->DefaultTimeout;
         if (!(Fcb->PipeConfiguration & FILE_PIPE_OUTBOUND) ||
             Fcb->PipeConfiguration & FILE_PIPE_FULL_DUPLEX)
         {
-            if (Buffer->InboundQuota == 0)
+            if (Parameters->InboundQuota == 0)
             {
                 Fcb->InboundQuota = Vcb->DefaultQuota;
             }
             else
             {
-                Fcb->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
+                Fcb->InboundQuota = PAGE_ROUND_UP(Parameters->InboundQuota);
                 if (Fcb->InboundQuota < Vcb->MinQuota)
                 {
                     Fcb->InboundQuota = Vcb->MinQuota;
@@ -597,13 +667,13 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
 
         if (Fcb->PipeConfiguration & (FILE_PIPE_FULL_DUPLEX|FILE_PIPE_OUTBOUND))
         {
-            if (Buffer->OutboundQuota == 0)
+            if (Parameters->OutboundQuota == 0)
             {
                 Fcb->OutboundQuota = Vcb->DefaultQuota;
             }
             else
             {
-                Fcb->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
+                Fcb->OutboundQuota = PAGE_ROUND_UP(Parameters->OutboundQuota);
                 if (Fcb->OutboundQuota < Vcb->MinQuota)
                 {
                     Fcb->OutboundQuota = Vcb->MinQuota;
@@ -623,21 +693,26 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         KeUnlockMutex(&Vcb->PipeListLock);
     }
 
+    Ccb = NpfsAllocateCcb(CCB_PIPE, Fcb);
+    if (Ccb == NULL)
+    {
+        NpfsDereferenceFcb(Fcb);
+        Irp->IoStatus.Status = STATUS_NO_MEMORY;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_NO_MEMORY;
+    }
+
+    Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
+
     if (Fcb->InboundQuota)
     {
-        Ccb->Data = ExAllocatePool(PagedPool, Fcb->InboundQuota);
+        Ccb->Data = ExAllocatePoolWithTag(PagedPool,
+                                          Fcb->InboundQuota,
+                                          TAG_NPFS_CCB_DATA);
         if (Ccb->Data == NULL)
         {
-            ExFreePool(Ccb);
-
-            if (NewPipe)
-            {
-                KeLockMutex(&Vcb->PipeListLock);
-                RemoveEntryList(&Fcb->PipeListEntry);
-                KeUnlockMutex(&Vcb->PipeListLock);
-                RtlFreeUnicodeString(&Fcb->PipeName);
-                ExFreePool(Fcb);
-            }
+            NpfsDereferenceCcb(Ccb);
+            NpfsDereferenceFcb(Fcb);
 
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
             IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -660,9 +735,9 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
     Fcb->CurrentInstances++;
 
     Ccb->Fcb = Fcb;
+    Ccb->FileObject = FileObject;
     Ccb->PipeEnd = FILE_PIPE_SERVER_END;
     Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
-    Ccb->OtherSide = NULL;
 
     DPRINT("CCB: %p\n", Ccb);
 
@@ -691,7 +766,7 @@ NTSTATUS NTAPI
 NpfsCleanup(PDEVICE_OBJECT DeviceObject,
             PIRP Irp)
 {
-    PNPFS_VCB Vcb;
+    //PNPFS_VCB Vcb;
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
     PNPFS_CCB Ccb, OtherSide;
@@ -701,7 +776,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
     DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
+    //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     FileObject = IoStack->FileObject;
     Ccb = FileObject->FsContext2;
 
@@ -753,6 +828,8 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
     if ((Ccb->PipeState == FILE_PIPE_CONNECTED_STATE) && (Ccb->OtherSide))
     {
         OtherSide = Ccb->OtherSide;
+        ASSERT(OtherSide->OtherSide == Ccb);
+
         /* Lock the server first */
         if (Server)
         {
@@ -764,7 +841,11 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
             ExAcquireFastMutex(&OtherSide->DataListLock);
             ExAcquireFastMutex(&Ccb->DataListLock);
         }
-        OtherSide->OtherSide = NULL;
+
+        /* Unlink FCBs */
+        NpfsCcbSetOtherSide(OtherSide, NULL);
+        NpfsCcbSetOtherSide(Ccb, NULL);
+
         /*
         * Signaling the write event. If is possible that an other
         * thread waits for an empty buffer.
@@ -799,11 +880,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
                 RemoveEntryList(Entry);
                 tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
                 IoAcquireCancelSpinLock(&oldIrql);
-                if (!tmpIrp->Cancel)
-                {
-                    (void)IoSetCancelRoutine(tmpIrp, NULL);
-                    Complete = TRUE;
-                }
+                Complete = (NULL != IoSetCancelRoutine(tmpIrp, NULL));
                 IoReleaseCancelSpinLock(oldIrql);
                 if (Complete)
                 {
@@ -824,7 +901,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
     ExAcquireFastMutex(&Ccb->DataListLock);
     if (Ccb->Data)
     {
-        ExFreePool(Ccb->Data);
+        ExFreePoolWithTag(Ccb->Data, TAG_NPFS_CCB_DATA);
         Ccb->Data = NULL;
         Ccb->ReadPtr = NULL;
         Ccb->WritePtr = NULL;
@@ -846,7 +923,7 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
 {
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
-    PNPFS_VCB Vcb;
+    //PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
     BOOLEAN Server;
@@ -854,7 +931,7 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
+    //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     FileObject = IoStack->FileObject;
     Ccb = FileObject->FsContext2;
 
@@ -871,7 +948,7 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     {
         DPRINT("Closing the file system!\n");
 
-        ExFreePool(Ccb);
+        NpfsDereferenceCcb(Ccb);
         FileObject->FsContext = NULL;
         FileObject->FsContext2 = NULL;
 
@@ -886,9 +963,10 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
         DPRINT("Closing the root directory!\n");
 
         if (Ccb->u.Directory.SearchPattern.Buffer != NULL)
-            ExFreePool(Ccb->u.Directory.SearchPattern.Buffer);
+            ExFreePoolWithTag(Ccb->u.Directory.SearchPattern.Buffer,
+                              TAG_NPFS_NAMEBLOCK);
 
-        ExFreePool(Ccb);
+        NpfsDereferenceCcb(Ccb);
         FileObject->FsContext = NULL;
         FileObject->FsContext2 = NULL;
 
@@ -920,8 +998,10 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     /* Disconnect the pipes */
     if (Ccb->OtherSide)
     {
-        Ccb->OtherSide->OtherSide = NULL;
-        Ccb->OtherSide = NULL;
+        /* FIXME: Timo wants it rewritten */
+        /*ASSERT(Ccb->OtherSide->OtherSide == Ccb);*/
+        NpfsCcbSetOtherSide(Ccb->OtherSide, NULL);
+        NpfsCcbSetOtherSide(Ccb, NULL);
     }
 
     ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
@@ -930,20 +1010,12 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
 
     RemoveEntryList(&Ccb->CcbListEntry);
 
-    ExFreePool(Ccb);
+    NpfsDereferenceCcb(Ccb);
 
     KeUnlockMutex(&Fcb->CcbListLock);
 
-    if (IsListEmpty(&Fcb->ServerCcbListHead) &&
-        IsListEmpty(&Fcb->ClientCcbListHead))
-    {
-        RtlFreeUnicodeString(&Fcb->PipeName);
-        KeLockMutex(&Vcb->PipeListLock);
-        RemoveEntryList(&Fcb->PipeListEntry);
-        KeUnlockMutex(&Vcb->PipeListLock);
-        ExFreePool(Fcb);
-        FileObject->FsContext = NULL;
-    }
+    NpfsDereferenceFcb(Fcb);
+    FileObject->FsContext = NULL;
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
     Irp->IoStatus.Information = 0;