diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index e1a32fb619b..0c519851b83 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3790,9 +3790,10 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, { unsigned int i, options; int n, fd, err; - struct ws2_async *wsa; + struct ws2_async *wsa = NULL; int totalLength = 0; ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0; + DWORD bytes_sent; TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n", s, lpBuffers, dwBufferCount, dwFlags, @@ -3803,6 +3804,11 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, if ( fd == -1 ) return SOCKET_ERROR; + if (!lpOverlapped && !lpNumberOfBytesSent) + { + err = WSAEFAULT; + goto error; + } if (!(wsa = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(struct ws2_async, iovec[dwBufferCount]) ))) { err = WSAEFAULT; @@ -3824,12 +3830,6 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, totalLength += lpBuffers[i].len; } - if (!lpNumberOfBytesSent) - { - err = WSAEFAULT; - goto error; - } - for (;;) { n = WS2_send( fd, wsa ); @@ -3881,7 +3881,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, iosb->u.Status = STATUS_SUCCESS; iosb->Information = n; - *lpNumberOfBytesSent = n; + if (lpNumberOfBytesSent) *lpNumberOfBytesSent = n; if (!wsa->completion_func) { if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n ); @@ -3900,7 +3900,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, * sending blocks until the entire buffer is sent. */ DWORD timeout_start = GetTickCount(); - *lpNumberOfBytesSent = n == -1 ? 0 : n; + bytes_sent = n == -1 ? 0 : n; while (wsa->first_iovec < wsa->n_iovecs) { @@ -3930,7 +3930,7 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, } if (n >= 0) - *lpNumberOfBytesSent += n; + bytes_sent += n; } } else /* non-blocking */ @@ -3942,11 +3942,12 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, err = WSAEWOULDBLOCK; goto error; } - *lpNumberOfBytesSent = n; + bytes_sent = n; } - TRACE(" -> %i bytes\n", *lpNumberOfBytesSent); + TRACE(" -> %i bytes\n", bytes_sent); + if (lpNumberOfBytesSent) *lpNumberOfBytesSent = bytes_sent; HeapFree( GetProcessHeap(), 0, wsa ); release_sock_fd( s, fd ); WSASetLastError(0); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ef01ed20f64..de9c400e4b6 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3030,8 +3030,9 @@ static void test_send(void) goto end; bytes_sent = 0; + WSASetLastError(12345); ret = WSASend(dst, &buf, 1, &bytes_sent, 0, &ov, NULL); - ok((ret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING) || broken(bytes_sent == buflen), + ok((ret == SOCKET_ERROR && WSAGetLastError() == ERROR_IO_PENDING) || broken(bytes_sent == buflen), "Failed to start overlapped send %d - %d - %d/%d\n", ret, WSAGetLastError(), bytes_sent, buflen); /* don't check for completion yet, we may need to drain the buffer while still sending */ @@ -3064,6 +3065,16 @@ static void test_send(void) "Got %d instead of %d (%d - %d)\n", bytes_sent, buflen, bret, GetLastError()); } + WSASetLastError(12345); + ret = WSASend(INVALID_SOCKET, &buf, 1, NULL, 0, &ov, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, + "WSASend failed %d - %d\n", ret, WSAGetLastError()); + + WSASetLastError(12345); + ret = WSASend(dst, &buf, 1, NULL, 0, &ov, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == ERROR_IO_PENDING, + "Failed to start overlapped send %d - %d\n", ret, WSAGetLastError()); + end: if (src != INVALID_SOCKET) closesocket(src); @@ -3903,6 +3914,7 @@ static void test_WSASendTo(void) char buf[12] = "hello world"; WSABUF data_buf; DWORD bytesSent; + int ret; addr.sin_family = AF_INET; addr.sin_port = htons(139); @@ -3915,6 +3927,16 @@ static void test_WSASendTo(void) return; } + WSASetLastError(12345); + ret = WSASendTo(INVALID_SOCKET, &data_buf, 1, NULL, 0, (struct sockaddr*)&addr, sizeof(addr), NULL, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, + "WSASendTo() failed: %d/%d\n", ret, WSAGetLastError()); + + WSASetLastError(12345); + ret = WSASendTo(s, &data_buf, 1, NULL, 0, (struct sockaddr*)&addr, sizeof(addr), NULL, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT, + "WSASendTo() failed: %d/%d\n", ret, WSAGetLastError()); + WSASetLastError(12345); if(WSASendTo(s, &data_buf, 1, &bytesSent, 0, (struct sockaddr*)&addr, sizeof(addr), NULL, NULL)) { ok(0, "WSASendTo() failed error: %d\n", WSAGetLastError());