ws2_32: Reimplement WSASocketW() on top of NtOpenFile() and IOCTL_AFD_CREATE.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2933448979
commit
18df4912f4
|
@ -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))
|
||||
{
|
||||
CloseHandle(SOCKET2HANDLE(ret));
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (err == WSAEACCES) /* raw socket denied */
|
||||
if (unixaf == AF_INET6)
|
||||
{
|
||||
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");
|
||||
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))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
return ret;
|
||||
|
||||
done:
|
||||
WARN("\t\tfailed, error %d!\n", err);
|
||||
|
|
Loading…
Reference in New Issue