From be0d43d2b1561baff5c77981c7829afcbeb2f4d1 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 14 Jun 2017 15:00:38 +0200 Subject: [PATCH] kernel32-SetFileCompletionNotificationModes: Fix a corner-case related to AcceptEx (thanks Jacek). --- ...32-Don-t-skip-completion-in-AcceptEx.patch | 125 ++++++++++++++++++ patches/patchinstall.sh | 6 +- 2 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 patches/kernel32-SetFileCompletionNotificationModes/0007-ws2_32-Don-t-skip-completion-in-AcceptEx.patch diff --git a/patches/kernel32-SetFileCompletionNotificationModes/0007-ws2_32-Don-t-skip-completion-in-AcceptEx.patch b/patches/kernel32-SetFileCompletionNotificationModes/0007-ws2_32-Don-t-skip-completion-in-AcceptEx.patch new file mode 100644 index 00000000..994f377b --- /dev/null +++ b/patches/kernel32-SetFileCompletionNotificationModes/0007-ws2_32-Don-t-skip-completion-in-AcceptEx.patch @@ -0,0 +1,125 @@ +From 2289d4a4f8a8085bd6fd4eebee829ee22df8abc5 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +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 + diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 3f4d6d30..ba14757f 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -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