Zebediah Figura : ws2_32: Reimplement WSASocketW() on top of NtOpenFile() and IOCTL_AFD_CREATE.

Alexandre Julliard julliard at winehq.org
Tue Sep 22 15:46:41 CDT 2020


Module: wine
Branch: master
Commit: 18df4912f455e0fb09b232a409c5825a44ee8f2c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=18df4912f455e0fb09b232a409c5825a44ee8f2c

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Sat Sep 19 17:13:37 2020 -0500

ws2_32: Reimplement WSASocketW() on top of NtOpenFile() and IOCTL_AFD_CREATE.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ws2_32/socket.c | 109 +++++++++++++++++++++++++++++----------------------
 1 file changed, 63 insertions(+), 46 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 4162549d8b..1136ec87b9 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -155,6 +155,7 @@
 #define USE_WC_PREFIX   /* For CMSG_DATA */
 #include "iphlpapi.h"
 #include "ip2string.h"
+#include "wine/afd.h"
 #include "wine/server.h"
 #include "wine/debug.h"
 #include "wine/exception.h"
@@ -7593,8 +7594,15 @@ SOCKET WINAPI WSASocketA(int af, int type, int protocol,
  */
 SOCKET WINAPI WSASocketW(int af, int type, int protocol,
                          LPWSAPROTOCOL_INFOW lpProtocolInfo,
-                         GROUP g, DWORD dwFlags)
+                         GROUP g, DWORD flags)
 {
+    static const WCHAR afdW[] = {'\\','D','e','v','i','c','e','\\','A','f','d',0};
+    struct afd_create_params create_params;
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING string;
+    IO_STATUS_BLOCK io;
+    NTSTATUS status;
+    HANDLE handle;
     SOCKET ret;
     DWORD err;
     int unixaf, unixtype, ipxptype = -1;
@@ -7605,7 +7613,7 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
    */
 
    TRACE("af=%d type=%d protocol=%d protocol_info=%p group=%d flags=0x%x\n",
-         af, type, protocol, lpProtocolInfo, g, dwFlags );
+         af, type, protocol, lpProtocolInfo, g, flags );
 
     if (!num_startup)
     {
@@ -7706,62 +7714,71 @@ SOCKET WINAPI WSASocketW(int af, int type, int protocol,
         goto done;
     }
 
-    SERVER_START_REQ( create_socket )
+    RtlInitUnicodeString(&string, afdW);
+    InitializeObjectAttributes(&attr, &string, (flags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT, NULL, NULL);
+    if ((status = NtOpenFile(&handle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &attr, &io, 0, 0)))
     {
-        req->family     = unixaf;
-        req->type       = unixtype;
-        req->protocol   = protocol;
-        req->access     = GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE;
-        req->attributes = (dwFlags & WSA_FLAG_NO_HANDLE_INHERIT) ? 0 : OBJ_INHERIT;
-        req->flags      = dwFlags & ~WSA_FLAG_NO_HANDLE_INHERIT;
-        err = NtStatusToWSAError( wine_server_call( req ) );
-        ret = HANDLE2SOCKET( wine_server_ptr_handle( reply->handle ));
+        WARN("Failed to create socket, status %#x.\n", status);
+        WSASetLastError(NtStatusToWSAError(status));
+        return INVALID_SOCKET;
     }
-    SERVER_END_REQ;
-    if (ret)
-    {
-        TRACE("\tcreated %04lx\n", ret );
-        if (ipxptype > 0)
-            set_ipx_packettype(ret, ipxptype);
 
-        if (unixaf == AF_INET || unixaf == AF_INET6)
+    create_params.family = unixaf;
+    create_params.type = unixtype;
+    create_params.protocol = protocol;
+    create_params.flags = flags & ~WSA_FLAG_NO_HANDLE_INHERIT;
+    if ((status = NtDeviceIoControlFile(handle, NULL, NULL, NULL, &io,
+            IOCTL_AFD_CREATE, &create_params, sizeof(create_params), NULL, 0)))
+    {
+        WARN("Failed to initialize socket, status %#x.\n", status);
+        err = NtStatusToWSAError(status);
+        if (err == WSAEACCES) /* raw socket denied */
         {
-            /* ensure IP_DONTFRAGMENT is disabled for SOCK_DGRAM and SOCK_RAW, enabled for SOCK_STREAM */
-            if (unixtype == SOCK_DGRAM || unixtype == SOCK_RAW) /* in Linux the global default can be enabled */
-                set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, FALSE);
-            else if (unixtype == SOCK_STREAM)
-                set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, TRUE);
+            if (type == SOCK_RAW)
+                ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
+            else
+                ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
         }
+        WSASetLastError(err);
+        NtClose(handle);
+        return INVALID_SOCKET;
+    }
+
+    ret = HANDLE2SOCKET(handle);
+    TRACE("\tcreated %04lx\n", ret );
+
+    if (ipxptype > 0)
+        set_ipx_packettype(ret, ipxptype);
+
+    if (unixaf == AF_INET || unixaf == AF_INET6)
+    {
+        /* ensure IP_DONTFRAGMENT is disabled for SOCK_DGRAM and SOCK_RAW, enabled for SOCK_STREAM */
+        if (unixtype == SOCK_DGRAM || unixtype == SOCK_RAW) /* in Linux the global default can be enabled */
+            set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, FALSE);
+        else if (unixtype == SOCK_STREAM)
+            set_dont_fragment(ret, unixaf == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, TRUE);
+    }
 
 #ifdef IPV6_V6ONLY
-        if (unixaf == AF_INET6)
-        {
-            int fd = get_sock_fd(ret, 0, NULL);
-            if (fd != -1)
-            {
-                /* IPV6_V6ONLY is set by default on Windows */
-                int enable = 1;
-                if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)))
-                    WARN("\tsetting IPV6_V6ONLY failed - errno = %i\n", errno);
-                release_sock_fd(ret, fd);
-            }
-        }
-#endif
-        if (!socket_list_add(ret))
+    if (unixaf == AF_INET6)
+    {
+        int fd = get_sock_fd(ret, 0, NULL);
+        if (fd != -1)
         {
-            CloseHandle(SOCKET2HANDLE(ret));
-            return INVALID_SOCKET;
+            /* IPV6_V6ONLY is set by default on Windows */
+            int enable = 1;
+            if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &enable, sizeof(enable)))
+                WARN("\tsetting IPV6_V6ONLY failed - errno = %i\n", errno);
+            release_sock_fd(ret, fd);
         }
-        return ret;
     }
-
-    if (err == WSAEACCES) /* raw socket denied */
+#endif
+    if (!socket_list_add(ret))
     {
-        if (type == SOCK_RAW)
-            ERR_(winediag)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
-        else
-            ERR_(winediag)("Failed to create socket, this requires special permissions.\n");
+        CloseHandle(handle);
+        return INVALID_SOCKET;
     }
+    return ret;
 
 done:
     WARN("\t\tfailed, error %d!\n", err);




More information about the wine-cvs mailing list