mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
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:
parent
dcd4faf1c9
commit
d4918b4305
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user