kernel32-SetFileCompletionNotificationModes: Fix a corner-case related to AcceptEx (thanks Jacek).

This commit is contained in:
Sebastian Lackner 2017-06-14 15:00:38 +02:00
parent 2420bc89ed
commit be0d43d2b1
2 changed files with 129 additions and 2 deletions

View File

@ -0,0 +1,125 @@
From 2289d4a4f8a8085bd6fd4eebee829ee22df8abc5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 14 Jun 2017 14:47:33 +0200
Subject: ws2_32: Don't skip completion in AcceptEx.
Spotted by Jacek Caban.
FIXME: It would be better to get rid of the STATUS_MORE_PROCESSING_REQUIRED handling.
---
dlls/ws2_32/socket.c | 13 +++++++------
dlls/ws2_32/tests/sock.c | 5 +++++
server/fd.c | 2 +-
server/protocol.def | 1 +
4 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 886ff82dba9..0340547dce0 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -654,7 +654,7 @@ static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, in
int WSAIOCTL_GetInterfaceCount(void);
int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
-static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information );
+static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information, BOOL force );
#define MAP_OPTION(opt) { WS_##opt, opt }
@@ -2510,7 +2510,7 @@ static NTSTATUS WS2_async_accept_recv( void *user, IO_STATUS_BLOCK *iosb, NTSTAT
return status;
if (wsa->cvalue)
- WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information );
+ WS_AddCompletion( HANDLE2SOCKET(wsa->listen_socket), wsa->cvalue, iosb->u.Status, iosb->Information, TRUE );
release_async_io( &wsa->io );
return status;
@@ -5139,7 +5139,7 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
overlapped->Internal = status;
overlapped->InternalHigh = total;
if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL );
- if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, status, total );
+ if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, status, total, FALSE );
}
if (!status)
@@ -5534,7 +5534,7 @@ int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
/* helper to send completion messages for client-only i/o operation case */
static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus,
- ULONG Information )
+ ULONG Information, BOOL force )
{
SERVER_START_REQ( add_fd_completion )
{
@@ -5542,6 +5542,7 @@ static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS C
req->cvalue = CompletionValue;
req->status = CompletionStatus;
req->information = Information;
+ req->force = force;
wine_server_call( req );
}
SERVER_END_REQ;
@@ -5686,7 +5687,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if (lpNumberOfBytesSent) *lpNumberOfBytesSent = n;
if (!wsa->completion_func)
{
- if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
+ if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
HeapFree( GetProcessHeap(), 0, wsa );
}
@@ -7888,7 +7889,7 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
iosb->Information = n;
if (!wsa->completion_func)
{
- if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
+ if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n, FALSE );
if (lpOverlapped->hEvent) SetEvent( lpOverlapped->hEvent );
HeapFree( GetProcessHeap(), 0, wsa );
}
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index acbec940954..c7f0c01112a 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -9939,6 +9939,11 @@ static void test_completion_port(void)
ok(io_port != NULL, "failed to create completion port %u\n", GetLastError());
io_info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
+ status = pNtSetInformationFile((HANDLE)src, &io, &io_info, sizeof(io_info), FileIoCompletionNotificationInformation);
+ ok(status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS) /* XP */,
+ "expected STATUS_SUCCESS, got %08x\n", status);
+
+ io_info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile((HANDLE)dest, &io, &io_info, sizeof(io_info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS) /* XP */,
"expected STATUS_SUCCESS, got %08x\n", status);
diff --git a/server/fd.c b/server/fd.c
index 1b82bd30860..94febea990b 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -2704,7 +2704,7 @@ DECL_HANDLER(add_fd_completion)
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
if (fd)
{
- if (fd->completion && (!(fd->comp_flags & COMPLETION_SKIP_ON_SUCCESS) || req->status))
+ if (fd->completion && (!(fd->comp_flags & COMPLETION_SKIP_ON_SUCCESS) || req->status || req->force))
add_completion( fd->completion, fd->comp_key, req->cvalue, req->status, req->information );
release_object( fd );
}
diff --git a/server/protocol.def b/server/protocol.def
index 3912908e519..ba047d5581c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3725,6 +3725,7 @@ struct handle_info
apc_param_t cvalue; /* completion value */
apc_param_t information; /* IO_STATUS_BLOCK Information */
unsigned int status; /* completion status */
+ int force; /* don't check if skip-on-success is set */
@END
--
2.13.1

View File

@ -5088,8 +5088,8 @@ fi
# | * [#38960] Add support for kernel32.SetFileCompletionNotificationModes
# |
# | Modified files:
# | * dlls/kernel32/file.c, dlls/ntdll/file.c, dlls/ntdll/tests/file.c, dlls/ntdll/tests/pipe.c, dlls/ws2_32/tests/sock.c,
# | server/async.c, server/fd.c, server/file.h, server/protocol.def
# | * dlls/kernel32/file.c, dlls/ntdll/file.c, dlls/ntdll/tests/file.c, dlls/ntdll/tests/pipe.c, dlls/ws2_32/socket.c,
# | dlls/ws2_32/tests/sock.c, server/async.c, server/fd.c, server/file.h, server/protocol.def
# |
if test "$enable_kernel32_SetFileCompletionNotificationModes" -eq 1; then
patch_apply kernel32-SetFileCompletionNotificationModes/0001-ntdll-Implement-FileIoCompletionNotificationInformat.patch
@ -5098,6 +5098,7 @@ if test "$enable_kernel32_SetFileCompletionNotificationModes" -eq 1; then
patch_apply kernel32-SetFileCompletionNotificationModes/0004-ntdll-tests-Add-more-tests-for-FileIoCompletionNotif.patch
patch_apply kernel32-SetFileCompletionNotificationModes/0005-ntdll-Do-not-require-unix-fd-for-FileIoCompletionNot.patch
patch_apply kernel32-SetFileCompletionNotificationModes/0006-server-Skip-async-completion-when-possible.patch
patch_apply kernel32-SetFileCompletionNotificationModes/0007-ws2_32-Don-t-skip-completion-in-AcceptEx.patch
(
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Implement FileIoCompletionNotificationInformation info class.", 2 },';
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Allow to query file IO completion notification mode.", 1 },';
@ -5105,6 +5106,7 @@ if test "$enable_kernel32_SetFileCompletionNotificationModes" -eq 1; then
printf '%s\n' '+ { "Sebastian Lackner", "ntdll/tests: Add more tests for FileIoCompletionNotificationInformation.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Do not require unix fd for FileIoCompletionNotificationInformation.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "server: Skip async completion when possible.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "ws2_32: Don'\''t skip completion in AcceptEx.", 1 },';
) >> "$patchlist"
fi