[NPFS]
[reactos.git] / reactos / drivers / filesystems / npfs / create.c
index 5236e20..0462003 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
-static PNPFS_FCB
-NpfsFindPipe(PNPFS_DEVICE_EXTENSION DeviceExt,
+PNPFS_FCB
+NpfsFindPipe(PNPFS_VCB Vcb,
              PUNICODE_STRING PipeName)
 {
     PLIST_ENTRY CurrentEntry;
     PNPFS_FCB Fcb;
 
-    CurrentEntry = DeviceExt->PipeListHead.Flink;
-    while (CurrentEntry != &DeviceExt->PipeListHead)
+    CurrentEntry = Vcb->PipeListHead.Flink;
+    while (CurrentEntry != &Vcb->PipeListHead)
     {
         Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, PipeListEntry);
         if (RtlCompareUnicodeString(PipeName,
@@ -103,53 +103,95 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_FCB Fcb,
 }
 
 
+static VOID
+NpfsOpenRootDirectory(PNPFS_FCB Fcb,
+                      PFILE_OBJECT FileObject,
+                      PIO_STATUS_BLOCK IoStatus)
+{
+    PNPFS_CCB Ccb;
+
+    DPRINT("NpfsOpenRootDirectory()\n");
+
+    Ccb = ExAllocatePool(NonPagedPool, sizeof(NPFS_CCB));
+    if (Ccb == NULL)
+    {
+        IoStatus->Status = STATUS_NO_MEMORY;
+        return;
+    }
+
+    Ccb->Type = CCB_DIRECTORY;
+    Ccb->Fcb = Fcb;
+
+    FileObject->FsContext = Fcb;
+    FileObject->FsContext2 = Ccb;
+
+    IoStatus->Information = FILE_OPENED;
+    IoStatus->Status = STATUS_SUCCESS;
+
+    return;
+}
+
+
 NTSTATUS NTAPI
 NpfsCreate(PDEVICE_OBJECT DeviceObject,
            PIRP Irp)
 {
     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_DEVICE_EXTENSION DeviceExt;
-    BOOLEAN SpecialAccess;
+    PNPFS_VCB Vcb;
     ACCESS_MASK DesiredAccess;
+    NTSTATUS Status;
 
     DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
-    DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
     FileObject = IoStack->FileObject;
+    RelatedFileObject = FileObject->RelatedFileObject;
+    FileName = &FileObject->FileName;
     DesiredAccess = IoStack->Parameters.CreatePipe.SecurityContext->DesiredAccess;
+
     DPRINT("FileObject %p\n", FileObject);
     DPRINT("FileName %wZ\n", &FileObject->FileName);
 
     Irp->IoStatus.Information = 0;
 
-    SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
-    if (SpecialAccess)
+    if (FileName->Length == 2 && FileName->Buffer[0] == L'\\' && RelatedFileObject == NULL)
     {
-        DPRINT("NpfsCreate() open client end for special use!\n");
+        DPRINT("Open the root directory\n");
+
+        NpfsOpenRootDirectory(Vcb->RootFcb,
+                              FileObject,
+                              &Irp->IoStatus);
+
+        Status = Irp->IoStatus.Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return Status;
     }
 
+
     /*
     * Step 1. Find the pipe we're trying to open.
     */
-    KeLockMutex(&DeviceExt->PipeListLock);
-    Fcb = NpfsFindPipe(DeviceExt,
+    KeLockMutex(&Vcb->PipeListLock);
+    Fcb = NpfsFindPipe(Vcb,
         &FileObject->FileName);
     if (Fcb == NULL)
     {
         /* Not found, bail out with error. */
         DPRINT("No pipe found!\n");
-        KeUnlockMutex(&DeviceExt->PipeListLock);
+        KeUnlockMutex(&Vcb->PipeListLock);
         Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_OBJECT_NAME_NOT_FOUND;
     }
 
-    KeUnlockMutex(&DeviceExt->PipeListLock);
+    KeUnlockMutex(&Vcb->PipeListLock);
 
     /*
     * Acquire the lock for CCB lists. From now on no modifications to the
@@ -170,11 +212,13 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
         return STATUS_NO_MEMORY;
     }
 
+    ClientCcb->Type = CCB_PIPE;
     ClientCcb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
     ClientCcb->Fcb = Fcb;
     ClientCcb->PipeEnd = FILE_PIPE_CLIENT_END;
     ClientCcb->OtherSide = NULL;
-    ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
+//    ClientCcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
+    ClientCcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
     InitializeListHead(&ClientCcb->ReadRequestListHead);
 
     DPRINT("CCB: %p\n", ClientCcb);
@@ -205,16 +249,17 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     ClientCcb->MaxDataLength = Fcb->OutboundQuota;
     ExInitializeFastMutex(&ClientCcb->DataListLock);
     KeInitializeEvent(&ClientCcb->ConnectEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&ClientCcb->ReadEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&ClientCcb->WriteEvent, SynchronizationEvent, FALSE);
+    KeInitializeEvent(&ClientCcb->ReadEvent, NotificationEvent, FALSE);
+    KeInitializeEvent(&ClientCcb->WriteEvent, NotificationEvent, FALSE);
 
 
     /*
     * Step 3. Search for listening server CCB.
     */
-
+/*
     if (!SpecialAccess)
     {
+*/
         /*
         * 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
@@ -255,8 +300,9 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
                 if (ClientCcb->Data)
                 {
                     ExFreePool(ClientCcb->Data);
-                    ClientCcb->Data = NULL;
                 }
+
+                ExFreePool(ClientCcb);
                 KeUnlockMutex(&Fcb->CcbListLock);
                 Irp->IoStatus.Status = STATUS_OBJECT_PATH_NOT_FOUND;
                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -269,15 +315,25 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
             /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
             NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
         }
+/*
     }
     else if (IsListEmpty(&Fcb->ServerCcbListHead))
     {
         DPRINT("No server fcb found!\n");
+
+        if (ClientCcb->Data)
+        {
+            ExFreePool(ClientCcb->Data);
+        }
+
+        ExFreePool(ClientCcb);
+
         KeUnlockMutex(&Fcb->CcbListLock);
         Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_UNSUCCESSFUL;
     }
+*/
 
     /*
     * Step 4. Add the client CCB to a list and connect it if possible.
@@ -317,7 +373,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
 {
     PEXTENDED_IO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
-    PNPFS_DEVICE_EXTENSION DeviceExt;
+    PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
     PNAMED_PIPE_CREATE_PARAMETERS Buffer;
@@ -325,7 +381,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
 
     DPRINT("NpfsCreateNamedPipe(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
-    DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
     FileObject = IoStack->FileObject;
     DPRINT("FileObject %p\n", FileObject);
@@ -351,13 +407,14 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         return STATUS_NO_MEMORY;
     }
 
+    Ccb->Type = CCB_PIPE;
     Ccb->Thread = (struct ETHREAD *)Irp->Tail.Overlay.Thread;
-    KeLockMutex(&DeviceExt->PipeListLock);
+    KeLockMutex(&Vcb->PipeListLock);
 
     /*
     * First search for existing Pipe with the same name.
     */
-    Fcb = NpfsFindPipe(DeviceExt,
+    Fcb = NpfsFindPipe(Vcb,
         &FileObject->FileName);
     if (Fcb != NULL)
     {
@@ -365,7 +422,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         * Found Pipe with the same name. Check if we are
         * allowed to use it.
         */
-        KeUnlockMutex(&DeviceExt->PipeListLock);
+        KeUnlockMutex(&Vcb->PipeListLock);
 
         if (Fcb->CurrentInstances >= Fcb->MaximumInstances)
         {
@@ -393,7 +450,7 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         Fcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
         if (Fcb == NULL)
         {
-            KeUnlockMutex(&DeviceExt->PipeListLock);
+            KeUnlockMutex(&Vcb->PipeListLock);
             ExFreePool(Ccb);
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
             Irp->IoStatus.Information = 0;
@@ -401,12 +458,14 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
             return STATUS_NO_MEMORY;
         }
 
+        Fcb->Type = FCB_PIPE;
+        Fcb->Vcb = Vcb;
         Fcb->PipeName.Length = FileObject->FileName.Length;
         Fcb->PipeName.MaximumLength = Fcb->PipeName.Length + sizeof(UNICODE_NULL);
         Fcb->PipeName.Buffer = ExAllocatePool(NonPagedPool, Fcb->PipeName.MaximumLength);
         if (Fcb->PipeName.Buffer == NULL)
         {
-            KeUnlockMutex(&DeviceExt->PipeListLock);
+            KeUnlockMutex(&Vcb->PipeListLock);
             ExFreePool(Fcb);
             ExFreePool(Ccb);
             Irp->IoStatus.Status = STATUS_NO_MEMORY;
@@ -448,18 +507,18 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         {
             if (Buffer->InboundQuota == 0)
             {
-                Fcb->InboundQuota = DeviceExt->DefaultQuota;
+                Fcb->InboundQuota = Vcb->DefaultQuota;
             }
             else
             {
                 Fcb->InboundQuota = PAGE_ROUND_UP(Buffer->InboundQuota);
-                if (Fcb->InboundQuota < DeviceExt->MinQuota)
+                if (Fcb->InboundQuota < Vcb->MinQuota)
                 {
-                    Fcb->InboundQuota = DeviceExt->MinQuota;
+                    Fcb->InboundQuota = Vcb->MinQuota;
                 }
-                else if (Fcb->InboundQuota > DeviceExt->MaxQuota)
+                else if (Fcb->InboundQuota > Vcb->MaxQuota)
                 {
-                    Fcb->InboundQuota = DeviceExt->MaxQuota;
+                    Fcb->InboundQuota = Vcb->MaxQuota;
                 }
             }
         }
@@ -472,18 +531,18 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
         {
             if (Buffer->OutboundQuota == 0)
             {
-                Fcb->OutboundQuota = DeviceExt->DefaultQuota;
+                Fcb->OutboundQuota = Vcb->DefaultQuota;
             }
             else
             {
                 Fcb->OutboundQuota = PAGE_ROUND_UP(Buffer->OutboundQuota);
-                if (Fcb->OutboundQuota < DeviceExt->MinQuota)
+                if (Fcb->OutboundQuota < Vcb->MinQuota)
                 {
-                    Fcb->OutboundQuota = DeviceExt->MinQuota;
+                    Fcb->OutboundQuota = Vcb->MinQuota;
                 }
-                else if (Fcb->OutboundQuota > DeviceExt->MaxQuota)
+                else if (Fcb->OutboundQuota > Vcb->MaxQuota)
                 {
-                    Fcb->OutboundQuota = DeviceExt->MaxQuota;
+                    Fcb->OutboundQuota = Vcb->MaxQuota;
                 }
             }
         }
@@ -492,8 +551,8 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
             Fcb->OutboundQuota = 0;
         }
 
-        InsertTailList(&DeviceExt->PipeListHead, &Fcb->PipeListEntry);
-        KeUnlockMutex(&DeviceExt->PipeListLock);
+        InsertTailList(&Vcb->PipeListHead, &Fcb->PipeListEntry);
+        KeUnlockMutex(&Vcb->PipeListLock);
     }
 
     if (Fcb->InboundQuota)
@@ -505,9 +564,9 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
 
             if (NewPipe)
             {
-                KeLockMutex(&DeviceExt->PipeListLock);
+                KeLockMutex(&Vcb->PipeListLock);
                 RemoveEntryList(&Fcb->PipeListEntry);
-                KeUnlockMutex(&DeviceExt->PipeListLock);
+                KeUnlockMutex(&Vcb->PipeListLock);
                 RtlFreeUnicodeString(&Fcb->PipeName);
                 ExFreePool(Fcb);
             }
@@ -540,8 +599,8 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
     DPRINT("CCB: %p\n", Ccb);
 
     KeInitializeEvent(&Ccb->ConnectEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&Ccb->ReadEvent, SynchronizationEvent, FALSE);
-    KeInitializeEvent(&Ccb->WriteEvent, SynchronizationEvent, FALSE);
+    KeInitializeEvent(&Ccb->ReadEvent, NotificationEvent, FALSE);
+    KeInitializeEvent(&Ccb->WriteEvent, NotificationEvent, FALSE);
 
     KeLockMutex(&Fcb->CcbListLock);
     InsertTailList(&Fcb->ServerCcbListHead, &Ccb->CcbListEntry);
@@ -564,7 +623,7 @@ NTSTATUS NTAPI
 NpfsCleanup(PDEVICE_OBJECT DeviceObject,
             PIRP Irp)
 {
-    PNPFS_DEVICE_EXTENSION DeviceExt;
+    PNPFS_VCB Vcb;
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
     PNPFS_CCB Ccb, OtherSide;
@@ -574,7 +633,7 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
     DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     FileObject = IoStack->FileObject;
     Ccb = FileObject->FsContext2;
 
@@ -587,6 +646,15 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
         return STATUS_SUCCESS;
     }
 
+    if (Ccb->Type == CCB_DIRECTORY)
+    {
+        DPRINT("Cleanup the root directory!\n");
+        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;
 
@@ -619,7 +687,6 @@ NpfsCleanup(PDEVICE_OBJECT DeviceObject,
             ExAcquireFastMutex(&OtherSide->DataListLock);
             ExAcquireFastMutex(&Ccb->DataListLock);
         }
-        //OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
         OtherSide->OtherSide = NULL;
         /*
         * Signaling the write event. If is possible that an other
@@ -700,9 +767,9 @@ NTSTATUS NTAPI
 NpfsClose(PDEVICE_OBJECT DeviceObject,
           PIRP Irp)
 {
-    PNPFS_DEVICE_EXTENSION DeviceExt;
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
+    PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
     BOOLEAN Server;
@@ -710,7 +777,7 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     DPRINT("NpfsClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     FileObject = IoStack->FileObject;
     Ccb = FileObject->FsContext2;
 
@@ -723,6 +790,20 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
         return STATUS_SUCCESS;
     }
 
+    if (Ccb->Type == CCB_DIRECTORY)
+    {
+        DPRINT("Closing the root directory!\n");
+
+        ExFreePool(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;
 
@@ -743,8 +824,11 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
     }
 
     /* Disconnect the pipes */
-    if (Ccb->OtherSide) Ccb->OtherSide->OtherSide = NULL;
-    if (Ccb) Ccb->OtherSide = NULL;
+    if (Ccb->OtherSide)
+    {
+        Ccb->OtherSide->OtherSide = NULL;
+        Ccb->OtherSide = NULL;
+    }
 
     ASSERT(Ccb->PipeState == FILE_PIPE_CLOSING_STATE);
 
@@ -760,9 +844,9 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
         IsListEmpty(&Fcb->ClientCcbListHead))
     {
         RtlFreeUnicodeString(&Fcb->PipeName);
-        KeLockMutex(&DeviceExt->PipeListLock);
+        KeLockMutex(&Vcb->PipeListLock);
         RemoveEntryList(&Fcb->PipeListEntry);
-        KeUnlockMutex(&DeviceExt->PipeListLock);
+        KeUnlockMutex(&Vcb->PipeListLock);
         ExFreePool(Fcb);
         FileObject->FsContext = NULL;
     }