Module: wine Branch: master Commit: e32252efae7f249b611015d32199057c0914e02b URL: http://source.winehq.org/git/wine.git/?a=commit;h=e32252efae7f249b611015d321...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Jun 4 17:44:24 2007 +0200
ws2_32: Queue a proper user APC also on immediate success in WSARecvFrom/WSASendTo.
---
dlls/ws2_32/socket.c | 133 +++++++++++++++++++++++++++++++------------------- 1 files changed, 82 insertions(+), 51 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 4c87d23..2b7efdc 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2634,37 +2634,37 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags ); if (n != -1 || errno != EINTR) break; } - if (n == -1) + if (n == -1 && errno != EAGAIN) { - if (errno != EAGAIN) + err = wsaErrno(); + goto error; + } + + if ((lpOverlapped || lpCompletionRoutine) && + !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) + { + IO_STATUS_BLOCK *iosb; + struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) ); + + if ( !wsa ) { - err = wsaErrno(); + err = WSAEFAULT; goto error; } + release_sock_fd( s, fd );
- if ((lpOverlapped || lpCompletionRoutine) && - !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) - { - IO_STATUS_BLOCK *iosb; - struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) ); - - if ( !wsa ) - { - err = WSAEFAULT; - goto error; - } - release_sock_fd( s, fd ); - - wsa->hSocket = SOCKET2HANDLE(s); - wsa->addr = (struct WS_sockaddr *)to; - wsa->addrlen.val = tolen; - wsa->flags = 0; - wsa->user_overlapped = lpOverlapped; - wsa->completion_func = lpCompletionRoutine; - wsa->n_iovecs = dwBufferCount; - memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) ); + wsa->hSocket = SOCKET2HANDLE(s); + wsa->addr = (struct WS_sockaddr *)to; + wsa->addrlen.val = tolen; + wsa->flags = 0; + wsa->user_overlapped = lpOverlapped; + wsa->completion_func = lpCompletionRoutine; + wsa->n_iovecs = dwBufferCount; + memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
- iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb; + iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb; + if (n == -1) + { iosb->u.Status = STATUS_PENDING; iosb->Information = 0;
@@ -2689,6 +2689,18 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, WSASetLastError( NtStatusToWSAError( err )); return SOCKET_ERROR; } + + iosb->u.Status = STATUS_SUCCESS; + iosb->Information = n; + *lpNumberOfBytesSent = n; + if (!wsa->completion_func) + { + SetEvent( lpOverlapped->hEvent ); + HeapFree( GetProcessHeap(), 0, wsa ); + } + else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc, + (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 ); + return 0; }
if ( _is_blocking(s) ) @@ -4140,14 +4152,17 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, for (;;) { n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags ); - if (n != -1) break; - - if (errno == EINTR) continue; - if (errno != EAGAIN) + if (n == -1) { - err = wsaErrno(); - goto error; + if (errno == EINTR) continue; + if (errno != EAGAIN) + { + err = wsaErrno(); + goto error; + } } + else + *lpNumberOfBytesRecvd = n;
if ((lpOverlapped || lpCompletionRoutine) && !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) @@ -4172,31 +4187,49 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb; - iosb->u.Status = STATUS_PENDING; - iosb->Information = 0;
- SERVER_START_REQ( register_async ) + if (n == -1) { - req->handle = wsa->hSocket; - req->type = ASYNC_TYPE_READ; - req->async.callback = WS2_async_recv; - req->async.iosb = iosb; - req->async.arg = wsa; - req->async.apc = ws2_async_apc; - req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; - err = wine_server_call( req ); + iosb->u.Status = STATUS_PENDING; + iosb->Information = 0; + + SERVER_START_REQ( register_async ) + { + req->handle = wsa->hSocket; + req->type = ASYNC_TYPE_READ; + req->async.callback = WS2_async_recv; + req->async.iosb = iosb; + req->async.arg = wsa; + req->async.apc = ws2_async_apc; + req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; + err = wine_server_call( req ); + } + SERVER_END_REQ; + + if (err == STATUS_PENDING) + NtCurrentTeb()->num_async_io++; + else + HeapFree( GetProcessHeap(), 0, wsa ); + + WSASetLastError( NtStatusToWSAError( err )); + return SOCKET_ERROR; } - SERVER_END_REQ;
- if (err == STATUS_PENDING) - NtCurrentTeb()->num_async_io++; - else + iosb->u.Status = STATUS_SUCCESS; + iosb->Information = n; + if (!wsa->completion_func) + { + SetEvent( lpOverlapped->hEvent ); HeapFree( GetProcessHeap(), 0, wsa ); - - WSASetLastError( NtStatusToWSAError( err )); - return SOCKET_ERROR; + } + else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc, + (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 ); + _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0); + return 0; }
+ if (n != -1) break; + if ( _is_blocking(s) ) { struct pollfd pfd; @@ -4228,8 +4261,6 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, }
TRACE(" -> %i bytes\n", n); - *lpNumberOfBytesRecvd = n; - release_sock_fd( s, fd ); _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);