ws2_32: Implement get socket option SO_PROTOCOL_INFO (try 2)
Bruno Jesus
00cpxxx at gmail.com
Mon Sep 2 21:51:37 CDT 2013
try 2:
Narrow the loop for the specified protocol
Add a new test for invalid sockets
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 462f153..60419d8 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1116,6 +1116,65 @@ convert_socktype_u2w(int unixsocktype) {
return -1;
}
+static int fill_protocol_info(SOCKET s, int unicode, char *optval)
+{
+ int items, sz, i, targetproto[2] = {0, 0};
+ DWORD listsize = 0;
+ WSAPROTOCOL_INFOW *buffer = NULL;
+
+ union _info
+ {
+ WSAPROTOCOL_INFOA *a;
+ WSAPROTOCOL_INFOA *w;
+ } info;
+ info.a = (WSAPROTOCOL_INFOA *) optval;
+
+ sz = unicode ? sizeof(WSAPROTOCOL_INFOW) : sizeof(WSAPROTOCOL_INFOA);
+ memset(optval, 0, sz);
+ info.a->iAddressFamily = WS_AF_UNSPEC;
+
+ SERVER_START_REQ( get_socket_info )
+ {
+ req->handle = wine_server_obj_handle( SOCKET2HANDLE(s) );
+ wine_server_call( req );
+ info.a->iAddressFamily = convert_af_u2w(reply->family);
+ info.a->iSocketType = convert_socktype_u2w(reply->type);
+ info.a->iProtocol = convert_proto_u2w(reply->protocol);
+ }
+ SERVER_END_REQ;
+
+ if(info.a->iAddressFamily == WS_AF_UNSPEC)
+ return 0;
+
+ targetproto[0] = info.a->iProtocol;
+ items = WSAEnumProtocolsW(targetproto, NULL, &listsize);
+ if (items == SOCKET_ERROR && WSAGetLastError() == WSAENOBUFS &&
+ (buffer = HeapAlloc(GetProcessHeap(), 0, listsize)))
+ {
+ items = WSAEnumProtocolsW(targetproto, buffer, &listsize);
+ for (i = 0; i < items; i++)
+ {
+ if (buffer[i].iAddressFamily == info.a->iAddressFamily &&
+ buffer[i].iSocketType == info.a->iSocketType)
+ {
+ if (unicode)
+ memcpy(info.w, &buffer[i], sz);
+ else
+ {
+ /* convert the structure from W to A */
+ memcpy(info.a, &buffer[i], FIELD_OFFSET(WSAPROTOCOL_INFOA, szProtocol));
+ WideCharToMultiByte(CP_ACP, 0, buffer[i].szProtocol, -1,
+ info.a->szProtocol, WSAPROTOCOL_LEN+1, NULL, NULL);
+ }
+ break;
+ }
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, buffer);
+ return sz;
+}
+
/* ----------------------------------- API -----
*
* Init / cleanup / error checking.
@@ -2776,6 +2835,26 @@ INT WINAPI WS_getsockopt(SOCKET s, INT level,
TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval) );
return 0;
+ case WS_SO_PROTOCOL_INFOA:
+ case WS_SO_PROTOCOL_INFOW:
+ if ( (fd = get_sock_fd( s, 0, NULL )) == -1)
+ {
+ SetLastError(WSAENOTSOCK);
+ return SOCKET_ERROR;
+ }
+ release_sock_fd( s, fd );
+
+ if (!optlen || !optval ||
+ *optlen < (optname == WS_SO_PROTOCOL_INFOA ?
+ sizeof(WSAPROTOCOL_INFOA) : sizeof(WSAPROTOCOL_INFOW)))
+ {
+ SetLastError(WSAEFAULT);
+ return SOCKET_ERROR;
+ }
+
+ *optlen = fill_protocol_info(s, optname == WS_SO_PROTOCOL_INFOW, optval);
+ return *optlen ? 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 5d80fca..85de960 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -1235,28 +1235,28 @@ 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);
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);
closesocket(s);
@@ -1273,21 +1273,28 @@ 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());
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());
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], "WSAPROTOCOL_INFOA was not filled\n");
- ok(infoW.szProtocol[0], "WSAPROTOCOL_INFOW was not filled\n");
+ /* Remove IF when WSAEnumProtocols is fixed to return AF_INET6 data */
+ if (prottest[i].family == AF_INET6)
+ {
+ todo_wine {
+ ok(infoA.szProtocol[0], "WSAPROTOCOL_INFOA was not filled\n");
+ ok(infoW.szProtocol[0], "WSAPROTOCOL_INFOW was not filled\n");
+ }
+ }
+ else
+ {
+ ok(infoA.szProtocol[0], "WSAPROTOCOL_INFOA was not filled\n");
+ ok(infoW.szProtocol[0], "WSAPROTOCOL_INFOW was not filled\n");
}
WideCharToMultiByte(CP_ACP, 0, infoW.szProtocol, -1,
@@ -1295,7 +1302,6 @@ todo_wine
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",
@@ -1304,7 +1310,6 @@ todo_wine
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