Alexandre Julliard : ws2_32:
Queue a proper user APC also on immediate success in
WSARecvFrom/WSASendTo .
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Jun 5 05:48:11 CDT 2007
Module: wine
Branch: master
Commit: e32252efae7f249b611015d32199057c0914e02b
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e32252efae7f249b611015d32199057c0914e02b
Author: Alexandre Julliard <julliard at 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);
More information about the wine-cvs
mailing list