[NPFS/KERNEL32]
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 1 Sep 2013 10:16:29 +0000 (10:16 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 1 Sep 2013 10:16:29 +0000 (10:16 +0000)
* Back out r59915 for a moment so we can use Patchbot.

svn path=/trunk/; revision=59934

reactos/dll/win32/kernel32/client/file/npipe.c
reactos/drivers/filesystems/npfs/create.c
reactos/drivers/filesystems/npfs/fsctrl.c

index ff61054..1844ef4 100644 (file)
@@ -14,6 +14,8 @@
 #include <debug.h>
 DEBUG_CHANNEL(kernel32file);
 
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
+
 /* GLOBALS ********************************************************************/
 
 LONG ProcessPipeId;
@@ -362,6 +364,17 @@ WaitNamedPipeA(LPCSTR lpNamedPipeName,
     return r;
 }
 
+
+/*
+ * When NPFS will work properly, use this code instead. It is compatible with
+ * Microsoft's NPFS.SYS. The main difference is that:
+ *      - This code actually respects the timeout instead of ignoring it!
+ *      - This code validates and creates the proper names for both UNC and local pipes
+ *      - On NT, you open the *root* pipe directory (either \DosDevices\Pipe or
+ *        \DosDevices\Unc\Server\Pipe) and then send the pipe to wait on in the
+ *        FILE_PIPE_WAIT_FOR_BUFFER structure.
+ */
+#ifdef USING_PROPER_NPFS_WAIT_SEMANTICS
 /*
  * @implemented
  */
@@ -546,6 +559,96 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
     /* Success */
     return TRUE;
 }
+#else
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+WaitNamedPipeW(LPCWSTR lpNamedPipeName,
+               DWORD nTimeOut)
+{
+    UNICODE_STRING NamedPipeName;
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    FILE_PIPE_WAIT_FOR_BUFFER WaitPipe;
+    HANDLE FileHandle;
+    IO_STATUS_BLOCK Iosb;
+
+    if (RtlDosPathNameToNtPathName_U(lpNamedPipeName,
+                                     &NamedPipeName,
+                                     NULL,
+                                     NULL) == FALSE)
+    {
+        return FALSE;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &NamedPipeName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenFile(&FileHandle,
+                        FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &Iosb,
+                        FILE_SHARE_READ | FILE_SHARE_WRITE,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        RtlFreeUnicodeString(&NamedPipeName);
+        return FALSE;
+    }
+
+    /* Check what timeout we got */
+    if (nTimeOut == NMPWAIT_WAIT_FOREVER)
+    {
+        /* Don't use a timeout */
+        WaitPipe.TimeoutSpecified = FALSE;
+    }
+    else
+    {
+        /* Check if default */
+        if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
+        {
+            /* Set it to 0 */
+            WaitPipe.Timeout.LowPart = 0;
+            WaitPipe.Timeout.HighPart = 0;
+        }
+        else
+        {
+            /* Convert to NT format */
+            WaitPipe.Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut);
+        }
+
+        /* In both cases, we do have a timeout */
+        WaitPipe.TimeoutSpecified = TRUE;
+    }
+
+    Status = NtFsControlFile(FileHandle,
+                             NULL,
+                             NULL,
+                             NULL,
+                             &Iosb,
+                             FSCTL_PIPE_WAIT,
+                             &WaitPipe,
+                             sizeof(WaitPipe),
+                             NULL,
+                             0);
+    NtClose(FileHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        RtlFreeUnicodeString(&NamedPipeName);
+        return FALSE;
+    }
+
+    RtlFreeUnicodeString(&NamedPipeName);
+    return TRUE;
+}
+#endif
+
 
 /*
  * @implemented
index 7114b98..abdfe5e 100644 (file)
@@ -13,6 +13,8 @@
 #define NDEBUG
 #include <debug.h>
 
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
+
 /* FUNCTIONS *****************************************************************/
 
 VOID
@@ -249,6 +251,10 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     PNPFS_CCB ServerCcb = NULL;
     PNPFS_VCB Vcb;
     NTSTATUS Status;
+#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
+    ACCESS_MASK DesiredAccess;
+    BOOLEAN SpecialAccess;
+#endif
 
     DPRINT("NpfsCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
 
@@ -257,12 +263,23 @@ 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);
 
     Irp->IoStatus.Information = 0;
 
+#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
+    SpecialAccess = ((DesiredAccess & SPECIFIC_RIGHTS_ALL) == FILE_READ_ATTRIBUTES);
+    if (SpecialAccess)
+    {
+        DPRINT("NpfsCreate() open client end for special use!\n");
+    }
+#endif
+
     DPRINT("FileName->Length: %hu  RelatedFileObject: %p\n", FileName->Length, RelatedFileObject);
 
     /* Open the file system */
@@ -336,7 +353,11 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     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);
@@ -377,62 +398,85 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
     /*
     * Step 3. Search for listening server CCB.
     */
-    /*
-    * 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)
+#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
+    if (!SpecialAccess)
     {
-        PLIST_ENTRY CurrentEntry;
-        PNPFS_CCB Ccb;
-
+#endif
         /*
-        * If no waiting server CCB was found then try to pick
-        * one of the listing server CCB on the pipe.
+        * 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.
         */
 
-        CurrentEntry = Fcb->ServerCcbListHead.Flink;
-        while (CurrentEntry != &Fcb->ServerCcbListHead)
+        ServerCcb = NpfsFindListeningServerInstance(Fcb);
+        if (ServerCcb == NULL)
         {
-            Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
-            if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
+            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.
+            */
+
+            CurrentEntry = Fcb->ServerCcbListHead.Flink;
+            while (CurrentEntry != &Fcb->ServerCcbListHead)
             {
-                ServerCcb = Ccb;
-                break;
+                Ccb = CONTAINING_RECORD(CurrentEntry, NPFS_CCB, CcbListEntry);
+                if (Ccb->PipeState == FILE_PIPE_LISTENING_STATE)
+                {
+                    ServerCcb = Ccb;
+                    break;
+                }
+                CurrentEntry = CurrentEntry->Flink;
             }
-            CurrentEntry = CurrentEntry->Flink;
-        }
 
-        /*
-        * No one is listening to me?! I'm so lonely... :(
-        */
+            /*
+            * 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)
+            if (ServerCcb == NULL)
             {
-                ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
-            }
+                /* 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;
+                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);
+        }
+#ifndef USING_PROPER_NPFS_WAIT_SEMANTICS
     }
-    else
+    else if (IsListEmpty(&Fcb->ServerCcbListHead))
     {
-        /* Signal the server thread and remove it from the waiter list */
-        /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
-        NpfsSignalAndRemoveListeningServerInstance(Fcb, ServerCcb);
+        DPRINT("No server fcb found!\n");
+
+        if (ClientCcb->Data)
+        {
+            ExFreePoolWithTag(ClientCcb->Data, TAG_NPFS_CCB_DATA);
+        }
+
+        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.
index 09870e9..ce68432 100644 (file)
@@ -15,6 +15,8 @@
 #define NDEBUG
 #include <debug.h>
 
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
+
 /* FUNCTIONS *****************************************************************/
 
 static DRIVER_CANCEL NpfsListeningCancelRoutine;
@@ -317,9 +319,109 @@ NpfsDisconnectPipe(PNPFS_CCB Ccb)
     return Status;
 }
 
-NTSTATUS
+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");
+        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;
@@ -327,12 +429,16 @@ NpfsWaitPipe(PIRP Irp,
     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;
@@ -382,6 +488,15 @@ NpfsWaitPipe(PIRP Irp,
     }
 
     DPRINT("Fcb %p\n", Fcb);
+#else
+    Fcb = Ccb->Fcb;
+
+    if (Ccb->PipeState != 0)
+    {
+        DPRINT("Pipe is not in passive (waiting) state!\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+#endif
 
     /* search for listening server */
     current_entry = Fcb->ServerCcbListHead.Flink;
@@ -395,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;
         }
 
@@ -409,8 +526,9 @@ 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,