mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Added patches to fix error code for ReadFile/WriteFile on closed pipe (fixes Wine Staging Bug #348).
This commit is contained in:
parent
a110e490b8
commit
9149fde0ff
2
debian/changelog
vendored
2
debian/changelog
vendored
@ -26,6 +26,8 @@ wine-staging (1.7.45) UNRELEASED; urgency=low
|
||||
Smudde).
|
||||
* Added patch to support AT_ROUND_TO_PAGE flag in NtMapViewOfSection (fixes
|
||||
Wine Staging Bug 347).
|
||||
* Added patches to fix error code for ReadFile/WriteFile on closed pipe (fixes
|
||||
Wine Staging Bug #348).
|
||||
* Removed patch to handle '\r' as whitespace in wbemprox queries (accepted
|
||||
upstream).
|
||||
* Removed patch to make sure OpenClipboard with current owner doesn't fail
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 7939dafa125d74e832436adf2443a19f2689425e Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Fri, 5 Jun 2015 23:06:29 +0200
|
||||
Subject: kernel32/tests: Add tests for behaviour of WriteFile on closed pipe.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/pipe.c | 24 ++++++++++++++++++++----
|
||||
1 file changed, 20 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 654d508..0fca432 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -1189,7 +1189,11 @@ static void test_CloseNamedPipe(void)
|
||||
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);
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
+ todo_wine
|
||||
+ ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
@@ -1224,7 +1228,11 @@ static void test_CloseNamedPipe(void)
|
||||
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);
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
+ todo_wine
|
||||
+ ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
@@ -1265,7 +1273,11 @@ static void test_CloseNamedPipe(void)
|
||||
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);
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
+ todo_wine
|
||||
+ ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
}
|
||||
@@ -1299,7 +1311,11 @@ static void test_CloseNamedPipe(void)
|
||||
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);
|
||||
+
|
||||
+ SetLastError(0xdeadbeef);
|
||||
+ ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
+ todo_wine
|
||||
+ ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
}
|
||||
--
|
||||
2.4.2
|
||||
|
@ -0,0 +1,166 @@
|
||||
From 4b593f0dd46be8b51cb4e1d31efc5e16bc61cdc9 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 6 Jun 2015 01:21:05 +0200
|
||||
Subject: server: Return correct error codes for NtWriteFile when pipes are
|
||||
closed without disconnecting.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/pipe.c | 3 ---
|
||||
dlls/ntdll/file.c | 3 +++
|
||||
server/named_pipe.c | 43 +++++++++++++++++++++++++++++++++++++++++--
|
||||
server/protocol.def | 1 +
|
||||
4 files changed, 45 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 0fca432..4590d3c 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -1192,7 +1192,6 @@ static void test_CloseNamedPipe(void)
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
- todo_wine
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
@@ -1276,7 +1275,6 @@ static void test_CloseNamedPipe(void)
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
- todo_wine
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
@@ -1314,7 +1312,6 @@ static void test_CloseNamedPipe(void)
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ok(!WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
- todo_wine
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hnp);
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index f0d816f..26707e2 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -1198,6 +1198,9 @@ static NTSTATUS write_unix_fd(int fd, const char *buf, ULONG *total, ULONG lengt
|
||||
return STATUS_SUCCESS;
|
||||
else if (errno == EFAULT)
|
||||
return STATUS_INVALID_USER_BUFFER;
|
||||
+ else if (type == FD_TYPE_PIPE && (errno == EPIPE || errno == ECONNRESET))
|
||||
+ return (get_pipe_flags( fd ) & NAMED_PIPE_CLOSED_HANDLE) ?
|
||||
+ STATUS_PIPE_EMPTY : STATUS_PIPE_DISCONNECTED;
|
||||
return FILE_GetNtStatus();
|
||||
}
|
||||
}
|
||||
diff --git a/server/named_pipe.c b/server/named_pipe.c
|
||||
index cd647c4..4718d1b 100644
|
||||
--- a/server/named_pipe.c
|
||||
+++ b/server/named_pipe.c
|
||||
@@ -144,6 +144,7 @@ static const struct object_ops named_pipe_ops =
|
||||
/* server end functions */
|
||||
static void pipe_server_dump( struct object *obj, int verbose );
|
||||
static struct fd *pipe_server_get_fd( struct object *obj );
|
||||
+static int pipe_server_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
static void pipe_server_destroy( struct object *obj);
|
||||
static obj_handle_t pipe_server_flush( struct fd *fd, const async_data_t *async, int blocking );
|
||||
static enum server_fd_type pipe_server_get_fd_type( struct fd *fd );
|
||||
@@ -166,7 +167,7 @@ static const struct object_ops pipe_server_ops =
|
||||
default_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
- fd_close_handle, /* close_handle */
|
||||
+ pipe_server_close_handle, /* close_handle */
|
||||
pipe_server_destroy /* destroy */
|
||||
};
|
||||
|
||||
@@ -188,6 +189,7 @@ static const struct fd_ops pipe_server_fd_ops =
|
||||
static void pipe_client_dump( struct object *obj, int verbose );
|
||||
static int pipe_client_signaled( struct object *obj, struct wait_queue_entry *entry );
|
||||
static struct fd *pipe_client_get_fd( struct object *obj );
|
||||
+static int pipe_client_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
|
||||
static void pipe_client_destroy( struct object *obj );
|
||||
static obj_handle_t pipe_client_flush( struct fd *fd, const async_data_t *async, int blocking );
|
||||
static enum server_fd_type pipe_client_get_fd_type( struct fd *fd );
|
||||
@@ -208,7 +210,7 @@ static const struct object_ops pipe_client_ops =
|
||||
default_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_open_file, /* open_file */
|
||||
- fd_close_handle, /* close_handle */
|
||||
+ pipe_client_close_handle, /* close_handle */
|
||||
pipe_client_destroy /* destroy */
|
||||
};
|
||||
|
||||
@@ -272,6 +274,8 @@ static const struct fd_ops named_pipe_device_fd_ops =
|
||||
default_fd_cancel_async /* cancel_async */
|
||||
};
|
||||
|
||||
+static inline int messagemode_flags( int flags );
|
||||
+
|
||||
static void named_pipe_dump( struct object *obj, int verbose )
|
||||
{
|
||||
struct named_pipe *pipe = (struct named_pipe *) obj;
|
||||
@@ -386,6 +390,23 @@ static void do_disconnect( struct pipe_server *server )
|
||||
server->fd = NULL;
|
||||
}
|
||||
|
||||
+static int pipe_server_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
+{
|
||||
+#ifdef __linux__
|
||||
+ struct pipe_server *server = (struct pipe_server *)obj;
|
||||
+ struct pipe_client *client = server->client;
|
||||
+ int unix_fd;
|
||||
+
|
||||
+ assert( obj->ops == &pipe_server_ops );
|
||||
+ if (obj->handle_count == 1 && client && client->fd && (unix_fd = get_unix_fd( client->fd )) != -1)
|
||||
+ {
|
||||
+ /* set the NAMED_PIPE_CLOSED_HANDLE flag, to distinguish disconnect / closing pipe */
|
||||
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( client->pipe_flags ) | NAMED_PIPE_CLOSED_HANDLE );
|
||||
+ }
|
||||
+#endif
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static void pipe_server_destroy( struct object *obj)
|
||||
{
|
||||
struct pipe_server *server = (struct pipe_server *)obj;
|
||||
@@ -412,6 +433,24 @@ static void pipe_server_destroy( struct object *obj)
|
||||
release_object( server->pipe );
|
||||
}
|
||||
|
||||
+static int pipe_client_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
+{
|
||||
+#ifdef __linux__
|
||||
+ struct pipe_client *client = (struct pipe_client *)obj;
|
||||
+ struct pipe_server *server = client->server;
|
||||
+ int unix_fd;
|
||||
+
|
||||
+ assert( obj->ops == &pipe_client_ops );
|
||||
+ if (obj->handle_count == 1 && server && server->fd && server->state != ps_disconnected_server &&
|
||||
+ server->state != ps_wait_connect && (unix_fd = get_unix_fd( server->fd )) != -1)
|
||||
+ {
|
||||
+ /* set the NAMED_PIPE_CLOSED_HANDLE flag, to distinguish disconnect / closing pipe */
|
||||
+ fcntl( unix_fd, F_SETSIG, messagemode_flags( server->pipe_flags ) | NAMED_PIPE_CLOSED_HANDLE );
|
||||
+ }
|
||||
+#endif
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static void pipe_client_destroy( struct object *obj)
|
||||
{
|
||||
struct pipe_client *client = (struct pipe_client *)obj;
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 428f2e0..4efda91 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -2351,6 +2351,7 @@ enum message_type
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_WRITE 0x0001
|
||||
#define NAMED_PIPE_MESSAGE_STREAM_READ 0x0002
|
||||
#define NAMED_PIPE_NONBLOCKING_MODE 0x0004
|
||||
+#define NAMED_PIPE_CLOSED_HANDLE 0x0008
|
||||
#define NAMED_PIPE_SERVER_END 0x8000
|
||||
|
||||
/* Get named pipe information by handle */
|
||||
--
|
||||
2.4.2
|
||||
|
@ -0,0 +1,53 @@
|
||||
From 2fc1f5ba4668fb0a33ee55118da34a43668fe169 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 6 Jun 2015 01:44:20 +0200
|
||||
Subject: ntdll: Pre-cache file descriptors after opening a file.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/pipe.c | 2 --
|
||||
dlls/ntdll/file.c | 12 +++++++++++-
|
||||
2 files changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
|
||||
index 146b7f7..ddad351 100644
|
||||
--- a/dlls/kernel32/tests/pipe.c
|
||||
+++ b/dlls/kernel32/tests/pipe.c
|
||||
@@ -1235,12 +1235,10 @@ static void test_CloseNamedPipe(void)
|
||||
|
||||
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(0xdeadbeef);
|
||||
ok(!WriteFile(hFile, obuf, sizeof(obuf), &written, NULL), "WriteFile() succeeded\n");
|
||||
- todo_wine
|
||||
ok(GetLastError() == ERROR_NO_DATA, "GetLastError() returned %08x, expected ERROR_NO_DATA\n", GetLastError());
|
||||
|
||||
CloseHandle(hFile);
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index ff0d306..25e9826 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -274,7 +274,17 @@ static NTSTATUS FILE_CreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATT
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
- if (io->u.Status == STATUS_SUCCESS) io->Information = FILE_OPENED;
|
||||
+ if (io->u.Status == STATUS_SUCCESS)
|
||||
+ {
|
||||
+ /* pre-cache the file descriptor. this is necessary because the fd cannot be
|
||||
+ * acquired anymore after one end of the pipe has been closed - see kernel32/pipe
|
||||
+ * tests. */
|
||||
+ int unix_fd, needs_close;
|
||||
+ int ret = server_get_unix_fd( *handle, 0, &unix_fd, &needs_close, NULL, NULL );
|
||||
+ if (!ret && needs_close) close( unix_fd );
|
||||
+ io->Information = FILE_OPENED;
|
||||
+ }
|
||||
+
|
||||
return io->u.Status;
|
||||
}
|
||||
|
||||
--
|
||||
2.4.2
|
||||
|
1
patches/ntdll-AT_ROUND_TO_PAGE/definition
Normal file
1
patches/ntdll-AT_ROUND_TO_PAGE/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: Support for AT_ROUND_TO_PAGE flag in NtMapViewOfSection
|
@ -3178,6 +3178,9 @@ if test "$enable_kernel32_Named_Pipe" -eq 1; then
|
||||
patch_apply kernel32-Named_Pipe/0017-kernel32-tests-Add-additional-tests-for-PIPE_NOWAIT-.patch
|
||||
patch_apply kernel32-Named_Pipe/0018-ntdll-Improve-ReadDataAvailable-handling-in-FilePipe.patch
|
||||
patch_apply kernel32-Named_Pipe/0019-ntdll-Set-NamedPipeState-to-FILE_PIPE_CLOSING_STATE-.patch
|
||||
patch_apply kernel32-Named_Pipe/0020-kernel32-tests-Add-tests-for-behaviour-of-WriteFile-.patch
|
||||
patch_apply kernel32-Named_Pipe/0021-server-Return-correct-error-codes-for-NtWriteFile-wh.patch
|
||||
patch_apply kernel32-Named_Pipe/0022-ntdll-Pre-cache-file-descriptors-after-opening-a-fil.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 },';
|
||||
@ -3198,6 +3201,9 @@ if test "$enable_kernel32_Named_Pipe" -eq 1; then
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add additional tests for PIPE_NOWAIT in overlapped mode.", 1 },';
|
||||
echo '+ { "Qian Hong", "ntdll: Improve ReadDataAvailable handling in FilePipeLocalInformation class support.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Set NamedPipeState to FILE_PIPE_CLOSING_STATE on broken pipe in NtQueryInformationFile.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Add tests for behaviour of WriteFile on closed pipe.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: Return correct error codes for NtWriteFile when pipes are closed without disconnecting.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "ntdll: Pre-cache file descriptors after opening a file.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user