Commit fe7c5d86 authored by Alexandre Julliard's avatar Alexandre Julliard

ws2_32: Allow arbitrary-sized iovecs again in WSASendTo and WSARecvFrom.

parent c928aa67
...@@ -187,8 +187,6 @@ typedef struct ws2_async ...@@ -187,8 +187,6 @@ typedef struct ws2_async
LPWSAOVERLAPPED user_overlapped; LPWSAOVERLAPPED user_overlapped;
LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func; LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func;
IO_STATUS_BLOCK local_iosb; IO_STATUS_BLOCK local_iosb;
struct iovec iovec[WS_MSG_MAXIOVLEN];
int n_iovecs;
struct WS_sockaddr *addr; struct WS_sockaddr *addr;
union union
{ {
...@@ -196,6 +194,9 @@ typedef struct ws2_async ...@@ -196,6 +194,9 @@ typedef struct ws2_async
int *ptr; /* for recv operations */ int *ptr; /* for recv operations */
} addrlen; } addrlen;
DWORD flags; DWORD flags;
unsigned int n_iovecs;
unsigned int first_iovec;
struct iovec iovec[1];
} ws2_async; } ws2_async;
/****************************************************************/ /****************************************************************/
...@@ -1071,9 +1072,7 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv ...@@ -1071,9 +1072,7 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv
* *
* Workhorse for both synchronous and asynchronous recv() operations. * Workhorse for both synchronous and asynchronous recv() operations.
*/ */
static int WS2_recv( int fd, struct iovec* iov, int count, static int WS2_recv( int fd, struct ws2_async *wsa )
struct WS_sockaddr *lpFrom, LPINT lpFromlen,
LPDWORD lpFlags )
{ {
struct msghdr hdr; struct msghdr hdr;
union generic_unix_sockaddr unix_sockaddr; union generic_unix_sockaddr unix_sockaddr;
...@@ -1081,7 +1080,7 @@ static int WS2_recv( int fd, struct iovec* iov, int count, ...@@ -1081,7 +1080,7 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
hdr.msg_name = NULL; hdr.msg_name = NULL;
if ( lpFrom ) if (wsa->addr)
{ {
hdr.msg_namelen = sizeof(unix_sockaddr); hdr.msg_namelen = sizeof(unix_sockaddr);
hdr.msg_name = &unix_sockaddr; hdr.msg_name = &unix_sockaddr;
...@@ -1089,8 +1088,8 @@ static int WS2_recv( int fd, struct iovec* iov, int count, ...@@ -1089,8 +1088,8 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
else else
hdr.msg_namelen = 0; hdr.msg_namelen = 0;
hdr.msg_iov = iov; hdr.msg_iov = wsa->iovec + wsa->first_iovec;
hdr.msg_iovlen = count; hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
hdr.msg_accrights = NULL; hdr.msg_accrights = NULL;
hdr.msg_accrightslen = 0; hdr.msg_accrightslen = 0;
...@@ -1100,7 +1099,7 @@ static int WS2_recv( int fd, struct iovec* iov, int count, ...@@ -1100,7 +1099,7 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
hdr.msg_flags = 0; hdr.msg_flags = 0;
#endif #endif
if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 ) if ( (n = recvmsg(fd, &hdr, wsa->flags)) == -1 )
return -1; return -1;
/* if this socket is connected and lpFrom is not NULL, Linux doesn't give us /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
...@@ -1113,13 +1112,8 @@ static int WS2_recv( int fd, struct iovec* iov, int count, ...@@ -1113,13 +1112,8 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
* likewise MSDN says that lpFrom and lpFromlen are ignored for * likewise MSDN says that lpFrom and lpFromlen are ignored for
* connection-oriented sockets, so don't try to update lpFrom. * connection-oriented sockets, so don't try to update lpFrom.
*/ */
if ( lpFrom && hdr.msg_namelen && if (wsa->addr && hdr.msg_namelen)
ws_sockaddr_u2ws( &unix_sockaddr.addr, lpFrom, lpFromlen ) != 0 ) ws_sockaddr_u2ws( &unix_sockaddr.addr, wsa->addr, wsa->addrlen.ptr );
{
/* The from buffer was too small, but we read the data
* anyway. Is that really bad?
*/
}
return n; return n;
} }
...@@ -1140,8 +1134,7 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat ...@@ -1140,8 +1134,7 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat
if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) )) if ((status = wine_server_handle_to_fd( wsa->hSocket, FILE_READ_DATA, &fd, NULL ) ))
break; break;
result = WS2_recv( fd, wsa->iovec, wsa->n_iovecs, result = WS2_recv( fd, wsa );
wsa->addr, wsa->addrlen.ptr, &wsa->flags );
wine_server_release_fd( wsa->hSocket, fd ); wine_server_release_fd( wsa->hSocket, fd );
if (result >= 0) if (result >= 0)
{ {
...@@ -1176,20 +1169,18 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat ...@@ -1176,20 +1169,18 @@ static NTSTATUS WS2_async_recv( void* user, IO_STATUS_BLOCK* iosb, NTSTATUS stat
* *
* Workhorse for both synchronous and asynchronous send() operations. * Workhorse for both synchronous and asynchronous send() operations.
*/ */
static int WS2_send( int fd, struct iovec* iov, int count, static int WS2_send( int fd, struct ws2_async *wsa )
const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
{ {
struct msghdr hdr; struct msghdr hdr;
union generic_unix_sockaddr unix_addr; union generic_unix_sockaddr unix_addr;
hdr.msg_name = NULL; hdr.msg_name = NULL;
hdr.msg_namelen = 0; hdr.msg_namelen = 0;
if ( to ) if (wsa->addr)
{ {
hdr.msg_name = &unix_addr; hdr.msg_name = &unix_addr;
hdr.msg_namelen = ws_sockaddr_ws2u( to, tolen, &unix_addr ); hdr.msg_namelen = ws_sockaddr_ws2u( wsa->addr, wsa->addrlen.val, &unix_addr );
if ( !hdr.msg_namelen ) if ( !hdr.msg_namelen )
{ {
errno = EFAULT; errno = EFAULT;
...@@ -1197,7 +1188,7 @@ static int WS2_send( int fd, struct iovec* iov, int count, ...@@ -1197,7 +1188,7 @@ static int WS2_send( int fd, struct iovec* iov, int count,
} }
#if defined(HAVE_IPX) && defined(SOL_IPX) #if defined(HAVE_IPX) && defined(SOL_IPX)
if(to->sa_family == WS_AF_IPX) if(wsa->addr->sa_family == WS_AF_IPX)
{ {
struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name; struct sockaddr_ipx* uipx = (struct sockaddr_ipx*)hdr.msg_name;
int val=0; int val=0;
...@@ -1214,8 +1205,8 @@ static int WS2_send( int fd, struct iovec* iov, int count, ...@@ -1214,8 +1205,8 @@ static int WS2_send( int fd, struct iovec* iov, int count,
#endif #endif
} }
hdr.msg_iov = iov; hdr.msg_iov = wsa->iovec + wsa->first_iovec;
hdr.msg_iovlen = count; hdr.msg_iovlen = wsa->n_iovecs - wsa->first_iovec;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
hdr.msg_accrights = NULL; hdr.msg_accrights = NULL;
hdr.msg_accrightslen = 0; hdr.msg_accrightslen = 0;
...@@ -1225,7 +1216,7 @@ static int WS2_send( int fd, struct iovec* iov, int count, ...@@ -1225,7 +1216,7 @@ static int WS2_send( int fd, struct iovec* iov, int count,
hdr.msg_flags = 0; hdr.msg_flags = 0;
#endif #endif
return sendmsg(fd, &hdr, dwFlags); return sendmsg(fd, &hdr, wsa->flags);
} }
/*********************************************************************** /***********************************************************************
...@@ -1245,13 +1236,13 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu ...@@ -1245,13 +1236,13 @@ static NTSTATUS WS2_async_send(void* user, IO_STATUS_BLOCK* iosb, NTSTATUS statu
break; break;
/* check to see if the data is ready (non-blocking) */ /* check to see if the data is ready (non-blocking) */
result = WS2_send( fd, wsa->iovec, wsa->n_iovecs, wsa->addr, wsa->addrlen.val, wsa->flags ); result = WS2_send( fd, wsa );
wine_server_release_fd( wsa->hSocket, fd ); wine_server_release_fd( wsa->hSocket, fd );
if (result >= 0) if (result >= 0)
{ {
int totalLength = 0; int totalLength = 0;
int i; unsigned int i;
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
for (i = 0; i < wsa->n_iovecs; i++) for (i = 0; i < wsa->n_iovecs; i++)
totalLength += wsa->iovec[i].iov_len; totalLength += wsa->iovec[i].iov_len;
...@@ -2677,7 +2668,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2677,7 +2668,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
{ {
unsigned int i, options; unsigned int i, options;
int n, fd, err; int n, fd, err;
struct iovec iovec[WS_MSG_MAXIOVLEN]; struct ws2_async *wsa;
int totalLength = 0; int totalLength = 0;
ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0; ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
...@@ -2685,33 +2676,39 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2685,33 +2676,39 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
s, lpBuffers, dwBufferCount, dwFlags, s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine); to, tolen, lpOverlapped, lpCompletionRoutine);
if (dwBufferCount > WS_MSG_MAXIOVLEN)
{
WSASetLastError( WSAEINVAL );
return SOCKET_ERROR;
}
fd = get_sock_fd( s, FILE_WRITE_DATA, &options ); fd = get_sock_fd( s, FILE_WRITE_DATA, &options );
TRACE( "fd=%d, options=%x\n", fd, options ); TRACE( "fd=%d, options=%x\n", fd, options );
if ( fd == -1 ) return SOCKET_ERROR; if ( fd == -1 ) return SOCKET_ERROR;
if ( !lpNumberOfBytesSent ) if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
{ {
err = WSAEFAULT; err = WSAEFAULT;
goto error; goto error;
} }
wsa->hSocket = SOCKET2HANDLE(s);
wsa->addr = (struct WS_sockaddr *)to;
wsa->addrlen.val = tolen;
wsa->flags = dwFlags;
wsa->n_iovecs = dwBufferCount;
wsa->first_iovec = 0;
for ( i = 0; i < dwBufferCount; i++ ) for ( i = 0; i < dwBufferCount; i++ )
{ {
iovec[i].iov_base = lpBuffers[i].buf; wsa->iovec[i].iov_base = lpBuffers[i].buf;
iovec[i].iov_len = lpBuffers[i].len; wsa->iovec[i].iov_len = lpBuffers[i].len;
totalLength += lpBuffers[i].len; totalLength += lpBuffers[i].len;
} }
if (!lpNumberOfBytesSent)
{
err = WSAEFAULT;
goto error;
}
for (;;) for (;;)
{ {
n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags ); n = WS2_send( fd, wsa );
if (n != -1 || errno != EINTR) break; if (n != -1 || errno != EINTR) break;
} }
if (n == -1 && errno != EAGAIN) if (n == -1 && errno != EAGAIN)
...@@ -2724,26 +2721,12 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2724,26 +2721,12 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if ((lpOverlapped || lpCompletionRoutine) && if ((lpOverlapped || lpCompletionRoutine) &&
!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
IO_STATUS_BLOCK *iosb; IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_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->user_overlapped = lpOverlapped;
wsa->completion_func = lpCompletionRoutine; wsa->completion_func = lpCompletionRoutine;
wsa->n_iovecs = dwBufferCount; release_sock_fd( s, fd );
memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
if (n == -1) if (n == -1)
{ {
iosb->u.Status = STATUS_PENDING; iosb->u.Status = STATUS_PENDING;
...@@ -2788,11 +2771,10 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2788,11 +2771,10 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
/* On a blocking non-overlapped stream socket, /* On a blocking non-overlapped stream socket,
* sending blocks until the entire buffer is sent. */ * sending blocks until the entire buffer is sent. */
DWORD timeout_start = GetTickCount(); DWORD timeout_start = GetTickCount();
unsigned int first_buff = 0;
*lpNumberOfBytesSent = 0; *lpNumberOfBytesSent = 0;
while (first_buff < dwBufferCount) while (wsa->first_iovec < dwBufferCount)
{ {
struct pollfd pfd; struct pollfd pfd;
int timeout = GET_SNDTIMEO(fd); int timeout = GET_SNDTIMEO(fd);
...@@ -2800,11 +2782,11 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2800,11 +2782,11 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if (n >= 0) if (n >= 0)
{ {
*lpNumberOfBytesSent += n; *lpNumberOfBytesSent += n;
while (first_buff < dwBufferCount && iovec[first_buff].iov_len <= n) while (wsa->first_iovec < dwBufferCount && wsa->iovec[wsa->first_iovec].iov_len <= n)
n -= iovec[first_buff++].iov_len; n -= wsa->iovec[wsa->first_iovec++].iov_len;
if (first_buff >= dwBufferCount) break; if (wsa->first_iovec >= dwBufferCount) break;
iovec[first_buff].iov_base = (char*)iovec[first_buff].iov_base + n; wsa->iovec[wsa->first_iovec].iov_base = (char*)wsa->iovec[wsa->first_iovec].iov_base + n;
iovec[first_buff].iov_len -= n; wsa->iovec[wsa->first_iovec].iov_len -= n;
} }
if (timeout != -1) if (timeout != -1)
...@@ -2822,7 +2804,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2822,7 +2804,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
goto error; /* msdn says a timeout in send is fatal */ goto error; /* msdn says a timeout in send is fatal */
} }
n = WS2_send( fd, iovec + first_buff, dwBufferCount - first_buff, to, tolen, dwFlags ); n = WS2_send( fd, wsa );
if (n == -1 && errno != EAGAIN && errno != EINTR) if (n == -1 && errno != EAGAIN && errno != EINTR)
{ {
err = wsaErrno(); err = wsaErrno();
...@@ -2844,11 +2826,13 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -2844,11 +2826,13 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
TRACE(" -> %i bytes\n", *lpNumberOfBytesSent); TRACE(" -> %i bytes\n", *lpNumberOfBytesSent);
HeapFree( GetProcessHeap(), 0, wsa );
release_sock_fd( s, fd ); release_sock_fd( s, fd );
WSASetLastError(0); WSASetLastError(0);
return 0; return 0;
error: error:
HeapFree( GetProcessHeap(), 0, wsa );
release_sock_fd( s, fd ); release_sock_fd( s, fd );
WARN(" -> ERROR %d\n", err); WARN(" -> ERROR %d\n", err);
WSASetLastError(err); WSASetLastError(err);
...@@ -4209,8 +4193,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4209,8 +4193,8 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
{ {
unsigned int i, options; unsigned int i, options;
int n, fd, err; int n, fd, err;
struct ws2_async *wsa;
DWORD timeout_start = GetTickCount(); DWORD timeout_start = GetTickCount();
struct iovec iovec[WS_MSG_MAXIOVLEN];
ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0; ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n", TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
...@@ -4218,26 +4202,32 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4218,26 +4202,32 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
(lpFromlen ? *lpFromlen : -1), (lpFromlen ? *lpFromlen : -1),
lpOverlapped, lpCompletionRoutine); lpOverlapped, lpCompletionRoutine);
if (dwBufferCount > WS_MSG_MAXIOVLEN)
{
WSASetLastError( WSAEINVAL );
return SOCKET_ERROR;
}
fd = get_sock_fd( s, FILE_READ_DATA, &options ); fd = get_sock_fd( s, FILE_READ_DATA, &options );
TRACE( "fd=%d, options=%x\n", fd, options ); TRACE( "fd=%d, options=%x\n", fd, options );
if (fd == -1) return SOCKET_ERROR; if (fd == -1) return SOCKET_ERROR;
if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) )))
{
err = WSAEFAULT;
goto error;
}
wsa->hSocket = SOCKET2HANDLE(s);
wsa->flags = *lpFlags;
wsa->addr = lpFrom;
wsa->addrlen.ptr = lpFromlen;
wsa->n_iovecs = dwBufferCount;
wsa->first_iovec = 0;
for (i = 0; i < dwBufferCount; i++) for (i = 0; i < dwBufferCount; i++)
{ {
iovec[i].iov_base = lpBuffers[i].buf; wsa->iovec[i].iov_base = lpBuffers[i].buf;
iovec[i].iov_len = lpBuffers[i].len; wsa->iovec[i].iov_len = lpBuffers[i].len;
} }
for (;;) for (;;)
{ {
n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags ); n = WS2_recv( fd, wsa );
if (n == -1) if (n == -1)
{ {
if (errno == EINTR) continue; if (errno == EINTR) continue;
...@@ -4254,26 +4244,11 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4254,26 +4244,11 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
if ((lpOverlapped || lpCompletionRoutine) && if ((lpOverlapped || lpCompletionRoutine) &&
!(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT))) !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
{ {
IO_STATUS_BLOCK *iosb; IO_STATUS_BLOCK *iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_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->flags = *lpFlags;
wsa->addr = lpFrom;
wsa->addrlen.ptr = lpFromlen;
wsa->user_overlapped = lpOverlapped; wsa->user_overlapped = lpOverlapped;
wsa->completion_func = lpCompletionRoutine; wsa->completion_func = lpCompletionRoutine;
wsa->n_iovecs = dwBufferCount; release_sock_fd( s, fd );
memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
if (n == -1) if (n == -1)
{ {
...@@ -4346,12 +4321,14 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, ...@@ -4346,12 +4321,14 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
} }
TRACE(" -> %i bytes\n", n); TRACE(" -> %i bytes\n", n);
HeapFree( GetProcessHeap(), 0, wsa );
release_sock_fd( s, fd ); release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0); _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
return 0; return 0;
error: error:
HeapFree( GetProcessHeap(), 0, wsa );
release_sock_fd( s, fd ); release_sock_fd( s, fd );
WARN(" -> ERROR %d\n", err); WARN(" -> ERROR %d\n", err);
WSASetLastError( err ); WSASetLastError( err );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment