ws2_32: Queue a proper user APC also on immediate success in WSARecvFrom/WSASendTo.

This commit is contained in:
Alexandre Julliard 2007-06-04 17:44:24 +02:00
parent 8992f89f27
commit e32252efae
1 changed files with 82 additions and 51 deletions

View File

@ -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)))
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;
if (n == -1)
{
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) );
iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
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);