kernel32-Named_Pipe: Remove patch set.

We have had complete message mode named pipe support for multiple years now, and PIPE_NOWAIT for a while too.
This commit is contained in:
Zebediah Figura 2020-05-02 10:09:40 -05:00
parent dcd4faf1c9
commit d4918b4305
22 changed files with 0 additions and 3477 deletions

View File

@ -1,76 +0,0 @@
From a483b0d4d6a16c07bcc7f65564974f5fc26c26d8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 9 Nov 2015 17:19:42 +0100
Subject: kernel32/tests: Only allow one test result.
This reverts commit 3b7cdc0b8475f4eac910c5260c96c381ddbb630e.
Instead of hiding errors, update the todo_wine flags accordingly.
---
dlls/kernel32/tests/pipe.c | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index ae09ef6..62ac77f 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -294,14 +294,11 @@ static void test_CreateNamedPipe(int pipemode)
ok(written == sizeof(obuf2), "write file len 3b\n");
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek3\n");
if (pipemode == PIPE_TYPE_BYTE) {
- /* currently the Wine behavior depends on the kernel version */
- /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden); */
- if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek3 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes\n", readden);
}
else
{
- /* ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden); */
- if (readden != sizeof(obuf)) todo_wine ok(0, "peek3 got %d bytes\n", readden);
+ todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
pbuf = ibuf;
@@ -325,14 +322,11 @@ static void test_CreateNamedPipe(int pipemode)
ok(written == sizeof(obuf2), "write file len 4b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek4\n");
if (pipemode == PIPE_TYPE_BYTE) {
- /* currently the Wine behavior depends on the kernel version */
- /* ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden); */
- if (readden != sizeof(obuf) + sizeof(obuf2)) todo_wine ok(0, "peek4 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes\n", readden);
}
else
{
- /* ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden); */
- if (readden != sizeof(obuf)) todo_wine ok(0, "peek4 got %d bytes\n", readden);
+ todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
pbuf = ibuf;
@@ -373,10 +367,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
- /* currently the Wine behavior depends on the kernel version */
- /* ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden); */
- if (readden != sizeof(obuf)) todo_wine ok(0, "peek5 got %d bytes\n", readden);
-
+ todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
@@ -408,10 +399,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
ok(written == sizeof(obuf2), "write file len 6b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
- /* currently the Wine behavior depends on the kernel version */
- /* ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden); */
- if (readden != sizeof(obuf)) todo_wine ok(0, "peek6 got %d bytes\n", readden);
-
+ todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
--
2.6.2

View File

@ -1,280 +0,0 @@
From 14bade0152141ee9ce78acd98b13d29abc450fea Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 31 Jul 2014 00:28:59 +0200
Subject: kernel32/tests: Add tests for PeekNamedPipe with partial received
messages.
This patch adds a couple more tests to ensure that PeekNamedPipe correctly
returns the number of remaining bytes which are part of the same message.
Moreover we have to be sure, that PeekNamedPipe also returns the same
information from all threads.
Changes in v2:
* Also add tests for reverse direction.
Changes in v3:
* Fix compiler warning on x86_64.
---
dlls/kernel32/tests/pipe.c | 142 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 140 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 7d89da5..13fdf60 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -46,7 +46,8 @@ static void CALLBACK user_apc(ULONG_PTR param)
enum rpcThreadOp
{
- RPC_READFILE
+ RPC_READFILE,
+ RPC_PEEKNAMEDPIPE
};
struct rpcThreadArgs
@@ -54,7 +55,7 @@ struct rpcThreadArgs
ULONG_PTR returnValue;
DWORD lastError;
enum rpcThreadOp op;
- ULONG_PTR args[5];
+ ULONG_PTR args[6];
};
static DWORD CALLBACK rpcThreadMain(LPVOID arg)
@@ -73,6 +74,15 @@ static DWORD CALLBACK rpcThreadMain(LPVOID arg)
(LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
break;
+ case RPC_PEEKNAMEDPIPE:
+ rpcargs->returnValue = (ULONG_PTR)PeekNamedPipe( (HANDLE)rpcargs->args[0], /* hPipe */
+ (LPVOID)rpcargs->args[1], /* lpvBuffer */
+ (DWORD)rpcargs->args[2], /* cbBuffer */
+ (LPDWORD)rpcargs->args[3], /* lpcbRead */
+ (LPDWORD)rpcargs->args[4], /* lpcbAvail */
+ (LPDWORD)rpcargs->args[5] ); /* lpcbMessage */
+ break;
+
default:
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
rpcargs->returnValue = 0;
@@ -117,6 +127,33 @@ static void _test_signaled(unsigned line, HANDLE handle)
ok_(__FILE__,line)(res == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", res);
}
+/* Runs PeekNamedPipe(...) from a different thread */
+static BOOL RpcPeekNamedPipe(HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
+ LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage)
+{
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_PEEKNAMEDPIPE;
+ rpcargs.args[0] = (ULONG_PTR)hPipe;
+ rpcargs.args[1] = (ULONG_PTR)lpvBuffer;
+ rpcargs.args[2] = (ULONG_PTR)cbBuffer;
+ rpcargs.args[3] = (ULONG_PTR)lpcbRead;
+ rpcargs.args[4] = (ULONG_PTR)lpcbAvail;
+ rpcargs.args[5] = (ULONG_PTR)lpcbMessage;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0,"WaitForSingleObject failed with %d.\n", GetLastError());
+ CloseHandle(thread);
+
+ SetLastError(rpcargs.lastError);
+ return (BOOL)rpcargs.returnValue;
+}
+
static void test_CreateNamedPipe(int pipemode)
{
HANDLE hnp;
@@ -126,6 +163,7 @@ static void test_CreateNamedPipe(int pipemode)
char ibuf[32], *pbuf;
DWORD written;
DWORD readden;
+ DWORD leftmsg;
DWORD avail;
DWORD lpmode;
BOOL ret;
@@ -241,9 +279,21 @@ static void test_CreateNamedPipe(int pipemode)
ok(written == sizeof(obuf2), "write file len\n");
ok(ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile\n");
ok(readden == 4, "read got %d bytes\n", readden);
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
+ ok(readden == sizeof(obuf2) - 4, "peek got %d bytes total\n", readden);
+ if (pipemode == PIPE_TYPE_BYTE)
+ ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
+ else
+ todo_wine
+ ok(leftmsg == sizeof(obuf2) - 4, "peek got %d bytes left in message\n", leftmsg);
ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
+ ok(readden == 0, "peek got %d bytes total\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
@@ -456,6 +506,16 @@ static void test_CreateNamedPipe(int pipemode)
ok(written == sizeof(obuf), "write file len 9\n");
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 9\n");
ok(written == sizeof(obuf2), "write file len 9\n");
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
todo_wine
ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
@@ -469,6 +529,16 @@ static void test_CreateNamedPipe(int pipemode)
todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
todo_wine
@@ -477,6 +547,14 @@ static void test_CreateNamedPipe(int pipemode)
if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
{
memset(ibuf, 0, sizeof(ibuf));
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 9\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 9\n");
@@ -489,11 +567,27 @@ static void test_CreateNamedPipe(int pipemode)
todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf2) - 8, "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 9\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
+ ok(readden == sizeof(obuf2) - 8, "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 9\n", readden);
ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 9\n");
}
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
+ ok(readden == 0, "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message 9\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
+ ok(readden == 0, "peek got %d bytes total 9\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message 9\n", leftmsg);
/* Now the reverse direction */
memset(ibuf, 0, sizeof(ibuf));
@@ -501,6 +595,16 @@ static void test_CreateNamedPipe(int pipemode)
ok(written == sizeof(obuf2), "write file len 10\n");
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 10\n");
ok(written == sizeof(obuf), "write file len 10\n");
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
todo_wine
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
@@ -514,6 +618,16 @@ static void test_CreateNamedPipe(int pipemode)
todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
+ todo_wine
+ ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
todo_wine
@@ -522,6 +636,14 @@ static void test_CreateNamedPipe(int pipemode)
if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
{
memset(ibuf, 0, sizeof(ibuf));
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 10\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 10\n");
@@ -534,11 +656,27 @@ static void test_CreateNamedPipe(int pipemode)
todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf) - 8, "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 10\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
+ ok(readden == sizeof(obuf) - 8, "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
ok(readden == sizeof(obuf) - 8, "read got %d bytes 10\n", readden);
ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 10\n");
}
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
+ ok(readden == 0, "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message 10\n", leftmsg);
+ readden = leftmsg = -1;
+ ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
+ ok(readden == 0, "peek got %d bytes total 10\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message 10\n", leftmsg);
}
--
2.9.0

View File

@ -1,168 +0,0 @@
From 695d78fbb48472fce38f103fba76f56c36a4cb5d Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 3 Aug 2014 23:14:35 +0200
Subject: kernel32/tests: Add tests for sending and receiving large messages.
This set of tests seems to confirm that on Windows, there is no upper size
limit where messages are splitted. The kernel seems to temporarily allocate
additional buffers (or use existing buffers very efficient), so WriteFile()
can never fail because of size limitations.
Changes in v2:
* Avoid compilation warning on x86_64.
---
dlls/kernel32/tests/pipe.c | 124 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 124 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index a252bc8..246ee30 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -47,6 +47,7 @@ static void CALLBACK user_apc(ULONG_PTR param)
enum rpcThreadOp
{
RPC_READFILE,
+ RPC_WRITEFILE,
RPC_PEEKNAMEDPIPE
};
@@ -74,6 +75,14 @@ static DWORD CALLBACK rpcThreadMain(LPVOID arg)
(LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
break;
+ case RPC_WRITEFILE:
+ rpcargs->returnValue = (ULONG_PTR)WriteFile( (HANDLE)rpcargs->args[0], /* hFile */
+ (LPCVOID)rpcargs->args[1], /* buffer */
+ (DWORD)rpcargs->args[2], /* bytesToWrite */
+ (LPDWORD)rpcargs->args[3], /* bytesWritten */
+ (LPOVERLAPPED)rpcargs->args[4] ); /* overlapped */
+ break;
+
case RPC_PEEKNAMEDPIPE:
rpcargs->returnValue = (ULONG_PTR)PeekNamedPipe( (HANDLE)rpcargs->args[0], /* hPipe */
(LPVOID)rpcargs->args[1], /* lpvBuffer */
@@ -671,6 +680,121 @@ static void test_CreateNamedPipe(int pipemode)
}
+ /* Test behaviour for very huge messages (which don't fit completely in the buffer) */
+ {
+ static char big_obuf[512 * 1024];
+ static char big_ibuf[512 * 1024];
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+ memset(big_obuf, 0xAA, sizeof(big_obuf));
+
+ /* Ensure that both pipes are empty before we continue with the next test */
+ while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
+ ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
+ GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
+
+ while (PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL) && readden > 0)
+ ok(ReadFile(hnp, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
+ GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
+
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
+ ok(readden == 0, "peek got %d bytes total\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
+
+ /* transmit big message, receive with buffer of equal size */
+ memset(big_ibuf, 0, sizeof(big_ibuf));
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_WRITEFILE;
+ rpcargs.args[0] = (ULONG_PTR)hnp;
+ rpcargs.args[1] = (ULONG_PTR)big_obuf;
+ rpcargs.args[2] = (ULONG_PTR)sizeof(big_obuf);
+ rpcargs.args[3] = (ULONG_PTR)&written;
+ rpcargs.args[4] = (ULONG_PTR)NULL;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_TIMEOUT);
+ ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(readden == sizeof(big_obuf), "read got %d bytes\n", readden);
+ todo_wine
+ ok(memcmp(big_ibuf, big_obuf, sizeof(big_obuf)) == 0, "content check\n");
+ do
+ {
+ ret = WaitForSingleObject(thread, 1);
+ while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
+ ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
+ GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
+ }
+ while (ret == WAIT_TIMEOUT);
+ ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
+ ok((BOOL)rpcargs.returnValue, "WriteFile\n");
+ ok(written == sizeof(big_obuf), "write file len\n");
+ CloseHandle(thread);
+
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
+ ok(readden == 0, "peek got %d bytes total\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
+
+ /* same as above, but receive as multiple parts */
+ memset(big_ibuf, 0, sizeof(big_ibuf));
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_TIMEOUT);
+ if (pipemode == PIPE_TYPE_BYTE)
+ {
+ ok(ReadFile(hFile, big_ibuf, 32, &readden, NULL), "ReadFile\n");
+ ok(readden == 32, "read got %d bytes\n", readden);
+ ok(ReadFile(hFile, big_ibuf + 32, 32, &readden, NULL), "ReadFile\n");
+ }
+ else
+ {
+ SetLastError(0xdeadbeef);
+ todo_wine
+ ok(!ReadFile(hFile, big_ibuf, 32, &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
+ ok(readden == 32, "read got %d bytes\n", readden);
+ SetLastError(0xdeadbeef);
+ todo_wine
+ ok(!ReadFile(hFile, big_ibuf + 32, 32, &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
+ }
+ ok(readden == 32, "read got %d bytes\n", readden);
+ ok(ReadFile(hFile, big_ibuf + 64, sizeof(big_ibuf) - 64, &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(readden == sizeof(big_obuf) - 64, "read got %d bytes\n", readden);
+ todo_wine
+ ok(memcmp(big_ibuf, big_obuf, sizeof(big_obuf)) == 0, "content check\n");
+ do
+ {
+ ret = WaitForSingleObject(thread, 1);
+ while (PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL) && readden > 0)
+ ok(ReadFile(hFile, big_ibuf, sizeof(big_ibuf), &readden, NULL) ||
+ GetLastError() == ERROR_MORE_DATA, "ReadFile\n");
+ }
+ while (ret == WAIT_TIMEOUT);
+ ok(WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed with %d.\n", GetLastError());
+ ok((BOOL)rpcargs.returnValue, "WriteFile\n");
+ ok(written == sizeof(big_obuf), "write file len\n");
+ CloseHandle(thread);
+
+ readden = leftmsg = -1;
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe\n");
+ ok(readden == 0, "peek got %d bytes total\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
+ }
+
/* Picky conformance tests */
/* Verify that you can't connect to pipe again
--
2.1.3

View File

@ -1,89 +0,0 @@
From 630edc66479db789c7541e2c356a41090524d838 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 4 Aug 2014 00:29:26 +0200
Subject: server: Show warning if message mode is not supported.
This patch changes the create_named_pipe wineserver call to return
which flags were supported. This allows to show a FIXME in ntdll for
missing message mode support.
---
dlls/ntdll/file.c | 14 ++++++++++----
server/named_pipe.c | 2 ++
server/protocol.def | 1 +
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 3883e5a..9e98f36 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -3507,6 +3507,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
NTSTATUS status;
data_size_t len;
struct object_attributes *objattr;
+ unsigned int flags;
TRACE("(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
handle, access, debugstr_w(attr->ObjectName->Buffer), iosb, sharing, dispo,
@@ -3521,15 +3522,16 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
if ((status = alloc_object_attributes( attr, &objattr, &len ))) return status;
+ flags = (pipe_type ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0) |
+ (read_mode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0) |
+ (completion_mode ? NAMED_PIPE_NONBLOCKING_MODE : 0);
+
SERVER_START_REQ( create_named_pipe )
{
req->access = access;
req->options = options;
req->sharing = sharing;
- req->flags =
- (pipe_type ? NAMED_PIPE_MESSAGE_STREAM_WRITE : 0) |
- (read_mode ? NAMED_PIPE_MESSAGE_STREAM_READ : 0) |
- (completion_mode ? NAMED_PIPE_NONBLOCKING_MODE : 0);
+ req->flags = flags;
req->maxinstances = max_inst;
req->outsize = outbound_quota;
req->insize = inbound_quota;
@@ -3537,9 +3539,13 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
wine_server_add_data( req, objattr, len );
status = wine_server_call( req );
if (!status) *handle = wine_server_ptr_handle( reply->handle );
+ flags &= ~reply->flags; /* contains now all unsupported flags */
}
SERVER_END_REQ;
+ if (!status && (flags & (NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ)))
+ FIXME("Message mode not supported, falling back to byte mode.\n");
+
RtlFreeHeap( GetProcessHeap(), 0, objattr );
return status;
}
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 7a97e35..ee6008c 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -934,6 +934,8 @@ DECL_HANDLER(create_named_pipe)
return;
}
+ reply->flags = req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
+
if (!name.len) /* pipes need a root directory even without a name */
{
if (!objattr->rootdir)
diff --git a/server/protocol.def b/server/protocol.def
index a5a45eb..2d87f03 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2370,6 +2370,7 @@ enum message_type
unsigned int flags;
VARARG(objattr,object_attributes); /* object attributes */
@REPLY
+ unsigned int flags;
obj_handle_t handle; /* handle to the pipe */
@END
--
2.7.0

View File

@ -1,171 +0,0 @@
From db2c7e03ab42dc8e97a02e8531948c86840b207a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 15 Aug 2014 22:23:08 +0200
Subject: ntdll: Unify similar code in NtReadFile and FILE_AsyncReadService.
Please note that besides merging the functions (which makes the code much
more readable) this also fixes some inconsistencies. Basically the code
from a unix fd should do the same in both cases, but it didn't...
Changes in FILE_AsyncReadService:
* Immediately retry on EINTR, chances are very good that it will
succeed in a second attempt, and its not worth to use different code
because of this small difference.
* When read(...) == 0 the result code was always STATUS_PIPE_BROKEN,
whereas NtReadFile uses different behaviour based on the fd type.
Now both implementations match, and behave the same way.
---
dlls/ntdll/file.c | 107 +++++++++++++++++++++++-------------------------------
1 file changed, 46 insertions(+), 61 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 1c23f9e..5dab5c9 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -484,6 +484,45 @@ NTSTATUS FILE_GetNtStatus(void)
}
}
+/* helper function for NtReadFile and FILE_AsyncReadService */
+static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
+ enum server_fd_type type, BOOL avail_mode)
+{
+ int result;
+ for(;;)
+ {
+ result = read( fd, buf + *total, length - *total );
+ if (result >= 0)
+ {
+ *total += result;
+ if (!result || *total >= length || avail_mode)
+ {
+ if (*total)
+ return STATUS_SUCCESS;
+ switch (type)
+ {
+ case FD_TYPE_FILE:
+ case FD_TYPE_CHAR:
+ case FD_TYPE_DEVICE:
+ return length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
+ case FD_TYPE_SERIAL:
+ return length ? STATUS_PENDING : STATUS_SUCCESS;
+ default:
+ return STATUS_PIPE_BROKEN;
+ }
+ }
+ else if (type != FD_TYPE_FILE) /* no async I/O on regular files */
+ return STATUS_PENDING;
+ }
+ else if (errno != EINTR)
+ {
+ if (errno == EAGAIN) break;
+ return FILE_GetNtStatus();
+ }
+ }
+ return STATUS_PENDING;
+}
+
/***********************************************************************
* FILE_AsyncReadService (INTERNAL)
*/
@@ -491,38 +530,19 @@ static NTSTATUS FILE_AsyncReadService( void *user, IO_STATUS_BLOCK *iosb,
NTSTATUS status, void **apc, void **arg )
{
struct async_fileio_read *fileio = user;
- int fd, needs_close, result;
+ int fd, needs_close;
+ enum server_fd_type type;
switch (status)
{
case STATUS_ALERTED: /* got some new data */
/* check to see if the data is ready (non-blocking) */
if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd,
- &needs_close, NULL, NULL )))
+ &needs_close, &type, NULL )))
break;
-
- result = read(fd, &fileio->buffer[fileio->already], fileio->count - fileio->already);
+ status = read_unix_fd( fd, fileio->buffer, &fileio->already, fileio->count,
+ type, fileio->avail_mode );
if (needs_close) close( fd );
-
- if (result < 0)
- {
- if (errno == EAGAIN || errno == EINTR)
- status = STATUS_PENDING;
- else /* check to see if the transfer is complete */
- status = FILE_GetNtStatus();
- }
- else if (result == 0)
- {
- status = fileio->already ? STATUS_SUCCESS : STATUS_PIPE_BROKEN;
- }
- else
- {
- fileio->already += result;
- if (fileio->already >= fileio->count || fileio->avail_mode)
- status = STATUS_SUCCESS;
- else
- status = STATUS_PENDING;
- }
break;
case STATUS_TIMEOUT:
@@ -769,7 +789,6 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL
return status;
}
-
/******************************************************************************
* NtReadFile [NTDLL.@]
* ZwReadFile [NTDLL.@]
@@ -865,43 +884,9 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
for (;;)
{
- if ((result = read( unix_handle, (char *)buffer + total, length - total )) >= 0)
- {
- total += result;
- if (!result || total == length)
- {
- if (total)
- {
- status = STATUS_SUCCESS;
- goto done;
- }
- switch (type)
- {
- case FD_TYPE_FILE:
- case FD_TYPE_CHAR:
- case FD_TYPE_DEVICE:
- status = length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
- goto done;
- case FD_TYPE_SERIAL:
- if (!length)
- {
- status = STATUS_SUCCESS;
- goto done;
- }
- break;
- default:
- status = STATUS_PIPE_BROKEN;
- goto done;
- }
- }
- else if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
- }
- else if (errno != EAGAIN)
- {
- if (errno == EINTR) continue;
- if (!total) status = FILE_GetNtStatus();
+ status = read_unix_fd( unix_handle, buffer, &total, length, type, FALSE );
+ if (status != STATUS_PENDING)
goto done;
- }
if (async_read)
{
--
2.7.1

View File

@ -1,107 +0,0 @@
From a469c846c5e2abc7a0a4c478b33aeaa83e53f6bb Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 15 Aug 2014 23:06:06 +0200
Subject: ntdll: Move logic to check for broken pipe into a separate function.
---
dlls/ntdll/file.c | 75 +++++++++++++++++++++++++++++--------------------------
1 file changed, 39 insertions(+), 36 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 41dd1ae877..03864b7239 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -490,6 +490,31 @@ NTSTATUS FILE_GetNtStatus(void)
}
}
+/* helper function for FSCTL_PIPE_PEEK */
+static NTSTATUS unix_fd_avail(int fd, int *avail)
+{
+ struct pollfd pollfd;
+ int ret;
+ *avail = 0;
+
+#ifdef FIONREAD
+ if (ioctl( fd, FIONREAD, avail ) != 0)
+ {
+ TRACE("FIONREAD failed reason: %s\n", strerror(errno));
+ return FILE_GetNtStatus();
+ }
+ if (*avail)
+ return STATUS_SUCCESS;
+#endif
+
+ pollfd.fd = fd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ ret = poll( &pollfd, 1, 0 );
+ return (ret == -1 || (ret == 1 && (pollfd.revents & (POLLHUP|POLLERR)))) ?
+ STATUS_PIPE_BROKEN : STATUS_SUCCESS;
+}
+
/* helper function for NtReadFile and FILE_AsyncReadService */
static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
enum server_fd_type type, BOOL avail_mode)
@@ -1719,44 +1744,22 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
break;
}
-#ifdef FIONREAD
- if (ioctl( fd, FIONREAD, &avail ) != 0)
- {
- TRACE("FIONREAD failed reason: %s\n",strerror(errno));
- if (needs_close) close( fd );
- status = FILE_GetNtStatus();
- break;
- }
-#endif
- if (!avail) /* check for closed pipe */
- {
- struct pollfd pollfd;
- int ret;
-
- pollfd.fd = fd;
- pollfd.events = POLLIN;
- pollfd.revents = 0;
- ret = poll( &pollfd, 1, 0 );
- if (ret == -1 || (ret == 1 && (pollfd.revents & (POLLHUP|POLLERR))))
- {
- if (needs_close) close( fd );
- status = STATUS_PIPE_BROKEN;
- break;
- }
- }
- buffer->NamedPipeState = 0; /* FIXME */
- buffer->ReadDataAvailable = avail;
- buffer->NumberOfMessages = 0; /* FIXME */
- buffer->MessageLength = 0; /* FIXME */
- io->Information = FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
- status = STATUS_SUCCESS;
- if (avail)
+ status = unix_fd_avail( fd, &avail );
+ if (!status)
{
- ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
- if (data_size)
+ buffer->NamedPipeState = 0; /* FIXME */
+ buffer->ReadDataAvailable = avail;
+ buffer->NumberOfMessages = 0; /* FIXME */
+ buffer->MessageLength = 0; /* FIXME */
+ io->Information = FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
+ if (avail)
{
- int res = recv( fd, buffer->Data, data_size, MSG_PEEK );
- if (res >= 0) io->Information += res;
+ ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
+ if (data_size)
+ {
+ int res = recv( fd, buffer->Data, data_size, MSG_PEEK );
+ if (res >= 0) io->Information += res;
+ }
}
}
if (needs_close) close( fd );
--
2.11.0

View File

@ -1,130 +0,0 @@
From 27b2dcf526597a12cfebcbc6bb53d45185b6f65f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 18 Aug 2014 01:48:17 +0200
Subject: ntdll: Unify similar code in NtWriteFile and FILE_AsyncWriteService.
Changes in FILE_AsyncWriteService:
* Immediately retry on EINTR, chances are very good that it will
succeed in a second attempt, and its not worth to use different code
because of this small difference.
* Why is it STATUS_SUCCESS when we have a partial sync write, but
an error for async? Lets assume its always success...
---
dlls/ntdll/file.c | 78 +++++++++++++++++++++++++------------------------------
1 file changed, 35 insertions(+), 43 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 54f31d6..f6679b1 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -953,6 +953,37 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
return status;
}
+/* helper function for NtWriteFile and FILE_AsyncWriteService */
+static NTSTATUS write_unix_fd(int fd, const char *buf, ULONG *total, ULONG length, enum server_fd_type type)
+{
+ int result;
+ for(;;)
+ {
+ if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
+ result = send( fd, buf, 0, 0 );
+ else
+ result = write( fd, buf + *total, length - *total );
+ if (result >= 0)
+ {
+ *total += result;
+ if (*total >= length)
+ return STATUS_SUCCESS;
+ else if (type != FD_TYPE_FILE) /* no async I/O on regular files */
+ return STATUS_PENDING;
+ }
+ else if (errno != EINTR)
+ {
+ if (errno == EAGAIN)
+ break;
+ else if (*total)
+ return STATUS_SUCCESS;
+ else if (errno == EFAULT)
+ return STATUS_INVALID_USER_BUFFER;
+ return FILE_GetNtStatus();
+ }
+ }
+ return STATUS_PENDING;
+}
/***********************************************************************
* FILE_AsyncWriteService (INTERNAL)
@@ -961,7 +992,7 @@ static NTSTATUS FILE_AsyncWriteService( void *user, IO_STATUS_BLOCK *iosb,
NTSTATUS status, void **apc, void **arg )
{
struct async_fileio_write *fileio = user;
- int result, fd, needs_close;
+ int fd, needs_close;
enum server_fd_type type;
switch (status)
@@ -971,24 +1002,8 @@ static NTSTATUS FILE_AsyncWriteService( void *user, IO_STATUS_BLOCK *iosb,
if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd,
&needs_close, &type, NULL )))
break;
-
- if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
- result = send( fd, fileio->buffer, 0, 0 );
- else
- result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already );
-
+ status = write_unix_fd( fd, fileio->buffer, &fileio->already, fileio->count, type );
if (needs_close) close( fd );
-
- if (result < 0)
- {
- if (errno == EAGAIN || errno == EINTR) status = STATUS_PENDING;
- else status = FILE_GetNtStatus();
- }
- else
- {
- fileio->already += result;
- status = (fileio->already < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS;
- }
break;
case STATUS_TIMEOUT:
@@ -1150,32 +1165,9 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
for (;;)
{
- /* zero-length writes on sockets may not work with plain write(2) */
- if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
- result = send( unix_handle, buffer, 0, 0 );
- else
- result = write( unix_handle, (const char *)buffer + total, length - total );
-
- if (result >= 0)
- {
- total += result;
- if (total == length)
- {
- status = STATUS_SUCCESS;
- goto done;
- }
- if (type == FD_TYPE_FILE) continue; /* no async I/O on regular files */
- }
- else if (errno != EAGAIN)
- {
- if (errno == EINTR) continue;
- if (!total)
- {
- if (errno == EFAULT) status = STATUS_INVALID_USER_BUFFER;
- else status = FILE_GetNtStatus();
- }
+ status = write_unix_fd( unix_handle, buffer, &total, length, type );
+ if (status != STATUS_PENDING)
goto done;
- }
if (async_write)
{
--
2.3.0

View File

@ -1,582 +0,0 @@
From 104443cbb9a1087ec753af2462ccf41ba26eb444 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 4 Aug 2014 05:01:11 +0200
Subject: server: Use SOCK_SEQPACKET socket in combination with SO_PEEK_OFF to
implement message mode on Unix. (rev 6)
Based on ideas by Erich E. Hoover.
Similar to Windows, when a pipe has been created with message mode flags, then all
sending operations always behave in "message mode". Currently the read mode isn't
handled yet, and the default is byte mode, to stay backwards compatible.
Changes in v2:
* Show FIXME when message is too big and was splitted
* Simplify logic for FSCTL_PIPE_PEEK
Changes in v3:
* Avoid changes in later patches, directly store pipe mode in signal attributes.
Changes in v4:
* Moved changes into read_unix_fd function to make them available for async reads.
Changes in v5:
* Rebased, merged with following patch.
Changes in v6:
* When running on an older kernel make sure that ntdll doesn't try to use message mode features.
---
dlls/kernel32/sync.c | 2 +-
dlls/kernel32/tests/pipe.c | 17 ++------
dlls/ntdll/file.c | 106 ++++++++++++++++++++++++++++++++++++++-------
server/named_pipe.c | 103 ++++++++++++++++++++++++++++++++++++-------
server/sock.c | 4 +-
server/sock.h | 26 +++++++++++
6 files changed, 212 insertions(+), 46 deletions(-)
create mode 100644 server/sock.h
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index 494db9c1a3..38aaccfa55 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -1475,7 +1475,7 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
ULONG read_size = io.Information - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
if (lpcbAvail) *lpcbAvail = buffer->ReadDataAvailable;
if (lpcbRead) *lpcbRead = read_size;
- if (lpcbMessage) *lpcbMessage = 0; /* FIXME */
+ if (lpcbMessage) *lpcbMessage = buffer->MessageLength;
if (lpvBuffer) memcpy( lpvBuffer, buffer->Data, read_size );
}
else SetLastError( RtlNtStatusToDosError(status) );
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index e7cfce4c00..71d75be90e 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -294,7 +294,6 @@ static void test_CreateNamedPipe(int pipemode)
if (pipemode == PIPE_TYPE_BYTE)
ok(leftmsg == 0, "peek got %d bytes left in message\n", leftmsg);
else
- todo_wine
ok(leftmsg == sizeof(obuf2) - 4, "peek got %d bytes left in message\n", leftmsg);
ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2) - 4, "read got %d bytes\n", readden);
@@ -365,7 +364,7 @@ static void test_CreateNamedPipe(int pipemode)
}
else
{
- todo_wine ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf), "peek3 got %d bytes\n", readden);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek3 got %d bytes available\n", avail);
pbuf = ibuf;
@@ -393,7 +392,7 @@ static void test_CreateNamedPipe(int pipemode)
}
else
{
- todo_wine ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf), "peek4 got %d bytes\n", readden);
}
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek4 got %d bytes available\n", avail);
pbuf = ibuf;
@@ -434,7 +433,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), " WriteFile5b\n");
ok(written == sizeof(obuf2), "write file len 3b\n");
ok(PeekNamedPipe(hFile, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek5\n");
- todo_wine ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf), "peek5 got %d bytes\n", readden);
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek5 got %d bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
@@ -466,7 +465,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), " WriteFile6b\n");
ok(written == sizeof(obuf2), "write file len 6b\n");
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6\n");
- todo_wine ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
+ ok(readden == sizeof(obuf), "peek6 got %d bytes\n", readden);
ok(avail == sizeof(obuf) + sizeof(obuf2), "peek6b got %d bytes available\n", avail);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
@@ -518,12 +517,10 @@ static void test_CreateNamedPipe(int pipemode)
readden = leftmsg = -1;
ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
readden = leftmsg = -1;
ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
todo_wine
@@ -541,12 +538,10 @@ static void test_CreateNamedPipe(int pipemode)
readden = leftmsg = -1;
ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 9\n");
ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
readden = leftmsg = -1;
ok(RpcPeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 9\n");
ok(readden == sizeof(obuf) - 8 + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
@@ -607,12 +602,10 @@ static void test_CreateNamedPipe(int pipemode)
readden = leftmsg = -1;
ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
readden = leftmsg = -1;
ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
todo_wine
@@ -630,12 +623,10 @@ static void test_CreateNamedPipe(int pipemode)
readden = leftmsg = -1;
ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "PeekNamedPipe 10\n");
ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
readden = leftmsg = -1;
ok(RpcPeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "RpcPeekNamedPipe 10\n");
ok(readden == sizeof(obuf2) - 8 + sizeof(obuf), "peek got %d bytes total 10\n", readden);
- todo_wine
ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 41d44c9af4..1b0eff02f2 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -96,6 +96,10 @@
# include <valgrind/memcheck.h>
#endif
+#ifndef SO_PEEK_OFF
+#define SO_PEEK_OFF 42
+#endif
+
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define NONAMELESSUNION
@@ -515,18 +519,57 @@ static NTSTATUS unix_fd_avail(int fd, int *avail)
STATUS_PIPE_BROKEN : STATUS_SUCCESS;
}
+/* returns the pipe flags for a file descriptor */
+static inline int get_pipe_flags(int fd)
+{
+#ifdef __linux__
+ return fcntl( fd, F_GETSIG );
+#else
+ return 0;
+#endif
+}
+
/* helper function for NtReadFile and FILE_AsyncReadService */
static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
enum server_fd_type type, BOOL avail_mode)
{
- int result;
+ struct msghdr msg;
+ struct iovec iov;
+ int pipe_flags = 0, result;
+
+ if (type == FD_TYPE_PIPE)
+ pipe_flags = get_pipe_flags( fd );
+
for(;;)
{
- result = read( fd, buf + *total, length - *total );
+ if (pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
+ {
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ msg.msg_flags = 0;
+
+ iov.iov_base = buf + *total;
+ iov.iov_len = length - *total;
+
+ result = recvmsg( fd, &msg, MSG_PEEK | (*total ? MSG_DONTWAIT : 0) );
+ if (result >= 0 && !(msg.msg_flags & MSG_TRUNC))
+ {
+ int ret;
+ while (!(ret = recv( fd, NULL, 0, MSG_TRUNC)) && result > 0);
+ if (ret < 0) ERR("dequeue message failed reason: %s\n", strerror(errno));
+ }
+ }
+ else
+ result = read( fd, buf + *total, length - *total );
+
if (result >= 0)
{
*total += result;
- if (!result || *total >= length || avail_mode)
+ if (!result || *total >= length || (avail_mode && !(pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)))
{
if (*total)
return STATUS_SUCCESS;
@@ -542,16 +585,17 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
return STATUS_PIPE_BROKEN;
}
}
+ else if (pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
+ continue;
else if (type != FD_TYPE_FILE) /* no async I/O on regular files */
return STATUS_PENDING;
}
+ else if (errno == EAGAIN)
+ return (avail_mode && *total) ? STATUS_SUCCESS : STATUS_PENDING;
else if (errno != EINTR)
- {
- if (errno == EAGAIN) break;
return FILE_GetNtStatus();
- }
}
- return STATUS_PENDING;
+ return STATUS_UNSUCCESSFUL; /* never reached */
}
/***********************************************************************
@@ -1127,13 +1171,14 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
/* helper function for NtWriteFile and FILE_AsyncWriteService */
static NTSTATUS write_unix_fd(int fd, const char *buf, ULONG *total, ULONG length, enum server_fd_type type)
{
+ ULONG msgsize = (ULONG)-1;
int result;
for(;;)
{
if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_PIPE || type == FD_TYPE_SOCKET))
result = send( fd, buf, 0, 0 );
else
- result = write( fd, buf + *total, length - *total );
+ result = write( fd, buf + *total, min(length - *total, msgsize) );
if (result >= 0)
{
*total += result;
@@ -1142,6 +1187,17 @@ static NTSTATUS write_unix_fd(int fd, const char *buf, ULONG *total, ULONG lengt
else if (type != FD_TYPE_FILE) /* no async I/O on regular files */
return STATUS_PENDING;
}
+ else if (errno == EMSGSIZE && type == FD_TYPE_PIPE && msgsize > 4096)
+ {
+ static ULONG warn_msgsize;
+ if (msgsize == (ULONG)-1) msgsize = (length + 32 + 4095) & ~4095;
+ if (msgsize > warn_msgsize)
+ {
+ FIXME("Message is too big, try to increase /proc/sys/net/core/wmem_default to at least %d\n", msgsize);
+ warn_msgsize = msgsize;
+ }
+ msgsize -= 4096; /* FIXME: use more intelligent algorithm to discover msgsize */
+ }
else if (errno != EINTR)
{
if (errno == EAGAIN)
@@ -1734,20 +1790,40 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
status = unix_fd_avail( fd, &avail );
if (!status)
{
+ ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
+ int pipe_flags = get_pipe_flags( fd );
+
buffer->NamedPipeState = 0; /* FIXME */
buffer->ReadDataAvailable = avail;
- buffer->NumberOfMessages = 0; /* FIXME */
- buffer->MessageLength = 0; /* FIXME */
+ buffer->NumberOfMessages = 0;
+ buffer->MessageLength = 0;
io->Information = FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
- if (avail)
+
+ if (pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
{
- ULONG data_size = out_size - FIELD_OFFSET( FILE_PIPE_PEEK_BUFFER, Data );
- if (data_size)
+ int peek_offset;
+ socklen_t sock_opt_len = sizeof(peek_offset);
+ if (getsockopt( fd, SOL_SOCKET, SO_PEEK_OFF, &peek_offset, &sock_opt_len ))
+ ERR("getsockopt(SO_PEEK_OFF) failed reason: %s\n", strerror(errno));
+ else
{
- int res = recv( fd, buffer->Data, data_size, MSG_PEEK );
- if (res >= 0) io->Information += res;
+ char *data = data_size ? buffer->Data : NULL;
+ int res = recv( fd, data, data_size, MSG_PEEK | MSG_TRUNC | MSG_DONTWAIT );
+ if (res >= 0) io->Information += min(res, data_size);
+
+ if (setsockopt( fd, SOL_SOCKET, SO_PEEK_OFF, &peek_offset, sizeof(peek_offset) ))
+ ERR("setsockopt(SO_PEEK_OFF) failed reason: %s\n", strerror(errno));
+
+ buffer->ReadDataAvailable = avail - peek_offset;
+ buffer->NumberOfMessages = avail > peek_offset; /* FIXME */
+ buffer->MessageLength = max(0, res);
}
}
+ else if (avail && data_size)
+ {
+ int res = recv( fd, buffer->Data, data_size, MSG_PEEK | MSG_DONTWAIT );
+ if (res >= 0) io->Information += res;
+ }
}
if (needs_close) close( fd );
}
diff --git a/server/named_pipe.c b/server/named_pipe.c
index b215816650..74a9a44dcf 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -42,6 +42,10 @@
#include <poll.h>
#endif
+#ifndef SO_PEEK_OFF
+#define SO_PEEK_OFF 42
+#endif
+
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
@@ -49,6 +53,7 @@
#include "winioctl.h"
#include "file.h"
+#include "sock.h"
#include "handle.h"
#include "thread.h"
#include "request.h"
@@ -804,14 +809,43 @@ static int named_pipe_link_name( struct object *obj, struct object_name *name, s
return 1;
}
+/* check if message mode named pipes are supported */
+static int is_messagemode_supported(void)
+{
+#ifdef __linux__
+ static const int zero = 0;
+ static int messagemode = -1;
+ int fd;
+
+ if (messagemode < 0)
+ {
+ fd = socket( PF_UNIX, SOCK_SEQPACKET, 0 );
+ messagemode = (fd != -1) && (setsockopt( fd, SOL_SOCKET, SO_PEEK_OFF, &zero, sizeof(zero) ) != -1);
+ if (fd != -1) close( fd );
+ }
+
+ return messagemode;
+#else
+ return 0;
+#endif
+}
+
+static inline int messagemode_flags( int flags )
+{
+ if (!is_messagemode_supported())
+ flags &= ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
+ return flags;
+}
+
static struct object *named_pipe_open_file( struct object *obj, unsigned int access,
unsigned int sharing, unsigned int options )
{
+ static const int zero = 0;
struct named_pipe *pipe = (struct named_pipe *)obj;
struct pipe_server *server;
struct pipe_client *client;
unsigned int pipe_sharing;
- int fds[2];
+ int fds[2], type;
if (!(server = find_available_server( pipe )))
{
@@ -830,6 +864,9 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
if ((client = create_pipe_client( options, pipe->flags, pipe->outsize )))
{
+ type = ((pipe->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE) && is_messagemode_supported()) ?
+ SOCK_SEQPACKET : SOCK_STREAM;
+
if (use_server_io( &server->pipe_end ))
{
client->pipe_end.fd = alloc_pseudo_fd( &pipe_client_fd_ops, &client->pipe_end.obj, options );
@@ -845,7 +882,7 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
client = NULL;
}
}
- else if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
+ else if (!socketpair( PF_UNIX, type, 0, fds ))
{
assert( !server->pipe_end.fd );
@@ -855,25 +892,48 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
if (is_overlapped( options )) fcntl( fds[1], F_SETFL, O_NONBLOCK );
if (is_overlapped( server->options )) fcntl( fds[0], F_SETFL, O_NONBLOCK );
- if (pipe->insize)
+ /* FIXME: For message mode we don't pay attention to the provided buffer size.
+ * Linux pipes cannot dynamically adjust size, so we leave the size to the system
+ * instead of using the application provided value. Please note that this will
+ * have the effect that the application doesn't block when sending very large
+ * messages. */
+ if (type != SOCK_SEQPACKET)
{
- setsockopt( fds[0], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
- setsockopt( fds[1], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
- }
- if (pipe->outsize)
- {
- setsockopt( fds[0], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
- setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
+ if (pipe->insize)
+ {
+ setsockopt( fds[0], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
+ setsockopt( fds[1], SOL_SOCKET, SO_RCVBUF, &pipe->insize, sizeof(pipe->insize) );
+ }
+ if (pipe->outsize)
+ {
+ setsockopt( fds[0], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
+ setsockopt( fds[1], SOL_SOCKET, SO_SNDBUF, &pipe->outsize, sizeof(pipe->outsize) );
+ }
}
- client->pipe_end.fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->pipe_end.obj, options );
- server->pipe_end.fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->pipe_end.obj, server->options );
- if (client->pipe_end.fd && server->pipe_end.fd)
+ if (type != SOCK_SEQPACKET || (setsockopt( fds[0], SOL_SOCKET, SO_PEEK_OFF, &zero, sizeof(zero) ) != -1 &&
+ setsockopt( fds[1], SOL_SOCKET, SO_PEEK_OFF, &zero, sizeof(zero) ) != -1))
{
- fd_copy_completion( server->ioctl_fd, server->pipe_end.fd );
+ #ifdef __linux__
+ fcntl( fds[0], F_SETSIG, messagemode_flags( server->pipe_end.flags ) );
+ fcntl( fds[1], F_SETSIG, messagemode_flags( client->pipe_end.flags ) );
+ #endif
+
+ client->pipe_end.fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->pipe_end.obj, options );
+ server->pipe_end.fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->pipe_end.obj, server->options );
+ if (client->pipe_end.fd && server->pipe_end.fd)
+ {
+ fd_copy_completion( server->ioctl_fd, server->pipe_end.fd );
+ }
+ else
+ {
+ release_object( client );
+ client = NULL;
+ }
}
else
{
+ sock_set_error();
release_object( client );
client = NULL;
}
@@ -970,7 +1030,7 @@ DECL_HANDLER(create_named_pipe)
return;
}
- reply->flags = req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
+ reply->flags = messagemode_flags(req->flags);
if (!name.len) /* pipes need a root directory even without a name */
{
@@ -1073,6 +1133,9 @@ DECL_HANDLER(set_named_pipe_info)
{
struct pipe_server *server;
struct pipe_client *client = NULL;
+#ifdef __linux__
+ int unix_fd;
+#endif
server = get_pipe_server_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES );
if (!server)
@@ -1099,10 +1162,20 @@ DECL_HANDLER(set_named_pipe_info)
else if (client)
{
client->pipe_end.flags = server->pipe->flags | req->flags;
+ #ifdef __linux__
+ if (client->pipe_end.fd && (unix_fd = get_unix_fd( client->pipe_end.fd )) != -1)
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( client->pipe_end.flags ) );
+ clear_error();
+ #endif
}
else
{
server->pipe_end.flags = server->pipe->flags | req->flags;
+ #ifdef __linux__
+ if (server->pipe_end.fd && (unix_fd = get_unix_fd( server->pipe_end.fd )) != -1)
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( server->pipe_end.flags ) );
+ clear_error();
+ #endif
}
if (client)
diff --git a/server/sock.c b/server/sock.c
index d6b4fb2fa5..49b6d3d575 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -61,6 +61,7 @@
#include "process.h"
#include "file.h"
+#include "sock.h"
#include "handle.h"
#include "thread.h"
#include "request.h"
@@ -135,7 +136,6 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
static int sock_get_ntstatus( int err );
static int sock_get_error( int err );
-static void sock_set_error(void);
static const struct object_ops sock_ops =
{
@@ -941,7 +941,7 @@ static int sock_get_ntstatus( int err )
}
/* set the last error depending on errno */
-static void sock_set_error(void)
+void sock_set_error(void)
{
set_error( sock_get_ntstatus( errno ) );
}
diff --git a/server/sock.h b/server/sock.h
new file mode 100644
index 0000000000..21551b42b1
--- /dev/null
+++ b/server/sock.h
@@ -0,0 +1,26 @@
+/*
+ * Server-side socket definitions
+ *
+ * Copyright (C) 2014 Sebastian Lackner
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_SERVER_SOCK_H
+#define __WINE_SERVER_SOCK_H
+
+extern void sock_set_error(void);
+
+#endif /* __WINE_SERVER_SOCK_H */
--
2.11.0

View File

@ -1,325 +0,0 @@
From ddcad4846ab1fe881bed762210f369c621bbb2de Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 11 Aug 2014 05:01:11 +0200
Subject: ntdll: Add handling for partially received messages in NtReadFile.
Changes in v2:
* Merged with final version of error code handling.
* Poll for broken pipe to distinguish between zero-byte messages and errors.
Changes in v3:
* Rebased. Simplified check for broken pipe.
Changes in v4:
* Include changes from later patch.
---
dlls/kernel32/tests/pipe.c | 57 +++++++---------------------------------------
dlls/ntdll/file.c | 28 ++++++++++++++++++-----
2 files changed, 30 insertions(+), 55 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 71d75be90e8..ae37afd2ee7 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -313,9 +313,7 @@ static void test_CreateNamedPipe(int pipemode)
else
{
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
}
ok(readden == 4, "read got %d bytes\n", readden);
@@ -336,15 +334,11 @@ static void test_CreateNamedPipe(int pipemode)
else
{
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
ok(readden == 4, "read got %d bytes\n", readden);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
}
ok(readden == 4, "read got %d bytes\n", readden);
@@ -406,9 +400,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(readden == sizeof(obuf) + sizeof(obuf2), "read 4 got %d bytes\n", readden);
}
else {
- todo_wine {
- ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
- }
+ ok(readden == sizeof(obuf), "read 4 got %d bytes\n", readden);
}
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 4a check\n");
@@ -438,9 +430,7 @@ static void test_CreateNamedPipe(int pipemode)
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- todo_wine {
- ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
- }
+ ok(readden == sizeof(obuf), "read 5 got %d bytes\n", readden);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 5a check\n");
if (readden <= sizeof(obuf))
@@ -449,10 +439,8 @@ static void test_CreateNamedPipe(int pipemode)
/* Multiple writes in the reverse direction */
/* the write of obuf2 from write4 should still be in the buffer */
ok(PeekNamedPipe(hnp, ibuf, sizeof(ibuf), &readden, &avail, NULL), "Peek6a\n");
- todo_wine {
- ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
- ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
- }
+ ok(readden == sizeof(obuf2), "peek6a got %d bytes\n", readden);
+ ok(avail == sizeof(obuf2), "peek6a got %d bytes available\n", avail);
if (avail > 0) {
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
ok(readden == sizeof(obuf2), "read 6a got %d bytes\n", readden);
@@ -470,9 +458,7 @@ static void test_CreateNamedPipe(int pipemode)
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
- todo_wine {
- ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
- }
+ ok(readden == sizeof(obuf), "read 6b got %d bytes\n", readden);
pbuf = ibuf;
ok(memcmp(obuf, pbuf, sizeof(obuf)) == 0, "content 6a check\n");
if (readden <= sizeof(obuf))
@@ -483,9 +469,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
ok(written == sizeof(obuf2), "write file len 7\n");
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 7\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 7\n");
ok(readden == 4, "read got %d bytes 7\n", readden);
ok(ReadFile(hFile, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 7\n");
@@ -496,9 +480,7 @@ static void test_CreateNamedPipe(int pipemode)
ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile 8\n");
ok(written == sizeof(obuf), "write file len 8\n");
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 8\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 8\n");
ok(readden == 4, "read got %d bytes 8\n", readden);
ok(ReadFile(hnp, ibuf + 4, sizeof(ibuf) - 4, &readden, NULL), "ReadFile 8\n");
@@ -523,16 +505,12 @@ static void test_CreateNamedPipe(int pipemode)
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 9\n", readden);
ok(leftmsg == sizeof(obuf), "peek got %d bytes left in message 9\n", leftmsg);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hFile, ibuf, 4, &readden, NULL), "ReadFile 9\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hFile, ibuf + 4, 4, &readden, NULL);
- todo_wine
ok(!ret, "RpcReadFile 9\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
readden = leftmsg = -1;
@@ -545,7 +523,6 @@ static void test_CreateNamedPipe(int pipemode)
ok(leftmsg == sizeof(obuf) - 8, "peek got %d bytes left in message 9\n", leftmsg);
ret = RpcReadFile(hFile, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 9\n");
- todo_wine
ok(readden == sizeof(obuf) - 8, "read got %d bytes 9\n", readden);
ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check 9\n");
if (readden <= sizeof(obuf) - 8) /* blocks forever if second part was already received */
@@ -562,13 +539,10 @@ static void test_CreateNamedPipe(int pipemode)
SetLastError(0xdeadbeef);
ret = RpcReadFile(hFile, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 9\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hFile, ibuf + 4, 4, &readden, NULL), "ReadFile 9\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 9\n");
ok(readden == 4, "read got %d bytes 9\n", readden);
readden = leftmsg = -1;
@@ -608,16 +582,12 @@ static void test_CreateNamedPipe(int pipemode)
ok(readden == sizeof(obuf) + sizeof(obuf2), "peek got %d bytes total 10\n", readden);
ok(leftmsg == sizeof(obuf2), "peek got %d bytes left in message 10\n", leftmsg);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf, 4, &readden, NULL), "ReadFile 10\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
SetLastError(0xdeadbeef);
ret = RpcReadFile(hnp, ibuf + 4, 4, &readden, NULL);
- todo_wine
ok(!ret, "RpcReadFile 10\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
readden = leftmsg = -1;
@@ -630,7 +600,6 @@ static void test_CreateNamedPipe(int pipemode)
ok(leftmsg == sizeof(obuf2) - 8, "peek got %d bytes left in message 10\n", leftmsg);
ret = RpcReadFile(hnp, ibuf + 8, sizeof(ibuf), &readden, NULL);
ok(ret, "RpcReadFile 10\n");
- todo_wine
ok(readden == sizeof(obuf2) - 8, "read got %d bytes 10\n", readden);
ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check 10\n");
if (readden <= sizeof(obuf2) - 8) /* blocks forever if second part was already received */
@@ -647,13 +616,10 @@ static void test_CreateNamedPipe(int pipemode)
SetLastError(0xdeadbeef);
ret = RpcReadFile(hnp, ibuf, 4, &readden, NULL);
ok(!ret, "RpcReadFile 10\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hnp, ibuf + 4, 4, &readden, NULL), "ReadFile 10\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error 10\n");
ok(readden == 4, "read got %d bytes 10\n", readden);
readden = leftmsg = -1;
@@ -759,15 +725,11 @@ static void test_CreateNamedPipe(int pipemode)
else
{
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hFile, big_ibuf, 32, &readden, NULL), "ReadFile\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
ok(readden == 32, "read got %d bytes\n", readden);
SetLastError(0xdeadbeef);
- todo_wine
ok(!ReadFile(hFile, big_ibuf + 32, 32, &readden, NULL), "ReadFile\n");
- todo_wine
ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
}
ok(readden == 32, "read got %d bytes\n", readden);
@@ -1665,7 +1627,7 @@ static void test_CloseHandle(void)
numbytes = 0xdeadbeef;
memset(buffer, 0, sizeof(buffer));
ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
- todo_wine ok(ret, "ReadFile failed with %u\n", GetLastError());
+ ok(ret, "ReadFile failed with %u\n", GetLastError());
ok(numbytes == 0, "expected 0, got %u\n", numbytes);
numbytes = 0xdeadbeef;
@@ -1763,8 +1725,8 @@ static void test_CloseHandle(void)
numbytes = 0xdeadbeef;
memset(buffer, 0, sizeof(buffer));
ret = ReadFile(hpipe, buffer, 0, &numbytes, NULL);
- todo_wine ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
- "ReadFile failed with %u\n", GetLastError());
+ ok(ret || GetLastError() == ERROR_MORE_DATA /* >= Win 8 */,
+ "ReadFile failed with %u\n", GetLastError());
ok(numbytes == 0, "expected 0, got %u\n", numbytes);
numbytes = 0xdeadbeef;
@@ -2720,7 +2682,6 @@ static void test_readfileex_pending(void)
SetLastError(0xdeadbeef);
ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
ok(!ret, "ReadFile should fail\n");
-todo_wine
ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
ok(num_bytes == 0, "bytes %u\n", num_bytes);
ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
@@ -2736,11 +2697,9 @@ todo_wine
ok(num_bytes == 1, "bytes %u\n", num_bytes);
wait = WaitForSingleObject(event, 100);
-todo_wine
ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
ok(num_bytes == 1, "bytes %u\n", num_bytes);
-todo_wine
ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
ok(overlapped.InternalHigh == 0, "expected 0, got %lu\n", overlapped.InternalHigh);
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 4a736f42d6d..4347e419029 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -492,7 +492,7 @@ NTSTATUS FILE_GetNtStatus(void)
}
}
-/* helper function for FSCTL_PIPE_PEEK */
+/* helper function for FSCTL_PIPE_PEEK and read_unix_fd */
static NTSTATUS unix_fd_avail(int fd, int *avail)
{
struct pollfd pollfd;
@@ -521,7 +521,14 @@ static NTSTATUS unix_fd_avail(int fd, int *avail)
static inline int get_pipe_flags(int fd)
{
#ifdef __linux__
- return fcntl( fd, F_GETSIG );
+ int flags = fcntl( fd, F_GETSIG );
+
+ /* NAMED_PIPE_MESSAGE_STREAM_READ only allowed in
+ * combination with NAMED_PIPE_MESSAGE_STREAM_WRITE. */
+ if (!(flags & NAMED_PIPE_MESSAGE_STREAM_WRITE))
+ flags &= ~NAMED_PIPE_MESSAGE_STREAM_READ;
+
+ return flags;
#else
return 0;
#endif
@@ -567,10 +574,12 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
if (result >= 0)
{
*total += result;
- if (!result || *total >= length || (avail_mode && !(pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)))
+ if (!result || *total >= length || (avail_mode && !(pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)) ||
+ ((pipe_flags & NAMED_PIPE_MESSAGE_STREAM_READ) && !(msg.msg_flags & MSG_TRUNC)))
{
if (*total)
- return STATUS_SUCCESS;
+ return ((pipe_flags & NAMED_PIPE_MESSAGE_STREAM_READ) && (msg.msg_flags & MSG_TRUNC)) ?
+ STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
switch (type)
{
case FD_TYPE_FILE:
@@ -579,11 +588,18 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
return length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
case FD_TYPE_SERIAL:
return length ? STATUS_PENDING : STATUS_SUCCESS;
+ case FD_TYPE_PIPE:
+ {
+ NTSTATUS status = unix_fd_avail( fd, &result );
+ if (!status && !result && !length) status = STATUS_PENDING;
+ return status;
+ }
default:
return STATUS_PIPE_BROKEN;
}
}
- else if (pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
+ else if ((pipe_flags & (NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ)) ==
+ NAMED_PIPE_MESSAGE_STREAM_WRITE)
continue;
else if (type != FD_TYPE_FILE) /* no async I/O on regular files */
return STATUS_PENDING;
@@ -1061,7 +1077,7 @@ done:
err:
if (needs_close) close( unix_handle );
- if (status == STATUS_SUCCESS || (status == STATUS_END_OF_FILE && !async_read))
+ if (status == STATUS_SUCCESS || status == STATUS_BUFFER_OVERFLOW || (status == STATUS_END_OF_FILE && !async_read))
{
io_status->u.Status = status;
io_status->Information = total;
--
2.11.0

View File

@ -1,188 +0,0 @@
From d94857ffb00c9e24dcaff68aed1e14a6b99745f5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 17 Aug 2014 00:47:26 +0200
Subject: kernel32/tests: Add more tests with overlapped IO and partial reads
from named pipes.
---
dlls/kernel32/tests/pipe.c | 150 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 150 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 6a27826..ba49974 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2300,6 +2300,7 @@ static void test_readfileex_pending(void)
OVERLAPPED overlapped;
char read_buf[1024];
char write_buf[1024];
+ const char long_test_string[] = "12test3456ab";
const char test_string[] = "test";
int i;
@@ -2339,6 +2340,9 @@ static void test_readfileex_pending(void)
ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 0, "completion routine called before WriteFile started\n");
ret = WriteFile(client, test_string, strlen(test_string), &num_bytes, NULL);
ok(ret == TRUE, "WriteFile failed\n");
@@ -2449,6 +2453,152 @@ todo_wine
CloseHandle(client);
CloseHandle(server);
+
+ server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 1024,
+ /* nInBufSize */ 1024,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
+
+ client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, 0, NULL);
+ ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
+
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = event;
+
+ /* Start a call to ReadFileEx which cannot complete immediately */
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
+ ok(completion_called == 0, "completion routine called before WriteFile started\n");
+
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret == TRUE, "WriteFile failed\n");
+ ok(num_bytes == strlen(long_test_string), "only %i bytes written\n", num_bytes);
+ ok(completion_called == 0, "completion routine called during WriteFile\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ todo_wine
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ ok(!memcmp(long_test_string, read_buf, 4), "ReadFileEx read wrong bytes\n");
+
+ ret = ReadFile(server, read_buf + 4, 4, &num_bytes, NULL);
+ ok(ret == FALSE, "ReadFile succeeded\n");
+ ok(num_bytes == 4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(GetLastError() == ERROR_MORE_DATA, "wrong error\n");
+ ret = ReadFile(server, read_buf + 8, sizeof(read_buf) - 8, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-8, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Call ReadFileEx when there is already some content in the pipe */
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret == TRUE, "WriteFile failed\n");
+ ok(num_bytes == strlen(long_test_string), "only %i bytes written\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ todo_wine
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ todo_wine
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ todo_wine
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ todo_wine
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ ok(!memcmp(long_test_string, read_buf, 4), "ReadFileEx read wrong bytes\n");
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Check content of overlapped structure */
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %d\n", GetLastError());
+ ok(num_bytes == 0, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ todo_wine
+ ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObject returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed\n");
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Call ReadFile when there is already some content in the pipe */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed\n");
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(ret == FALSE, "ReadFile succeeded\n");
+ ok(GetLastError() == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", GetLastError());
+ todo_wine
+ ok(num_bytes == 0, "ReadFile returned %d bytes\n", num_bytes);
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ todo_wine
+ ok(num_bytes == 0, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ CloseHandle(client);
+ CloseHandle(server);
CloseHandle(event);
}
--
2.1.3

View File

@ -1,85 +0,0 @@
From 87e6095901f7405efc256997f1e1d6f0338ab2b5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 17 Aug 2014 01:13:44 +0200
Subject: ntdll: Fix some tests for overlapped partial reads.
Windows also sends as APC user notification for STATUS_BUFFER_OVERFLOW.
Moreover in some cases STATUS_BUFFER_OVERFLOW is reported as success, not
as failure.
---
dlls/kernel32/file.c | 7 ++++---
dlls/kernel32/tests/pipe.c | 5 -----
dlls/ntdll/file.c | 4 ++--
3 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/file.c b/dlls/kernel32/file.c
index 006db1c..78cfdb7 100644
--- a/dlls/kernel32/file.c
+++ b/dlls/kernel32/file.c
@@ -325,8 +325,9 @@ BOOL WINAPI AreFileApisANSI(void)
static void WINAPI FILE_ReadWriteApc(void* apc_user, PIO_STATUS_BLOCK io_status, ULONG reserved)
{
LPOVERLAPPED_COMPLETION_ROUTINE cr = apc_user;
-
- cr(RtlNtStatusToDosError(io_status->u.Status), io_status->Information, (LPOVERLAPPED)io_status);
+ NTSTATUS status = io_status->u.Status;
+ if (status == STATUS_BUFFER_OVERFLOW) status = STATUS_SUCCESS;
+ cr(RtlNtStatusToDosError(status), io_status->Information, (LPOVERLAPPED)io_status);
}
@@ -358,7 +359,7 @@ BOOL WINAPI ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
status = NtReadFile(hFile, NULL, FILE_ReadWriteApc, lpCompletionRoutine,
io_status, buffer, bytesToRead, &offset, NULL);
- if (status && status != STATUS_PENDING)
+ if (status && status != STATUS_PENDING && status != STATUS_BUFFER_OVERFLOW)
{
SetLastError( RtlNtStatusToDosError(status) );
return FALSE;
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index ba49974..53f8f30 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2489,7 +2489,6 @@ todo_wine
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
ok(completion_called == 1, "completion not called after writing pipe\n");
- todo_wine
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
@@ -2513,15 +2512,11 @@ todo_wine
completion_called = 0;
ResetEvent(event);
ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
- todo_wine
ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
wait = WaitForSingleObjectEx(event, 0, TRUE);
- todo_wine
ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
- todo_wine
ok(completion_called == 1, "completion not called after writing pipe\n");
- todo_wine
ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 81f941d..d3f0c0e 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -885,8 +885,8 @@ err:
io_status->Information = total;
TRACE("= SUCCESS (%u)\n", total);
if (hEvent) NtSetEvent( hEvent, NULL );
- if (apc && !status) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
- (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
+ if (apc && status != STATUS_END_OF_FILE) NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)apc,
+ (ULONG_PTR)apc_user, (ULONG_PTR)io_status, 0 );
}
else
{
--
2.1.3

View File

@ -1,301 +0,0 @@
From 8208e3f7c671c71b3b7d25d854e860aad7c45697 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 11 Aug 2014 00:56:46 +0200
Subject: kernel32/tests: Test sending, peeking and receiving an empty message.
Changes in v2:
* As async handling is now working correctly, it breaks some tests :/
We need a lot of ugly code to prevent the tests from deadlocking...
* Fix issue in broken pipe check, should be moved into an earlier patch.
---
dlls/kernel32/tests/pipe.c | 267 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 267 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 5f2c4d7..76cf018 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -338,6 +338,146 @@ static void test_CreateNamedPipe(int pipemode)
ok(readden == sizeof(obuf2) - 8, "read got %d bytes\n", readden);
ok(memcmp(obuf2, ibuf, written) == 0, "content check\n");
+ /* Tests for sending empty messages */
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ if (pipemode != PIPE_TYPE_BYTE)
+ {
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ if (pipemode != PIPE_TYPE_BYTE)
+ {
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ /* similar to above, but with an additional call to PeekNamedPipe inbetween */
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == 0, "peek got %d bytes\n", readden);
+ if (pipemode != PIPE_TYPE_BYTE)
+ {
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_READFILE;
+ rpcargs.args[0] = (ULONG_PTR)hFile;
+ rpcargs.args[1] = (ULONG_PTR)ibuf;
+ rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
+ rpcargs.args[3] = (ULONG_PTR)&readden;
+ rpcargs.args[4] = (ULONG_PTR)NULL;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ todo_wine
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ if (ret == WAIT_TIMEOUT)
+ {
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ }
+ CloseHandle(thread);
+ ok((BOOL)rpcargs.returnValue, "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == 0, "peek got %d bytes\n", readden);
+ if (pipemode != PIPE_TYPE_BYTE)
+ {
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_READFILE;
+ rpcargs.args[0] = (ULONG_PTR)hnp;
+ rpcargs.args[1] = (ULONG_PTR)ibuf;
+ rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
+ rpcargs.args[3] = (ULONG_PTR)&readden;
+ rpcargs.args[4] = (ULONG_PTR)NULL;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ todo_wine
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ if (ret == WAIT_TIMEOUT)
+ {
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ }
+ CloseHandle(thread);
+ ok((BOOL)rpcargs.returnValue, "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ /* similar to above, but now with PeekNamedPipe and multiple messages */
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf), "write file len\n");
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
+ if (pipemode != PIPE_TYPE_BYTE)
+ todo_wine
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ else
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
+ ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hFile, obuf2, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf2), "write file len\n");
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
+ if (pipemode != PIPE_TYPE_BYTE)
+ todo_wine
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ else
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ if (pipemode != PIPE_TYPE_BYTE)
+ {
+ todo_wine
+ ok(readden == 0, "read got %d bytes\n", readden);
+ if (readden == 0)
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ }
+ ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
+ ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check\n");
+
/* Test reading of multiple writes */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile3a\n");
@@ -456,6 +596,133 @@ static void test_CreateNamedPipe(int pipemode)
if (readden <= sizeof(obuf))
ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ /* Tests for sending empty messages */
+ memset(ibuf, 0, sizeof(ibuf));
+ 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\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+
+ memset(ibuf, 0, sizeof(ibuf));
+ 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\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+
+ /* similar to above, but with an additional call to PeekNamedPipe inbetween */
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == 0, "peek got %d bytes\n", readden);
+ {
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_READFILE;
+ rpcargs.args[0] = (ULONG_PTR)hFile;
+ rpcargs.args[1] = (ULONG_PTR)ibuf;
+ rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
+ rpcargs.args[3] = (ULONG_PTR)&readden;
+ rpcargs.args[4] = (ULONG_PTR)NULL;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ todo_wine
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ if (ret == WAIT_TIMEOUT)
+ {
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ }
+ CloseHandle(thread);
+ ok((BOOL)rpcargs.returnValue, "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == 0, "peek got %d bytes\n", readden);
+ {
+ struct rpcThreadArgs rpcargs;
+ HANDLE thread;
+ DWORD threadId;
+
+ rpcargs.returnValue = 0;
+ rpcargs.lastError = GetLastError();
+ rpcargs.op = RPC_READFILE;
+ rpcargs.args[0] = (ULONG_PTR)hnp;
+ rpcargs.args[1] = (ULONG_PTR)ibuf;
+ rpcargs.args[2] = (ULONG_PTR)sizeof(ibuf);
+ rpcargs.args[3] = (ULONG_PTR)&readden;
+ rpcargs.args[4] = (ULONG_PTR)NULL;
+
+ thread = CreateThread(NULL, 0, rpcThreadMain, (void *)&rpcargs, 0, &threadId);
+ ok(thread != NULL, "CreateThread failed. %d\n", GetLastError());
+ ret = WaitForSingleObject(thread, 200);
+ todo_wine
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ if (ret == WAIT_TIMEOUT)
+ {
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ret = WaitForSingleObject(thread, 200);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d instead of %d.\n", ret, WAIT_OBJECT_0);
+ }
+ CloseHandle(thread);
+ ok((BOOL)rpcargs.returnValue, "ReadFile\n");
+ ok(readden == 0, "read got %d bytes\n", readden);
+ }
+
+ /* similar to above, but now with PeekNamedPipe and multiple messages */
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf), "write file len\n");
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf), "peek got %d bytes\n", readden);
+ todo_wine
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(readden == 0, "read got %d bytes\n", readden);
+ if (readden == 0)
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ ok(readden == sizeof(obuf), "read got %d bytes\n", readden);
+ ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(WriteFile(hFile, obuf2, 0, &written, NULL), "WriteFile\n");
+ ok(written == 0, "write file len\n");
+ ok(WriteFile(hFile, obuf2, sizeof(obuf2), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf2), "write file len\n");
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, &leftmsg), "Peek\n");
+ ok(readden == sizeof(obuf2), "peek got %d bytes\n", readden);
+ todo_wine
+ ok(leftmsg == 0, "peek got %d bytes left in msg\n", leftmsg);
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ todo_wine
+ ok(readden == 0, "read got %d bytes\n", readden);
+ if (readden == 0)
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile\n");
+ ok(readden == sizeof(obuf2), "read got %d bytes\n", readden);
+ ok(memcmp(obuf2, ibuf, sizeof(obuf2)) == 0, "content check\n");
+
/* Test how ReadFile behaves when the buffer is not big enough for the whole message */
memset(ibuf, 0, sizeof(ibuf));
ok(WriteFile(hnp, obuf2, sizeof(obuf2), &written, NULL), "WriteFile 7\n");
--
2.6.2

View File

@ -1,52 +0,0 @@
From fb6d82077a362f002300cd171547c292cbb5d0bd Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 17 Aug 2014 01:29:06 +0200
Subject: ntdll: Add support for nonblocking pipes.
---
dlls/ntdll/file.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index d3f0c0e..ba3814e 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -472,6 +472,10 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
{
if (pipe_flags & NAMED_PIPE_MESSAGE_STREAM_WRITE)
{
+ int recvmsg_flags = MSG_PEEK;
+ if (*total || (pipe_flags & NAMED_PIPE_NONBLOCKING_MODE))
+ recvmsg_flags |= MSG_DONTWAIT;
+
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
@@ -483,7 +487,7 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
iov.iov_base = buf + *total;
iov.iov_len = length - *total;
- result = recvmsg( fd, &msg, MSG_PEEK | (*total ? MSG_DONTWAIT : 0) );
+ result = recvmsg( fd, &msg, recvmsg_flags );
if (result >= 0 && !(msg.msg_flags & MSG_TRUNC))
{
int ret;
@@ -527,7 +531,14 @@ static NTSTATUS read_unix_fd(int fd, char *buf, ULONG *total, ULONG length,
return STATUS_PENDING;
}
else if (errno == EAGAIN)
- return (avail_mode && *total) ? STATUS_SUCCESS : STATUS_PENDING;
+ {
+ if (avail_mode && *total)
+ return STATUS_SUCCESS;
+ else if (pipe_flags & NAMED_PIPE_NONBLOCKING_MODE)
+ return *total ? STATUS_SUCCESS : STATUS_PIPE_EMPTY;
+ else
+ return STATUS_PENDING;
+ }
else if (errno != EINTR)
return FILE_GetNtStatus();
}
--
2.1.3

View File

@ -1,126 +0,0 @@
From c5fd5022f2e8a00a520f030919394f1b2b6559d4 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 11 Aug 2014 04:19:49 +0200
Subject: kernel32/tests: Add tests for PIPE_NOWAIT in message mode.
---
dlls/kernel32/tests/pipe.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 81d4d39..18b371c 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2619,6 +2619,101 @@ static void test_overlapped_error(void)
CloseHandle(event);
}
+static void test_nowait(void)
+{
+ HANDLE hnp;
+ HANDLE hFile;
+ static const char obuf[] = "Bit Bucket";
+ char ibuf[32];
+ DWORD written;
+ DWORD readden;
+ DWORD lpmode;
+
+ hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 1024,
+ /* nInBufSize */ 1024,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(hnp != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
+
+ hFile = CreateFileA(PIPENAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+ ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
+
+ /* don't try to do i/o if one side couldn't be opened, as it hangs */
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+ /* send message from client to server */
+ ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf), "write file len\n");
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
+ ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
+
+ readden = 0xdeadbeef;
+ 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());
+
+ lpmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
+ ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
+
+ /* send message from server to client */
+ ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
+ ok(written == sizeof(obuf), "write file len\n");
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
+
+ memset(ibuf, 0, sizeof(ibuf));
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
+ ok(memcmp(obuf, ibuf, sizeof(obuf)) == 0, "content check\n");
+
+ readden = 0xdeadbeef;
+ 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());
+
+ /* now again the bad zero byte message test */
+ 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);
+
+ readden = 0xdeadbeef;
+ 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());
+
+ /* and the same for the reverse direction */
+ 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);
+
+ readden = 0xdeadbeef;
+ 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());
+
+ ok(CloseHandle(hFile), "CloseHandle\n");
+ }
+
+ ok(CloseHandle(hnp), "CloseHandle\n");
+
+}
+
static void test_NamedPipeHandleState(void)
{
HANDLE server, client;
@@ -3114,6 +3209,7 @@ START_TEST(pipe)
test_impersonation();
test_overlapped();
test_overlapped_error();
+ test_nowait();
test_NamedPipeHandleState();
test_GetNamedPipeInfo();
test_readfileex_pending();
--
2.9.0

View File

@ -1,112 +0,0 @@
From 8ce5ed62d1e49a3e738a8287e4611fe9f63437e0 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 18b371c..55f8d4f 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2619,7 +2619,7 @@ static void test_overlapped_error(void)
CloseHandle(event);
}
-static void test_nowait(void)
+static void test_nowait(int pipemode)
{
HANDLE hnp;
HANDLE hFile;
@@ -2630,7 +2630,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,
@@ -2661,7 +2661,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 */
@@ -2685,8 +2685,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);
@@ -2698,8 +2708,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);
@@ -3209,7 +3229,8 @@ START_TEST(pipe)
test_impersonation();
test_overlapped();
test_overlapped_error();
- test_nowait();
+ test_nowait(PIPE_TYPE_BYTE);
+ test_nowait(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
test_NamedPipeHandleState();
test_GetNamedPipeInfo();
test_readfileex_pending();
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 622cc45..c27a13f 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -573,6 +573,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.9.0

View File

@ -1,331 +0,0 @@
From 5f05e5517f75081777b26d6f0e300a12121d094a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 17 Aug 2014 02:56:57 +0200
Subject: kernel32/tests: Add additional tests for PIPE_NOWAIT in overlapped
mode.
---
dlls/kernel32/tests/pipe.c | 293 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 292 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 3f753f8..c3f0b19 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -2748,7 +2748,7 @@ static void test_readfileex_pending(void)
{
HANDLE server, client, event;
BOOL ret;
- DWORD err, wait, num_bytes;
+ DWORD err, wait, num_bytes, lpmode;
OVERLAPPED overlapped;
char read_buf[1024];
char write_buf[1024];
@@ -2903,6 +2903,159 @@ todo_wine
CloseHandle(client);
CloseHandle(server);
+ /* On Windows versions > 2000 it is not possible to add PIPE_NOWAIT to a byte-mode
+ * PIPE after creating. Create a new pipe for the following tests. */
+ server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
+ /* dwOpenMode */ PIPE_TYPE_BYTE | PIPE_NOWAIT,
+ /* nMaxInstances */ 1,
+ /* nOutBufSize */ 1024,
+ /* nInBufSize */ 1024,
+ /* nDefaultWait */ NMPWAIT_USE_DEFAULT_WAIT,
+ /* lpSecurityAttrib */ NULL);
+ ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
+
+ client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, 0, NULL);
+ ok(client != INVALID_HANDLE_VALUE, "cf failed\n");
+
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = event;
+
+ /* Initial check with empty pipe */
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ ok(ret == FALSE, "ReadFileEx succeded\n");
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 0, "completion routine called before writing to file\n");
+
+ /* Call ReadFileEx after writing content to the pipe */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile succeeded\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Same again, but read as a single part */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == strlen(long_test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Check content of overlapped structure */
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(ret == FALSE, "ReadFile succeeded\n");
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
+ ok(num_bytes == 0, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ todo_wine
+ ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ todo_wine
+ ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+
+ /* Call ReadFile after writing to the pipe */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == 4, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Same again, but read as a single part */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, sizeof(read_buf), &num_bytes, &overlapped);
+ ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ CloseHandle(client);
+ CloseHandle(server);
+
server = CreateNamedPipeA(PIPENAME, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
/* dwOpenMode */ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
/* nMaxInstances */ 1,
@@ -3041,6 +3194,144 @@ todo_wine
ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+ /* Tests for PIPE_NOWAIT in message mode */
+ lpmode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
+ ok(SetNamedPipeHandleState(server, &lpmode, NULL, NULL), "Change mode\n");
+
+ /* Initial check with empty pipe */
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ ok(ret == FALSE, "ReadFileEx succeded\n");
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 0, "completion routine called before writing to file\n");
+
+ /* Call ReadFileEx after writing content to the pipe */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, 4, &overlapped, completion_routine);
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == 4, "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile succeeded\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Same again, but read as a single part */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ completion_called = 0;
+ ResetEvent(event);
+ ret = ReadFileEx(server, read_buf, sizeof(read_buf), &overlapped, completion_routine);
+ ok(ret == TRUE, "ReadFileEx failed, err=%i\n", GetLastError());
+ ok(completion_called == 0, "completion routine called before ReadFileEx returned\n");
+ wait = WaitForSingleObjectEx(event, 0, TRUE);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObjectEx returned %x\n", wait);
+ ok(completion_called == 1, "completion not called after writing pipe\n");
+ ok(completion_errorcode == 0, "completion called with error %x\n", completion_errorcode);
+ ok(completion_num_bytes == strlen(long_test_string), "ReadFileEx returned only %d bytes\n", completion_num_bytes);
+ ok(completion_lpoverlapped == &overlapped, "completion called with wrong overlapped pointer\n");
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Check content of overlapped structure */
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(ret == FALSE, "ReadFile succeeded\n");
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %d\n", GetLastError());
+ ok(num_bytes == 0, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ todo_wine
+ ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_TIMEOUT, "WaitForSingleObjectEx returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "expected STATUS_PENDING, got %#lx\n", overlapped.Internal);
+ todo_wine
+ ok(overlapped.InternalHigh == -1, "expected -1, got %lu\n", overlapped.InternalHigh);
+
+ /* Call ReadFile after writing to the pipe */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, 4, &num_bytes, &overlapped);
+ ok(ret == FALSE, "ReadFile succeeded\n");
+ ok(GetLastError() == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", GetLastError());
+ todo_wine
+ ok(num_bytes == 0, "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == STATUS_BUFFER_OVERFLOW, "expected STATUS_BUFFER_OVERFLOW, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == 4, "expected 4, got %lu\n", overlapped.InternalHigh);
+
+ ret = ReadFile(server, read_buf + 4, sizeof(read_buf) - 4, &num_bytes, NULL);
+ ok(ret == TRUE, "ReadFile failed\n");
+ ok(num_bytes == strlen(long_test_string)-4, "ReadFile returned only %d bytes\n", num_bytes);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
+ /* Same again, but read as a single part */
+ num_bytes = 0xdeadbeef;
+ ret = WriteFile(client, long_test_string, strlen(long_test_string), &num_bytes, NULL);
+ ok(ret, "WriteFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+
+ memset(read_buf, 0, sizeof(read_buf));
+ S(U(overlapped)).Offset = 0;
+ S(U(overlapped)).OffsetHigh = 0;
+ overlapped.Internal = -1;
+ overlapped.InternalHigh = -1;
+ overlapped.hEvent = event;
+ num_bytes = 0xdeadbeef;
+ SetLastError(0xdeadbeef);
+ ret = ReadFile(server, read_buf, sizeof(read_buf), &num_bytes, &overlapped);
+ ok(ret == TRUE, "ReadFile failed, err=%i\n", GetLastError());
+ ok(num_bytes == strlen(long_test_string), "bytes %u\n", num_bytes);
+ ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
+ wait = WaitForSingleObject(event, 100);
+ ok(wait == WAIT_IO_COMPLETION || wait == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", wait);
+ ok((NTSTATUS)overlapped.Internal == 0, "expected 0, got %#lx\n", overlapped.Internal);
+ ok(overlapped.InternalHigh == strlen(long_test_string), "expected %u, got %lu\n", (DWORD)strlen(long_test_string), overlapped.InternalHigh);
+ ok(!memcmp(long_test_string, read_buf, strlen(long_test_string)), "ReadFile read wrong bytes\n");
+
CloseHandle(client);
CloseHandle(server);
CloseHandle(event);
--
2.3.0

View File

@ -1,46 +0,0 @@
From b2c20a6b49fdd1ec392b8a7406401343555da73a Mon Sep 17 00:00:00 2001
From: Qian Hong <qhong@codeweavers.com>
Date: Mon, 30 Mar 2015 07:25:35 +0800
Subject: ntdll: Improve ReadDataAvailable handling in FilePipeLocalInformation
class support.
---
dlls/ntdll/file.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 0dc5c13..a1ca1d1 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2367,6 +2367,7 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
case FilePipeLocalInformation:
{
FILE_PIPE_LOCAL_INFORMATION* pli = ptr;
+ int avail, fd, needs_close;
SERVER_START_REQ( get_named_pipe_info )
{
@@ -2390,12 +2391,19 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
pli->MaximumInstances = reply->maxinstances;
pli->CurrentInstances = reply->instances;
pli->InboundQuota = reply->insize;
- pli->ReadDataAvailable = 0; /* FIXME */
+ pli->ReadDataAvailable = 0;
pli->OutboundQuota = reply->outsize;
pli->WriteQuotaAvailable = 0; /* FIXME */
pli->NamedPipeState = 0; /* FIXME */
pli->NamedPipeEnd = (reply->flags & NAMED_PIPE_SERVER_END) ?
FILE_PIPE_SERVER_END : FILE_PIPE_CLIENT_END;
+
+ if (!server_get_unix_fd( hFile, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))
+ {
+ if (!unix_fd_avail( fd, &avail ))
+ pli->ReadDataAvailable = min(avail, reply->outsize); /* FIXME */
+ if (needs_close) close( fd );
+ }
}
}
SERVER_END_REQ;
--
2.3.7

View File

@ -1,48 +0,0 @@
From a39228203e7fd6d24ac9cae794fc4903e2d67ad7 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 4 Jun 2015 00:02:13 +0200
Subject: ntdll: Set NamedPipeState to FILE_PIPE_CLOSING_STATE on broken pipe
in NtQueryInformationFile.
---
dlls/ntdll/file.c | 6 +++++-
include/winternl.h | 5 +++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index c1f5a7a..00b3ccd 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -2625,8 +2625,12 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
if (!server_get_unix_fd( hFile, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))
{
- if (!unix_fd_avail( fd, &avail ))
+ NTSTATUS status = unix_fd_avail( fd, &avail );
+ if (!status)
pli->ReadDataAvailable = min(avail, reply->outsize); /* FIXME */
+ else if (status == STATUS_PIPE_BROKEN)
+ pli->NamedPipeState = FILE_PIPE_CLOSING_STATE;
+
if (needs_close) close( fd );
}
}
diff --git a/include/winternl.h b/include/winternl.h
index 0489395..41abff8 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -713,6 +713,11 @@ typedef struct _FILE_REPARSE_POINT_INFORMATION {
ULONG Tag;
} FILE_REPARSE_POINT_INFORMATION, *PFILE_REPARSE_POINT_INFORMATION;
+#define FILE_PIPE_DISCONNECTED_STATE 0x01
+#define FILE_PIPE_LISTENING_STATE 0x02
+#define FILE_PIPE_CONNECTED_STATE 0x03
+#define FILE_PIPE_CLOSING_STATE 0x04
+
typedef struct _FILE_ALL_INFORMATION {
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
--
2.8.0

View File

@ -1,151 +0,0 @@
From bb9a6f2fb4431cb18e2a835808c02156bbd9d709 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 6 Jun 2015 01:21:05 +0200
Subject: server: Return correct error codes for NtWriteFile when pipes are
closed without disconnecting.
---
dlls/kernel32/tests/pipe.c | 2 +-
dlls/ntdll/file.c | 3 +++
server/named_pipe.c | 43 +++++++++++++++++++++++++++++++++++++++++--
server/protocol.def | 1 +
4 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index ba365ed666..23f1a5f5f5 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -1917,7 +1917,7 @@ static void test_CloseHandle(void)
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
ok(!ret, "WriteFile unexpectedly succeeded\n");
- todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
CloseHandle(hfile);
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 98a699e48f..25f59761cf 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -1235,6 +1235,9 @@ static NTSTATUS write_unix_fd(int fd, const char *buf, ULONG *total, ULONG lengt
return STATUS_SUCCESS;
else if (errno == EFAULT)
return STATUS_INVALID_USER_BUFFER;
+ else if (type == FD_TYPE_PIPE && (errno == EPIPE || errno == ECONNRESET))
+ return (get_pipe_flags( fd ) & NAMED_PIPE_CLOSED_HANDLE) ?
+ STATUS_PIPE_EMPTY : STATUS_PIPE_DISCONNECTED;
return FILE_GetNtStatus();
}
}
diff --git a/server/named_pipe.c b/server/named_pipe.c
index d310740165..2775fcab51 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -129,6 +129,8 @@ struct named_pipe_device
struct namespace *pipes; /* named pipe namespace */
};
+static inline int messagemode_flags( int flags );
+
static void named_pipe_dump( struct object *obj, int verbose );
static unsigned int named_pipe_map_access( struct object *obj, unsigned int access );
static int named_pipe_link_name( struct object *obj, struct object_name *name, struct object *parent );
@@ -167,6 +169,7 @@ static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue );
/* server end functions */
static void pipe_server_dump( struct object *obj, int verbose );
static struct fd *pipe_server_get_fd( struct object *obj );
+static int pipe_server_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
static void pipe_server_destroy( struct object *obj);
static obj_handle_t pipe_server_flush( struct fd *fd, struct async *async, int blocking );
static enum server_fd_type pipe_server_get_fd_type( struct fd *fd );
@@ -192,7 +195,7 @@ static const struct object_ops pipe_server_ops =
NULL, /* unlink_name */
no_open_file, /* open_file */
no_alloc_handle, /* alloc_handle */
- fd_close_handle, /* close_handle */
+ pipe_server_close_handle, /* close_handle */
pipe_server_destroy /* destroy */
};
@@ -213,6 +216,7 @@ static const struct fd_ops pipe_server_fd_ops =
static void pipe_client_dump( struct object *obj, int verbose );
static int pipe_client_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *pipe_client_get_fd( struct object *obj );
+static int pipe_client_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
static void pipe_client_destroy( struct object *obj );
static obj_handle_t pipe_client_flush( struct fd *fd, struct async *async, int blocking );
static obj_handle_t pipe_client_ioctl( struct fd *fd, ioctl_code_t code, struct async *async,
@@ -238,7 +242,7 @@ static const struct object_ops pipe_client_ops =
NULL, /* unlink_name */
no_open_file, /* open_file */
no_alloc_handle, /* alloc_handle */
- fd_close_handle, /* close_handle */
+ pipe_client_close_handle, /* close_handle */
pipe_client_destroy /* destroy */
};
@@ -482,6 +486,23 @@ static void pipe_end_destroy( struct pipe_end *pipe_end )
free_async_queue( pipe_end->write_q );
}
+static int pipe_server_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
+{
+#ifdef __linux__
+ struct pipe_server *server = (struct pipe_server *)obj;
+ struct pipe_client *client = server->client;
+ int unix_fd;
+
+ assert( obj->ops == &pipe_server_ops );
+ if (obj->handle_count == 1 && client && client->pipe_end.fd && (unix_fd = get_unix_fd( client->pipe_end.fd )) != -1)
+ {
+ /* set the NAMED_PIPE_CLOSED_HANDLE flag, to distinguish disconnect / closing pipe */
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( client->pipe_end.flags ) | NAMED_PIPE_CLOSED_HANDLE );
+ }
+#endif
+ return 1;
+}
+
static void pipe_server_destroy( struct object *obj)
{
struct pipe_server *server = (struct pipe_server *)obj;
@@ -511,6 +532,24 @@ static void pipe_server_destroy( struct object *obj)
release_object( server->pipe );
}
+static int pipe_client_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
+{
+#ifdef __linux__
+ struct pipe_client *client = (struct pipe_client *)obj;
+ struct pipe_server *server = client->server;
+ int unix_fd;
+
+ assert( obj->ops == &pipe_client_ops );
+ if (obj->handle_count == 1 && server && server->pipe_end.fd &&
+ server->state != ps_wait_connect && (unix_fd = get_unix_fd( server->pipe_end.fd )) != -1)
+ {
+ /* set the NAMED_PIPE_CLOSED_HANDLE flag, to distinguish disconnect / closing pipe */
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( server->pipe_end.flags ) | NAMED_PIPE_CLOSED_HANDLE );
+ }
+#endif
+ return 1;
+}
+
static void pipe_client_destroy( struct object *obj)
{
struct pipe_client *client = (struct pipe_client *)obj;
diff --git a/server/protocol.def b/server/protocol.def
index 341a6f6085..9769bb9e7b 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2431,6 +2431,7 @@ enum message_type
#define NAMED_PIPE_MESSAGE_STREAM_WRITE 0x0001
#define NAMED_PIPE_MESSAGE_STREAM_READ 0x0002
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004
+#define NAMED_PIPE_CLOSED_HANDLE 0x0008
#define NAMED_PIPE_SERVER_END 0x8000
/* Get named pipe information by handle */
--
2.11.0

View File

@ -1,64 +0,0 @@
From 91fcadbc95667961575d55cad728f7151a8766d7 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 6 Jun 2015 01:21:05 +0200
Subject: ntdll: Pre-cache file descriptors after opening a file.
---
dlls/kernel32/tests/pipe.c | 6 +++---
dlls/ntdll/file.c | 12 +++++++++++-
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 16a0aab928a..f0e2180ec83 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -1946,7 +1946,7 @@ static void test_CloseHandle(void)
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
ok(!ret, "ReadFile unexpectedly succeeded\n");
- todo_wine ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
ret = GetNamedPipeHandleStateA(hfile, &state, NULL, NULL, NULL, NULL, 0);
ok(ret, "GetNamedPipeHandleState failed with %u\n", GetLastError());
@@ -1957,12 +1957,12 @@ static void test_CloseHandle(void)
SetLastError(0xdeadbeef);
ret = ReadFile(hfile, buffer, 0, &numbytes, NULL);
ok(!ret, "ReadFile unexpectedly succeeded\n");
- todo_wine ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "expected ERROR_BROKEN_PIPE, got %u\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, testdata, sizeof(testdata), &numbytes, NULL);
ok(!ret, "WriteFile unexpectedly succeeded\n");
- todo_wine ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
+ ok(GetLastError() == ERROR_NO_DATA, "expected ERROR_NO_DATA, got %u\n", GetLastError());
CloseHandle(hfile);
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index e9efa92d60a..3b30c741433 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -214,7 +214,17 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
*handle = wine_server_ptr_handle( reply->handle );
}
SERVER_END_REQ;
- if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
+ if (io->u.Status == STATUS_SUCCESS)
+ {
+ /* pre-cache the file descriptor. this is necessary because the fd cannot be
+ * acquired anymore after one end of the pipe has been closed - see kernel32/pipe
+ * tests. */
+ int unix_fd, needs_close;
+ int ret = server_get_unix_fd( *handle, 0, &unix_fd, &needs_close, NULL, NULL );
+ if (!ret && needs_close) close( unix_fd );
+ io->Information = FILE_OPENED;
+ }
+
return io->u.Status;
}
--
2.11.0

View File

@ -1,39 +0,0 @@
From 657d43d3027ea116d3348542eac23d1d915258f0 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 24 Feb 2016 15:45:09 +0100
Subject: server: Do not allow to queue async operation for broken pipes.
---
server/named_pipe.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 2775fcab51..3542c91b4a 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -811,8 +811,20 @@ static obj_handle_t pipe_end_write( struct fd *fd, struct async *async, int bloc
static void pipe_end_queue_async( struct fd *fd, struct async *async, int type, int count )
{
struct pipe_end *pipe_end = get_fd_user( fd );
- if (use_server_io( pipe_end )) no_fd_queue_async( fd, async, type, count );
- else default_fd_queue_async( fd, async, type, count );
+
+ if (use_server_io( pipe_end ))
+ {
+ no_fd_queue_async( fd, async, type, count );
+ return;
+ }
+
+ if (!pipe_end->connection)
+ {
+ set_error( STATUS_PIPE_BROKEN );
+ return;
+ }
+
+ default_fd_queue_async( fd, async, type, count );
}
static void pipe_end_reselect_async( struct fd *fd, struct async_queue *queue )
--
2.11.0

View File

@ -1,6 +0,0 @@
# Fixes: [17195] Support for named pipe message mode (Linux only)
# Fixes: Improve ReadDataAvailable handling in FilePipeLocalInformation class
# Fixes: Set NamedPipeState to FILE_PIPE_CLOSING_STATE on broken pipe in NtQueryInformationFile
# Fixes: Return proper status codes when NtReadFile/NtWriteFile is called on closed (but not disconnected) pipe
Depends: server-Desktop_Refcount
Disabled: true