From dea4f7bc02c388f6d17b28217995e2dc7611beb1 Mon Sep 17 00:00:00 2001 From: Bruno Jesus <00cpxxx@gmail.com> Date: Tue, 10 Sep 2013 00:56:47 -0300 Subject: [PATCH] ws2_32: Implement get socket option SO_PROTOCOL_INFO. --- dlls/ws2_32/socket.c | 53 ++++++++++++++++++++++++++++++++++++++++ dlls/ws2_32/tests/sock.c | 45 +++++++++++++++++++++++----------- 2 files changed, 84 insertions(+), 14 deletions(-) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 833c7139fbe..5f5f1612852 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1747,6 +1747,40 @@ static INT WS_EnumProtocols( BOOL unicode, const INT *protocols, LPWSAPROTOCOL_I return items; } +static BOOL ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, int *size) +{ + NTSTATUS status; + + *size = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA); + memset(buffer, 0, *size); + + SERVER_START_REQ( get_socket_info ) + { + req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) ); + status = wine_server_call( req ); + if (!status) + { + buffer->iAddressFamily = convert_af_u2w(reply->family); + buffer->iSocketType = convert_socktype_u2w(reply->type); + buffer->iProtocol = convert_proto_u2w(reply->protocol); + } + } + SERVER_END_REQ; + + if (status) + { + set_error(status); + return FALSE; + } + + if (unicode) + WS_EnterSingleProtocolW( buffer->iProtocol, buffer); + else + WS_EnterSingleProtocolA( buffer->iProtocol, (WSAPROTOCOL_INFOA *)buffer); + + return TRUE; +} + /************************************************************************** * Functions for handling overlapped I/O **************************************************************************/ @@ -3024,7 +3058,26 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level, *optlen = sizeof(int); TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) ); return 0; + case WS_SO_PROTOCOL_INFOA: + case WS_SO_PROTOCOL_INFOW: + { + int size; + WSAPROTOCOL_INFOW infow; + ret = ws_protocol_info(s, optname == WS_SO_PROTOCOL_INFOW, &infow, &size); + if (ret) + { + if (!optlen || !optval || *optlen < size) + { + if(optlen) *optlen = size; + ret = 0; + SetLastError(WSAEFAULT); + } + else + memcpy(optval, &infow, size); + } + return ret ? 0 : SOCKET_ERROR; + } #ifdef SO_RCVTIMEO case WS_SO_RCVTIMEO: #endif diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 78521aeff2d..e072033a3a1 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -1235,29 +1235,40 @@ todo_wine closesocket(s); /* test SO_PROTOCOL_INFOA invalid parameters */ + ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL), + "getsockopt should have failed\n"); + err = WSAGetLastError(); + ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err); + size = sizeof(WSAPROTOCOL_INFOA); + ok(getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size), + "getsockopt should have failed\n"); + ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size); + err = WSAGetLastError(); + ok(err == WSAENOTSOCK, "expected 10038, got %d instead\n", err); s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, NULL), "getsockopt should have failed\n"); err = WSAGetLastError(); -todo_wine ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err); ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, NULL), "getsockopt should have failed\n"); err = WSAGetLastError(); -todo_wine ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err); ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, NULL, &size), "getsockopt should have failed\n"); err = WSAGetLastError(); -todo_wine ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err); - size = sizeof(WSAPROTOCOL_INFOA) / 2; ok(getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size), "getsockopt should have failed\n"); err = WSAGetLastError(); -todo_wine ok(err == WSAEFAULT, "expected 10014, got %d instead\n", err); + ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size); + size = sizeof(WSAPROTOCOL_INFOA) * 2; + err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size); + ok(!err,"getsockopt failed with %d\n", WSAGetLastError()); + ok(size == sizeof(WSAPROTOCOL_INFOA) * 2, "got size %d\n", size); + closesocket(s); /* test SO_PROTOCOL_INFO structure returned for different protocols */ @@ -1273,40 +1284,46 @@ todo_wine infoA.szProtocol[0] = 0; size = sizeof(WSAPROTOCOL_INFOA); err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &infoA, &size); -todo_wine ok(!err,"getsockopt failed with %d\n", WSAGetLastError()); + ok(size == sizeof(WSAPROTOCOL_INFOA), "got size %d\n", size); infoW.szProtocol[0] = 0; size = sizeof(WSAPROTOCOL_INFOW); err = getsockopt(s, SOL_SOCKET, SO_PROTOCOL_INFOW, (char *) &infoW, &size); -todo_wine ok(!err,"getsockopt failed with %d\n", WSAGetLastError()); + ok(size == sizeof(WSAPROTOCOL_INFOW), "got size %d\n", size); trace("provider name '%s', family %d, type %d, proto %d\n", infoA.szProtocol, prottest[i].family, prottest[i].type, prottest[i].proto); - todo_wine { ok(infoA.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */, "WSAPROTOCOL_INFOA was not filled\n"); ok(infoW.szProtocol[0] || broken(!infoA.szProtocol[0]) /* NT4 */, "WSAPROTOCOL_INFOW was not filled\n"); - } WideCharToMultiByte(CP_ACP, 0, infoW.szProtocol, -1, providername, sizeof(providername), NULL, NULL); ok(!strcmp(infoA.szProtocol,providername), "different provider names '%s' != '%s'\n", infoA.szProtocol, providername); - todo_wine { ok(!memcmp(&infoA, &infoW, FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol)), "SO_PROTOCOL_INFO[A/W] comparison failed\n"); - ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n", - prottest[i].family, infoA.iAddressFamily); - ok(infoA.iSocketType == prottest[i].type, "socket type invalid, expected %d received %d\n", + + /* Remove IF when WSAEnumProtocols support IPV6 data */ + if (prottest[i].family == AF_INET6) + { + todo_wine + ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n", + prottest[i].family, infoA.iAddressFamily); + } + else + { + ok(infoA.iAddressFamily == prottest[i].family, "socket family invalid, expected %d received %d\n", + prottest[i].family, infoA.iAddressFamily); + } ok(infoA.iSocketType == prottest[i].type, "socket type invalid, expected %d received %d\n", prottest[i].type, infoA.iSocketType); ok(infoA.iProtocol == prottest[i].proto, "socket protocol invalid, expected %d received %d\n", prottest[i].proto, infoA.iProtocol); - } closesocket(s); }