From 813744368ba23f2e06e06029bf93955760f10a7c Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 11 Aug 2014 05:34:19 +0200
Subject: ntdll: Allow to set PIPE_NOWAIT on byte-mode pipes.

This patch implements the functionality to set PIPE_NOWAIT on regular bytemode
pipes. This patch also extends the test to show that the implemented behaviour
matches the native implementation.
---
 dlls/kernel32/tests/pipe.c | 37 +++++++++++++++++++++++++++++--------
 dlls/ntdll/file.c          |  2 ++
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 35755b3..e464469 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2561,7 +2561,7 @@ static void test_overlapped(void)
     CloseHandle(thread);
 }
 
-static void test_nowait(void)
+static void test_nowait(int pipemode)
 {
     HANDLE hnp;
     HANDLE hFile;
@@ -2572,7 +2572,7 @@ static void test_nowait(void)
     DWORD lpmode;
 
     hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
-                           PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
+                           pipemode | PIPE_NOWAIT,
                            /* nMaxInstances */ 1,
                            /* nOutBufSize */ 1024,
                            /* nInBufSize */ 1024,
@@ -2603,7 +2603,7 @@ static void test_nowait(void)
         ok(readden == 0, "got %d bytes\n", readden);
         ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
 
-        lpmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
+        lpmode = (pipemode & PIPE_READMODE_MESSAGE) | PIPE_NOWAIT;
         ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
 
         /* send message from server to client */
@@ -2627,8 +2627,18 @@ static void test_nowait(void)
         ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
         ok(written == 0, "write file len\n");
 
-        ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
-        ok(readden == 0, "got %d bytes\n", readden);
+        if (pipemode != PIPE_TYPE_BYTE)
+        {
+            ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
+            ok(readden == 0, "got %d bytes\n", readden);
+        }
+        else
+        {
+            SetLastError(0xdeadbeef);
+            ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
+            ok(readden == 0, "got %d bytes\n", readden);
+            ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
+        }
 
         readden = 0xdeadbeef;
         SetLastError(0xdeadbeef);
@@ -2640,8 +2650,18 @@ static void test_nowait(void)
         ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
         ok(written == 0, "write file len\n");
 
-        ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
-        ok(readden == 0, "got %d bytes\n", readden);
+        if (pipemode != PIPE_TYPE_BYTE)
+        {
+            ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
+            ok(readden == 0, "got %d bytes\n", readden);
+        }
+        else
+        {
+            SetLastError(0xdeadbeef);
+            ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
+            ok(readden == 0, "got %d bytes\n", readden);
+            ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
+        }
 
         readden = 0xdeadbeef;
         SetLastError(0xdeadbeef);
@@ -3079,7 +3099,8 @@ START_TEST(pipe)
     test_CloseHandle();
     test_impersonation();
     test_overlapped();
-    test_nowait();
+    test_nowait(PIPE_TYPE_BYTE);
+    test_nowait(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
     test_NamedPipeHandleState();
     test_readfileex_pending();
 }
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index ad08987..c9be586 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -570,6 +570,8 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
                 if (ret < 0) ERR("dequeue message failed reason: %s\n", strerror(errno));
             }
         }
+        else if (pipe_flags & NAMED_PIPE_NONBLOCKING_MODE)
+            result = recv( fd, buf + *total, length - *total, MSG_DONTWAIT );
         else
             result = read( fd, buf + *total, length - *total );
 
-- 
2.6.2

