[3/4] ws2_32: Add extended IPX protocol support (try 2)

Bruno Jesus 00cpxxx at gmail.com
Fri Dec 27 10:56:18 CST 2013


try 2:
Fix the error check when no ipx is available.

original:
Windows has an extension to the IPX protocol that allows to create
sockets and set the IPX packet type at the same time, to do that a
caller will use a protocol like NSPROTO_IPX + <PACKET TYPE>
-------------- next part --------------
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 6b06ee5..8911048 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -201,6 +201,8 @@ static const INT valid_protocols[] =
     0
 };
 
+#define IS_IPX_PROTO(X) ((X) >= WS_NSPROTO_IPX && (X) <= WS_NSPROTO_IPX + 255)
+
 #if defined(IP_UNICAST_IF) && defined(SO_ATTACH_FILTER)
 # define LINUX_BOUND_IF
 struct interface_filter {
@@ -1110,6 +1112,11 @@ convert_proto_w2u(int windowsproto) {
     for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
     	if (ws_proto_map[i][0] == windowsproto)
 	    return ws_proto_map[i][1];
+
+    /* check for extended IPX */
+    if (IS_IPX_PROTO(windowsproto))
+      return windowsproto;
+
     FIXME("unhandled Windows socket protocol %d\n", windowsproto);
     return -1;
 }
@@ -1121,6 +1128,12 @@ convert_proto_u2w(int unixproto) {
     for (i=0;i<sizeof(ws_proto_map)/sizeof(ws_proto_map[0]);i++)
     	if (ws_proto_map[i][1] == unixproto)
 	    return ws_proto_map[i][0];
+
+    /* if value is inside IPX range just return it - the kernel simply
+     * echoes the value used in the socket() function */
+    if (IS_IPX_PROTO(unixproto))
+      return unixproto;
+
     FIXME("unhandled UNIX socket protocol %d\n", unixproto);
     return -1;
 }
@@ -5953,7 +5966,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
 {
     SOCKET ret;
     DWORD err;
-    int unixaf, unixtype;
+    int unixaf, unixtype, ipxptype = -1;
 
    /*
       FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
@@ -5988,13 +6001,16 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
 
     if (!type && (af || protocol))
     {
+        int autoproto = protocol;
         WSAPROTOCOL_INFOW infow;
 
         /* default to the first valid protocol */
-        if (!protocol)
-            protocol = valid_protocols[0];
+        if (!autoproto)
+            autoproto = valid_protocols[0];
+        else if(IS_IPX_PROTO(autoproto))
+            autoproto = WS_NSPROTO_IPX;
 
-        if (WS_EnterSingleProtocolW(protocol, &infow))
+        if (WS_EnterSingleProtocolW(autoproto, &infow))
         {
             type = infow.iSocketType;
 
@@ -6005,6 +6021,14 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
         }
     }
 
+    /*
+       Windows has an extension to the IPX protocol that allows to create sockets
+       and set the IPX packet type at the same time, to do that a caller will use
+       a protocol like NSPROTO_IPX + <PACKET TYPE>
+    */
+    if (IS_IPX_PROTO(protocol))
+        ipxptype = protocol - WS_NSPROTO_IPX;
+
     /* convert the socket family, type and protocol */
     unixaf = convert_af_w2u(af);
     unixtype = convert_socktype_w2u(type);
@@ -6059,7 +6083,10 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
     SERVER_END_REQ;
     if (ret)
     {
-        TRACE("\tcreated %04lx\n", ret );
+         if (ipxptype >= 0)
+            set_ipx_ptype(ret, ipxptype);
+
+       TRACE("\tcreated %04lx\n", ret );
         return ret;
     }
 
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 341b7e7..815cbbb 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -26,6 +26,8 @@
 #include <windows.h>
 #include <winternl.h>
 #include <ws2tcpip.h>
+#include <wsipx.h>
+#include <wsnwlink.h>
 #include <mswsock.h>
 #include <mstcpip.h>
 #include <stdio.h>
@@ -2088,6 +2090,73 @@ static void test_WSASocket(void)
            SOCK_RAW, socktype);
         closesocket(sock);
     }
+
+    /* IPX socket tests */
+
+    SetLastError(0xdeadbeef);
+    sock = WSASocketA(AF_IPX, SOCK_DGRAM, NSPROTO_IPX, NULL, 0, 0);
+    if (sock == INVALID_SOCKET)
+    {
+        err = WSAGetLastError();
+        ok(err == WSAEAFNOSUPPORT || broken(err == WSAEPROTONOSUPPORT), "Expected 10047, received %d\n", err);
+        skip("IPX is not supported\n");
+    }
+    else
+    {
+        WSAPROTOCOL_INFOA info;
+        closesocket(sock);
+
+        trace("IPX is supported\n");
+
+        sock = WSASocketA(0, 0, NSPROTO_IPX, NULL, 0, 0);
+        ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+                WSAGetLastError());
+
+        size = sizeof(socktype);
+        socktype = 0xdead;
+        err = getsockopt(sock, SOL_SOCKET, SO_TYPE, (char *) &socktype, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(socktype == SOCK_DGRAM, "Wrong socket type, expected %d received %d\n",
+           SOCK_DGRAM, socktype);
+
+        /* check socket family, type and protocol */
+        size = sizeof(WSAPROTOCOL_INFOA);
+        err = getsockopt(sock, SOL_SOCKET, SO_PROTOCOL_INFOA, (char *) &info, &size);
+        ok(!err,"getsockopt failed with %d\n", WSAGetLastError());
+        ok(info.iProtocol == NSPROTO_IPX, "expected protocol %d, received %d\n",
+           NSPROTO_IPX, info.iProtocol);
+        ok(info.iAddressFamily == AF_IPX, "expected family %d, received %d\n",
+           AF_IPX, info.iProtocol);
+        ok(info.iSocketType == SOCK_DGRAM, "expected type %d, received %d\n",
+           SOCK_DGRAM, info.iSocketType);
+        closesocket(sock);
+
+        /* SOCK_STREAM does not support NSPROTO_IPX */
+        SetLastError(0xdeadbeef);
+        ok(WSASocketA(AF_IPX, SOCK_STREAM, NSPROTO_IPX, NULL, 0, 0) == INVALID_SOCKET,
+           "WSASocketA should have failed\n");
+        err = WSAGetLastError();
+        ok(err == WSAEPROTONOSUPPORT, "Expected 10043, received %d\n", err);
+
+        /* test extended IPX support - that is adding any number between 0 and 255
+         * to the IPX protocol value will make it be used as IPX packet type */
+        for(i = 0;i <= 255;i += 17)
+        {
+          SetLastError(0xdeadbeef);
+          sock = WSASocketA(0, 0, NSPROTO_IPX + i, NULL, 0, 0);
+          ok(sock != INVALID_SOCKET, "Failed to create socket: %d\n",
+                  WSAGetLastError());
+
+          size = sizeof(int);
+          socktype = -1;
+          err = getsockopt(sock, NSPROTO_IPX, IPX_PTYPE, (char *) &socktype, &size);
+          ok(!err, "getsockopt failed with %d\n", WSAGetLastError());
+          ok(socktype == i, "Wrong IPX packet type, expected %d received %d\n",
+             i, socktype);
+
+          closesocket(sock);
+        }
+    }
 }
 
 static void test_WSADuplicateSocket(void)


More information about the wine-patches mailing list