[NPFS]
[reactos.git] / reactos / drivers / filesystems / npfs / fsctrl.c
index decae59..c6ebd5e 100644 (file)
@@ -1,7 +1,7 @@
 /*
 * COPYRIGHT:  See COPYING in the top level directory
 * PROJECT:    ReactOS kernel
-* FILE:       drivers/fs/np/fsctrl.c
+* FILE:       drivers/filesystems/npfs/fsctrl.c
 * PURPOSE:    Named pipe filesystem
 * PROGRAMMER: David Welch <welch@cwcom.net>
 *             Eric Kohl
@@ -26,6 +26,8 @@ NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
 {
     PNPFS_WAITER_ENTRY Waiter;
 
+    UNREFERENCED_PARAMETER(DeviceObject);
+
     Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
 
     DPRINT("NpfsListeningCancelRoutine() called for <%wZ>\n",
@@ -57,12 +59,12 @@ NpfsAddListeningServerInstance(PIRP Irp,
 
     KeLockMutex(&Ccb->Fcb->CcbListLock);
 
-    IoMarkIrpPending(Irp);
-    InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry);
-
     IoAcquireCancelSpinLock(&oldIrql);
     if (!Irp->Cancel)
     {
+        Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
+        IoMarkIrpPending(Irp);
+        InsertTailList(&Ccb->Fcb->WaiterListHead, &Entry->Entry);
         (void)IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
         IoReleaseCancelSpinLock(oldIrql);
         KeUnlockMutex(&Ccb->Fcb->CcbListLock);
@@ -92,20 +94,21 @@ NpfsConnectPipe(PIRP Irp,
     PNPFS_FCB Fcb;
     PNPFS_CCB ClientCcb;
     NTSTATUS Status;
+    KPROCESSOR_MODE WaitMode;
 
     DPRINT("NpfsConnectPipe()\n");
 
     /* Fail, if the CCB is not a pipe CCB */
     if (Ccb->Type != CCB_PIPE)
     {
-        DPRINT1("Not a pipe\n");
+        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)
     {
-        DPRINT1("Not the server end\n");
+        DPRINT("Not the server end\n");
         return STATUS_ILLEGAL_FUNCTION;
     }
 
@@ -124,6 +127,7 @@ NpfsConnectPipe(PIRP Irp,
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     FileObject = IoStack->FileObject;
     Flags = FileObject->Flags;
+    WaitMode = Irp->RequestorMode;
 
     /* search for a listening client fcb */
     KeLockMutex(&Fcb->CcbListLock);
@@ -175,18 +179,16 @@ NpfsConnectPipe(PIRP Irp,
     /* no listening client fcb found */
     DPRINT("No listening client fcb found -- waiting for client\n");
 
-    Ccb->PipeState = FILE_PIPE_LISTENING_STATE;
-
     Status = NpfsAddListeningServerInstance(Irp, Ccb);
 
     KeUnlockMutex(&Fcb->CcbListLock);
 
-    if (Flags & FO_SYNCHRONOUS_IO)
+    if ((Status == STATUS_PENDING) && (Flags & FO_SYNCHRONOUS_IO))
     {
         KeWaitForSingleObject(&Ccb->ConnectEvent,
             UserRequest,
-            Irp->RequestorMode,
-            FALSE,
+            WaitMode,
+            (Flags & FO_ALERTABLE_IO) != 0,
             NULL);
     }
 
@@ -209,14 +211,14 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
     /* Fail, if the CCB is not a pipe CCB */
     if (Ccb->Type != CCB_PIPE)
     {
-        DPRINT1("Not a pipe\n");
+        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)
     {
-        DPRINT1("Not the server end\n");
+        DPRINT("Not the server end\n");
         return STATUS_ILLEGAL_FUNCTION;
     }
 
@@ -287,7 +289,7 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
             {
                 RemoveEntryList(Entry);
                 Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
-                Complete = (NULL == IoSetCancelRoutine(Irp, NULL));
+                Complete = (NULL != IoSetCancelRoutine(Irp, NULL));
                 break;
             }
             Entry = Entry->Flink;
@@ -317,10 +319,109 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
     return Status;
 }
 
-
 static NTSTATUS
 NpfsWaitPipe(PIRP Irp,
              PNPFS_CCB Ccb)
+{
+    PLIST_ENTRY current_entry;
+    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");
+            NpfsDereferenceFcb(Fcb);
+            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;
+    }
+    NpfsDereferenceFcb(Fcb);
+
+    Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
+                                   UserRequest,
+                                   Irp->RequestorMode,
+                                   (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0,
+                                   TimeOut);
+    if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED))
+        Status = STATUS_CANCELLED;
+
+    DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
+
+    return Status;
+}
+
+NTSTATUS
+NpfsWaitPipe2(PIRP Irp,
+             PNPFS_CCB Ccb)
 {
     PLIST_ENTRY current_entry;
     PNPFS_FCB Fcb;
@@ -345,7 +446,9 @@ NpfsWaitPipe(PIRP Irp,
     /* Calculate the pipe name length and allocate the buffer */
     PipeName.Length = WaitPipe->NameLength + sizeof(WCHAR);
     PipeName.MaximumLength = PipeName.Length + sizeof(WCHAR);
-    PipeName.Buffer = ExAllocatePool(NonPagedPool, PipeName.MaximumLength);
+    PipeName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+                                            PipeName.MaximumLength,
+                                            TAG_NPFS_NAMEBLOCK);
     if (PipeName.Buffer == NULL)
     {
         DPRINT1("Could not allocate memory for the pipe name!\n");
@@ -375,7 +478,7 @@ NpfsWaitPipe(PIRP Irp,
     KeUnlockMutex(&Vcb->PipeListLock);
 
     /* Release the pipe name buffer */
-    ExFreePool(PipeName.Buffer);
+    ExFreePoolWithTag(PipeName.Buffer, TAG_NPFS_NAMEBLOCK);
 
     /* Fail if not pipe was found */
     if (Fcb == NULL)
@@ -407,7 +510,9 @@ NpfsWaitPipe(PIRP Irp,
         {
             /* found a listening server CCB */
             DPRINT("Listening server CCB found -- connecting\n");
-
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
+            NpfsDereferenceFcb(Fcb);
+#endif
             return STATUS_SUCCESS;
         }
 
@@ -421,13 +526,18 @@ NpfsWaitPipe(PIRP Irp,
         TimeOut = WaitPipe->Timeout;
     else
         TimeOut = Fcb->TimeOut;
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
+    NpfsDereferenceFcb(Fcb);
+#endif
 
     /* Wait for one */
     Status = KeWaitForSingleObject(&Ccb->ConnectEvent,
         UserRequest,
-        KernelMode,
-        FALSE,
+        Irp->RequestorMode,
+        (Ccb->FileObject->Flags & FO_ALERTABLE_IO) != 0,
         &TimeOut);
+    if ((Status == STATUS_USER_APC) || (Status == STATUS_KERNEL_APC) || (Status == STATUS_ALERTED))
+        Status = STATUS_CANCELLED;
 
     DPRINT("KeWaitForSingleObject() returned (Status %lx)\n", Status);
 
@@ -459,7 +569,7 @@ NpfsPeekPipe(PIRP Irp,
     ULONG OutputBufferLength;
     ULONG ReturnLength = 0;
     PFILE_PIPE_PEEK_BUFFER Reply;
-    PNPFS_FCB Fcb;
+    //PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
     NTSTATUS Status;
     ULONG MessageCount = 0;
@@ -473,15 +583,15 @@ NpfsPeekPipe(PIRP Irp,
     DPRINT("OutputBufferLength: %lu\n", OutputBufferLength);
 
     /* Validate parameters */
-    if (OutputBufferLength < sizeof(FILE_PIPE_PEEK_BUFFER))
+    if (OutputBufferLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))
     {
         DPRINT1("Buffer too small\n");
         return STATUS_INVALID_PARAMETER;
     }
 
     Ccb = IoStack->FileObject->FsContext2;
-    Reply = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
-    Fcb = Ccb->Fcb;
+    Reply = Irp->AssociatedIrp.SystemBuffer;
+    //Fcb = Ccb->Fcb;
 
 
     Reply->NamedPipeState = Ccb->PipeState;
@@ -496,46 +606,49 @@ NpfsPeekPipe(PIRP Irp,
     {
         DPRINT("Byte Stream Mode\n");
         Reply->MessageLength = Ccb->ReadDataAvailable;
-        DPRINT("Reply->MessageLength  %lu\n",Reply->MessageLength );
+        DPRINT("Reply->MessageLength  %lu\n", Reply->MessageLength);
         MessageCount = 1;
 
-        if (Reply->Data[0] && (OutputBufferLength >= Ccb->ReadDataAvailable + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0])))
+        if (OutputBufferLength >= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[Ccb->ReadDataAvailable]))
         {
+            RtlCopyMemory(Reply->Data, BufferPtr, Ccb->ReadDataAvailable);
             ReturnLength = Ccb->ReadDataAvailable;
-            memcpy(&Reply->Data[0], (PVOID)BufferPtr, Ccb->ReadDataAvailable);
         }
     }
     else
     {
         DPRINT("Message Mode\n");
-        ReadDataAvailable=Ccb->ReadDataAvailable;
+        ReadDataAvailable = Ccb->ReadDataAvailable;
 
         if (ReadDataAvailable > 0)
         {
-            memcpy(&Reply->MessageLength, BufferPtr, sizeof(ULONG));
+            RtlCopyMemory(&Reply->MessageLength,
+                          BufferPtr,
+                          sizeof(Reply->MessageLength));
 
             while ((ReadDataAvailable > 0) && (BufferPtr < Ccb->WritePtr))
             {
-                memcpy(&MessageLength, BufferPtr, sizeof(MessageLength));
+                RtlCopyMemory(&MessageLength, BufferPtr, sizeof(MessageLength));
 
                 ASSERT(MessageLength > 0);
 
-                DPRINT("MessageLength = %lu\n",MessageLength);
+                DPRINT("MessageLength = %lu\n", MessageLength);
                 ReadDataAvailable -= MessageLength;
                 MessageCount++;
 
                 /* If its the first message, copy the Message if the size of buffer is large enough */
-                if (MessageCount==1)
+                if (MessageCount == 1)
                 {
-                    if ((Reply->Data[0])
-                        && (OutputBufferLength >= (MessageLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]))))
+                    if (OutputBufferLength >= FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[MessageLength]))
                     {
-                        memcpy(&Reply->Data[0], (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)), MessageLength);
+                        RtlCopyMemory(Reply->Data,
+                                      (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength)),
+                                      MessageLength);
                         ReturnLength = MessageLength;
                     }
                 }
 
-                BufferPtr =(PVOID)((ULONG_PTR)BufferPtr + MessageLength + sizeof(MessageLength));
+                BufferPtr = (PVOID)((ULONG_PTR)BufferPtr + sizeof(MessageLength) + MessageLength);
                 DPRINT("BufferPtr = %x\n", BufferPtr);
                 DPRINT("ReadDataAvailable: %lu\n", ReadDataAvailable);
             }
@@ -551,7 +664,7 @@ NpfsPeekPipe(PIRP Irp,
 
     Reply->NumberOfMessages = MessageCount;
 
-    Irp->IoStatus.Information = ReturnLength + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
+    Irp->IoStatus.Information = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[ReturnLength]);
     Irp->IoStatus.Status = STATUS_SUCCESS;
 
     Status = STATUS_SUCCESS;
@@ -569,13 +682,13 @@ NpfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
     PIO_STACK_LOCATION IoStack;
     PFILE_OBJECT FileObject;
     NTSTATUS Status;
-    PNPFS_VCB Vcb;
+    //PNPFS_VCB Vcb;
     PNPFS_FCB Fcb;
     PNPFS_CCB Ccb;
 
     DPRINT("NpfsFileSystemContol(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
-    Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
+    //Vcb = (PNPFS_VCB)DeviceObject->DeviceExtension;
     IoStack = IoGetCurrentIrpStackLocation(Irp);
     DPRINT("IoStack: %p\n", IoStack);
     FileObject = IoStack->FileObject;
@@ -684,6 +797,7 @@ NpfsFlushBuffers(PDEVICE_OBJECT DeviceObject,
                  PIRP Irp)
 {
     /* FIXME: Implement */
+    UNREFERENCED_PARAMETER(DeviceObject);
 
     Irp->IoStatus.Status = STATUS_SUCCESS;
     Irp->IoStatus.Information = 0;