ws2_32: Implement get socket option SO_PROTOCOL_INFO (try 5)
Bruno Jesus
00cpxxx at gmail.com
Mon Sep 9 22:56:47 CDT 2013
try 5:
Don't use get_sock_fd without need
Fill the size correctly (with tests)
try 4:
Check the server call status
try 3:
Use the merged functions to simplify implementation
try 2:
Narrow the loop for the specified protocol
Add a new test for invalid sockets
Test results:
https://testbot.winehq.org/JobDetails.pl?Key=27006
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 833c713..d3783c5 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1747,6 +1747,46 @@ 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;
+ union _info
+ {
+ WSAPROTOCOL_INFOA *a;
+ WSAPROTOCOL_INFOW *w;
+ } info;
+ info.w = buffer;
+
+ *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)
+ {
+ info.w->iAddressFamily = convert_af_u2w(reply->family);
+ info.w->iSocketType = convert_socktype_u2w(reply->type);
+ info.w->iProtocol = convert_proto_u2w(reply->protocol);
+ }
+ }
+ SERVER_END_REQ;
+
+ if (status)
+ {
+ set_error(status);
+ return FALSE;
+ }
+
+ if (unicode)
+ WS_EnterSingleProtocolW( info.w->iProtocol, info.w);
+ else
+ WS_EnterSingleProtocolA( info.a->iProtocol, info.a);
+
+ return TRUE;
+}
+
/**************************************************************************
* Functions for handling overlapped I/O
**************************************************************************/
@@ -3024,7 +3064,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 78521ae..9e53fd7 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1235,29 +1235,43 @@ 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), "expected size %d, received %d\n",
+ sizeof(WSAPROTOCOL_INFOA), 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), "expected size %d, received %d\n",
+ sizeof(WSAPROTOCOL_INFOA), 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, "expected size %d, received %d\n",
+ sizeof(WSAPROTOCOL_INFOA) * 2, size);
+
closesocket(s);
/* test SO_PROTOCOL_INFO structure returned for different protocols */
@@ -1273,40 +1287,48 @@ 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), "expected size %d, received %d\n",
+ sizeof(WSAPROTOCOL_INFOA), 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), "expected size %d, received %d\n",
+ sizeof(WSAPROTOCOL_INFOW), 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);
}
More information about the wine-patches
mailing list