mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patch to add support for named pipe message mode.
This commit is contained in:
parent
1f74cc531e
commit
9c6e895b0b
@ -37,7 +37,7 @@ Wine. All those differences are also documented on the
|
||||
Included bug fixes and improvements
|
||||
===================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [11]:**
|
||||
**Bugfixes and features included in the next upcoming release [12]:**
|
||||
|
||||
* Add stub for D3DXComputeTangentFrameEx ([Wine Bug #31984](https://bugs.winehq.org/show_bug.cgi?id=31984))
|
||||
* Add stub for D3DXIntersect
|
||||
@ -48,6 +48,7 @@ Included bug fixes and improvements
|
||||
* Implement ID3DXEffect::FindNextValidTechnique ([Wine Bug #34101](https://bugs.winehq.org/show_bug.cgi?id=34101))
|
||||
* Implement IDXGIOutput::GetDesc
|
||||
* Support for SLGetWindowsInformationDWORD ([Wine Bug #36709](https://bugs.winehq.org/show_bug.cgi?id=36709))
|
||||
* Support for named pipe message mode ([Wine Bug #17195](https://bugs.winehq.org/show_bug.cgi?id=17195))
|
||||
* Try harder to get the host name address in getaddrinfo() ([Wine Bug #29609](https://bugs.winehq.org/show_bug.cgi?id=29609))
|
||||
* Use actual program name if available to describe PulseAudio streams
|
||||
|
||||
|
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -18,6 +18,7 @@ wine-staging (1.7.34) UNRELEASED; urgency=low
|
||||
* Added patch to use actual program name if available to describe PulseAudio streams.
|
||||
* Added patch to try harder to get the host name address in getaddrinfo().
|
||||
* Added patch to fix invalid usage of RegOpenKeyExW in msdmo.
|
||||
* Added patch to add support for named pipe message mode.
|
||||
* Removed patch to implement combase HSTRING objects (accepted upstream).
|
||||
* Removed patch to add fake ProductId to registry (accepted upstream).
|
||||
* Removed patch to implement stubs for MFStartup and MFShutdown (accepted upstream).
|
||||
|
@ -761,15 +761,49 @@ kernel32-GetVolumePathName.ok:
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#16550] Fix for ConnectNamedPort return value in overlapped mode
|
||||
# | * [#17195] Support for named pipe message mode
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/sync.c
|
||||
# | * dlls/kernel32/file.c, dlls/kernel32/sync.c, dlls/kernel32/tests/pipe.c, dlls/ntdll/file.c, server/named_pipe.c,
|
||||
# | server/protocol.def, server/sock.c, server/sock.h
|
||||
# |
|
||||
.INTERMEDIATE: kernel32-Named_Pipe.ok
|
||||
kernel32-Named_Pipe.ok:
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0001-kernel32-ConnectNamedPort-should-return-FALSE-and-se.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0002-kernel32-tests-Add-tests-for-PeekNamedPipe-with-part.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0003-kernel32-tests-Add-tests-for-sending-and-receiving-l.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0004-kernel32-tests-Add-tests-for-closing-named-pipes.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0005-server-Show-warning-if-message-mode-is-not-supported.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0006-ntdll-Unify-similar-code-in-NtReadFile-and-FILE_Asyn.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0007-ntdll-Move-logic-to-check-for-broken-pipe-into-a-sep.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0008-ntdll-Unify-similar-code-in-NtWriteFile-and-FILE_Asy.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0009-server-Use-SOCK_SEQPACKET-socket-in-combination-with.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0010-ntdll-Add-handling-for-partially-received-messages-i.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0011-kernel32-tests-Add-more-tests-with-overlapped-IO-and.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0012-ntdll-Fix-some-tests-for-overlapped-partial-reads.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0013-kernel32-tests-Test-sending-peeking-and-receiving-an.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0014-ntdll-Add-support-for-nonblocking-pipes.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0015-kernel32-tests-Add-tests-for-PIPE_NOWAIT-in-message-.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0016-ntdll-Allow-to-set-PIPE_NOWAIT-on-byte-mode-pipes.patch)
|
||||
$(call APPLY_FILE,kernel32-Named_Pipe/0017-kernel32-tests-Add-additional-tests-for-PIPE_NOWAIT-.patch)
|
||||
@( \
|
||||
echo '+ { "Dan Kegel", "kernel32: ConnectNamedPort should return FALSE and set ERROR_PIPE_CONNECTED on success in overlapped mode.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add tests for PeekNamedPipe with partial received messages.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add tests for sending and receiving large messages.", 1 },'; \
|
||||
echo '+ { "Adam Martinson", "kernel32/tests: Add tests for closing named pipes.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "server: Show warning if message mode is not supported.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Unify similar code in NtReadFile and FILE_AsyncReadService.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Move logic to check for broken pipe into a separate function.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Unify similar code in NtWriteFile and FILE_AsyncWriteService.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "server: Use SOCK_SEQPACKET socket in combination with SO_PEEK_OFF to implement message mode on Unix.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Add handling for partially received messages in NtReadFile.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add more tests with overlapped IO and partial reads from named pipes.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Fix some tests for overlapped partial reads.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Test sending, peeking and receiving an empty message.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Add support for nonblocking pipes.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add tests for PIPE_NOWAIT in message mode.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Allow to set PIPE_NOWAIT on byte-mode pipes.", 1 },'; \
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add additional tests for PIPE_NOWAIT in overlapped mode.", 1 },'; \
|
||||
) > kernel32-Named_Pipe.ok
|
||||
|
||||
# Patchset kernel32-Profile
|
||||
|
@ -0,0 +1,280 @@
|
||||
From a08cd0cbb65ca0c53857c35e40f6d3d910119b22 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 056f95b..a252bc8 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;
|
||||
@@ -109,6 +119,33 @@ static BOOL RpcReadFile(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, LPDWORD
|
||||
return (BOOL)rpcargs.returnValue;
|
||||
}
|
||||
|
||||
+/* 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;
|
||||
@@ -118,6 +155,7 @@ static void test_CreateNamedPipe(int pipemode)
|
||||
char ibuf[32], *pbuf;
|
||||
DWORD written;
|
||||
DWORD readden;
|
||||
+ DWORD leftmsg;
|
||||
DWORD avail;
|
||||
DWORD lpmode;
|
||||
BOOL ret;
|
||||
@@ -232,9 +270,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");
|
||||
@@ -447,6 +497,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");
|
||||
@@ -460,6 +520,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
|
||||
@@ -468,6 +538,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");
|
||||
@@ -480,11 +558,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));
|
||||
@@ -492,6 +586,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");
|
||||
@@ -505,6 +609,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
|
||||
@@ -513,6 +627,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");
|
||||
@@ -525,11 +647,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.1.3
|
||||
|
@ -0,0 +1,168 @@
|
||||
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
|
||||
|
@ -0,0 +1,127 @@
|
||||
From ce6c2fe58743667cec2ce798bbcd938f44d71b80 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Martinson <adam.r.martinson@gmail.com>
|
||||
Date: Tue, 18 Dec 2012 15:52:57 -0600
|
||||
Subject: kernel32/tests: Add tests for closing named pipes.
|
||||
|
||||
Changes in v2:
|
||||
* Add SetLastError().
|
||||
---
|
||||
dlls/kernel32/tests/pipe.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 95 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 246ee30..f42fe5c 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -923,6 +923,100 @@ static void test_CreateNamedPipe_instances_must_match(void)
|
||||
ok(CloseHandle(hnp2), "CloseHandle\n");
|
||||
}
|
||||
|
||||
+static void test_CloseNamedPipe(void)
|
||||
+{
|
||||
+ HANDLE hnp;
|
||||
+ HANDLE hFile;
|
||||
+ static const char obuf[] = "Bit Bucket";
|
||||
+ char ibuf[32];
|
||||
+ DWORD written;
|
||||
+ DWORD readden;
|
||||
+
|
||||
+ hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
|
||||
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
+ /* 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)
|
||||
+ {
|
||||
+ /* Make sure we can read and write a few bytes in both directions */
|
||||
+ memset(ibuf, 0, sizeof(ibuf));
|
||||
+ ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
|
||||
+ ok(written == sizeof(obuf), "write file len 1\n");
|
||||
+ ok(PeekNamedPipe(hFile, NULL, 0, NULL, &readden, NULL), "Peek\n");
|
||||
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
|
||||
+
|
||||
+ /* close server end without disconnecting */
|
||||
+ ok(CloseHandle(hnp), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
+
|
||||
+ todo_wine
|
||||
+ ok(ReadFile(hFile, ibuf, 0, &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
+ ok(readden == 0, "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);
|
||||
+ /* pipe is empty now */
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!ReadFile(hFile, ibuf, 0, &readden, NULL), "ReadFile() succeeded\n");
|
||||
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
+ SetLastError(0);
|
||||
+
|
||||
+ CloseHandle(hFile);
|
||||
+ }
|
||||
+
|
||||
+ hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
|
||||
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
+ /* 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());
|
||||
+
|
||||
+ if (hFile != INVALID_HANDLE_VALUE)
|
||||
+ {
|
||||
+ /* Make sure we can read and write a few bytes in both directions */
|
||||
+ memset(ibuf, 0, sizeof(ibuf));
|
||||
+ ok(WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile\n");
|
||||
+ ok(written == sizeof(obuf), "write file len 1\n");
|
||||
+ ok(PeekNamedPipe(hnp, NULL, 0, NULL, &readden, NULL), "Peek\n");
|
||||
+ ok(readden == sizeof(obuf), "got %d bytes\n", readden);
|
||||
+
|
||||
+ /* close client end without disconnecting */
|
||||
+ ok(CloseHandle(hFile), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
+
|
||||
+ /* you'd think ERROR_MORE_DATA, but no */
|
||||
+ todo_wine
|
||||
+ ok(ReadFile(hnp, ibuf, 0, &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
+ ok(readden == 0, "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);
|
||||
+ /* pipe is empty now */
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!ReadFile(hnp, ibuf, 0, &readden, NULL), "ReadFile() succeeded\n");
|
||||
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
+ SetLastError(0);
|
||||
+
|
||||
+ CloseHandle(hnp);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/** implementation of alarm() */
|
||||
static DWORD CALLBACK alarmThreadMain(LPVOID arg)
|
||||
{
|
||||
@@ -2425,6 +2519,7 @@ START_TEST(pipe)
|
||||
test_NamedPipe_2();
|
||||
test_CreateNamedPipe(PIPE_TYPE_BYTE);
|
||||
test_CreateNamedPipe(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
|
||||
+ test_CloseNamedPipe();
|
||||
test_CreatePipe();
|
||||
test_impersonation();
|
||||
test_overlapped();
|
||||
--
|
||||
2.1.3
|
||||
|
@ -0,0 +1,89 @@
|
||||
From db0a81d0a3513d169335286471969b1fb9c38be1 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 | 1 +
|
||||
server/protocol.def | 1 +
|
||||
3 files changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 5232027..01cef2c 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -3091,6 +3091,7 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||
{
|
||||
struct security_descriptor *sd = NULL;
|
||||
struct object_attributes objattr;
|
||||
+ unsigned int flags;
|
||||
NTSTATUS status;
|
||||
|
||||
TRACE("(%p %x %s %p %x %d %x %d %d %d %d %d %d %p)\n",
|
||||
@@ -3109,16 +3110,17 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||
status = NTDLL_create_struct_sd( attr->SecurityDescriptor, &sd, &objattr.sd_len );
|
||||
if (status != STATUS_SUCCESS) 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->attributes = attr->Attributes;
|
||||
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;
|
||||
@@ -3128,9 +3130,13 @@ NTSTATUS WINAPI NtCreateNamedPipeFile( PHANDLE handle, ULONG access,
|
||||
wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
|
||||
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");
|
||||
+
|
||||
NTDLL_free_struct_sd( sd );
|
||||
return status;
|
||||
}
|
||||
diff --git a/server/named_pipe.c b/server/named_pipe.c
|
||||
index 047b62c..81741de 100644
|
||||
--- a/server/named_pipe.c
|
||||
+++ b/server/named_pipe.c
|
||||
@@ -965,6 +965,7 @@ DECL_HANDLER(create_named_pipe)
|
||||
return;
|
||||
}
|
||||
|
||||
+ reply->flags = req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
|
||||
reply->handle = 0;
|
||||
|
||||
if (!objattr_is_valid( objattr, get_req_data_size() ))
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index fc6bec5..503b02f 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -2283,6 +2283,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.1.3
|
||||
|
@ -0,0 +1,169 @@
|
||||
From a1d2578281a218b32b84d4be18c75680439f60c9 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 | 106 +++++++++++++++++++++++-------------------------------
|
||||
1 file changed, 45 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 01cef2c..a20c3e8 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -411,50 +411,63 @@ 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:
|
||||
+ return length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
||||
+ case FD_TYPE_SERIAL:
|
||||
+ return STATUS_PENDING;
|
||||
+ 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)
|
||||
*/
|
||||
static NTSTATUS FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, NTSTATUS status, void **apc)
|
||||
{
|
||||
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
|
||||
- {
|
||||
- /* if we only have to read the available data, and none is available,
|
||||
- * simply cancel the request. If data was available, it has been read
|
||||
- * while in by previous call (NtDelayExecution)
|
||||
- */
|
||||
- status = (fileio->avail_mode) ? STATUS_SUCCESS : STATUS_PENDING;
|
||||
- }
|
||||
- }
|
||||
break;
|
||||
|
||||
case STATUS_TIMEOUT:
|
||||
@@ -603,7 +616,6 @@ static NTSTATUS get_io_avail_mode( HANDLE handle, enum server_fd_type type, BOOL
|
||||
return status;
|
||||
}
|
||||
|
||||
-
|
||||
/******************************************************************************
|
||||
* NtReadFile [NTDLL.@]
|
||||
* ZwReadFile [NTDLL.@]
|
||||
@@ -696,37 +708,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:
|
||||
- status = length ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
||||
- goto done;
|
||||
- case FD_TYPE_SERIAL:
|
||||
- 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.1.3
|
||||
|
@ -0,0 +1,107 @@
|
||||
From 32d3c69ae680a7b6f71e203ca33f882eb0b69c47 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 a20c3e8..8de4b98 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -411,6 +411,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)
|
||||
@@ -1557,44 +1582,22 @@ NTSTATUS WINAPI NtFsControlFile(HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc
|
||||
if ((status = server_get_unix_fd( handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL )))
|
||||
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.1.3
|
||||
|
@ -0,0 +1,130 @@
|
||||
From cbfe442e44c7297e524c1e3b6ae077b2c84d4ab5 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 8de4b98..e8a1066 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -926,6 +926,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)
|
||||
@@ -933,7 +964,7 @@ NTSTATUS WINAPI NtReadFileScatter( HANDLE file, HANDLE event, PIO_APC_ROUTINE ap
|
||||
static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTATUS status, void **apc)
|
||||
{
|
||||
async_fileio_write *fileio = user;
|
||||
- int result, fd, needs_close;
|
||||
+ int fd, needs_close;
|
||||
enum server_fd_type type;
|
||||
|
||||
switch (status)
|
||||
@@ -943,24 +974,8 @@ static NTSTATUS FILE_AsyncWriteService(void *user, IO_STATUS_BLOCK *iosb, NTSTAT
|
||||
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:
|
||||
@@ -1120,32 +1135,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.1.3
|
||||
|
@ -0,0 +1,542 @@
|
||||
From b52ac9f6c1d7391d350e9b7cefbcbb0ac2b62516 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.
|
||||
|
||||
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.
|
||||
---
|
||||
dlls/kernel32/sync.c | 2 +-
|
||||
dlls/kernel32/tests/pipe.c | 9 ----
|
||||
dlls/ntdll/file.c | 106 ++++++++++++++++++++++++++++++++++++-------
|
||||
server/named_pipe.c | 109 ++++++++++++++++++++++++++++++++++++---------
|
||||
server/sock.c | 4 +-
|
||||
server/sock.h | 26 +++++++++++
|
||||
6 files changed, 207 insertions(+), 49 deletions(-)
|
||||
create mode 100644 server/sock.h
|
||||
|
||||
diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
|
||||
index 12887ff..5be278e 100644
|
||||
--- a/dlls/kernel32/sync.c
|
||||
+++ b/dlls/kernel32/sync.c
|
||||
@@ -1472,7 +1472,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 f42fe5c..743144e 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -285,7 +285,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);
|
||||
@@ -509,12 +508,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
|
||||
@@ -532,12 +529,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");
|
||||
@@ -598,12 +593,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
|
||||
@@ -621,12 +614,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 e8a1066..5cbfa40 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -76,6 +76,10 @@
|
||||
# include <valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
+#ifndef SO_PEEK_OFF
|
||||
+#define SO_PEEK_OFF 42
|
||||
+#endif
|
||||
+
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "ntstatus.h"
|
||||
@@ -436,18 +440,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;
|
||||
@@ -462,16 +505,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 */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -929,13 +973,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;
|
||||
@@ -944,6 +989,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)
|
||||
@@ -1577,20 +1633,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 81741de..0631159 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,36 @@ static struct pipe_server *find_available_server( struct named_pipe *pipe )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/* check if message mode named pipes are supported */
|
||||
+static int check_messagemode(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 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,7 +857,10 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc
|
||||
|
||||
if ((client = create_pipe_client( options, pipe->flags )))
|
||||
{
|
||||
- if (!socketpair( PF_UNIX, SOCK_STREAM, 0, fds ))
|
||||
+ type = ((pipe->flags & NAMED_PIPE_MESSAGE_STREAM_WRITE) && check_messagemode()) ?
|
||||
+ SOCK_SEQPACKET : SOCK_STREAM;
|
||||
+
|
||||
+ if (!socketpair( PF_UNIX, type, 0, fds ))
|
||||
{
|
||||
assert( !server->fd );
|
||||
|
||||
@@ -840,32 +870,53 @@ 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)
|
||||
- {
|
||||
- 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)
|
||||
+ /* 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_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->fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->obj, options );
|
||||
- server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options );
|
||||
- if (client->fd && server->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))
|
||||
{
|
||||
- allow_fd_caching( client->fd );
|
||||
- allow_fd_caching( server->fd );
|
||||
- fd_copy_completion( server->ioctl_fd, server->fd );
|
||||
- if (server->state == ps_wait_open)
|
||||
- fd_async_wake_up( server->ioctl_fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
|
||||
- set_server_state( server, ps_connected_server );
|
||||
- server->client = client;
|
||||
- client->server = server;
|
||||
+ fcntl( fds[0], F_SETSIG, server->pipe_flags );
|
||||
+ fcntl( fds[1], F_SETSIG, client->pipe_flags );
|
||||
+
|
||||
+ client->fd = create_anonymous_fd( &pipe_client_fd_ops, fds[1], &client->obj, options );
|
||||
+ server->fd = create_anonymous_fd( &pipe_server_fd_ops, fds[0], &server->obj, server->options );
|
||||
+ if (client->fd && server->fd)
|
||||
+ {
|
||||
+ allow_fd_caching( client->fd );
|
||||
+ allow_fd_caching( server->fd );
|
||||
+ fd_copy_completion( server->ioctl_fd, server->fd );
|
||||
+ if (server->state == ps_wait_open)
|
||||
+ fd_async_wake_up( server->ioctl_fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
|
||||
+ set_server_state( server, ps_connected_server );
|
||||
+ server->client = client;
|
||||
+ client->server = server;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ release_object( client );
|
||||
+ client = NULL;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
+ sock_set_error();
|
||||
release_object( client );
|
||||
client = NULL;
|
||||
}
|
||||
@@ -965,7 +1016,10 @@ DECL_HANDLER(create_named_pipe)
|
||||
return;
|
||||
}
|
||||
|
||||
- reply->flags = req->flags & ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
|
||||
+ reply->flags = req->flags;
|
||||
+ if (!check_messagemode())
|
||||
+ reply->flags &= ~(NAMED_PIPE_MESSAGE_STREAM_WRITE | NAMED_PIPE_MESSAGE_STREAM_READ);
|
||||
+
|
||||
reply->handle = 0;
|
||||
|
||||
if (!objattr_is_valid( objattr, get_req_data_size() ))
|
||||
@@ -1065,6 +1119,7 @@ DECL_HANDLER(set_named_pipe_info)
|
||||
{
|
||||
struct pipe_server *server;
|
||||
struct pipe_client *client = NULL;
|
||||
+ int unix_fd;
|
||||
|
||||
server = get_pipe_server_obj( current->process, req->handle, FILE_WRITE_ATTRIBUTES );
|
||||
if (!server)
|
||||
@@ -1087,10 +1142,20 @@ DECL_HANDLER(set_named_pipe_info)
|
||||
else if (client)
|
||||
{
|
||||
client->pipe_flags = server->pipe->flags | req->flags;
|
||||
+ #ifdef __linux__
|
||||
+ if (client->fd && (unix_fd = get_unix_fd( client->fd )) != -1)
|
||||
+ fcntl( unix_fd, F_SETSIG, client->pipe_flags );
|
||||
+ clear_error();
|
||||
+ #endif
|
||||
}
|
||||
else
|
||||
{
|
||||
server->pipe_flags = server->pipe->flags | req->flags;
|
||||
+ #ifdef __linux__
|
||||
+ if (server->fd && (unix_fd = get_unix_fd( server->fd )) != -1)
|
||||
+ fcntl( unix_fd, F_SETSIG, server->pipe_flags );
|
||||
+ clear_error();
|
||||
+ #endif
|
||||
}
|
||||
|
||||
if (client)
|
||||
diff --git a/server/sock.c b/server/sock.c
|
||||
index 7c0212e..73a2549 100644
|
||||
--- a/server/sock.c
|
||||
+++ b/server/sock.c
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
#include "process.h"
|
||||
#include "file.h"
|
||||
+#include "sock.h"
|
||||
#include "handle.h"
|
||||
#include "thread.h"
|
||||
#include "request.h"
|
||||
@@ -127,7 +128,6 @@ static void sock_cancel_async( struct fd *fd, struct process *process, struct th
|
||||
|
||||
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 =
|
||||
{
|
||||
@@ -910,7 +910,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 0000000..21551b4
|
||||
--- /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.1.3
|
||||
|
@ -0,0 +1,321 @@
|
||||
From 8d70c149974dafbdabc76cf2fb9daf9108a853f2 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 11 Aug 2014 18:20:52 +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 | 53 +++++-----------------------------------------
|
||||
dlls/ntdll/file.c | 28 ++++++++++++++++++------
|
||||
2 files changed, 27 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 743144e..6a27826 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -304,9 +304,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);
|
||||
@@ -327,15 +325,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);
|
||||
@@ -397,9 +391,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");
|
||||
@@ -429,9 +421,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))
|
||||
@@ -440,10 +430,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);
|
||||
@@ -461,9 +449,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))
|
||||
@@ -474,9 +460,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");
|
||||
@@ -487,9 +471,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");
|
||||
@@ -514,16 +496,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;
|
||||
@@ -536,7 +514,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 */
|
||||
@@ -553,13 +530,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;
|
||||
@@ -599,16 +573,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;
|
||||
@@ -621,7 +591,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 */
|
||||
@@ -638,13 +607,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;
|
||||
@@ -750,15 +716,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);
|
||||
@@ -948,7 +910,6 @@ static void test_CloseNamedPipe(void)
|
||||
/* close server end without disconnecting */
|
||||
ok(CloseHandle(hnp), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
|
||||
- todo_wine
|
||||
ok(ReadFile(hFile, ibuf, 0, &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
ok(readden == 0, "got %d bytes\n", readden);
|
||||
|
||||
@@ -990,7 +951,6 @@ static void test_CloseNamedPipe(void)
|
||||
ok(CloseHandle(hFile), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
|
||||
/* you'd think ERROR_MORE_DATA, but no */
|
||||
- todo_wine
|
||||
ok(ReadFile(hnp, ibuf, 0, &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
ok(readden == 0, "got %d bytes\n", readden);
|
||||
|
||||
@@ -2460,7 +2420,6 @@ static void test_readfileex_pending(void)
|
||||
num_bytes = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = ReadFile(server, read_buf, 0, &num_bytes, &overlapped);
|
||||
-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);
|
||||
@@ -2476,11 +2435,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 5cbfa40..81f941d 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -415,7 +415,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;
|
||||
@@ -444,7 +444,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
|
||||
@@ -490,10 +497,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:
|
||||
@@ -501,11 +510,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 STATUS_PENDING;
|
||||
+ 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;
|
||||
@@ -863,7 +879,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.1.3
|
||||
|
@ -0,0 +1,188 @@
|
||||
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
|
||||
|
@ -0,0 +1,85 @@
|
||||
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
|
||||
|
@ -0,0 +1,384 @@
|
||||
From 186746674015db7533c9b25c8b633c2e3881334e 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 | 336 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 336 insertions(+)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 53f8f30..89a13f5 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -337,6 +337,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");
|
||||
@@ -455,6 +595,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");
|
||||
@@ -938,6 +1205,41 @@ static void test_CloseNamedPipe(void)
|
||||
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)
|
||||
+ {
|
||||
+ ok(WriteFile(hnp, obuf, 0, &written, NULL), "WriteFile\n");
|
||||
+ ok(written == 0, "write file len 1\n");
|
||||
+
|
||||
+ /* close server end without disconnecting */
|
||||
+ ok(CloseHandle(hnp), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
+
|
||||
+ todo_wine
|
||||
+ ok(ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
+ ok(readden == 0, "got %d bytes\n", readden);
|
||||
+ /* pipe is empty now */
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!ReadFile(hFile, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
|
||||
+ todo_wine
|
||||
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
+ SetLastError(0);
|
||||
+
|
||||
+ CloseHandle(hFile);
|
||||
+ }
|
||||
+
|
||||
+ hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
|
||||
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
+ /* 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());
|
||||
+
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* Make sure we can read and write a few bytes in both directions */
|
||||
@@ -966,6 +1268,40 @@ static void test_CloseNamedPipe(void)
|
||||
|
||||
CloseHandle(hnp);
|
||||
}
|
||||
+
|
||||
+ hnp = CreateNamedPipeA(PIPENAME, PIPE_ACCESS_DUPLEX,
|
||||
+ PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
|
||||
+ /* 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)
|
||||
+ {
|
||||
+ ok(WriteFile(hFile, obuf, 0, &written, NULL), "WriteFile\n");
|
||||
+ ok(written == 0, "write file len 1\n");
|
||||
+
|
||||
+ /* close server end without disconnecting */
|
||||
+ ok(CloseHandle(hFile), "CloseHandle() failed: %08x\n", GetLastError());
|
||||
+
|
||||
+ todo_wine
|
||||
+ ok(ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() failed: %08x\n", GetLastError());
|
||||
+ ok(readden == 0, "got %d bytes\n", readden);
|
||||
+ /* pipe is empty now */
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!ReadFile(hnp, ibuf, sizeof(ibuf), &readden, NULL), "ReadFile() succeeded\n");
|
||||
+ ok(GetLastError() == ERROR_BROKEN_PIPE, "GetLastError() returned %08x, expected ERROR_BROKEN_PIPE\n", GetLastError());
|
||||
+ SetLastError(0);
|
||||
+
|
||||
+ CloseHandle(hnp);
|
||||
+ }
|
||||
}
|
||||
|
||||
/** implementation of alarm() */
|
||||
--
|
||||
2.1.3
|
||||
|
@ -0,0 +1,52 @@
|
||||
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
|
||||
|
@ -0,0 +1,126 @@
|
||||
From bd5a5c11c29a52bd7891e8c3da6ff77846085ecd 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 89a13f5..49a1017 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -2527,6 +2527,101 @@ static void test_overlapped(void)
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
+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;
|
||||
@@ -2952,6 +3047,7 @@ START_TEST(pipe)
|
||||
test_CreatePipe();
|
||||
test_impersonation();
|
||||
test_overlapped();
|
||||
+ test_nowait();
|
||||
test_NamedPipeHandleState();
|
||||
test_readfileex_pending();
|
||||
}
|
||||
--
|
||||
2.1.3
|
||||
|
@ -0,0 +1,112 @@
|
||||
From f0904b45622aa329e02dba205bfedd78379cde98 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 49a1017..f90401a 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -2527,7 +2527,7 @@ static void test_overlapped(void)
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
-static void test_nowait(void)
|
||||
+static void test_nowait(int pipemode)
|
||||
{
|
||||
HANDLE hnp;
|
||||
HANDLE hFile;
|
||||
@@ -2538,7 +2538,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,
|
||||
@@ -2569,7 +2569,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 */
|
||||
@@ -2593,8 +2593,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);
|
||||
@@ -2606,8 +2616,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);
|
||||
@@ -3047,7 +3067,8 @@ START_TEST(pipe)
|
||||
test_CreatePipe();
|
||||
test_impersonation();
|
||||
test_overlapped();
|
||||
- test_nowait();
|
||||
+ test_nowait(PIPE_TYPE_BYTE);
|
||||
+ test_nowait(PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
|
||||
test_NamedPipeHandleState();
|
||||
test_readfileex_pending();
|
||||
}
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index ba3814e..e564bdd 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -495,6 +495,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.1.3
|
||||
|
@ -0,0 +1,333 @@
|
||||
From c0f999092e3f10053fb710d7f2ab134f9fdea592 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 | 295 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 294 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index f90401a..2107294 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -2747,7 +2747,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];
|
||||
@@ -2905,6 +2905,160 @@ 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);
|
||||
+ todo_wine
|
||||
+ 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 %d, got %lu\n", 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 %d, got %lu\n", 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,
|
||||
@@ -3043,6 +3197,145 @@ 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);
|
||||
+ todo_wine
|
||||
+ 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 %d, got %lu\n", 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 %d, got %lu\n", 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.1.3
|
||||
|
@ -1 +1,2 @@
|
||||
Fixes: [16550] Fix for ConnectNamedPort return value in overlapped mode
|
||||
Fixes: [17195] Support for named pipe message mode
|
||||
|
@ -1,22 +1,22 @@
|
||||
From 8acfd293ecd49b7cad340dc90e6ea6b0ed07289a Mon Sep 17 00:00:00 2001
|
||||
From 9986fca2fe9cc57f9c7a01f08fc6a826a398de47 Mon Sep 17 00:00:00 2001
|
||||
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
|
||||
Date: Thu, 16 Jan 2014 19:08:30 -0700
|
||||
Subject: ws2_32: Add support for TF_DISCONNECT and TF_REUSE_SOCKET to
|
||||
TransmitFile.
|
||||
|
||||
---
|
||||
dlls/ws2_32/socket.c | 17 ++++++++++--
|
||||
dlls/ws2_32/tests/sock.c | 11 +++++++-
|
||||
include/winsock.h | 1 +
|
||||
server/protocol.def | 6 +++++
|
||||
server/sock.c | 66 +++++++++++++++++++++++++++++++++++++++-------
|
||||
5 files changed, 89 insertions(+), 12 deletions(-)
|
||||
dlls/ws2_32/socket.c | 17 +++++++++++--
|
||||
dlls/ws2_32/tests/sock.c | 11 +++++++-
|
||||
include/winsock.h | 1 +
|
||||
server/protocol.def | 6 +++++
|
||||
server/sock.c | 65 +++++++++++++++++++++++++++++++++++++++++-------
|
||||
5 files changed, 88 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
||||
index 42c7832..ddb50a5 100644
|
||||
index dbcadb3..e74aa7c 100644
|
||||
--- a/dlls/ws2_32/socket.c
|
||||
+++ b/dlls/ws2_32/socket.c
|
||||
@@ -2558,6 +2558,18 @@ static BOOL WS2_transmitfile_base( SOCKET s, HANDLE h, DWORD total_bytes, DWORD
|
||||
@@ -2560,6 +2560,18 @@ static BOOL WS2_transmitfile_base( SOCKET s, HANDLE h, DWORD total_bytes, DWORD
|
||||
if (buffers && WS_send( s, buffers->Tail, buffers->TailLength, 0 ) == SOCKET_ERROR)
|
||||
goto cleanup;
|
||||
|
||||
@ -35,7 +35,7 @@ index 42c7832..ddb50a5 100644
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
@@ -2599,6 +2611,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
@@ -2601,6 +2613,7 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
{
|
||||
union generic_unix_sockaddr uaddr;
|
||||
unsigned int uaddrlen = sizeof(uaddr);
|
||||
@ -43,7 +43,7 @@ index 42c7832..ddb50a5 100644
|
||||
IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)overlapped;
|
||||
struct ws2_transmitfile_async *wsa;
|
||||
int status, fd;
|
||||
@@ -2619,8 +2632,8 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
@@ -2621,8 +2634,8 @@ static BOOL WINAPI WS2_TransmitFile( SOCKET s, HANDLE h, DWORD total_bytes, DWOR
|
||||
return FALSE;
|
||||
}
|
||||
release_sock_fd( s, fd );
|
||||
@ -55,10 +55,10 @@ index 42c7832..ddb50a5 100644
|
||||
if (!overlapped)
|
||||
return WS2_transmitfile_base( s, h, total_bytes, bytes_per_send, overlapped, buffers, flags );
|
||||
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
|
||||
index dbb762a..5bf23a0 100644
|
||||
index 9708cf1..cf9ba23 100644
|
||||
--- a/dlls/ws2_32/tests/sock.c
|
||||
+++ b/dlls/ws2_32/tests/sock.c
|
||||
@@ -6684,8 +6684,17 @@ static void test_TransmitFile(void)
|
||||
@@ -7008,8 +7008,17 @@ static void test_TransmitFile(void)
|
||||
ok(iret == WAIT_OBJECT_0, "Overlapped TransmitFile failed.\n");
|
||||
compare_file(file, dest, 10);
|
||||
|
||||
@ -78,10 +78,10 @@ index dbb762a..5bf23a0 100644
|
||||
bret = pTransmitFile(client, NULL, 0, 0, NULL, NULL, 0);
|
||||
err = WSAGetLastError();
|
||||
diff --git a/include/winsock.h b/include/winsock.h
|
||||
index 06e6309..4426557 100644
|
||||
index 50237e8..e53aa1e 100644
|
||||
--- a/include/winsock.h
|
||||
+++ b/include/winsock.h
|
||||
@@ -810,6 +810,7 @@ typedef struct WS(WSAData)
|
||||
@@ -814,6 +814,7 @@ typedef struct WS(WSAData)
|
||||
|
||||
/* internal per-socket flags */
|
||||
#ifdef __WINESRC__
|
||||
@ -90,7 +90,7 @@ index 06e6309..4426557 100644
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index c9270ea..328f8a8 100644
|
||||
index fc6bec5..64e3f18 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -1208,6 +1208,12 @@ enum server_fd_type
|
||||
@ -107,7 +107,7 @@ index c9270ea..328f8a8 100644
|
||||
@REQ(set_socket_event)
|
||||
obj_handle_t handle; /* handle to the socket */
|
||||
diff --git a/server/sock.c b/server/sock.c
|
||||
index 4adad0f..15afe81 100644
|
||||
index 7c0212e..4d51950 100644
|
||||
--- a/server/sock.c
|
||||
+++ b/server/sock.c
|
||||
@@ -80,6 +80,7 @@
|
||||
@ -118,16 +118,15 @@ index 4adad0f..15afe81 100644
|
||||
#define FD_WINE_LISTENING 0x10000000
|
||||
#define FD_WINE_NONBLOCKING 0x20000000
|
||||
#define FD_WINE_CONNECTED 0x40000000
|
||||
@@ -124,6 +125,8 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type,
|
||||
@@ -124,6 +125,7 @@ static enum server_fd_type sock_get_fd_type( struct fd *fd );
|
||||
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
|
||||
static void sock_reselect_async( struct fd *fd, struct async_queue *queue );
|
||||
static void sock_cancel_async( struct fd *fd, struct process *process, struct thread *thread, client_ptr_t iosb );
|
||||
|
||||
+static int sock_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
+
|
||||
|
||||
static int sock_get_ntstatus( int err );
|
||||
static int sock_get_error( int err );
|
||||
static void sock_set_error(void);
|
||||
@@ -144,7 +147,7 @@ static const struct object_ops sock_ops =
|
||||
@@ -145,7 +147,7 @@ static const struct object_ops sock_ops =
|
||||
default_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
@ -136,7 +135,7 @@ index 4adad0f..15afe81 100644
|
||||
sock_destroy /* destroy */
|
||||
};
|
||||
|
||||
@@ -583,6 +586,47 @@ static struct fd *sock_get_fd( struct object *obj )
|
||||
@@ -585,6 +587,47 @@ static struct fd *sock_get_fd( struct object *obj )
|
||||
return (struct fd *)grab_object( sock->fd );
|
||||
}
|
||||
|
||||
@ -184,7 +183,7 @@ index 4adad0f..15afe81 100644
|
||||
static void sock_destroy( struct object *obj )
|
||||
{
|
||||
struct sock *sock = (struct sock *)obj;
|
||||
@@ -630,15 +674,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
||||
@@ -633,15 +676,8 @@ static struct object *create_socket( int family, int type, int protocol, unsigne
|
||||
struct sock *sock;
|
||||
int sockfd;
|
||||
|
||||
@ -201,7 +200,7 @@ index 4adad0f..15afe81 100644
|
||||
if (!(sock = alloc_object( &sock_ops )))
|
||||
{
|
||||
close( sockfd );
|
||||
@@ -963,6 +1000,17 @@ DECL_HANDLER(accept_into_socket)
|
||||
@@ -969,6 +1005,17 @@ DECL_HANDLER(accept_into_socket)
|
||||
release_object( sock );
|
||||
}
|
||||
|
||||
@ -220,5 +219,5 @@ index 4adad0f..15afe81 100644
|
||||
DECL_HANDLER(set_socket_event)
|
||||
{
|
||||
--
|
||||
1.7.9.5
|
||||
2.1.3
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user