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