[NPFS/KERNEL32]
[reactos.git] / reactos / dll / win32 / kernel32 / client / file / npipe.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