- Update to r53061
[reactos.git] / drivers / filesystems / npfs / fsctrl.c
index 242102d..5e723b4 100644 (file)
@@ -15,6 +15,8 @@
 #define NDEBUG
 #include <debug.h>
 
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
+
 /* FUNCTIONS *****************************************************************/
 
 static DRIVER_CANCEL NpfsListeningCancelRoutine;
@@ -93,6 +95,20 @@ NpfsConnectPipe(PIRP Irp,
 
     DPRINT("NpfsConnectPipe()\n");
 
+    /* Fail, if the CCB is not a pipe CCB */
+    if (Ccb->Type != CCB_PIPE)
+    {
+        DPRINT("Not a pipe\n");
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+
+    /* Fail, if the CCB is not a server end CCB */
+    if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
+    {
+        DPRINT("Not the server end\n");
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+
     if (Ccb->PipeState == FILE_PIPE_CONNECTED_STATE)
     {
         KeResetEvent(&Ccb->ConnectEvent);
@@ -190,6 +206,20 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
 
     DPRINT("NpfsDisconnectPipe()\n");
 
+    /* Fail, if the CCB is not a pipe CCB */
+    if (Ccb->Type != CCB_PIPE)
+    {
+        DPRINT("Not a pipe\n");
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+
+    /* Fail, if the CCB is not a server end CCB */
+    if (Ccb->PipeEnd != FILE_PIPE_SERVER_END)
+    {
+        DPRINT("Not the server end\n");
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+
     Fcb = Ccb->Fcb;
     KeLockMutex(&Fcb->CcbListLock);
 
@@ -287,7 +317,6 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
     return Status;
 }
 
-
 static NTSTATUS
 NpfsWaitPipe(PIRP Irp,
              PNPFS_CCB Ccb)
@@ -296,12 +325,165 @@ NpfsWaitPipe(PIRP Irp,
     PNPFS_FCB Fcb;
     PNPFS_CCB ServerCcb;
     PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
+    PLARGE_INTEGER TimeOut;
     NTSTATUS Status;
+    PEXTENDED_IO_STACK_LOCATION IoStack;
+    PFILE_OBJECT FileObject;
+    PNPFS_VCB Vcb;
+
+    IoStack = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
+    ASSERT(IoStack);
+    FileObject = IoStack->FileObject;
+    ASSERT(FileObject);
+
+    DPRINT("Waiting on Pipe %wZ\n", &FileObject->FileName);
+
+    WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+
+    ASSERT(Ccb->Fcb);
+    ASSERT(Ccb->Fcb->Vcb);
+
+    /* Get the VCB */
+    Vcb = Ccb->Fcb->Vcb;
+
+    /* Lock the pipe list */
+    KeLockMutex(&Vcb->PipeListLock);
+
+    /* File a pipe with the given name */
+    Fcb = NpfsFindPipe(Vcb,
+                       &FileObject->FileName);
+
+    /* Unlock the pipe list */
+    KeUnlockMutex(&Vcb->PipeListLock);
+
+    /* Fail if not pipe was found */
+    if (Fcb == NULL)
+    {
+        DPRINT("No pipe found!\n", Fcb);
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+    /* search for listening server */
+    current_entry = Fcb->ServerCcbListHead.Flink;
+    while (current_entry != &Fcb->ServerCcbListHead)
+    {
+        ServerCcb = CONTAINING_RECORD(current_entry,
+                                      NPFS_CCB,
+                                      CcbListEntry);
+
+        if (ServerCcb->PipeState == FILE_PIPE_LISTENING_STATE)
+        {
+            /* found a listening server CCB */
+            DPRINT("Listening server CCB found -- connecting\n");
+
+            return STATUS_SUCCESS;
+        }
+
+        current_entry = current_entry->Flink;
+    }
+
+    /* No listening server fcb found, so wait for one */
+
+    /* If a timeout specified */
+    if (WaitPipe->TimeoutSpecified)
+    {
+        /* NMPWAIT_USE_DEFAULT_WAIT = 0 */
+        if (WaitPipe->Timeout.QuadPart == 0)
+        {
+            TimeOut = &Fcb->TimeOut;
+        }
+        else
+        {
+            TimeOut = &WaitPipe->Timeout;
+        }
+    }
+    else
+    {
+        /* Wait forever */
+        TimeOut = NULL;
+    }
+
+     Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
+                                    UserRequest,
+                                    KernelMode,
+                                    TRUE,
+                                    TimeOut);
+
+    DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
+
+    return Status;
+}
+
+NTSTATUS
+NpfsWaitPipe2(PIRP Irp,
+             PNPFS_CCB Ccb)
+{
+    PLIST_ENTRY current_entry;
+    PNPFS_FCB Fcb;
+    PNPFS_CCB ServerCcb;
+    PFILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
     LARGE_INTEGER TimeOut;
+    NTSTATUS Status;
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
+    PNPFS_VCB Vcb;
+    UNICODE_STRING PipeName;
+#endif
 
     DPRINT("NpfsWaitPipe\n");
 
     WaitPipe = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
+    /* Fail, if the CCB does not represent the root directory */
+    if (Ccb->Type != CCB_DIRECTORY)
+        return STATUS_ILLEGAL_FUNCTION;
+
+    /* Calculate the pipe name length and allocate the buffer */
+    PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR);
+    PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR);
+    PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                            PipeName.MaximumLength,
+                                            TAG_NPFS_NAMEBLOCK);
+    if (PipeName.Buffer == NULL)
+    {
+        DPRINT1("Could not allocate memory for the pipe name!\n");
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Copy the pipe name into the buffer, prepend a backslash and append a 0 character */
+    PipeName.Buffer[0] = L'\\';
+    RtlCopyMemory(&PipeName.Buffer[1],
+                  &WaitPipe->Name[0],
+                  WaitPipe->NameLength);
+    PipeName.Buffer[PipeName.Length / sizeof(WCHAR)] = 0;
+
+    DPRINT("Waiting for Pipe %wZ\n", &PipeName);
+
+    /* Get the VCB */
+    Vcb = Ccb->Fcb->Vcb;
+
+    /* Lock the pipe list */
+    KeLockMutex(&Vcb->PipeListLock);
+
+    /* File a pipe with the given name */
+    Fcb = NpfsFindPipe(Vcb,
+                       &PipeName);
+
+    /* Unlock the pipe list */
+    KeUnlockMutex(&Vcb->PipeListLock);
+
+    /* Release the pipe name buffer */
+    ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK);
+
+    /* Fail if not pipe was found */
+    if (Fcb == NULL)
+    {
+        DPRINT("No pipe found!\n", Fcb);
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+    DPRINT("Fcb %p\n", Fcb);
+#else
     Fcb = Ccb->Fcb;
 
     if (Ccb->PipeState != 0)
@@ -309,6 +491,7 @@ NpfsWaitPipe(PIRP Irp,
         DPRINT("Pipe is not in passive (waiting) state!\n");
         return STATUS_UNSUCCESSFUL;
     }
+#endif
 
     /* search for listening server */
     current_entry = Fcb->ServerCcbListHead.Flink;
@@ -484,13 +667,13 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
     NTSTATUS Status;
-    PNPFS_DEVICE_EXTENSION DeviceExt;
+    PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
 
     DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
-    DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     DPRINT("IoStack: %p\n", IoStack);
     FileObject = IoStack->FileObject;