2 * based on Windows Sockets 1.1 specs
4 * Copyright (C) 1993,1994,1996,1997 John Brezak, Erik Bos, Alex Korobka.
5 * Copyright (C) 2001 Stefan Leichter
6 * Copyright (C) 2004 Hans Leidekker
7 * Copyright (C) 2005 Marcus Meissner
8 * Copyright (C) 2006-2008 Kai Blin
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * NOTE: If you make any changes to fix a particular app, make sure
25 * they don't break something else like Netscape or telnet and ftp
26 * clients and servers (www.winsite.com got a lot of those).
29 #include "ws2_32_private.h"
31 #define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
33 WINE_DEFAULT_DEBUG_CHANNEL(winsock
);
34 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
36 #define TIMEOUT_INFINITE _I64_MAX
38 #define u64_from_user_ptr(ptr) ((ULONGLONG)(uintptr_t)(ptr))
40 static const WSAPROTOCOL_INFOW supported_protocols
[] =
43 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_EXPEDITED_DATA
| XP1_GRACEFUL_CLOSE
44 | XP1_GUARANTEED_ORDER
| XP1_GUARANTEED_DELIVERY
,
45 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
46 .ProviderId
= {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
47 .dwCatalogEntryId
= 1001,
48 .ProtocolChain
.ChainLen
= 1,
50 .iAddressFamily
= AF_INET
,
51 .iMaxSockAddr
= sizeof(struct sockaddr_in
),
52 .iMinSockAddr
= sizeof(struct sockaddr_in
),
53 .iSocketType
= SOCK_STREAM
,
54 .iProtocol
= IPPROTO_TCP
,
55 .szProtocol
= L
"TCP/IP",
58 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_SUPPORT_BROADCAST
59 | XP1_SUPPORT_MULTIPOINT
| XP1_MESSAGE_ORIENTED
| XP1_CONNECTIONLESS
,
60 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
61 .ProviderId
= {0xe70f1aa0, 0xab8b, 0x11cf, {0x8c, 0xa3, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
62 .dwCatalogEntryId
= 1002,
63 .ProtocolChain
.ChainLen
= 1,
65 .iAddressFamily
= AF_INET
,
66 .iMaxSockAddr
= sizeof(struct sockaddr_in
),
67 .iMinSockAddr
= sizeof(struct sockaddr_in
),
68 .iSocketType
= SOCK_DGRAM
,
69 .iProtocol
= IPPROTO_UDP
,
70 .dwMessageSize
= 0xffbb,
71 .szProtocol
= L
"UDP/IP",
74 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_EXPEDITED_DATA
| XP1_GRACEFUL_CLOSE
75 | XP1_GUARANTEED_ORDER
| XP1_GUARANTEED_DELIVERY
,
76 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
77 .ProviderId
= {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
78 .dwCatalogEntryId
= 1004,
79 .ProtocolChain
.ChainLen
= 1,
81 .iAddressFamily
= AF_INET6
,
82 .iMaxSockAddr
= sizeof(struct sockaddr_in6
),
83 .iMinSockAddr
= sizeof(struct sockaddr_in6
),
84 .iSocketType
= SOCK_STREAM
,
85 .iProtocol
= IPPROTO_TCP
,
86 .szProtocol
= L
"TCP/IPv6",
89 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_SUPPORT_BROADCAST
90 | XP1_SUPPORT_MULTIPOINT
| XP1_MESSAGE_ORIENTED
| XP1_CONNECTIONLESS
,
91 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
92 .ProviderId
= {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}},
93 .dwCatalogEntryId
= 1005,
94 .ProtocolChain
.ChainLen
= 1,
96 .iAddressFamily
= AF_INET6
,
97 .iMaxSockAddr
= sizeof(struct sockaddr_in6
),
98 .iMinSockAddr
= sizeof(struct sockaddr_in6
),
99 .iSocketType
= SOCK_DGRAM
,
100 .iProtocol
= IPPROTO_UDP
,
101 .dwMessageSize
= 0xffbb,
102 .szProtocol
= L
"UDP/IPv6",
105 .dwServiceFlags1
= XP1_PARTIAL_MESSAGE
| XP1_SUPPORT_BROADCAST
106 | XP1_SUPPORT_MULTIPOINT
| XP1_MESSAGE_ORIENTED
| XP1_CONNECTIONLESS
,
107 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
108 .ProviderId
= {0x11058240, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
109 .dwCatalogEntryId
= 1030,
110 .ProtocolChain
.ChainLen
= 1,
112 .iAddressFamily
= AF_IPX
,
113 .iMaxSockAddr
= sizeof(struct sockaddr
),
114 .iMinSockAddr
= sizeof(struct sockaddr_ipx
),
115 .iSocketType
= SOCK_DGRAM
,
116 .iProtocol
= NSPROTO_IPX
,
117 .iProtocolMaxOffset
= 255,
118 .dwMessageSize
= 0x240,
119 .szProtocol
= L
"IPX",
122 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_PSEUDO_STREAM
| XP1_MESSAGE_ORIENTED
123 | XP1_GUARANTEED_ORDER
| XP1_GUARANTEED_DELIVERY
,
124 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
125 .ProviderId
= {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
126 .dwCatalogEntryId
= 1031,
127 .ProtocolChain
.ChainLen
= 1,
129 .iAddressFamily
= AF_IPX
,
130 .iMaxSockAddr
= sizeof(struct sockaddr
),
131 .iMinSockAddr
= sizeof(struct sockaddr_ipx
),
132 .iSocketType
= SOCK_SEQPACKET
,
133 .iProtocol
= NSPROTO_SPX
,
134 .dwMessageSize
= UINT_MAX
,
135 .szProtocol
= L
"SPX",
138 .dwServiceFlags1
= XP1_IFS_HANDLES
| XP1_GRACEFUL_CLOSE
| XP1_PSEUDO_STREAM
139 | XP1_MESSAGE_ORIENTED
| XP1_GUARANTEED_ORDER
| XP1_GUARANTEED_DELIVERY
,
140 .dwProviderFlags
= PFL_MATCHES_PROTOCOL_ZERO
,
141 .ProviderId
= {0x11058241, 0xbe47, 0x11cf, {0x95, 0xc8, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}},
142 .dwCatalogEntryId
= 1033,
143 .ProtocolChain
.ChainLen
= 1,
145 .iAddressFamily
= AF_IPX
,
146 .iMaxSockAddr
= sizeof(struct sockaddr
),
147 .iMinSockAddr
= sizeof(struct sockaddr_ipx
),
148 .iSocketType
= SOCK_SEQPACKET
,
149 .iProtocol
= NSPROTO_SPXII
,
150 .dwMessageSize
= UINT_MAX
,
151 .szProtocol
= L
"SPX II",
155 DECLARE_CRITICAL_SECTION(cs_socket_list
);
157 static SOCKET
*socket_list
;
158 static unsigned int socket_list_size
;
160 const char *debugstr_sockaddr( const struct sockaddr
*a
)
162 if (!a
) return "(nil)";
163 switch (a
->sa_family
)
169 struct sockaddr_in
*sin
= (struct sockaddr_in
*)a
;
171 p
= inet_ntop( AF_INET
, &sin
->sin_addr
, buf
, sizeof(buf
) );
173 p
= "(unknown IPv4 address)";
175 return wine_dbg_sprintf("{ family AF_INET, address %s, port %d }",
176 p
, ntohs(sin
->sin_port
));
182 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*)a
;
184 p
= inet_ntop( AF_INET6
, &sin
->sin6_addr
, buf
, sizeof(buf
) );
186 p
= "(unknown IPv6 address)";
187 return wine_dbg_sprintf("{ family AF_INET6, address %s, flow label %#lx, port %d, scope %lu }",
188 p
, sin
->sin6_flowinfo
, ntohs(sin
->sin6_port
), sin
->sin6_scope_id
);
193 char netnum
[16], nodenum
[16];
194 struct sockaddr_ipx
*sin
= (struct sockaddr_ipx
*)a
;
196 for (i
= 0;i
< 4; i
++) sprintf(netnum
+ i
* 2, "%02X", (unsigned char) sin
->sa_netnum
[i
]);
197 for (i
= 0;i
< 6; i
++) sprintf(nodenum
+ i
* 2, "%02X", (unsigned char) sin
->sa_nodenum
[i
]);
199 return wine_dbg_sprintf("{ family AF_IPX, address %s.%s, ipx socket %d }",
200 netnum
, nodenum
, sin
->sa_socket
);
206 memcpy( &addr
, ((const SOCKADDR_IRDA
*)a
)->irdaDeviceID
, sizeof(addr
) );
207 addr
= ntohl( addr
);
208 return wine_dbg_sprintf("{ family AF_IRDA, addr %08lx, name %s }",
210 ((const SOCKADDR_IRDA
*)a
)->irdaServiceName
);
213 return wine_dbg_sprintf("{ family %d }", a
->sa_family
);
217 static inline const char *debugstr_sockopt(int level
, int optname
)
219 const char *stropt
= NULL
, *strlevel
= NULL
;
221 #define DEBUG_SOCKLEVEL(x) case (x): strlevel = #x
222 #define DEBUG_SOCKOPT(x) case (x): stropt = #x; break
226 DEBUG_SOCKLEVEL(SOL_SOCKET
);
229 DEBUG_SOCKOPT(SO_ACCEPTCONN
);
230 DEBUG_SOCKOPT(SO_BROADCAST
);
231 DEBUG_SOCKOPT(SO_BSP_STATE
);
232 DEBUG_SOCKOPT(SO_CONDITIONAL_ACCEPT
);
233 DEBUG_SOCKOPT(SO_CONNECT_TIME
);
234 DEBUG_SOCKOPT(SO_DEBUG
);
235 DEBUG_SOCKOPT(SO_DONTLINGER
);
236 DEBUG_SOCKOPT(SO_DONTROUTE
);
237 DEBUG_SOCKOPT(SO_ERROR
);
238 DEBUG_SOCKOPT(SO_EXCLUSIVEADDRUSE
);
239 DEBUG_SOCKOPT(SO_GROUP_ID
);
240 DEBUG_SOCKOPT(SO_GROUP_PRIORITY
);
241 DEBUG_SOCKOPT(SO_KEEPALIVE
);
242 DEBUG_SOCKOPT(SO_LINGER
);
243 DEBUG_SOCKOPT(SO_MAX_MSG_SIZE
);
244 DEBUG_SOCKOPT(SO_OOBINLINE
);
245 DEBUG_SOCKOPT(SO_OPENTYPE
);
246 DEBUG_SOCKOPT(SO_PROTOCOL_INFOA
);
247 DEBUG_SOCKOPT(SO_PROTOCOL_INFOW
);
248 DEBUG_SOCKOPT(SO_RCVBUF
);
249 DEBUG_SOCKOPT(SO_RCVTIMEO
);
250 DEBUG_SOCKOPT(SO_REUSEADDR
);
251 DEBUG_SOCKOPT(SO_SNDBUF
);
252 DEBUG_SOCKOPT(SO_SNDTIMEO
);
253 DEBUG_SOCKOPT(SO_TYPE
);
254 DEBUG_SOCKOPT(SO_UPDATE_CONNECT_CONTEXT
);
258 DEBUG_SOCKLEVEL(NSPROTO_IPX
);
261 DEBUG_SOCKOPT(IPX_PTYPE
);
262 DEBUG_SOCKOPT(IPX_FILTERPTYPE
);
263 DEBUG_SOCKOPT(IPX_DSTYPE
);
264 DEBUG_SOCKOPT(IPX_RECVHDR
);
265 DEBUG_SOCKOPT(IPX_MAXSIZE
);
266 DEBUG_SOCKOPT(IPX_ADDRESS
);
267 DEBUG_SOCKOPT(IPX_MAX_ADAPTER_NUM
);
271 DEBUG_SOCKLEVEL(SOL_IRLMP
);
274 DEBUG_SOCKOPT(IRLMP_ENUMDEVICES
);
278 DEBUG_SOCKLEVEL(IPPROTO_TCP
);
281 DEBUG_SOCKOPT(TCP_BSDURGENT
);
282 DEBUG_SOCKOPT(TCP_EXPEDITED_1122
);
283 DEBUG_SOCKOPT(TCP_NODELAY
);
287 DEBUG_SOCKLEVEL(IPPROTO_IP
);
290 DEBUG_SOCKOPT(IP_ADD_MEMBERSHIP
);
291 DEBUG_SOCKOPT(IP_DONTFRAGMENT
);
292 DEBUG_SOCKOPT(IP_DROP_MEMBERSHIP
);
293 DEBUG_SOCKOPT(IP_HDRINCL
);
294 DEBUG_SOCKOPT(IP_MULTICAST_IF
);
295 DEBUG_SOCKOPT(IP_MULTICAST_LOOP
);
296 DEBUG_SOCKOPT(IP_MULTICAST_TTL
);
297 DEBUG_SOCKOPT(IP_OPTIONS
);
298 DEBUG_SOCKOPT(IP_PKTINFO
);
299 DEBUG_SOCKOPT(IP_RECEIVE_BROADCAST
);
300 DEBUG_SOCKOPT(IP_RECVTOS
);
301 DEBUG_SOCKOPT(IP_RECVTTL
);
302 DEBUG_SOCKOPT(IP_TOS
);
303 DEBUG_SOCKOPT(IP_TTL
);
304 DEBUG_SOCKOPT(IP_UNICAST_IF
);
308 DEBUG_SOCKLEVEL(IPPROTO_IPV6
);
311 DEBUG_SOCKOPT(IPV6_ADD_MEMBERSHIP
);
312 DEBUG_SOCKOPT(IPV6_DROP_MEMBERSHIP
);
313 DEBUG_SOCKOPT(IPV6_HOPLIMIT
);
314 DEBUG_SOCKOPT(IPV6_MULTICAST_IF
);
315 DEBUG_SOCKOPT(IPV6_MULTICAST_HOPS
);
316 DEBUG_SOCKOPT(IPV6_MULTICAST_LOOP
);
317 DEBUG_SOCKOPT(IPV6_PKTINFO
);
318 DEBUG_SOCKOPT(IPV6_RECVTCLASS
);
319 DEBUG_SOCKOPT(IPV6_UNICAST_HOPS
);
320 DEBUG_SOCKOPT(IPV6_V6ONLY
);
321 DEBUG_SOCKOPT(IPV6_UNICAST_IF
);
322 DEBUG_SOCKOPT(IPV6_DONTFRAG
);
326 #undef DEBUG_SOCKLEVEL
330 strlevel
= wine_dbg_sprintf("0x%x", level
);
332 stropt
= wine_dbg_sprintf("0x%x", optname
);
334 return wine_dbg_sprintf("level %s, name %s", strlevel
, stropt
);
337 static inline const char *debugstr_optval(const char *optval
, int optlenval
)
339 if (optval
&& !IS_INTRESOURCE(optval
) && optlenval
>= 1 && optlenval
<= sizeof(DWORD
))
342 memcpy(&value
, optval
, optlenval
);
343 return wine_dbg_sprintf("%p (%lu)", optval
, value
);
345 return wine_dbg_sprintf("%p", optval
);
348 /* HANDLE<->SOCKET conversion (SOCKET is UINT_PTR). */
349 #define SOCKET2HANDLE(s) ((HANDLE)(s))
350 #define HANDLE2SOCKET(h) ((SOCKET)(h))
352 static BOOL
socket_list_add(SOCKET socket
)
354 unsigned int i
, new_size
;
357 EnterCriticalSection(&cs_socket_list
);
358 for (i
= 0; i
< socket_list_size
; ++i
)
362 socket_list
[i
] = socket
;
363 LeaveCriticalSection(&cs_socket_list
);
367 new_size
= max(socket_list_size
* 2, 8);
368 if (!(new_array
= realloc( socket_list
, new_size
* sizeof(*socket_list
) )))
370 LeaveCriticalSection(&cs_socket_list
);
373 socket_list
= new_array
;
374 memset(socket_list
+ socket_list_size
, 0, (new_size
- socket_list_size
) * sizeof(*socket_list
));
375 socket_list
[socket_list_size
] = socket
;
376 socket_list_size
= new_size
;
377 LeaveCriticalSection(&cs_socket_list
);
382 static BOOL
socket_list_find( SOCKET socket
)
386 if (!socket
) return FALSE
;
388 EnterCriticalSection( &cs_socket_list
);
389 for (i
= 0; i
< socket_list_size
; ++i
)
391 if (socket_list
[i
] == socket
)
393 LeaveCriticalSection( &cs_socket_list
);
397 LeaveCriticalSection( &cs_socket_list
);
402 static BOOL
socket_list_remove( SOCKET socket
)
406 if (!socket
) return FALSE
;
408 EnterCriticalSection(&cs_socket_list
);
409 for (i
= 0; i
< socket_list_size
; ++i
)
411 if (socket_list
[i
] == socket
)
414 LeaveCriticalSection( &cs_socket_list
);
418 LeaveCriticalSection(&cs_socket_list
);
422 static INT WINAPI
WSA_DefaultBlockingHook( FARPROC x
);
425 static FARPROC blocking_hook
= (FARPROC
)WSA_DefaultBlockingHook
;
427 /* function prototypes */
428 static int ws_protocol_info(SOCKET s
, int unicode
, WSAPROTOCOL_INFOW
*buffer
, int *size
);
430 static DWORD
NtStatusToWSAError( NTSTATUS status
)
439 {STATUS_PENDING
, ERROR_IO_PENDING
},
441 {STATUS_BUFFER_OVERFLOW
, WSAEMSGSIZE
},
443 {STATUS_NOT_IMPLEMENTED
, WSAEOPNOTSUPP
},
444 {STATUS_ACCESS_VIOLATION
, WSAEFAULT
},
445 {STATUS_PAGEFILE_QUOTA
, WSAENOBUFS
},
446 {STATUS_INVALID_HANDLE
, WSAENOTSOCK
},
447 {STATUS_NO_SUCH_DEVICE
, WSAENETDOWN
},
448 {STATUS_NO_SUCH_FILE
, WSAENETDOWN
},
449 {STATUS_NO_MEMORY
, WSAENOBUFS
},
450 {STATUS_CONFLICTING_ADDRESSES
, WSAENOBUFS
},
451 {STATUS_ACCESS_DENIED
, WSAEACCES
},
452 {STATUS_BUFFER_TOO_SMALL
, WSAEFAULT
},
453 {STATUS_OBJECT_TYPE_MISMATCH
, WSAENOTSOCK
},
454 {STATUS_OBJECT_NAME_NOT_FOUND
, WSAENETDOWN
},
455 {STATUS_OBJECT_PATH_NOT_FOUND
, WSAENETDOWN
},
456 {STATUS_SHARING_VIOLATION
, WSAEADDRINUSE
},
457 {STATUS_QUOTA_EXCEEDED
, WSAENOBUFS
},
458 {STATUS_TOO_MANY_PAGING_FILES
, WSAENOBUFS
},
459 {STATUS_INSUFFICIENT_RESOURCES
, WSAENOBUFS
},
460 {STATUS_WORKING_SET_QUOTA
, WSAENOBUFS
},
461 {STATUS_DEVICE_NOT_READY
, WSAEWOULDBLOCK
},
462 {STATUS_PIPE_DISCONNECTED
, WSAESHUTDOWN
},
463 {STATUS_IO_TIMEOUT
, WSAETIMEDOUT
},
464 {STATUS_NOT_SUPPORTED
, WSAEOPNOTSUPP
},
465 {STATUS_REMOTE_NOT_LISTENING
, WSAECONNREFUSED
},
466 {STATUS_BAD_NETWORK_PATH
, WSAENETUNREACH
},
467 {STATUS_NETWORK_BUSY
, WSAENETDOWN
},
468 {STATUS_INVALID_NETWORK_RESPONSE
, WSAENETDOWN
},
469 {STATUS_UNEXPECTED_NETWORK_ERROR
, WSAENETDOWN
},
470 {STATUS_REQUEST_NOT_ACCEPTED
, WSAEWOULDBLOCK
},
471 {STATUS_CANCELLED
, ERROR_OPERATION_ABORTED
},
472 {STATUS_COMMITMENT_LIMIT
, WSAENOBUFS
},
473 {STATUS_LOCAL_DISCONNECT
, WSAECONNABORTED
},
474 {STATUS_REMOTE_DISCONNECT
, WSAECONNRESET
},
475 {STATUS_REMOTE_RESOURCES
, WSAENOBUFS
},
476 {STATUS_LINK_FAILED
, WSAECONNRESET
},
477 {STATUS_LINK_TIMEOUT
, WSAETIMEDOUT
},
478 {STATUS_INVALID_CONNECTION
, WSAENOTCONN
},
479 {STATUS_INVALID_ADDRESS
, WSAEADDRNOTAVAIL
},
480 {STATUS_INVALID_BUFFER_SIZE
, WSAEMSGSIZE
},
481 {STATUS_INVALID_ADDRESS_COMPONENT
, WSAEADDRNOTAVAIL
},
482 {STATUS_TOO_MANY_ADDRESSES
, WSAENOBUFS
},
483 {STATUS_ADDRESS_ALREADY_EXISTS
, WSAEADDRINUSE
},
484 {STATUS_CONNECTION_DISCONNECTED
, WSAECONNRESET
},
485 {STATUS_CONNECTION_RESET
, WSAECONNRESET
},
486 {STATUS_TRANSACTION_ABORTED
, WSAECONNABORTED
},
487 {STATUS_CONNECTION_REFUSED
, WSAECONNREFUSED
},
488 {STATUS_GRACEFUL_DISCONNECT
, WSAEDISCON
},
489 {STATUS_CONNECTION_ACTIVE
, WSAEISCONN
},
490 {STATUS_NETWORK_UNREACHABLE
, WSAENETUNREACH
},
491 {STATUS_HOST_UNREACHABLE
, WSAEHOSTUNREACH
},
492 {STATUS_PROTOCOL_UNREACHABLE
, WSAENETUNREACH
},
493 {STATUS_PORT_UNREACHABLE
, WSAECONNRESET
},
494 {STATUS_REQUEST_ABORTED
, WSAEINTR
},
495 {STATUS_CONNECTION_ABORTED
, WSAECONNABORTED
},
496 {STATUS_DATATYPE_MISALIGNMENT_ERROR
,WSAEFAULT
},
497 {STATUS_HOST_DOWN
, WSAEHOSTDOWN
},
498 {0x80070000 | ERROR_IO_INCOMPLETE
, ERROR_IO_INCOMPLETE
},
499 {0xc0010000 | ERROR_IO_INCOMPLETE
, ERROR_IO_INCOMPLETE
},
500 {0xc0070000 | ERROR_IO_INCOMPLETE
, ERROR_IO_INCOMPLETE
},
505 for (i
= 0; i
< ARRAY_SIZE(errors
); ++i
)
507 if (errors
[i
].status
== status
)
508 return errors
[i
].error
;
511 return NT_SUCCESS(status
) ? RtlNtStatusToDosErrorNoTeb(status
) : WSAEINVAL
;
515 struct per_thread_data
*get_per_thread_data(void)
517 struct per_thread_data
*data
= NtCurrentTeb()->WinSockData
;
521 data
= calloc( 1, sizeof(*data
) );
522 NtCurrentTeb()->WinSockData
= data
;
527 static void free_per_thread_data(void)
529 struct per_thread_data
*data
= NtCurrentTeb()->WinSockData
;
533 CloseHandle( data
->sync_event
);
535 /* delete scratch buffers */
536 free( data
->he_buffer
);
537 free( data
->se_buffer
);
538 free( data
->pe_buffer
);
541 NtCurrentTeb()->WinSockData
= NULL
;
544 static HANDLE
get_sync_event(void)
546 struct per_thread_data
*data
;
548 if (!(data
= get_per_thread_data())) return NULL
;
549 if (!data
->sync_event
)
550 data
->sync_event
= CreateEventW( NULL
, TRUE
, FALSE
, NULL
);
551 return data
->sync_event
;
554 static DWORD
wait_event_alertable( HANDLE event
)
558 while ((ret
= WaitForSingleObjectEx( event
, INFINITE
, TRUE
)) == WAIT_IO_COMPLETION
)
563 BOOL WINAPI
DllMain( HINSTANCE instance
, DWORD reason
, void *reserved
)
567 case DLL_PROCESS_ATTACH
:
568 return !NtQueryVirtualMemory( GetCurrentProcess(), instance
, MemoryWineUnixFuncs
,
569 &ws_unix_handle
, sizeof(ws_unix_handle
), NULL
);
571 case DLL_THREAD_DETACH
:
572 free_per_thread_data();
578 /***********************************************************************
579 * WSAStartup (WS2_32.115)
581 int WINAPI
WSAStartup( WORD version
, WSADATA
*data
)
583 TRACE( "version %#x\n", version
);
587 if (!LOBYTE(version
) || LOBYTE(version
) > 2
588 || (LOBYTE(version
) == 2 && HIBYTE(version
) > 2))
589 data
->wVersion
= MAKEWORD(2, 2);
590 else if (LOBYTE(version
) == 1 && HIBYTE(version
) > 1)
591 data
->wVersion
= MAKEWORD(1, 1);
593 data
->wVersion
= version
;
594 data
->wHighVersion
= MAKEWORD(2, 2);
595 strcpy( data
->szDescription
, "WinSock 2.0" );
596 strcpy( data
->szSystemStatus
, "Running" );
597 data
->iMaxSockets
= (LOBYTE(version
) == 1 ? 32767 : 0);
598 data
->iMaxUdpDg
= (LOBYTE(version
) == 1 ? 65467 : 0);
599 /* don't fill lpVendorInfo */
602 if (!LOBYTE(version
))
603 return WSAVERNOTSUPPORTED
;
605 if (!data
) return WSAEFAULT
;
608 TRACE( "increasing startup count to %d\n", num_startup
);
613 /***********************************************************************
614 * WSACleanup (WS2_32.116)
616 INT WINAPI
WSACleanup(void)
618 TRACE("decreasing startup count from %d\n", num_startup
);
625 for (i
= 0; i
< socket_list_size
; ++i
)
626 CloseHandle(SOCKET2HANDLE(socket_list
[i
]));
627 memset(socket_list
, 0, socket_list_size
* sizeof(*socket_list
));
631 SetLastError(WSANOTINITIALISED
);
636 /***********************************************************************
637 * WSAGetLastError (WS2_32.111)
639 INT WINAPI
WSAGetLastError(void)
641 return GetLastError();
644 /***********************************************************************
645 * WSASetLastError (WS2_32.112)
647 void WINAPI
WSASetLastError(INT iError
) {
648 SetLastError(iError
);
651 static INT
WS_DuplicateSocket(BOOL unicode
, SOCKET s
, DWORD dwProcessId
, LPWSAPROTOCOL_INFOW lpProtocolInfo
)
655 WSAPROTOCOL_INFOW infow
;
657 TRACE( "unicode %d, socket %#Ix, pid %#lx, info %p\n", unicode
, s
, dwProcessId
, lpProtocolInfo
);
659 if (!ws_protocol_info(s
, unicode
, &infow
, &size
))
662 if (!(hProcess
= OpenProcess(PROCESS_DUP_HANDLE
, FALSE
, dwProcessId
)))
664 SetLastError(WSAEINVAL
);
670 CloseHandle(hProcess
);
671 SetLastError(WSAEFAULT
);
675 /* I don't know what the real Windoze does next, this is a hack */
676 /* ...we could duplicate and then use ConvertToGlobalHandle on the duplicate, then let
677 * the target use the global duplicate, or we could copy a reference to us to the structure
678 * and let the target duplicate it from us, but let's do it as simple as possible */
679 memcpy(lpProtocolInfo
, &infow
, size
);
680 DuplicateHandle(GetCurrentProcess(), SOCKET2HANDLE(s
),
681 hProcess
, (LPHANDLE
)&lpProtocolInfo
->dwServiceFlags3
,
682 0, FALSE
, DUPLICATE_SAME_ACCESS
);
683 CloseHandle(hProcess
);
684 lpProtocolInfo
->dwServiceFlags4
= 0xff00ff00; /* magic */
688 static BOOL
ws_protocol_info(SOCKET s
, int unicode
, WSAPROTOCOL_INFOW
*buffer
, int *size
)
690 struct afd_get_info_params params
;
695 *size
= unicode
? sizeof(WSAPROTOCOL_INFOW
) : sizeof(WSAPROTOCOL_INFOA
);
696 memset(buffer
, 0, *size
);
698 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
,
699 IOCTL_AFD_WINE_GET_INFO
, NULL
, 0, ¶ms
, sizeof(params
) );
702 SetLastError( NtStatusToWSAError( status
) );
706 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
708 const WSAPROTOCOL_INFOW
*info
= &supported_protocols
[i
];
709 if (params
.family
== info
->iAddressFamily
&&
710 params
.type
== info
->iSocketType
&&
711 params
.protocol
>= info
->iProtocol
&&
712 params
.protocol
<= info
->iProtocol
+ info
->iProtocolMaxOffset
)
718 WSAPROTOCOL_INFOA
*bufferA
= (WSAPROTOCOL_INFOA
*)buffer
;
719 memcpy( bufferA
, info
, offsetof( WSAPROTOCOL_INFOW
, szProtocol
) );
720 WideCharToMultiByte( CP_ACP
, 0, info
->szProtocol
, -1,
721 bufferA
->szProtocol
, sizeof(bufferA
->szProtocol
), NULL
, NULL
);
723 buffer
->iProtocol
= params
.protocol
;
727 FIXME( "Could not fill protocol information for family %d, type %d, protocol %d.\n",
728 params
.family
, params
.type
, params
.protocol
);
734 /***********************************************************************
737 SOCKET WINAPI
accept( SOCKET s
, struct sockaddr
*addr
, int *len
)
745 TRACE( "socket %#Ix\n", s
);
747 if (!(sync_event
= get_sync_event())) return INVALID_SOCKET
;
748 status
= NtDeviceIoControlFile( (HANDLE
)s
, sync_event
, NULL
, NULL
, &io
, IOCTL_AFD_WINE_ACCEPT
,
749 NULL
, 0, &accept_handle
, sizeof(accept_handle
) );
750 if (status
== STATUS_PENDING
)
752 if (WaitForSingleObject( sync_event
, INFINITE
) == WAIT_FAILED
)
754 status
= io
.u
.Status
;
758 TRACE( "failed, status %#lx\n", status
);
759 WSASetLastError( NtStatusToWSAError( status
) );
760 return INVALID_SOCKET
;
764 if (!socket_list_add( ret
))
766 CloseHandle( SOCKET2HANDLE(ret
) );
767 return INVALID_SOCKET
;
769 if (addr
&& len
&& getpeername( ret
, addr
, len
))
772 return INVALID_SOCKET
;
775 TRACE( "returning %#Ix\n", ret
);
779 /***********************************************************************
782 static BOOL WINAPI
WS2_AcceptEx( SOCKET listener
, SOCKET acceptor
, void *dest
, DWORD recv_len
,
783 DWORD local_len
, DWORD remote_len
, DWORD
*ret_len
, OVERLAPPED
*overlapped
)
785 struct afd_accept_into_params params
=
787 .accept_handle
= acceptor
,
788 .recv_len
= recv_len
,
789 .local_len
= local_len
,
794 TRACE( "listener %#Ix, acceptor %#Ix, dest %p, recv_len %lu, local_len %lu, remote_len %lu, ret_len %p, "
795 "overlapped %p\n", listener
, acceptor
, dest
, recv_len
, local_len
, remote_len
, ret_len
, overlapped
);
799 SetLastError(WSA_INVALID_PARAMETER
);
803 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
804 overlapped
->Internal
= STATUS_PENDING
;
805 overlapped
->InternalHigh
= 0;
809 SetLastError(WSAEINVAL
);
815 SetLastError(WSAEFAULT
);
819 status
= NtDeviceIoControlFile( SOCKET2HANDLE(listener
), overlapped
->hEvent
, NULL
, cvalue
,
820 (IO_STATUS_BLOCK
*)overlapped
, IOCTL_AFD_WINE_ACCEPT_INTO
, ¶ms
, sizeof(params
),
821 dest
, recv_len
+ local_len
+ remote_len
);
823 if (ret_len
) *ret_len
= overlapped
->InternalHigh
;
824 WSASetLastError( NtStatusToWSAError(status
) );
825 TRACE( "status %#lx.\n", status
);
830 static BOOL WINAPI
WS2_TransmitFile( SOCKET s
, HANDLE file
, DWORD file_len
, DWORD buffer_size
,
831 OVERLAPPED
*overlapped
, TRANSMIT_FILE_BUFFERS
*buffers
, DWORD flags
)
833 struct afd_transmit_params params
= {{{0}}};
834 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
839 TRACE( "socket %#Ix, file %p, file_len %lu, buffer_size %lu, overlapped %p, buffers %p, flags %#lx\n",
840 s
, file
, file_len
, buffer_size
, overlapped
, buffers
, flags
);
844 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
845 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
846 event
= overlapped
->hEvent
;
847 overlapped
->Internal
= STATUS_PENDING
;
848 overlapped
->InternalHigh
= 0;
849 params
.offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
850 params
.offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
854 if (!(event
= get_sync_event())) return -1;
855 params
.offset
.QuadPart
= FILE_USE_FILE_POINTER_POSITION
;
858 params
.file
= HandleToULong( file
);
859 params
.file_len
= file_len
;
860 params
.buffer_size
= buffer_size
;
863 params
.head_ptr
= u64_from_user_ptr(buffers
->Head
);
864 params
.head_len
= buffers
->HeadLength
;
865 params
.tail_ptr
= u64_from_user_ptr(buffers
->Tail
);
866 params
.tail_len
= buffers
->TailLength
;
868 params
.flags
= flags
;
870 status
= NtDeviceIoControlFile( (HANDLE
)s
, event
, NULL
, cvalue
, piosb
,
871 IOCTL_AFD_WINE_TRANSMIT
, ¶ms
, sizeof(params
), NULL
, 0 );
872 if (status
== STATUS_PENDING
&& !overlapped
)
874 if (WaitForSingleObject( event
, INFINITE
) == WAIT_FAILED
)
876 status
= piosb
->u
.Status
;
878 SetLastError( NtStatusToWSAError( status
) );
879 TRACE( "status %#lx.\n", status
);
884 /***********************************************************************
885 * GetAcceptExSockaddrs
887 static void WINAPI
WS2_GetAcceptExSockaddrs( void *buffer
, DWORD data_size
, DWORD local_size
, DWORD remote_size
,
888 struct sockaddr
**local_addr
, LPINT local_addr_len
,
889 struct sockaddr
**remote_addr
, LPINT remote_addr_len
)
893 TRACE( "buffer %p, data_size %lu, local_size %lu, remote_size %lu,"
894 " local_addr %p, local_addr_len %p, remote_addr %p, remote_addr_len %p\n",
895 buffer
, data_size
, local_size
, remote_size
,
896 local_addr
, local_addr_len
, remote_addr
, remote_addr_len
);
900 *local_addr_len
= *(int *) cbuf
;
901 *local_addr
= (struct sockaddr
*)(cbuf
+ sizeof(int));
905 *remote_addr_len
= *(int *) cbuf
;
906 *remote_addr
= (struct sockaddr
*)(cbuf
+ sizeof(int));
910 static void WINAPI
socket_apc( void *apc_user
, IO_STATUS_BLOCK
*io
, ULONG reserved
)
912 LPWSAOVERLAPPED_COMPLETION_ROUTINE func
= apc_user
;
913 func( NtStatusToWSAError( io
->u
.Status
), io
->Information
, (OVERLAPPED
*)io
, 0 );
916 static int WS2_recv_base( SOCKET s
, WSABUF
*buffers
, DWORD buffer_count
, DWORD
*ret_size
, DWORD
*flags
,
917 struct sockaddr
*addr
, int *addr_len
, OVERLAPPED
*overlapped
,
918 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
, WSABUF
*control
)
920 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
921 struct afd_recvmsg_params params
;
922 PIO_APC_ROUTINE apc
= NULL
;
927 TRACE( "socket %#Ix, buffers %p, buffer_count %lu, flags %#lx, addr %p, "
928 "addr_len %d, overlapped %p, completion %p, control %p\n",
929 s
, buffers
, buffer_count
, *flags
, addr
, addr_len
? *addr_len
: -1, overlapped
, completion
, control
);
933 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
934 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
935 event
= overlapped
->hEvent
;
939 if (!(event
= get_sync_event())) return -1;
941 piosb
->u
.Status
= STATUS_PENDING
;
950 params
.control_ptr
= u64_from_user_ptr(control
);
951 params
.addr_ptr
= u64_from_user_ptr(addr
);
952 params
.addr_len_ptr
= u64_from_user_ptr(addr_len
);
953 params
.ws_flags_ptr
= u64_from_user_ptr(flags
);
954 params
.force_async
= !!overlapped
;
955 params
.count
= buffer_count
;
956 params
.buffers_ptr
= u64_from_user_ptr(buffers
);
958 status
= NtDeviceIoControlFile( (HANDLE
)s
, event
, apc
, cvalue
, piosb
,
959 IOCTL_AFD_WINE_RECVMSG
, ¶ms
, sizeof(params
), NULL
, 0 );
960 if (status
== STATUS_PENDING
&& !overlapped
)
962 if (wait_event_alertable( event
) == WAIT_FAILED
)
964 status
= piosb
->u
.Status
;
966 if (!status
&& ret_size
) *ret_size
= piosb
->Information
;
967 SetLastError( NtStatusToWSAError( status
) );
968 TRACE( "status %#lx.\n", status
);
969 return status
? -1 : 0;
972 static int WS2_sendto( SOCKET s
, WSABUF
*buffers
, DWORD buffer_count
, DWORD
*ret_size
, DWORD flags
,
973 const struct sockaddr
*addr
, int addr_len
, OVERLAPPED
*overlapped
,
974 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
)
976 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
977 struct afd_sendmsg_params params
;
978 PIO_APC_ROUTINE apc
= NULL
;
983 TRACE( "socket %#Ix, buffers %p, buffer_count %lu, flags %#lx, addr %p, "
984 "addr_len %d, overlapped %p, completion %p\n",
985 s
, buffers
, buffer_count
, flags
, addr
, addr_len
, overlapped
, completion
);
987 if (!socket_list_find( s
))
989 SetLastError( WSAENOTSOCK
);
993 if (!overlapped
&& !ret_size
)
995 SetLastError( WSAEFAULT
);
1001 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
1002 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
1003 event
= overlapped
->hEvent
;
1007 if (!(event
= get_sync_event())) return -1;
1009 piosb
->u
.Status
= STATUS_PENDING
;
1014 cvalue
= completion
;
1018 params
.addr_ptr
= u64_from_user_ptr( addr
);
1019 params
.addr_len
= addr_len
;
1020 params
.ws_flags
= flags
;
1021 params
.force_async
= !!overlapped
;
1022 params
.count
= buffer_count
;
1023 params
.buffers_ptr
= u64_from_user_ptr( buffers
);
1025 status
= NtDeviceIoControlFile( (HANDLE
)s
, event
, apc
, cvalue
, piosb
,
1026 IOCTL_AFD_WINE_SENDMSG
, ¶ms
, sizeof(params
), NULL
, 0 );
1027 if (status
== STATUS_PENDING
&& !overlapped
)
1029 if (WaitForSingleObject( event
, INFINITE
) == WAIT_FAILED
)
1031 status
= piosb
->u
.Status
;
1033 if (!status
&& ret_size
) *ret_size
= piosb
->Information
;
1034 SetLastError( NtStatusToWSAError( status
) );
1035 TRACE( "status %#lx.\n", status
);
1036 return status
? -1 : 0;
1040 /***********************************************************************
1043 int WINAPI
WSASendMsg( SOCKET s
, LPWSAMSG msg
, DWORD dwFlags
, LPDWORD lpNumberOfBytesSent
,
1044 LPWSAOVERLAPPED lpOverlapped
,
1045 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
1049 SetLastError( WSAEFAULT
);
1050 return SOCKET_ERROR
;
1053 return WS2_sendto( s
, msg
->lpBuffers
, msg
->dwBufferCount
, lpNumberOfBytesSent
,
1054 dwFlags
, msg
->name
, msg
->namelen
,
1055 lpOverlapped
, lpCompletionRoutine
);
1058 /***********************************************************************
1061 * Perform a receive operation that is capable of returning message
1062 * control headers. It is important to note that the WSAMSG parameter
1063 * must remain valid throughout the operation, even when an overlapped
1064 * receive is performed.
1066 static int WINAPI
WS2_WSARecvMsg( SOCKET s
, LPWSAMSG msg
, LPDWORD lpNumberOfBytesRecvd
,
1067 LPWSAOVERLAPPED lpOverlapped
,
1068 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
1072 SetLastError( WSAEFAULT
);
1073 return SOCKET_ERROR
;
1076 return WS2_recv_base( s
, msg
->lpBuffers
, msg
->dwBufferCount
, lpNumberOfBytesRecvd
,
1077 &msg
->dwFlags
, msg
->name
, &msg
->namelen
,
1078 lpOverlapped
, lpCompletionRoutine
, &msg
->Control
);
1082 /***********************************************************************
1085 int WINAPI
bind( SOCKET s
, const struct sockaddr
*addr
, int len
)
1087 struct afd_bind_params
*params
;
1088 struct sockaddr
*ret_addr
;
1093 TRACE( "socket %#Ix, addr %s\n", s
, debugstr_sockaddr(addr
) );
1097 SetLastError( WSAEFAULT
);
1101 switch (addr
->sa_family
)
1104 if (len
< sizeof(struct sockaddr_in
))
1106 SetLastError( WSAEFAULT
);
1112 if (len
< sizeof(struct sockaddr_in6
))
1114 SetLastError( WSAEFAULT
);
1120 if (len
< sizeof(struct sockaddr_ipx
))
1122 SetLastError( WSAEFAULT
);
1128 if (len
< sizeof(SOCKADDR_IRDA
))
1130 SetLastError( WSAEFAULT
);
1136 FIXME( "unknown protocol %u\n", addr
->sa_family
);
1137 SetLastError( WSAEAFNOSUPPORT
);
1141 if (!(sync_event
= get_sync_event())) return -1;
1143 params
= malloc( sizeof(int) + len
);
1144 ret_addr
= malloc( len
);
1145 if (!params
|| !ret_addr
)
1149 SetLastError( WSAENOBUFS
);
1152 params
->unknown
= 0;
1153 memcpy( ¶ms
->addr
, addr
, len
);
1155 status
= NtDeviceIoControlFile( (HANDLE
)s
, sync_event
, NULL
, NULL
, &io
, IOCTL_AFD_BIND
,
1156 params
, sizeof(int) + len
, ret_addr
, len
);
1157 if (status
== STATUS_PENDING
)
1159 if (WaitForSingleObject( sync_event
, INFINITE
) == WAIT_FAILED
)
1161 status
= io
.u
.Status
;
1164 if (status
) TRACE( "failed, status %#lx.\n", status
);
1165 else TRACE( "successfully bound to address %s\n", debugstr_sockaddr( ret_addr
));
1170 SetLastError( NtStatusToWSAError( status
) );
1171 return status
? -1 : 0;
1175 /***********************************************************************
1176 * closesocket (ws2_32.3)
1178 int WINAPI
closesocket( SOCKET s
)
1180 TRACE( "%#Ix\n", s
);
1184 SetLastError( WSANOTINITIALISED
);
1188 if (!socket_list_remove( s
))
1190 SetLastError( WSAENOTSOCK
);
1194 CloseHandle( (HANDLE
)s
);
1199 /***********************************************************************
1200 * connect (ws2_32.4)
1202 int WINAPI
connect( SOCKET s
, const struct sockaddr
*addr
, int len
)
1204 struct afd_connect_params
*params
;
1209 TRACE( "socket %#Ix, addr %s, len %d\n", s
, debugstr_sockaddr(addr
), len
);
1211 if (!(sync_event
= get_sync_event())) return -1;
1213 if (!(params
= malloc( sizeof(*params
) + len
)))
1215 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1218 params
->addr_len
= len
;
1219 params
->synchronous
= TRUE
;
1220 memcpy( params
+ 1, addr
, len
);
1222 status
= NtDeviceIoControlFile( (HANDLE
)s
, sync_event
, NULL
, NULL
, &io
, IOCTL_AFD_WINE_CONNECT
,
1223 params
, sizeof(*params
) + len
, NULL
, 0 );
1225 if (status
== STATUS_PENDING
)
1227 if (WaitForSingleObject( sync_event
, INFINITE
) == WAIT_FAILED
) return -1;
1228 status
= io
.u
.Status
;
1232 /* NtStatusToWSAError() has no mapping for WSAEALREADY */
1233 SetLastError( status
== STATUS_ADDRESS_ALREADY_ASSOCIATED
? WSAEALREADY
: NtStatusToWSAError( status
) );
1234 TRACE( "failed, status %#lx.\n", status
);
1241 /***********************************************************************
1242 * WSAConnect (WS2_32.30)
1244 int WINAPI
WSAConnect( SOCKET s
, const struct sockaddr
*name
, int namelen
,
1245 LPWSABUF lpCallerData
, LPWSABUF lpCalleeData
,
1246 LPQOS lpSQOS
, LPQOS lpGQOS
)
1248 if ( lpCallerData
|| lpCalleeData
|| lpSQOS
|| lpGQOS
)
1249 FIXME("unsupported parameters!\n");
1250 return connect( s
, name
, namelen
);
1254 static BOOL WINAPI
WS2_ConnectEx( SOCKET s
, const struct sockaddr
*name
, int namelen
,
1255 void *send_buffer
, DWORD send_len
, DWORD
*ret_len
, OVERLAPPED
*overlapped
)
1257 struct afd_connect_params
*params
;
1258 void *cvalue
= NULL
;
1261 TRACE( "socket %#Ix, ptr %p %s, length %d, send_buffer %p, send_len %lu, overlapped %p\n",
1262 s
, name
, debugstr_sockaddr(name
), namelen
, send_buffer
, send_len
, overlapped
);
1266 SetLastError( WSA_INVALID_PARAMETER
);
1270 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
1271 overlapped
->Internal
= STATUS_PENDING
;
1272 overlapped
->InternalHigh
= 0;
1274 if (!(params
= malloc( sizeof(*params
) + namelen
+ send_len
)))
1276 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1277 return SOCKET_ERROR
;
1279 params
->addr_len
= namelen
;
1280 params
->synchronous
= FALSE
;
1281 memcpy( params
+ 1, name
, namelen
);
1282 memcpy( (char *)(params
+ 1) + namelen
, send_buffer
, send_len
);
1284 status
= NtDeviceIoControlFile( SOCKET2HANDLE(s
), overlapped
->hEvent
, NULL
, cvalue
,
1285 (IO_STATUS_BLOCK
*)overlapped
, IOCTL_AFD_WINE_CONNECT
,
1286 params
, sizeof(*params
) + namelen
+ send_len
, NULL
, 0 );
1288 if (ret_len
) *ret_len
= overlapped
->InternalHigh
;
1289 SetLastError( NtStatusToWSAError( status
) );
1290 TRACE( "status %#lx.\n", status
);
1295 /***********************************************************************
1296 * WSAConnectByNameA (WS2_32.@)
1298 BOOL WINAPI
WSAConnectByNameA(SOCKET s
, const char *node_name
, const char *service_name
,
1299 DWORD
*local_addr_len
, struct sockaddr
*local_addr
,
1300 DWORD
*remote_addr_len
, struct sockaddr
*remote_addr
,
1301 const struct timeval
*timeout
, WSAOVERLAPPED
*reserved
)
1303 WSAPROTOCOL_INFOA proto_info
;
1305 struct addrinfo
*service
, hints
;
1306 int ret
, proto_len
, sockaddr_size
, sockname_size
, sock_err
, int_len
;
1308 TRACE("socket %#Ix, node_name %s, service_name %s, local_addr_len %p, local_addr %p, \
1309 remote_addr_len %p, remote_addr %p, timeout %p, reserved %p\n",
1310 s
, debugstr_a(node_name
), debugstr_a(service_name
), local_addr_len
, local_addr
,
1311 remote_addr_len
, remote_addr
, timeout
, reserved
);
1313 if (!node_name
|| !service_name
|| reserved
)
1315 SetLastError(WSAEINVAL
);
1321 SetLastError(WSAENOTSOCK
);
1326 FIXME("WSAConnectByName timeout stub\n");
1328 proto_len
= sizeof(WSAPROTOCOL_INFOA
);
1329 ret
= getsockopt(s
, SOL_SOCKET
, SO_PROTOCOL_INFOA
, (char *)&proto_info
, &proto_len
);
1333 memset(&hints
, 0, sizeof(struct addrinfo
));
1334 hints
.ai_socktype
= proto_info
.iSocketType
;
1335 hints
.ai_family
= proto_info
.iAddressFamily
;
1336 hints
.ai_protocol
= proto_info
.iProtocol
;
1337 ret
= getaddrinfo(node_name
, service_name
, &hints
, &service
);
1341 if (proto_info
.iSocketType
!= SOCK_STREAM
)
1343 freeaddrinfo(service
);
1344 SetLastError(WSAEFAULT
);
1348 switch (proto_info
.iAddressFamily
)
1351 sockaddr_size
= sizeof(SOCKADDR_IN
);
1354 sockaddr_size
= sizeof(SOCKADDR_IN6
);
1357 freeaddrinfo(service
);
1358 SetLastError(WSAENOTSOCK
);
1362 ret
= connect(s
, service
->ai_addr
, sockaddr_size
);
1365 freeaddrinfo(service
);
1370 pollout
.events
= POLLWRNORM
;
1371 ret
= WSAPoll(&pollout
, 1, -1);
1372 if (ret
== SOCKET_ERROR
)
1374 freeaddrinfo(service
);
1377 if (pollout
.revents
& (POLLERR
| POLLHUP
| POLLNVAL
))
1379 freeaddrinfo(service
);
1380 int_len
= sizeof(int);
1381 ret
= getsockopt(s
, SOL_SOCKET
, SO_ERROR
, (char *)&sock_err
, &int_len
);
1382 if (ret
== SOCKET_ERROR
)
1384 SetLastError(sock_err
);
1388 if (remote_addr_len
&& remote_addr
)
1390 if (*remote_addr_len
>= sockaddr_size
)
1392 memcpy(remote_addr
, service
->ai_addr
, sockaddr_size
);
1393 *remote_addr_len
= sockaddr_size
;
1397 freeaddrinfo(service
);
1398 SetLastError(WSAEFAULT
);
1403 freeaddrinfo(service
);
1405 if (local_addr_len
&& local_addr
)
1407 if (*local_addr_len
>= sockaddr_size
)
1409 sockname_size
= sockaddr_size
;
1410 ret
= getsockname(s
, local_addr
, &sockname_size
);
1413 if (proto_info
.iAddressFamily
== AF_INET6
)
1414 ((SOCKADDR_IN6
*)local_addr
)->sin6_port
= 0;
1416 ((SOCKADDR_IN
*)local_addr
)->sin_port
= 0;
1417 *local_addr_len
= sockaddr_size
;
1421 SetLastError(WSAEFAULT
);
1430 /***********************************************************************
1431 * WSAConnectByNameW (WS2_32.@)
1433 BOOL WINAPI
WSAConnectByNameW(SOCKET s
, const WCHAR
*node_name
, const WCHAR
*service_name
,
1434 DWORD
*local_addr_len
, struct sockaddr
*local_addr
,
1435 DWORD
*remote_addr_len
, struct sockaddr
*remote_addr
,
1436 const struct timeval
*timeout
, WSAOVERLAPPED
*reserved
)
1438 char *node_nameA
, *service_nameA
;
1441 if (!node_name
|| !service_name
)
1443 SetLastError(WSAEINVAL
);
1447 node_nameA
= strdupWtoA(node_name
);
1448 service_nameA
= strdupWtoA(service_name
);
1449 if (!node_nameA
|| !service_nameA
)
1451 SetLastError(WSAENOBUFS
);
1455 ret
= WSAConnectByNameA(s
, node_nameA
, service_nameA
, local_addr_len
, local_addr
,
1456 remote_addr_len
, remote_addr
, timeout
, reserved
);
1458 free(service_nameA
);
1463 static BOOL WINAPI
WS2_DisconnectEx( SOCKET s
, OVERLAPPED
*overlapped
, DWORD flags
, DWORD reserved
)
1465 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
1466 void *cvalue
= NULL
;
1471 TRACE( "socket %#Ix, overlapped %p, flags %#lx, reserved %#lx\n", s
, overlapped
, flags
, reserved
);
1473 if (flags
& TF_REUSE_SOCKET
)
1474 FIXME( "Reusing socket not supported yet\n" );
1478 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
1479 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
1480 event
= overlapped
->hEvent
;
1481 overlapped
->Internal
= STATUS_PENDING
;
1482 overlapped
->InternalHigh
= 0;
1485 status
= NtDeviceIoControlFile( (HANDLE
)s
, event
, NULL
, cvalue
, piosb
,
1486 IOCTL_AFD_WINE_SHUTDOWN
, &how
, sizeof(how
), NULL
, 0 );
1487 if (!status
&& overlapped
) status
= STATUS_PENDING
;
1488 SetLastError( NtStatusToWSAError( status
) );
1489 TRACE( "status %#lx.\n", status
);
1494 /***********************************************************************
1495 * getpeername (ws2_32.5)
1497 int WINAPI
getpeername( SOCKET s
, struct sockaddr
*addr
, int *len
)
1502 TRACE( "socket %#Ix, addr %p, len %d\n", s
, addr
, len
? *len
: 0 );
1504 if (!socket_list_find( s
))
1506 WSASetLastError( WSAENOTSOCK
);
1512 SetLastError( WSAEFAULT
);
1516 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
,
1517 IOCTL_AFD_WINE_GETPEERNAME
, NULL
, 0, addr
, *len
);
1519 *len
= io
.Information
;
1520 SetLastError( NtStatusToWSAError( status
) );
1521 TRACE( "status %#lx.\n", status
);
1522 return status
? -1 : 0;
1526 /***********************************************************************
1527 * getsockname (ws2_32.6)
1529 int WINAPI
getsockname( SOCKET s
, struct sockaddr
*addr
, int *len
)
1534 TRACE( "socket %#Ix, addr %p, len %d\n", s
, addr
, len
? *len
: 0 );
1538 SetLastError( WSAEFAULT
);
1542 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, IOCTL_AFD_GETSOCKNAME
, NULL
, 0, addr
, *len
);
1544 *len
= io
.Information
;
1545 WSASetLastError( NtStatusToWSAError( status
) );
1546 TRACE( "status %#lx.\n", status
);
1547 return status
? -1 : 0;
1551 static int server_getsockopt( SOCKET s
, ULONG code
, char *optval
, int *optlen
)
1556 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, code
, NULL
, 0, optval
, *optlen
);
1557 if (!status
) *optlen
= io
.Information
;
1558 SetLastError( NtStatusToWSAError( status
) );
1559 TRACE( "status %#lx.\n", status
);
1560 return status
? -1 : 0;
1564 /***********************************************************************
1565 * getsockopt (WS2_32.7)
1567 int WINAPI
getsockopt( SOCKET s
, int level
, int optname
, char *optval
, int *optlen
)
1571 TRACE( "socket %#Ix, %s, optval %p, optlen %p (%d)\n",
1572 s
, debugstr_sockopt(level
, optname
), optval
, optlen
, optlen
? *optlen
: 0 );
1574 if ((level
!= SOL_SOCKET
|| optname
!= SO_OPENTYPE
))
1576 if (!socket_list_find( s
))
1578 SetLastError( WSAENOTSOCK
);
1579 return SOCKET_ERROR
;
1581 if (!optlen
|| *optlen
<= 0)
1583 SetLastError( WSAEFAULT
);
1595 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_ACCEPTCONN
, optval
, optlen
);
1598 ret
= server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_BROADCAST
, optval
, optlen
);
1599 if (!ret
&& *optlen
< sizeof(DWORD
)) *optlen
= 1;
1604 CSADDR_INFO
*csinfo
= (CSADDR_INFO
*)optval
;
1605 WSAPROTOCOL_INFOW infow
;
1608 if (!ws_protocol_info( s
, TRUE
, &infow
, &addr_size
))
1611 if (infow
.iAddressFamily
== AF_INET
)
1612 addr_size
= sizeof(struct sockaddr_in
);
1613 else if (infow
.iAddressFamily
== AF_INET6
)
1614 addr_size
= sizeof(struct sockaddr_in6
);
1617 FIXME( "family %d is unsupported for SO_BSP_STATE\n", infow
.iAddressFamily
);
1618 SetLastError( WSAEAFNOSUPPORT
);
1622 if (*optlen
< sizeof(CSADDR_INFO
) + addr_size
* 2)
1625 SetLastError( WSAEFAULT
);
1629 csinfo
->LocalAddr
.lpSockaddr
= (struct sockaddr
*)(csinfo
+ 1);
1630 csinfo
->RemoteAddr
.lpSockaddr
= (struct sockaddr
*)((char *)(csinfo
+ 1) + addr_size
);
1632 csinfo
->LocalAddr
.iSockaddrLength
= addr_size
;
1633 if (getsockname( s
, csinfo
->LocalAddr
.lpSockaddr
, &csinfo
->LocalAddr
.iSockaddrLength
) < 0)
1635 csinfo
->LocalAddr
.lpSockaddr
= NULL
;
1636 csinfo
->LocalAddr
.iSockaddrLength
= 0;
1639 csinfo
->RemoteAddr
.iSockaddrLength
= addr_size
;
1640 if (getpeername( s
, csinfo
->RemoteAddr
.lpSockaddr
, &csinfo
->RemoteAddr
.iSockaddrLength
) < 0)
1642 csinfo
->RemoteAddr
.lpSockaddr
= NULL
;
1643 csinfo
->RemoteAddr
.iSockaddrLength
= 0;
1646 csinfo
->iSocketType
= infow
.iSocketType
;
1647 csinfo
->iProtocol
= infow
.iProtocol
;
1651 case SO_CONNECT_TIME
:
1654 SetLastError( WSAEFAULT
);
1657 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_CONNECT_TIME
, optval
, optlen
);
1660 WARN( "returning 0 for SO_DEBUG\n" );
1661 *(DWORD
*)optval
= 0;
1668 int len
= sizeof(linger
);
1672 if (*optlen
< 1 || !optval
)
1674 SetLastError(WSAEFAULT
);
1675 return SOCKET_ERROR
;
1678 if (!(ret
= getsockopt( s
, SOL_SOCKET
, SO_LINGER
, (char *)&linger
, &len
)))
1680 value
= !linger
.l_onoff
;
1681 memcpy( optval
, &value
, min( sizeof(BOOL
), *optlen
));
1682 *optlen
= *optlen
>= sizeof(BOOL
) ? sizeof(BOOL
) : 1;
1687 /* As mentioned in setsockopt, Windows ignores this, so we
1688 * always return true here */
1690 if (*optlen
< 1 || !optval
)
1692 SetLastError( WSAEFAULT
);
1693 return SOCKET_ERROR
;
1697 SetLastError( ERROR_SUCCESS
);
1701 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_ERROR
, optval
, optlen
);
1704 if (*optlen
< 1 || !optval
)
1706 SetLastError( WSAEFAULT
);
1707 return SOCKET_ERROR
;
1710 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_KEEPALIVE
, optval
, optlen
);
1714 WSAPROTOCOL_INFOW info
;
1717 /* struct linger and LINGER have different sizes */
1718 if (*optlen
< sizeof(LINGER
) || !optval
)
1720 if (optval
) memset( optval
, 0, *optlen
);
1721 SetLastError( WSAEFAULT
);
1722 return SOCKET_ERROR
;
1725 if (!ws_protocol_info( s
, TRUE
, &info
, &size
))
1728 if (info
.iSocketType
== SOCK_DGRAM
)
1730 SetLastError( WSAENOPROTOOPT
);
1734 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_LINGER
, optval
, optlen
);
1737 case SO_MAX_MSG_SIZE
:
1738 if (*optlen
< sizeof(int) || !optval
)
1740 SetLastError(WSAEFAULT
);
1741 return SOCKET_ERROR
;
1743 TRACE("getting global SO_MAX_MSG_SIZE = 65507\n");
1744 *(int *)optval
= 65507;
1745 *optlen
= sizeof(int);
1749 ret
= server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_OOBINLINE
, optval
, optlen
);
1750 if (!ret
&& *optlen
< sizeof(DWORD
)) *optlen
= 1;
1753 /* SO_OPENTYPE does not require a valid socket handle. */
1755 if (!optlen
|| *optlen
< sizeof(int) || !optval
)
1757 SetLastError( WSAEFAULT
);
1758 return SOCKET_ERROR
;
1760 *(int *)optval
= get_per_thread_data()->opentype
;
1761 *optlen
= sizeof(int);
1762 TRACE("getting global SO_OPENTYPE = 0x%x\n", *((int*)optval
) );
1763 SetLastError( ERROR_SUCCESS
);
1766 case SO_PROTOCOL_INFOA
:
1767 case SO_PROTOCOL_INFOW
:
1770 WSAPROTOCOL_INFOW infow
;
1772 ret
= ws_protocol_info(s
, optname
== SO_PROTOCOL_INFOW
, &infow
, &size
);
1775 if (!optval
|| *optlen
< size
)
1779 SetLastError(WSAEFAULT
);
1782 memcpy(optval
, &infow
, size
);
1784 return ret
? 0 : SOCKET_ERROR
;
1788 if (*optlen
< sizeof(DWORD
) || !optval
)
1790 if (optval
) memset( optval
, 0, *optlen
);
1791 SetLastError( WSAEFAULT
);
1792 return SOCKET_ERROR
;
1794 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_RCVBUF
, optval
, optlen
);
1797 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_RCVTIMEO
, optval
, optlen
);
1800 ret
= server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_REUSEADDR
, optval
, optlen
);
1801 if (!ret
&& *optlen
< sizeof(DWORD
)) *optlen
= 1;
1805 if (*optlen
< sizeof(DWORD
) || !optval
)
1807 if (optval
) memset( optval
, 0, *optlen
);
1808 SetLastError( WSAEFAULT
);
1809 return SOCKET_ERROR
;
1811 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_SNDBUF
, optval
, optlen
);
1814 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_SO_SNDTIMEO
, optval
, optlen
);
1818 WSAPROTOCOL_INFOW info
;
1821 if (*optlen
< sizeof(int) || !optval
)
1823 SetLastError(WSAEFAULT
);
1824 return SOCKET_ERROR
;
1827 if (!ws_protocol_info( s
, TRUE
, &info
, &size
))
1830 *(int *)optval
= info
.iSocketType
;
1835 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname
);
1836 SetLastError(WSAENOPROTOOPT
);
1837 return SOCKET_ERROR
;
1838 } /* end switch(optname) */
1839 }/* end case SOL_SOCKET */
1843 struct sockaddr_ipx addr
;
1844 IPX_ADDRESS_DATA
*data
;
1850 * On a Win2000 system with one network card there are usually
1851 * three ipx devices one with a speed of 28.8kbps, 10Mbps and 100Mbps.
1852 * Using this call you can then retrieve info about this all.
1853 * In case of Linux it is a bit different. Usually you have
1854 * only "one" device active and further it is not possible to
1855 * query things like the linkspeed.
1857 FIXME("IPX_ADDRESS\n");
1858 namelen
= sizeof(struct sockaddr_ipx
);
1859 memset( &addr
, 0, sizeof(struct sockaddr_ipx
) );
1860 getsockname( s
, (struct sockaddr
*)&addr
, &namelen
);
1862 data
= (IPX_ADDRESS_DATA
*)optval
;
1863 memcpy(data
->nodenum
,addr
.sa_nodenum
,sizeof(data
->nodenum
));
1864 memcpy(data
->netnum
,addr
.sa_netnum
,sizeof(data
->netnum
));
1865 data
->adapternum
= 0;
1866 data
->wan
= FALSE
; /* We are not on a wan for now .. */
1867 data
->status
= FALSE
; /* Since we are not on a wan, the wan link isn't up */
1868 data
->maxpkt
= 1467; /* This value is the default one, at least on Win2k/WinXP */
1869 data
->linkspeed
= 100000; /* Set the line speed in 100bit/s to 10 Mbit;
1870 * note 1MB = 1000kB in this case */
1873 case IPX_MAX_ADAPTER_NUM
:
1874 FIXME("IPX_MAX_ADAPTER_NUM\n");
1875 *(int*)optval
= 1; /* As noted under IPX_ADDRESS we have just one card. */
1879 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPX_PTYPE
, optval
, optlen
);
1882 FIXME("IPX optname:%x\n", optname
);
1883 return SOCKET_ERROR
;
1884 }/* end switch(optname) */
1885 } /* end case NSPROTO_IPX */
1890 case IRLMP_ENUMDEVICES
:
1891 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IRLMP_ENUMDEVICES
, optval
, optlen
);
1894 FIXME("IrDA optname:0x%x\n", optname
);
1895 return SOCKET_ERROR
;
1897 break; /* case SOL_IRLMP */
1899 /* Levels IPPROTO_TCP and IPPROTO_IP convert directly */
1904 if (*optlen
< 1 || !optval
)
1906 SetLastError( WSAEFAULT
);
1907 return SOCKET_ERROR
;
1910 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_TCP_NODELAY
, optval
, optlen
);
1913 FIXME( "unrecognized TCP option %#x\n", optname
);
1914 SetLastError( WSAENOPROTOOPT
);
1921 case IP_DONTFRAGMENT
:
1922 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT
, optval
, optlen
);
1925 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_HDRINCL
, optval
, optlen
);
1927 case IP_MULTICAST_IF
:
1928 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_MULTICAST_IF
, optval
, optlen
);
1930 case IP_MULTICAST_LOOP
:
1931 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_MULTICAST_LOOP
, optval
, optlen
);
1933 case IP_MULTICAST_TTL
:
1934 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_MULTICAST_TTL
, optval
, optlen
);
1937 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_OPTIONS
, optval
, optlen
);
1940 if (*optlen
< sizeof(DWORD
) || !optval
)
1943 SetLastError( WSAEFAULT
);
1944 return SOCKET_ERROR
;
1946 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_PKTINFO
, optval
, optlen
);
1949 if (*optlen
< sizeof(DWORD
) || !optval
)
1952 SetLastError( WSAEFAULT
);
1953 return SOCKET_ERROR
;
1955 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_RECVTOS
, optval
, optlen
);
1958 if (*optlen
< sizeof(DWORD
) || !optval
)
1961 SetLastError( WSAEFAULT
);
1962 return SOCKET_ERROR
;
1964 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_RECVTTL
, optval
, optlen
);
1967 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_TOS
, optval
, optlen
);
1970 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_TTL
, optval
, optlen
);
1973 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IP_UNICAST_IF
, optval
, optlen
);
1976 FIXME( "unrecognized IP option %u\n", optname
);
1979 case IP_ADD_MEMBERSHIP
:
1980 case IP_DROP_MEMBERSHIP
:
1981 SetLastError( WSAENOPROTOOPT
);
1989 if (*optlen
< 1 || !optval
)
1991 SetLastError( WSAEFAULT
);
1992 return SOCKET_ERROR
;
1994 if (*optlen
< sizeof(DWORD
)) *optlen
= 1;
1995 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_DONTFRAG
, optval
, optlen
);
1998 if (*optlen
< sizeof(DWORD
) || !optval
)
2001 SetLastError( WSAEFAULT
);
2002 return SOCKET_ERROR
;
2004 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_RECVHOPLIMIT
, optval
, optlen
);
2006 case IPV6_MULTICAST_HOPS
:
2007 if (*optlen
< 1 || !optval
)
2009 SetLastError( WSAEFAULT
);
2010 return SOCKET_ERROR
;
2012 if (*optlen
< sizeof(DWORD
)) *optlen
= 1;
2013 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_HOPS
, optval
, optlen
);
2015 case IPV6_MULTICAST_IF
:
2016 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_IF
, optval
, optlen
);
2018 case IPV6_MULTICAST_LOOP
:
2019 if (*optlen
< 1 || !optval
)
2021 SetLastError( WSAEFAULT
);
2022 return SOCKET_ERROR
;
2024 if (*optlen
< sizeof(DWORD
)) *optlen
= 1;
2025 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_MULTICAST_LOOP
, optval
, optlen
);
2027 case IPV6_PROTECTION_LEVEL
:
2028 if (*optlen
< sizeof(UINT
) || !optval
)
2030 SetLastError( WSAEFAULT
);
2033 *optlen
= sizeof(UINT
);
2034 *optval
= PROTECTION_LEVEL_UNRESTRICTED
;
2035 FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
2039 if (*optlen
< sizeof(DWORD
) || !optval
)
2042 SetLastError( WSAEFAULT
);
2043 return SOCKET_ERROR
;
2045 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_RECVPKTINFO
, optval
, optlen
);
2047 case IPV6_RECVTCLASS
:
2048 if (*optlen
< sizeof(DWORD
) || !optval
)
2050 if (optlen
) *optlen
= 0;
2051 SetLastError( WSAEFAULT
);
2052 return SOCKET_ERROR
;
2054 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_RECVTCLASS
, optval
, optlen
);
2056 case IPV6_UNICAST_HOPS
:
2057 if (*optlen
< 1 || !optval
)
2059 SetLastError( WSAEFAULT
);
2060 return SOCKET_ERROR
;
2062 if (*optlen
< sizeof(DWORD
)) *optlen
= 1;
2063 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_UNICAST_HOPS
, optval
, optlen
);
2065 case IPV6_UNICAST_IF
:
2066 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_UNICAST_IF
, optval
, optlen
);
2069 if (*optlen
< 1 || !optval
)
2071 SetLastError( WSAEFAULT
);
2072 return SOCKET_ERROR
;
2075 return server_getsockopt( s
, IOCTL_AFD_WINE_GET_IPV6_V6ONLY
, optval
, optlen
);
2078 FIXME( "unrecognized IPv6 option %u\n", optname
);
2081 case IPV6_ADD_MEMBERSHIP
:
2082 case IPV6_DROP_MEMBERSHIP
:
2083 SetLastError( WSAENOPROTOOPT
);
2088 WARN("Unknown level: 0x%08x\n", level
);
2089 SetLastError(WSAEINVAL
);
2090 return SOCKET_ERROR
;
2091 } /* end switch(level) */
2095 static const char *debugstr_wsaioctl(DWORD code
)
2097 const char *buf_type
, *family
;
2099 #define IOCTL_NAME(x) case x: return #x
2102 IOCTL_NAME(FIONBIO
);
2103 IOCTL_NAME(FIONREAD
);
2104 IOCTL_NAME(SIOCATMARK
);
2105 /* IOCTL_NAME(SIO_ACQUIRE_PORT_RESERVATION); */
2106 IOCTL_NAME(SIO_ADDRESS_LIST_CHANGE
);
2107 IOCTL_NAME(SIO_ADDRESS_LIST_QUERY
);
2108 IOCTL_NAME(SIO_ASSOCIATE_HANDLE
);
2109 /* IOCTL_NAME(SIO_ASSOCIATE_PORT_RESERVATION);
2110 IOCTL_NAME(SIO_BASE_HANDLE);
2111 IOCTL_NAME(SIO_BSP_HANDLE);
2112 IOCTL_NAME(SIO_BSP_HANDLE_SELECT);
2113 IOCTL_NAME(SIO_BSP_HANDLE_POLL);
2114 IOCTL_NAME(SIO_CHK_QOS); */
2115 IOCTL_NAME(SIO_ENABLE_CIRCULAR_QUEUEING
);
2116 IOCTL_NAME(SIO_FIND_ROUTE
);
2117 IOCTL_NAME(SIO_FLUSH
);
2118 IOCTL_NAME(SIO_GET_BROADCAST_ADDRESS
);
2119 IOCTL_NAME(SIO_GET_EXTENSION_FUNCTION_POINTER
);
2120 IOCTL_NAME(SIO_GET_GROUP_QOS
);
2121 IOCTL_NAME(SIO_GET_INTERFACE_LIST
);
2122 /* IOCTL_NAME(SIO_GET_INTERFACE_LIST_EX); */
2123 IOCTL_NAME(SIO_GET_QOS
);
2124 IOCTL_NAME(SIO_IDEAL_SEND_BACKLOG_CHANGE
);
2125 IOCTL_NAME(SIO_IDEAL_SEND_BACKLOG_QUERY
);
2126 IOCTL_NAME(SIO_KEEPALIVE_VALS
);
2127 IOCTL_NAME(SIO_MULTIPOINT_LOOPBACK
);
2128 IOCTL_NAME(SIO_MULTICAST_SCOPE
);
2129 /* IOCTL_NAME(SIO_QUERY_RSS_SCALABILITY_INFO);
2130 IOCTL_NAME(SIO_QUERY_WFP_ALE_ENDPOINT_HANDLE); */
2131 IOCTL_NAME(SIO_RCVALL
);
2132 IOCTL_NAME(SIO_RCVALL_IGMPMCAST
);
2133 IOCTL_NAME(SIO_RCVALL_MCAST
);
2134 /* IOCTL_NAME(SIO_RELEASE_PORT_RESERVATION); */
2135 IOCTL_NAME(SIO_ROUTING_INTERFACE_CHANGE
);
2136 IOCTL_NAME(SIO_ROUTING_INTERFACE_QUERY
);
2137 IOCTL_NAME(SIO_SET_COMPATIBILITY_MODE
);
2138 IOCTL_NAME(SIO_SET_GROUP_QOS
);
2139 IOCTL_NAME(SIO_SET_QOS
);
2140 IOCTL_NAME(SIO_TRANSLATE_HANDLE
);
2141 IOCTL_NAME(SIO_UDP_CONNRESET
);
2145 /* If this is not a known code split its bits */
2146 switch(code
& 0x18000000)
2152 family
= "IOC_PROTOCOL";
2155 family
= "IOC_VENDOR";
2157 default: /* IOC_UNIX */
2159 BYTE size
= (code
>> 16) & IOCPARM_MASK
;
2160 char x
= (code
& 0xff00) >> 8;
2161 BYTE y
= code
& 0xff;
2164 switch (code
& (IOC_VOID
| IOC_INOUT
))
2168 sprintf(args
, "%d, %d", x
, y
);
2172 sprintf(args
, "'%c', %d, %d", x
, y
, size
);
2176 sprintf(args
, "'%c', %d, %d", x
, y
, size
);
2180 sprintf(args
, "'%c', %d, %d", x
, y
, size
);
2183 return wine_dbg_sprintf("%s(%s)", buf_type
, args
);
2187 /* We are different from IOC_UNIX. */
2188 switch (code
& (IOC_VOID
| IOC_INOUT
))
2191 buf_type
= "_WSAIO";
2194 buf_type
= "_WSAIORW";
2197 buf_type
= "_WSAIOW";
2200 buf_type
= "_WSAIOR";
2207 return wine_dbg_sprintf("%s(%s, %d)", buf_type
, family
,
2208 (USHORT
)(code
& 0xffff));
2211 /* do an ioctl call through the server */
2212 static DWORD
server_ioctl_sock( SOCKET s
, DWORD code
, LPVOID in_buff
, DWORD in_size
,
2213 LPVOID out_buff
, DWORD out_size
, LPDWORD ret_size
,
2214 LPWSAOVERLAPPED overlapped
,
2215 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
)
2217 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
2218 HANDLE handle
= SOCKET2HANDLE( s
);
2219 PIO_APC_ROUTINE apc
= NULL
;
2220 HANDLE event
= NULL
;
2221 void *cvalue
= NULL
;
2226 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
2227 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
2228 event
= overlapped
->hEvent
;
2232 if (!(event
= get_sync_event())) return GetLastError();
2238 cvalue
= completion
;
2242 status
= NtDeviceIoControlFile( handle
, event
, apc
, cvalue
, piosb
, code
,
2243 in_buff
, in_size
, out_buff
, out_size
);
2244 if (status
== STATUS_PENDING
&& !overlapped
)
2246 if (WaitForSingleObject( event
, INFINITE
) == WAIT_FAILED
)
2248 status
= piosb
->u
.Status
;
2250 if (status
== STATUS_NOT_SUPPORTED
)
2252 FIXME("Unsupported ioctl %#lx (device=%#lx access=%#lx func=%#lx method=%#lx)\n",
2253 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3);
2255 else if (status
== STATUS_SUCCESS
)
2256 *ret_size
= piosb
->Information
;
2258 TRACE( "status %#lx.\n", status
);
2259 return NtStatusToWSAError( status
);
2263 /**********************************************************************
2264 * WSAIoctl (WS2_32.50)
2267 INT WINAPI
WSAIoctl(SOCKET s
, DWORD code
, LPVOID in_buff
, DWORD in_size
, LPVOID out_buff
,
2268 DWORD out_size
, LPDWORD ret_size
, LPWSAOVERLAPPED overlapped
,
2269 LPWSAOVERLAPPED_COMPLETION_ROUTINE completion
)
2271 TRACE( "socket %#Ix, %s, in_buff %p, in_size %#lx, out_buff %p,"
2272 " out_size %#lx, ret_size %p, overlapped %p, completion %p\n",
2273 s
, debugstr_wsaioctl(code
), in_buff
, in_size
, out_buff
,
2274 out_size
, ret_size
, overlapped
, completion
);
2278 SetLastError( WSAEFAULT
);
2288 if (IS_INTRESOURCE( in_buff
))
2290 SetLastError( WSAEFAULT
);
2294 /* Explicitly ignore the output buffer; WeChat tries to pass an address
2295 * without write access. */
2296 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_FIONBIO
, in_buff
, in_size
,
2297 NULL
, 0, ret_size
, overlapped
, completion
);
2298 SetLastError( ret
);
2299 return ret
? -1 : 0;
2306 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_FIONREAD
, in_buff
, in_size
,
2307 out_buff
, out_size
, ret_size
, overlapped
, completion
);
2308 SetLastError( ret
);
2309 if (!ret
) *ret_size
= sizeof(u_long
);
2310 return ret
? -1 : 0;
2317 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_SIOCATMARK
, in_buff
, in_size
,
2318 out_buff
, out_size
, ret_size
, overlapped
, completion
);
2319 SetLastError( ret
);
2320 if (!ret
) *ret_size
= sizeof(u_long
);
2321 return ret
? -1 : 0;
2324 case SIO_GET_INTERFACE_LIST
:
2328 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_GET_INTERFACE_LIST
, in_buff
, in_size
,
2329 out_buff
, out_size
, ret_size
, overlapped
, completion
);
2330 SetLastError( ret
);
2331 if (ret
&& ret
!= ERROR_IO_PENDING
) *ret_size
= 0;
2332 return ret
? -1 : 0;
2335 case SIO_ADDRESS_LIST_QUERY
:
2339 TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
2341 if (out_size
&& out_size
< FIELD_OFFSET(SOCKET_ADDRESS_LIST
, Address
[0]))
2344 SetLastError(WSAEINVAL
);
2345 return SOCKET_ERROR
;
2348 if (GetAdaptersInfo(NULL
, &size
) == ERROR_BUFFER_OVERFLOW
)
2350 IP_ADAPTER_INFO
*p
, *table
= malloc( size
);
2351 NTSTATUS status
= STATUS_SUCCESS
;
2352 SOCKET_ADDRESS_LIST
*sa_list
;
2353 SOCKADDR_IN
*sockaddr
;
2359 if (!table
|| GetAdaptersInfo(table
, &size
))
2362 SetLastError( WSAEINVAL
);
2366 for (p
= table
, num
= 0; p
; p
= p
->Next
)
2367 if (p
->IpAddressList
.IpAddress
.String
[0]) num
++;
2369 total
= FIELD_OFFSET(SOCKET_ADDRESS_LIST
, Address
[num
]) + num
* sizeof(*sockaddr
);
2370 if (total
> out_size
|| !out_buff
)
2374 SetLastError( WSAEFAULT
);
2379 sa
= sa_list
->Address
;
2380 sockaddr
= (SOCKADDR_IN
*)&sa
[num
];
2381 sa_list
->iAddressCount
= num
;
2383 for (p
= table
, i
= 0; p
; p
= p
->Next
)
2385 if (!p
->IpAddressList
.IpAddress
.String
[0]) continue;
2387 sa
[i
].lpSockaddr
= (SOCKADDR
*)&sockaddr
[i
];
2388 sa
[i
].iSockaddrLength
= sizeof(SOCKADDR
);
2390 sockaddr
[i
].sin_family
= AF_INET
;
2391 sockaddr
[i
].sin_port
= 0;
2392 sockaddr
[i
].sin_addr
.s_addr
= inet_addr( p
->IpAddressList
.IpAddress
.String
);
2398 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2399 NULL
, 0, ret_size
, overlapped
, completion
);
2401 SetLastError( ret
);
2402 return ret
? -1 : 0;
2406 WARN("unable to get IP address list\n");
2407 SetLastError( WSAEINVAL
);
2412 case SIO_GET_EXTENSION_FUNCTION_POINTER
:
2414 #define EXTENSION_FUNCTION(x, y) { x, y, #y },
2421 EXTENSION_FUNCTION(WSAID_CONNECTEX
, WS2_ConnectEx
)
2422 EXTENSION_FUNCTION(WSAID_DISCONNECTEX
, WS2_DisconnectEx
)
2423 EXTENSION_FUNCTION(WSAID_ACCEPTEX
, WS2_AcceptEx
)
2424 EXTENSION_FUNCTION(WSAID_GETACCEPTEXSOCKADDRS
, WS2_GetAcceptExSockaddrs
)
2425 EXTENSION_FUNCTION(WSAID_TRANSMITFILE
, WS2_TransmitFile
)
2426 /* EXTENSION_FUNCTION(WSAID_TRANSMITPACKETS, WS2_TransmitPackets) */
2427 EXTENSION_FUNCTION(WSAID_WSARECVMSG
, WS2_WSARecvMsg
)
2428 EXTENSION_FUNCTION(WSAID_WSASENDMSG
, WSASendMsg
)
2430 #undef EXTENSION_FUNCTION
2433 for (i
= 0; i
< ARRAY_SIZE(guid_funcs
); i
++)
2435 if (IsEqualGUID(&guid_funcs
[i
].guid
, in_buff
))
2437 NTSTATUS status
= STATUS_SUCCESS
;
2440 TRACE( "returning %s\n", guid_funcs
[i
].name
);
2441 *(void **)out_buff
= guid_funcs
[i
].func_ptr
;
2443 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2444 NULL
, 0, ret_size
, overlapped
, completion
);
2445 *ret_size
= sizeof(void *);
2446 SetLastError( ret
);
2447 return ret
? -1 : 0;
2451 FIXME("SIO_GET_EXTENSION_FUNCTION_POINTER %s: stub\n", debugstr_guid(in_buff
));
2452 SetLastError( WSAEINVAL
);
2456 case SIO_KEEPALIVE_VALS
:
2460 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_KEEPALIVE_VALS
, in_buff
, in_size
,
2461 out_buff
, out_size
, ret_size
, overlapped
, completion
);
2462 if (!overlapped
|| completion
) *ret_size
= 0;
2463 SetLastError( ret
);
2464 return ret
? -1 : 0;
2467 case SIO_ROUTING_INTERFACE_QUERY
:
2469 struct sockaddr
*daddr
= (struct sockaddr
*)in_buff
;
2470 struct sockaddr_in
*daddr_in
= (struct sockaddr_in
*)daddr
;
2471 struct sockaddr_in
*saddr_in
= out_buff
;
2472 MIB_IPFORWARDROW row
;
2473 PMIB_IPADDRTABLE ipAddrTable
= NULL
;
2474 DWORD size
, i
, found_index
, ret
= 0;
2475 NTSTATUS status
= STATUS_SUCCESS
;
2477 if (!in_buff
|| in_size
< sizeof(struct sockaddr
) ||
2478 !out_buff
|| out_size
< sizeof(struct sockaddr_in
))
2480 SetLastError( WSAEFAULT
);
2483 if (daddr
->sa_family
!= AF_INET
)
2485 FIXME("unsupported address family %d\n", daddr
->sa_family
);
2486 SetLastError( WSAEAFNOSUPPORT
);
2489 if (GetBestRoute( daddr_in
->sin_addr
.S_un
.S_addr
, 0, &row
) != NOERROR
||
2490 GetIpAddrTable( NULL
, &size
, FALSE
) != ERROR_INSUFFICIENT_BUFFER
)
2492 SetLastError( WSAEFAULT
);
2495 ipAddrTable
= malloc( size
);
2496 if (GetIpAddrTable( ipAddrTable
, &size
, FALSE
))
2498 free( ipAddrTable
);
2499 SetLastError( WSAEFAULT
);
2502 for (i
= 0, found_index
= ipAddrTable
->dwNumEntries
;
2503 i
< ipAddrTable
->dwNumEntries
; i
++)
2505 if (ipAddrTable
->table
[i
].dwIndex
== row
.dwForwardIfIndex
)
2508 if (found_index
== ipAddrTable
->dwNumEntries
)
2510 ERR( "no matching IP address for interface %lu\n", row
.dwForwardIfIndex
);
2511 free( ipAddrTable
);
2512 SetLastError( WSAEFAULT
);
2515 saddr_in
->sin_family
= AF_INET
;
2516 saddr_in
->sin_addr
.S_un
.S_addr
= ipAddrTable
->table
[found_index
].dwAddr
;
2517 saddr_in
->sin_port
= 0;
2518 free( ipAddrTable
);
2520 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2521 NULL
, 0, ret_size
, overlapped
, completion
);
2522 if (!ret
) *ret_size
= sizeof(struct sockaddr_in
);
2523 SetLastError( ret
);
2524 return ret
? -1 : 0;
2527 case SIO_ADDRESS_LIST_CHANGE
:
2529 int force_async
= !!overlapped
;
2532 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE
, &force_async
, sizeof(force_async
),
2533 out_buff
, out_size
, ret_size
, overlapped
, completion
);
2534 SetLastError( ret
);
2535 return ret
? -1 : 0;
2538 case SIO_UDP_CONNRESET
:
2540 NTSTATUS status
= STATUS_SUCCESS
;
2543 FIXME( "SIO_UDP_CONNRESET stub\n" );
2544 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2545 NULL
, 0, ret_size
, overlapped
, completion
);
2546 SetLastError( ret
);
2547 return ret
? -1 : 0;
2550 case SIO_ENABLE_CIRCULAR_QUEUEING
:
2552 NTSTATUS status
= STATUS_SUCCESS
;
2555 FIXME( "SIO_ENABLE_CIRCULAR_QUEUEING stub\n" );
2556 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2557 NULL
, 0, ret_size
, overlapped
, completion
);
2558 SetLastError( ret
);
2559 return ret
? -1 : 0;
2562 case SIO_BASE_HANDLE
:
2569 status
= STATUS_NOT_SUPPORTED
;
2573 status
= STATUS_SUCCESS
;
2574 *(SOCKET
*)out_buff
= s
;
2576 ret
= server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2577 NULL
, 0, ret_size
, overlapped
, completion
);
2578 if (overlapped
) ret
= ERROR_IO_PENDING
;
2579 if (!ret
) *ret_size
= sizeof(SOCKET
);
2580 SetLastError( ret
);
2581 return ret
? -1 : 0;
2585 FIXME( "unimplemented ioctl %s\n", debugstr_wsaioctl( code
) );
2587 case LOWORD(FIONBIO
): /* Netscape tries to use this */
2588 case SIO_SET_COMPATIBILITY_MODE
:
2590 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
2592 server_ioctl_sock( s
, IOCTL_AFD_WINE_COMPLETE_ASYNC
, &status
, sizeof(status
),
2593 NULL
, 0, ret_size
, overlapped
, completion
);
2596 SetLastError( ERROR_IO_PENDING
);
2601 SetLastError( WSAEOPNOTSUPP
);
2609 /***********************************************************************
2610 * ioctlsocket (WS2_32.10)
2612 int WINAPI
ioctlsocket( SOCKET s
, LONG cmd
, u_long
*argp
)
2615 return WSAIoctl( s
, cmd
, argp
, sizeof(u_long
), argp
, sizeof(u_long
), &ret_size
, NULL
, NULL
);
2619 /***********************************************************************
2620 * listen (ws2_32.13)
2622 int WINAPI
listen( SOCKET s
, int backlog
)
2624 struct afd_listen_params params
= {.backlog
= backlog
};
2628 TRACE( "socket %#Ix, backlog %d\n", s
, backlog
);
2630 status
= NtDeviceIoControlFile( SOCKET2HANDLE(s
), NULL
, NULL
, NULL
, &io
,
2631 IOCTL_AFD_LISTEN
, ¶ms
, sizeof(params
), NULL
, 0 );
2632 SetLastError( NtStatusToWSAError( status
) );
2633 TRACE( "status %#lx.\n", status
);
2634 return status
? -1 : 0;
2638 /***********************************************************************
2641 int WINAPI
recv( SOCKET s
, char *buf
, int len
, int flags
)
2643 DWORD n
, dwFlags
= flags
;
2649 if ( WS2_recv_base(s
, &wsabuf
, 1, &n
, &dwFlags
, NULL
, NULL
, NULL
, NULL
, NULL
) == SOCKET_ERROR
)
2650 return SOCKET_ERROR
;
2655 /***********************************************************************
2656 * recvfrom (WS2_32.17)
2658 int WINAPI
recvfrom( SOCKET s
, char *buf
, int len
, int flags
, struct sockaddr
*from
, int *fromlen
)
2660 DWORD n
, dwFlags
= flags
;
2666 if ( WS2_recv_base(s
, &wsabuf
, 1, &n
, &dwFlags
, from
, fromlen
, NULL
, NULL
, NULL
) == SOCKET_ERROR
)
2667 return SOCKET_ERROR
;
2673 /* as FD_SET(), but returns 1 if the fd was added, 0 otherwise */
2674 static int add_fd_to_set( SOCKET fd
, struct fd_set
*set
)
2678 for (i
= 0; i
< set
->fd_count
; ++i
)
2680 if (set
->fd_array
[i
] == fd
)
2684 set
->fd_array
[set
->fd_count
++] = fd
;
2689 /***********************************************************************
2690 * select (ws2_32.18)
2692 int WINAPI
select( int count
, fd_set
*read_ptr
, fd_set
*write_ptr
,
2693 fd_set
*except_ptr
, const struct timeval
*timeout
)
2695 struct fd_set
*read_input
= NULL
;
2696 struct afd_poll_params
*params
;
2697 unsigned int poll_count
= 0;
2698 ULONG params_size
, i
, j
;
2699 SOCKET poll_socket
= 0;
2705 TRACE( "read %p, write %p, except %p, timeout %p\n", read_ptr
, write_ptr
, except_ptr
, timeout
);
2707 if (!(sync_event
= get_sync_event())) return -1;
2709 if (read_ptr
) poll_count
+= read_ptr
->fd_count
;
2710 if (write_ptr
) poll_count
+= write_ptr
->fd_count
;
2711 if (except_ptr
) poll_count
+= except_ptr
->fd_count
;
2715 SetLastError( WSAEINVAL
);
2719 params_size
= offsetof( struct afd_poll_params
, sockets
[poll_count
] );
2720 if (!(params
= calloc( params_size
, 1 )))
2722 SetLastError( WSAENOBUFS
);
2727 params
->timeout
= (LONGLONG
)timeout
->tv_sec
* -10000000 + (LONGLONG
)timeout
->tv_usec
* -10;
2729 params
->timeout
= TIMEOUT_INFINITE
;
2733 unsigned int read_size
= offsetof( struct fd_set
, fd_array
[read_ptr
->fd_count
] );
2735 if (!(read_input
= malloc( read_size
)))
2738 SetLastError( WSAENOBUFS
);
2741 memcpy( read_input
, read_ptr
, read_size
);
2743 for (i
= 0; i
< read_ptr
->fd_count
; ++i
)
2745 params
->sockets
[params
->count
].socket
= read_ptr
->fd_array
[i
];
2746 params
->sockets
[params
->count
].flags
= AFD_POLL_READ
| AFD_POLL_ACCEPT
| AFD_POLL_HUP
;
2748 poll_socket
= read_ptr
->fd_array
[i
];
2754 for (i
= 0; i
< write_ptr
->fd_count
; ++i
)
2756 params
->sockets
[params
->count
].socket
= write_ptr
->fd_array
[i
];
2757 params
->sockets
[params
->count
].flags
= AFD_POLL_WRITE
;
2759 poll_socket
= write_ptr
->fd_array
[i
];
2765 for (i
= 0; i
< except_ptr
->fd_count
; ++i
)
2767 params
->sockets
[params
->count
].socket
= except_ptr
->fd_array
[i
];
2768 params
->sockets
[params
->count
].flags
= AFD_POLL_OOB
| AFD_POLL_CONNECT_ERR
;
2770 poll_socket
= except_ptr
->fd_array
[i
];
2774 assert( params
->count
== poll_count
);
2776 status
= NtDeviceIoControlFile( (HANDLE
)poll_socket
, sync_event
, NULL
, NULL
, &io
,
2777 IOCTL_AFD_POLL
, params
, params_size
, params
, params_size
);
2778 if (status
== STATUS_PENDING
)
2780 if (wait_event_alertable( sync_event
) == WAIT_FAILED
)
2786 status
= io
.u
.Status
;
2788 if (status
== STATUS_TIMEOUT
) status
= STATUS_SUCCESS
;
2791 /* pointers may alias, so clear them all first */
2792 if (read_ptr
) read_ptr
->fd_count
= 0;
2793 if (write_ptr
) write_ptr
->fd_count
= 0;
2794 if (except_ptr
) except_ptr
->fd_count
= 0;
2796 for (i
= 0; i
< params
->count
; ++i
)
2798 unsigned int flags
= params
->sockets
[i
].flags
;
2799 SOCKET s
= params
->sockets
[i
].socket
;
2803 for (j
= 0; j
< read_input
->fd_count
; ++j
)
2805 if (read_input
->fd_array
[j
] == s
2806 && (flags
& (AFD_POLL_READ
| AFD_POLL_ACCEPT
| AFD_POLL_HUP
| AFD_POLL_CLOSE
)))
2808 ret_count
+= add_fd_to_set( s
, read_ptr
);
2809 flags
&= ~AFD_POLL_CLOSE
;
2814 if (flags
& AFD_POLL_CLOSE
)
2815 status
= STATUS_INVALID_HANDLE
;
2817 if (flags
& AFD_POLL_WRITE
)
2818 ret_count
+= add_fd_to_set( s
, write_ptr
);
2820 if (flags
& (AFD_POLL_OOB
| AFD_POLL_CONNECT_ERR
))
2821 ret_count
+= add_fd_to_set( s
, except_ptr
);
2828 SetLastError( NtStatusToWSAError( status
) );
2829 TRACE( "status %#lx.\n", status
);
2830 return status
? -1 : ret_count
;
2834 static unsigned int afd_poll_flag_to_win32( unsigned int flags
)
2836 static const unsigned int map
[] =
2840 FD_WRITE
, /* WRITE */
2842 FD_CLOSE
, /* RESET */
2844 FD_CONNECT
, /* CONNECT */
2845 FD_ACCEPT
, /* ACCEPT */
2846 FD_CONNECT
, /* CONNECT_ERR */
2849 unsigned int i
, ret
= 0;
2851 for (i
= 0; i
< ARRAY_SIZE(map
); ++i
)
2853 if (flags
& (1 << i
)) ret
|= map
[i
];
2860 /***********************************************************************
2861 * WSAPoll (ws2_32.@)
2863 int WINAPI
WSAPoll( WSAPOLLFD
*fds
, ULONG count
, int timeout
)
2865 struct afd_poll_params
*params
;
2866 ULONG params_size
, i
, j
;
2867 SOCKET poll_socket
= 0;
2875 SetLastError(WSAEINVAL
);
2876 return SOCKET_ERROR
;
2880 SetLastError(WSAEFAULT
);
2881 return SOCKET_ERROR
;
2884 if (!(sync_event
= get_sync_event())) return -1;
2886 params_size
= offsetof( struct afd_poll_params
, sockets
[count
] );
2887 if (!(params
= calloc( params_size
, 1 )))
2889 SetLastError(WSAENOBUFS
);
2890 return SOCKET_ERROR
;
2893 params
->timeout
= (timeout
>= 0 ? (LONGLONG
)timeout
* -10000 : TIMEOUT_INFINITE
);
2895 for (i
= 0; i
< count
; ++i
)
2897 unsigned int flags
= AFD_POLL_HUP
| AFD_POLL_RESET
| AFD_POLL_CONNECT_ERR
;
2899 if ((INT_PTR
)fds
[i
].fd
< 0 || !socket_list_find( fds
[i
].fd
))
2901 fds
[i
].revents
= POLLNVAL
;
2905 poll_socket
= fds
[i
].fd
;
2906 params
->sockets
[params
->count
].socket
= fds
[i
].fd
;
2908 if (fds
[i
].events
& POLLRDNORM
)
2909 flags
|= AFD_POLL_ACCEPT
| AFD_POLL_READ
;
2910 if (fds
[i
].events
& POLLRDBAND
)
2911 flags
|= AFD_POLL_OOB
;
2912 if (fds
[i
].events
& POLLWRNORM
)
2913 flags
|= AFD_POLL_WRITE
;
2914 params
->sockets
[params
->count
].flags
= flags
;
2922 SetLastError( WSAENOTSOCK
);
2927 status
= NtDeviceIoControlFile( (HANDLE
)poll_socket
, sync_event
, NULL
, NULL
, &io
, IOCTL_AFD_POLL
,
2928 params
, params_size
, params
, params_size
);
2929 if (status
== STATUS_PENDING
)
2931 if (WaitForSingleObject( sync_event
, INFINITE
) == WAIT_FAILED
)
2936 status
= io
.u
.Status
;
2940 for (i
= 0; i
< count
; ++i
)
2942 for (j
= 0; j
< params
->count
; ++j
)
2944 if (fds
[i
].fd
== params
->sockets
[j
].socket
)
2946 unsigned int revents
= 0;
2948 if (params
->sockets
[j
].flags
& (AFD_POLL_ACCEPT
| AFD_POLL_READ
))
2949 revents
|= POLLRDNORM
;
2950 if (params
->sockets
[j
].flags
& AFD_POLL_OOB
)
2951 revents
|= POLLRDBAND
;
2952 if (params
->sockets
[j
].flags
& AFD_POLL_WRITE
)
2953 revents
|= POLLWRNORM
;
2954 if (params
->sockets
[j
].flags
& AFD_POLL_HUP
)
2956 if (params
->sockets
[j
].flags
& (AFD_POLL_RESET
| AFD_POLL_CONNECT_ERR
))
2958 if (params
->sockets
[j
].flags
& AFD_POLL_CLOSE
)
2959 revents
|= POLLNVAL
;
2961 fds
[i
].revents
= revents
& (fds
[i
].events
| POLLHUP
| POLLERR
| POLLNVAL
);
2969 if (status
== STATUS_TIMEOUT
) status
= STATUS_SUCCESS
;
2973 SetLastError( NtStatusToWSAError( status
) );
2974 TRACE( "status %#lx.\n", status
);
2975 return status
? -1 : ret_count
;
2979 /***********************************************************************
2982 int WINAPI
send( SOCKET s
, const char *buf
, int len
, int flags
)
2988 wsabuf
.buf
= (char*) buf
;
2990 if ( WS2_sendto( s
, &wsabuf
, 1, &n
, flags
, NULL
, 0, NULL
, NULL
) == SOCKET_ERROR
)
2991 return SOCKET_ERROR
;
2996 /***********************************************************************
2997 * WSASend (WS2_32.72)
2999 INT WINAPI
WSASend( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3000 LPDWORD lpNumberOfBytesSent
, DWORD dwFlags
,
3001 LPWSAOVERLAPPED lpOverlapped
,
3002 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3004 return WS2_sendto( s
, lpBuffers
, dwBufferCount
, lpNumberOfBytesSent
, dwFlags
,
3005 NULL
, 0, lpOverlapped
, lpCompletionRoutine
);
3008 /***********************************************************************
3009 * WSASendDisconnect (WS2_32.73)
3011 INT WINAPI
WSASendDisconnect( SOCKET s
, LPWSABUF lpBuffers
)
3013 return shutdown( s
, SD_SEND
);
3017 /***********************************************************************
3018 * WSASendTo (WS2_32.74)
3020 INT WINAPI
WSASendTo( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3021 LPDWORD lpNumberOfBytesSent
, DWORD dwFlags
,
3022 const struct sockaddr
*to
, int tolen
,
3023 LPWSAOVERLAPPED lpOverlapped
,
3024 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3026 /* Garena hooks WSASendTo(), so we need a wrapper */
3027 return WS2_sendto( s
, lpBuffers
, dwBufferCount
,
3028 lpNumberOfBytesSent
, dwFlags
,
3030 lpOverlapped
, lpCompletionRoutine
);
3033 /***********************************************************************
3034 * sendto (WS2_32.20)
3036 int WINAPI
sendto( SOCKET s
, const char *buf
, int len
, int flags
, const struct sockaddr
*to
, int tolen
)
3042 wsabuf
.buf
= (char*) buf
;
3044 if ( WS2_sendto(s
, &wsabuf
, 1, &n
, flags
, to
, tolen
, NULL
, NULL
) == SOCKET_ERROR
)
3045 return SOCKET_ERROR
;
3051 static int server_setsockopt( SOCKET s
, ULONG code
, const char *optval
, int optlen
)
3056 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, code
, (void *)optval
, optlen
, NULL
, 0 );
3057 SetLastError( NtStatusToWSAError( status
) );
3058 TRACE( "status %#lx.\n", status
);
3059 return status
? -1 : 0;
3063 /***********************************************************************
3064 * setsockopt (WS2_32.21)
3066 int WINAPI
setsockopt( SOCKET s
, int level
, int optname
, const char *optval
, int optlen
)
3070 TRACE( "socket %#Ix, %s, optval %s, optlen %d\n",
3071 s
, debugstr_sockopt(level
, optname
), debugstr_optval(optval
, optlen
), optlen
);
3073 /* some broken apps pass the value directly instead of a pointer to it */
3074 if(optlen
&& IS_INTRESOURCE(optval
))
3076 SetLastError(WSAEFAULT
);
3077 return SOCKET_ERROR
;
3088 SetLastError( WSAEFAULT
);
3089 return SOCKET_ERROR
;
3091 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3092 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_BROADCAST
, (char *)&value
, sizeof(value
) );
3099 SetLastError( WSAEFAULT
);
3103 linger
.l_onoff
= !*(const BOOL
*)optval
;
3104 linger
.l_linger
= 0;
3105 return setsockopt( s
, SOL_SOCKET
, SO_LINGER
, (char *)&linger
, sizeof(linger
) );
3109 FIXME( "SO_ERROR, stub!\n" );
3110 SetLastError( WSAENOPROTOOPT
);
3114 if (optlen
<= 0 || !optval
)
3116 SetLastError( optlen
? WSAENOBUFS
: WSAEFAULT
);
3117 return SOCKET_ERROR
;
3120 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_KEEPALIVE
, (char *)&value
, sizeof(value
) );
3123 if (optlen
< sizeof(LINGER
) || !optval
)
3125 SetLastError( WSAEFAULT
);
3126 return SOCKET_ERROR
;
3128 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_LINGER
, optval
, optlen
);
3133 SetLastError( WSAEFAULT
);
3134 return SOCKET_ERROR
;
3136 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3137 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_OOBINLINE
, (char *)&value
, sizeof(value
) );
3140 if (optlen
< 0) optlen
= 4;
3141 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_RCVBUF
, optval
, optlen
);
3144 if (optlen
< 0) optlen
= 4;
3145 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_RCVTIMEO
, optval
, optlen
);
3150 SetLastError( WSAEFAULT
);
3151 return SOCKET_ERROR
;
3153 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3154 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_REUSEADDR
, (char *)&value
, sizeof(value
) );
3157 if (optlen
< 0) optlen
= 4;
3158 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_SNDBUF
, optval
, optlen
);
3161 if (optlen
< 0) optlen
= 4;
3162 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_SO_SNDTIMEO
, optval
, optlen
);
3164 /* SO_DEBUG is a privileged operation, ignore it. */
3166 TRACE("Ignoring SO_DEBUG\n");
3169 /* For some reason the game GrandPrixLegends does set SO_DONTROUTE on its
3170 * socket. According to MSDN, this option is silently ignored.*/
3172 TRACE( "Ignoring SO_DONTROUTE.\n" );
3175 SetLastError( optlen
? WSAENOBUFS
: WSAEFAULT
);
3178 SetLastError( ERROR_SUCCESS
);
3181 /* Stops two sockets from being bound to the same port. Always happens
3182 * on unix systems, so just drop it. */
3183 case SO_EXCLUSIVEADDRUSE
:
3184 TRACE("Ignoring SO_EXCLUSIVEADDRUSE, is always set.\n");
3187 /* After a ConnectEx call succeeds, the socket can't be used with half of the
3188 * normal winsock functions on windows. We don't have that problem. */
3189 case SO_UPDATE_CONNECT_CONTEXT
:
3190 TRACE("Ignoring SO_UPDATE_CONNECT_CONTEXT, since our sockets are normal\n");
3193 /* After a AcceptEx call succeeds, the socket can't be used with half of the
3194 * normal winsock functions on windows. We don't have that problem. */
3195 case SO_UPDATE_ACCEPT_CONTEXT
:
3196 TRACE("Ignoring SO_UPDATE_ACCEPT_CONTEXT, since our sockets are normal\n");
3199 /* SO_OPENTYPE does not require a valid socket handle. */
3201 if (!optlen
|| optlen
< sizeof(int) || !optval
)
3203 SetLastError( WSAEFAULT
);
3204 return SOCKET_ERROR
;
3206 get_per_thread_data()->opentype
= *(const int *)optval
;
3207 TRACE("setting global SO_OPENTYPE = 0x%x\n", *((const int*)optval
) );
3208 SetLastError( ERROR_SUCCESS
);
3211 case SO_RANDOMIZE_PORT
:
3212 FIXME("Ignoring SO_RANDOMIZE_PORT\n");
3215 case SO_PORT_SCALABILITY
:
3216 FIXME("Ignoring SO_PORT_SCALABILITY\n");
3219 case SO_REUSE_UNICASTPORT
:
3220 FIXME("Ignoring SO_REUSE_UNICASTPORT\n");
3223 case SO_REUSE_MULTICASTPORT
:
3224 FIXME("Ignoring SO_REUSE_MULTICASTPORT\n");
3228 TRACE("Unknown SOL_SOCKET optname: 0x%08x\n", optname
);
3233 SetLastError(WSAENOPROTOOPT
);
3234 return SOCKET_ERROR
;
3236 break; /* case SOL_SOCKET */
3242 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPX_PTYPE
, optval
, optlen
);
3244 case IPX_FILTERPTYPE
:
3245 /* Sets the receive filter packet type, at the moment we don't support it */
3246 FIXME("IPX_FILTERPTYPE: %x\n", *optval
);
3247 /* Returning 0 is better for now than returning a SOCKET_ERROR */
3251 FIXME("opt_name:%x\n", optname
);
3252 SetLastError(WSAENOPROTOOPT
);
3253 return SOCKET_ERROR
;
3255 break; /* case NSPROTO_IPX */
3261 if (optlen
<= 0 || !optval
)
3263 SetLastError( optlen
&& optval
? WSAENOBUFS
: WSAEFAULT
);
3264 return SOCKET_ERROR
;
3267 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_TCP_NODELAY
, (char*)&value
, sizeof(value
) );
3270 FIXME("Unknown IPPROTO_TCP optname 0x%08x\n", optname
);
3271 SetLastError(WSAENOPROTOOPT
);
3272 return SOCKET_ERROR
;
3279 SetLastError(WSAENOBUFS
);
3280 return SOCKET_ERROR
;
3285 case IP_ADD_MEMBERSHIP
:
3286 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_ADD_MEMBERSHIP
, optval
, optlen
);
3288 case IP_ADD_SOURCE_MEMBERSHIP
:
3289 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_ADD_SOURCE_MEMBERSHIP
, optval
, optlen
);
3291 case IP_BLOCK_SOURCE
:
3292 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_BLOCK_SOURCE
, optval
, optlen
);
3294 case IP_DONTFRAGMENT
:
3295 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT
, optval
, optlen
);
3297 case IP_DROP_MEMBERSHIP
:
3298 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP
, optval
, optlen
);
3300 case IP_DROP_SOURCE_MEMBERSHIP
:
3301 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP
, optval
, optlen
);
3304 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_HDRINCL
, optval
, optlen
);
3306 case IP_MULTICAST_IF
:
3307 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_MULTICAST_IF
, optval
, optlen
);
3309 case IP_MULTICAST_LOOP
:
3312 SetLastError( WSAEFAULT
);
3315 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_MULTICAST_LOOP
, optval
, optlen
);
3317 case IP_MULTICAST_TTL
:
3320 SetLastError( WSAEFAULT
);
3323 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_MULTICAST_TTL
, optval
, optlen
);
3326 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_OPTIONS
, optval
, optlen
);
3329 if (optlen
< sizeof(DWORD
) || !optval
)
3331 SetLastError( WSAEFAULT
);
3332 return SOCKET_ERROR
;
3334 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_PKTINFO
, optval
, optlen
);
3337 if (optlen
< sizeof(DWORD
) || !optval
)
3339 SetLastError( WSAEFAULT
);
3340 return SOCKET_ERROR
;
3342 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_RECVTOS
, optval
, optlen
);
3345 if (optlen
< sizeof(DWORD
) || !optval
)
3347 SetLastError( WSAEFAULT
);
3348 return SOCKET_ERROR
;
3350 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_RECVTTL
, optval
, optlen
);
3353 if (!optlen
|| !optval
)
3355 SetLastError(WSAEFAULT
);
3356 return SOCKET_ERROR
;
3358 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3361 SetLastError(WSAEINVAL
);
3362 return SOCKET_ERROR
;
3364 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_TOS
, optval
, optlen
);
3369 SetLastError( WSAEFAULT
);
3372 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_TTL
, optval
, optlen
);
3374 case IP_UNBLOCK_SOURCE
:
3375 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_UNBLOCK_SOURCE
, optval
, optlen
);
3378 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IP_UNICAST_IF
, optval
, optlen
);
3381 FIXME("Unknown IPPROTO_IP optname 0x%08x\n", optname
);
3382 SetLastError(WSAENOPROTOOPT
);
3383 return SOCKET_ERROR
;
3390 SetLastError( WSAENOBUFS
);
3391 return SOCKET_ERROR
;
3396 case IPV6_ADD_MEMBERSHIP
:
3397 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_ADD_MEMBERSHIP
, optval
, optlen
);
3400 if (!optlen
|| !optval
)
3402 SetLastError( WSAEFAULT
);
3403 return SOCKET_ERROR
;
3405 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3406 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_DONTFRAG
, (char *)&value
, sizeof(value
) );
3408 case IPV6_DROP_MEMBERSHIP
:
3409 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_DROP_MEMBERSHIP
, optval
, optlen
);
3412 if (optlen
< sizeof(DWORD
) || !optval
)
3414 SetLastError( WSAEFAULT
);
3415 return SOCKET_ERROR
;
3417 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_RECVHOPLIMIT
, optval
, optlen
);
3419 case IPV6_MULTICAST_HOPS
:
3420 if (!optlen
|| !optval
)
3422 SetLastError( WSAEFAULT
);
3423 return SOCKET_ERROR
;
3425 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3426 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_HOPS
, (char *)&value
, sizeof(value
) );
3428 case IPV6_MULTICAST_IF
:
3429 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_IF
, optval
, optlen
);
3431 case IPV6_MULTICAST_LOOP
:
3432 if (!optlen
|| !optval
)
3434 SetLastError( WSAEFAULT
);
3435 return SOCKET_ERROR
;
3437 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3439 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_MULTICAST_LOOP
, (char *)&value
, sizeof(value
) );
3442 if (optlen
< sizeof(DWORD
) || !optval
)
3444 SetLastError( WSAEFAULT
);
3445 return SOCKET_ERROR
;
3447 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_RECVPKTINFO
, optval
, optlen
);
3449 case IPV6_PROTECTION_LEVEL
:
3450 FIXME("IPV6_PROTECTION_LEVEL is ignored!\n");
3453 case IPV6_RECVTCLASS
:
3454 if (optlen
< sizeof(DWORD
) || !optval
)
3456 SetLastError( WSAEFAULT
);
3457 return SOCKET_ERROR
;
3459 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_RECVTCLASS
, optval
, optlen
);
3461 case IPV6_UNICAST_HOPS
:
3462 if (!optlen
|| !optval
)
3464 SetLastError( WSAEFAULT
);
3465 return SOCKET_ERROR
;
3467 memcpy( &value
, optval
, min( optlen
, sizeof(value
) ));
3468 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_UNICAST_HOPS
, (char *)&value
, sizeof(value
) );
3470 case IPV6_UNICAST_IF
:
3471 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_UNICAST_IF
, optval
, optlen
);
3474 if (!optlen
|| !optval
)
3476 SetLastError( WSAEFAULT
);
3477 return SOCKET_ERROR
;
3480 return server_setsockopt( s
, IOCTL_AFD_WINE_SET_IPV6_V6ONLY
, (char *)&value
, sizeof(value
) );
3483 FIXME("Unknown IPPROTO_IPV6 optname 0x%08x\n", optname
);
3484 SetLastError(WSAENOPROTOOPT
);
3485 return SOCKET_ERROR
;
3490 WARN("Unknown level: 0x%08x\n", level
);
3491 SetLastError(WSAEINVAL
);
3492 return SOCKET_ERROR
;
3493 } /* end switch(level) */
3497 /***********************************************************************
3498 * shutdown (ws2_32.22)
3500 int WINAPI
shutdown( SOCKET s
, int how
)
3505 TRACE( "socket %#Ix, how %u\n", s
, how
);
3507 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
,
3508 IOCTL_AFD_WINE_SHUTDOWN
, &how
, sizeof(how
), NULL
, 0 );
3509 SetLastError( NtStatusToWSAError( status
) );
3510 TRACE( "status %#lx.\n", status
);
3511 return status
? -1 : 0;
3515 /***********************************************************************
3516 * socket (WS2_32.23)
3518 SOCKET WINAPI
socket( int af
, int type
, int protocol
)
3520 TRACE("af=%d type=%d protocol=%d\n", af
, type
, protocol
);
3522 return WSASocketW( af
, type
, protocol
, NULL
, 0,
3523 get_per_thread_data()->opentype
? 0 : WSA_FLAG_OVERLAPPED
);
3527 /***********************************************************************
3528 * WSAEnumNetworkEvents (ws2_32.@)
3530 int WINAPI
WSAEnumNetworkEvents( SOCKET s
, WSAEVENT event
, WSANETWORKEVENTS
*ret_events
)
3532 struct afd_get_events_params params
;
3536 TRACE( "socket %#Ix, event %p, events %p\n", s
, event
, ret_events
);
3538 ResetEvent( event
);
3540 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, IOCTL_AFD_GET_EVENTS
,
3541 NULL
, 0, ¶ms
, sizeof(params
) );
3544 ret_events
->lNetworkEvents
= afd_poll_flag_to_win32( params
.flags
);
3546 if (ret_events
->lNetworkEvents
& FD_READ
)
3547 ret_events
->iErrorCode
[FD_READ_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_READ
] );
3549 if (ret_events
->lNetworkEvents
& FD_WRITE
)
3550 ret_events
->iErrorCode
[FD_WRITE_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_WRITE
] );
3552 if (ret_events
->lNetworkEvents
& FD_OOB
)
3553 ret_events
->iErrorCode
[FD_OOB_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_OOB
] );
3555 if (ret_events
->lNetworkEvents
& FD_ACCEPT
)
3556 ret_events
->iErrorCode
[FD_ACCEPT_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_ACCEPT
] );
3558 if (ret_events
->lNetworkEvents
& FD_CONNECT
)
3559 ret_events
->iErrorCode
[FD_CONNECT_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_CONNECT_ERR
] );
3561 if (ret_events
->lNetworkEvents
& FD_CLOSE
)
3563 if (!(ret_events
->iErrorCode
[FD_CLOSE_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_HUP
] )))
3564 ret_events
->iErrorCode
[FD_CLOSE_BIT
] = NtStatusToWSAError( params
.status
[AFD_POLL_BIT_RESET
] );
3567 SetLastError( NtStatusToWSAError( status
) );
3568 TRACE( "status %#lx.\n", status
);
3569 return status
? -1 : 0;
3573 static unsigned int afd_poll_flag_from_win32( unsigned int flags
)
3575 static const unsigned int map
[] =
3581 AFD_POLL_CONNECT
| AFD_POLL_CONNECT_ERR
,
3582 AFD_POLL_RESET
| AFD_POLL_HUP
,
3585 unsigned int i
, ret
= 0;
3587 for (i
= 0; i
< ARRAY_SIZE(map
); ++i
)
3589 if (flags
& (1 << i
)) ret
|= map
[i
];
3596 /***********************************************************************
3597 * WSAEventSelect (ws2_32.@)
3599 int WINAPI
WSAEventSelect( SOCKET s
, WSAEVENT event
, LONG mask
)
3601 struct afd_event_select_params params
;
3605 TRACE( "socket %#Ix, event %p, mask %#lx\n", s
, event
, mask
);
3607 params
.event
= event
;
3608 params
.mask
= afd_poll_flag_from_win32( mask
);
3610 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, IOCTL_AFD_EVENT_SELECT
,
3611 ¶ms
, sizeof(params
), NULL
, 0 );
3612 SetLastError( NtStatusToWSAError( status
) );
3613 TRACE( "status %#lx.\n", status
);
3614 return status
? -1 : 0;
3618 /**********************************************************************
3619 * WSAGetOverlappedResult (WS2_32.40)
3621 BOOL WINAPI
WSAGetOverlappedResult( SOCKET s
, LPWSAOVERLAPPED lpOverlapped
,
3622 LPDWORD lpcbTransfer
, BOOL fWait
,
3627 TRACE( "socket %#Ix, overlapped %p, transfer %p, wait %d, flags %p\n",
3628 s
, lpOverlapped
, lpcbTransfer
, fWait
, lpdwFlags
);
3630 if ( lpOverlapped
== NULL
)
3632 ERR( "Invalid pointer\n" );
3633 SetLastError(WSA_INVALID_PARAMETER
);
3637 if (!socket_list_find( s
))
3639 SetLastError( WSAENOTSOCK
);
3643 status
= lpOverlapped
->Internal
;
3644 if (status
== STATUS_PENDING
)
3648 SetLastError( WSA_IO_INCOMPLETE
);
3652 if (WaitForSingleObject( lpOverlapped
->hEvent
? lpOverlapped
->hEvent
: SOCKET2HANDLE(s
),
3653 INFINITE
) == WAIT_FAILED
)
3655 status
= lpOverlapped
->Internal
;
3659 *lpcbTransfer
= lpOverlapped
->InternalHigh
;
3662 *lpdwFlags
= lpOverlapped
->u
.s
.Offset
;
3664 SetLastError( NtStatusToWSAError(status
) );
3665 TRACE( "status %#lx.\n", status
);
3666 return NT_SUCCESS( status
);
3670 /***********************************************************************
3671 * WSAAsyncSelect (ws2_32.@)
3673 int WINAPI
WSAAsyncSelect( SOCKET s
, HWND window
, UINT message
, LONG mask
)
3675 struct afd_message_select_params params
;
3679 TRACE( "socket %#Ix, window %p, message %#x, mask %#lx\n", s
, window
, message
, mask
);
3682 params
.window
= HandleToULong( window
);
3683 params
.message
= message
;
3684 params
.mask
= afd_poll_flag_from_win32( mask
);
3686 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, IOCTL_AFD_WINE_MESSAGE_SELECT
,
3687 ¶ms
, sizeof(params
), NULL
, 0 );
3688 SetLastError( NtStatusToWSAError( status
) );
3689 TRACE( "status %#lx.\n", status
);
3690 return status
? -1 : 0;
3694 /***********************************************************************
3695 * WSACreateEvent (WS2_32.31)
3698 WSAEVENT WINAPI
WSACreateEvent(void)
3700 /* Create a manual-reset event, with initial state: unsignaled */
3703 return CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
3706 /***********************************************************************
3707 * WSACloseEvent (WS2_32.29)
3710 BOOL WINAPI
WSACloseEvent(WSAEVENT event
)
3712 TRACE ("event=%p\n", event
);
3714 return CloseHandle(event
);
3717 /***********************************************************************
3718 * WSASocketA (WS2_32.78)
3721 SOCKET WINAPI
WSASocketA(int af
, int type
, int protocol
,
3722 LPWSAPROTOCOL_INFOA lpProtocolInfo
,
3723 GROUP g
, DWORD dwFlags
)
3726 WSAPROTOCOL_INFOW info
;
3728 if (!lpProtocolInfo
) return WSASocketW(af
, type
, protocol
, NULL
, g
, dwFlags
);
3730 memcpy(&info
, lpProtocolInfo
, FIELD_OFFSET(WSAPROTOCOL_INFOW
, szProtocol
));
3731 len
= MultiByteToWideChar(CP_ACP
, 0, lpProtocolInfo
->szProtocol
, -1,
3732 info
.szProtocol
, WSAPROTOCOL_LEN
+ 1);
3736 SetLastError(WSAEINVAL
);
3737 return SOCKET_ERROR
;
3740 return WSASocketW(af
, type
, protocol
, &info
, g
, dwFlags
);
3743 /***********************************************************************
3744 * WSASocketW (WS2_32.79)
3747 SOCKET WINAPI
WSASocketW(int af
, int type
, int protocol
,
3748 LPWSAPROTOCOL_INFOW lpProtocolInfo
,
3749 GROUP g
, DWORD flags
)
3751 struct afd_create_params create_params
;
3752 OBJECT_ATTRIBUTES attr
;
3753 UNICODE_STRING string
;
3761 FIXME: The "advanced" parameters of WSASocketW (lpProtocolInfo,
3762 g, dwFlags except WSA_FLAG_OVERLAPPED) are ignored.
3765 TRACE( "family %d, type %d, protocol %d, info %p, group %u, flags %#lx\n",
3766 af
, type
, protocol
, lpProtocolInfo
, g
, flags
);
3770 WARN( "not initialised\n" );
3771 SetLastError( WSANOTINITIALISED
);
3775 /* hack for WSADuplicateSocket */
3776 if (lpProtocolInfo
&& lpProtocolInfo
->dwServiceFlags4
== 0xff00ff00)
3778 ret
= lpProtocolInfo
->dwServiceFlags3
;
3779 TRACE( "got duplicate %#Ix\n", ret
);
3780 if (!socket_list_add(ret
))
3782 CloseHandle(SOCKET2HANDLE(ret
));
3783 return INVALID_SOCKET
;
3790 if (af
== FROM_PROTOCOL_INFO
|| !af
)
3791 af
= lpProtocolInfo
->iAddressFamily
;
3792 if (type
== FROM_PROTOCOL_INFO
|| !type
)
3793 type
= lpProtocolInfo
->iSocketType
;
3794 if (protocol
== FROM_PROTOCOL_INFO
|| !protocol
)
3795 protocol
= lpProtocolInfo
->iProtocol
;
3798 if (!af
&& !protocol
)
3800 WSASetLastError(WSAEINVAL
);
3801 return INVALID_SOCKET
;
3804 if (!af
&& lpProtocolInfo
)
3806 WSASetLastError(WSAEAFNOSUPPORT
);
3807 return INVALID_SOCKET
;
3810 if (!af
|| !type
|| !protocol
)
3814 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
3816 const WSAPROTOCOL_INFOW
*info
= &supported_protocols
[i
];
3818 if (af
&& af
!= info
->iAddressFamily
) continue;
3819 if (type
&& type
!= info
->iSocketType
) continue;
3820 if (protocol
&& (protocol
< info
->iProtocol
||
3821 protocol
> info
->iProtocol
+ info
->iProtocolMaxOffset
)) continue;
3822 if (!protocol
&& !(info
->dwProviderFlags
& PFL_MATCHES_PROTOCOL_ZERO
)) continue;
3824 if (!af
) af
= supported_protocols
[i
].iAddressFamily
;
3825 if (!type
) type
= supported_protocols
[i
].iSocketType
;
3826 if (!protocol
) protocol
= supported_protocols
[i
].iProtocol
;
3831 RtlInitUnicodeString(&string
, L
"\\Device\\Afd");
3832 InitializeObjectAttributes(&attr
, &string
, (flags
& WSA_FLAG_NO_HANDLE_INHERIT
) ? 0 : OBJ_INHERIT
, NULL
, NULL
);
3833 if ((status
= NtOpenFile(&handle
, GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, &attr
,
3834 &io
, 0, (flags
& WSA_FLAG_OVERLAPPED
) ? 0 : FILE_SYNCHRONOUS_IO_NONALERT
)))
3836 WARN( "failed to create socket, status %#lx\n", status
);
3837 WSASetLastError(NtStatusToWSAError(status
));
3838 return INVALID_SOCKET
;
3841 create_params
.family
= af
;
3842 create_params
.type
= type
;
3843 create_params
.protocol
= protocol
;
3844 create_params
.flags
= flags
& ~(WSA_FLAG_NO_HANDLE_INHERIT
| WSA_FLAG_OVERLAPPED
);
3845 if ((status
= NtDeviceIoControlFile(handle
, NULL
, NULL
, NULL
, &io
,
3846 IOCTL_AFD_WINE_CREATE
, &create_params
, sizeof(create_params
), NULL
, 0)))
3848 WARN( "failed to initialize socket, status %#lx\n", status
);
3849 err
= RtlNtStatusToDosError( status
);
3850 if (err
== WSAEACCES
) /* raw socket denied */
3852 if (type
== SOCK_RAW
)
3853 ERR_(winediag
)("Failed to create a socket of type SOCK_RAW, this requires special permissions.\n");
3855 ERR_(winediag
)("Failed to create socket, this requires special permissions.\n");
3857 WSASetLastError(err
);
3859 return INVALID_SOCKET
;
3862 ret
= HANDLE2SOCKET(handle
);
3863 TRACE( "created %#Ix\n", ret
);
3865 if (!socket_list_add(ret
))
3867 CloseHandle(handle
);
3868 return INVALID_SOCKET
;
3874 /***********************************************************************
3875 * WSAJoinLeaf (WS2_32.58)
3878 SOCKET WINAPI
WSAJoinLeaf( SOCKET s
, const struct sockaddr
*addr
, int addrlen
, WSABUF
*caller_data
,
3879 WSABUF
*callee_data
, QOS
*socket_qos
, QOS
*group_qos
, DWORD flags
)
3882 return INVALID_SOCKET
;
3885 /***********************************************************************
3886 * __WSAFDIsSet (WS2_32.151)
3888 int WINAPI
__WSAFDIsSet( SOCKET s
, fd_set
*set
)
3890 int i
= set
->fd_count
, ret
= 0;
3893 if (set
->fd_array
[i
] == s
)
3902 /***********************************************************************
3903 * WSAIsBlocking (WS2_32.114)
3905 BOOL WINAPI
WSAIsBlocking(void)
3907 /* By default WinSock should set all its sockets to non-blocking mode
3908 * and poll in PeekMessage loop when processing "blocking" ones. This
3909 * function is supposed to tell if the program is in this loop. Our
3910 * blocking calls are truly blocking so we always return FALSE.
3912 * Note: It is allowed to call this function without prior WSAStartup().
3919 /***********************************************************************
3920 * WSACancelBlockingCall (WS2_32.113)
3922 INT WINAPI
WSACancelBlockingCall(void)
3928 static INT WINAPI
WSA_DefaultBlockingHook( FARPROC x
)
3930 FIXME("How was this called?\n");
3935 /***********************************************************************
3936 * WSASetBlockingHook (WS2_32.109)
3938 FARPROC WINAPI
WSASetBlockingHook(FARPROC lpBlockFunc
)
3940 FARPROC prev
= blocking_hook
;
3941 blocking_hook
= lpBlockFunc
;
3942 TRACE("hook %p\n", lpBlockFunc
);
3947 /***********************************************************************
3948 * WSAUnhookBlockingHook (WS2_32.110)
3950 INT WINAPI
WSAUnhookBlockingHook(void)
3952 blocking_hook
= (FARPROC
)WSA_DefaultBlockingHook
;
3957 /***********************************************************************
3958 * WSARecv (WS2_32.67)
3960 int WINAPI
WSARecv(SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3961 LPDWORD NumberOfBytesReceived
, LPDWORD lpFlags
,
3962 LPWSAOVERLAPPED lpOverlapped
,
3963 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3965 return WS2_recv_base(s
, lpBuffers
, dwBufferCount
, NumberOfBytesReceived
, lpFlags
,
3966 NULL
, NULL
, lpOverlapped
, lpCompletionRoutine
, NULL
);
3970 /***********************************************************************
3971 * WSARecvFrom (WS2_32.69)
3973 INT WINAPI
WSARecvFrom( SOCKET s
, LPWSABUF lpBuffers
, DWORD dwBufferCount
,
3974 DWORD
*lpNumberOfBytesRecvd
, DWORD
*lpFlags
, struct sockaddr
*lpFrom
,
3975 LPINT lpFromlen
, LPWSAOVERLAPPED lpOverlapped
,
3976 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
3979 /* Garena hooks WSARecvFrom(), so we need a wrapper */
3980 return WS2_recv_base( s
, lpBuffers
, dwBufferCount
,
3981 lpNumberOfBytesRecvd
, lpFlags
,
3983 lpOverlapped
, lpCompletionRoutine
, NULL
);
3987 /***********************************************************************
3988 * WSAAccept (ws2_32.@)
3990 SOCKET WINAPI
WSAAccept( SOCKET s
, struct sockaddr
*addr
, int *addrlen
,
3991 LPCONDITIONPROC callback
, DWORD_PTR context
)
3994 WSABUF caller_id
, caller_data
, callee_id
, callee_data
;
3995 struct sockaddr src_addr
, dst_addr
;
3999 TRACE( "socket %#Ix, addr %p, addrlen %p, callback %p, context %#Ix\n",
4000 s
, addr
, addrlen
, callback
, context
);
4002 cs
= accept( s
, addr
, addrlen
);
4003 if (cs
== SOCKET_ERROR
) return SOCKET_ERROR
;
4004 if (!callback
) return cs
;
4006 if (addr
&& addrlen
)
4008 caller_id
.buf
= (char *)addr
;
4009 caller_id
.len
= *addrlen
;
4013 size
= sizeof(src_addr
);
4014 getpeername( cs
, &src_addr
, &size
);
4015 caller_id
.buf
= (char *)&src_addr
;
4016 caller_id
.len
= size
;
4018 caller_data
.buf
= NULL
;
4019 caller_data
.len
= 0;
4021 size
= sizeof(dst_addr
);
4022 getsockname( cs
, &dst_addr
, &size
);
4024 callee_id
.buf
= (char *)&dst_addr
;
4025 callee_id
.len
= sizeof(dst_addr
);
4027 ret
= (*callback
)( &caller_id
, &caller_data
, NULL
, NULL
,
4028 &callee_id
, &callee_data
, &group
, context
);
4029 TRACE( "callback returned %d.\n", ret
);
4037 ULONG server_handle
= cs
;
4041 status
= NtDeviceIoControlFile( (HANDLE
)s
, NULL
, NULL
, NULL
, &io
, IOCTL_AFD_WINE_DEFER
,
4042 &server_handle
, sizeof(server_handle
), NULL
, 0 );
4044 SetLastError( status
? RtlNtStatusToDosError( status
) : WSATRY_AGAIN
);
4045 TRACE( "status %#lx.\n", status
);
4051 SetLastError( WSAECONNREFUSED
);
4052 return SOCKET_ERROR
;
4055 FIXME( "Unknown return type from Condition function\n" );
4056 SetLastError( WSAENOTSOCK
);
4057 return SOCKET_ERROR
;
4062 /***********************************************************************
4063 * WSADuplicateSocketA (WS2_32.32)
4065 int WINAPI
WSADuplicateSocketA( SOCKET s
, DWORD dwProcessId
, LPWSAPROTOCOL_INFOA lpProtocolInfo
)
4067 return WS_DuplicateSocket(FALSE
, s
, dwProcessId
, (LPWSAPROTOCOL_INFOW
) lpProtocolInfo
);
4070 /***********************************************************************
4071 * WSADuplicateSocketW (WS2_32.33)
4073 int WINAPI
WSADuplicateSocketW( SOCKET s
, DWORD dwProcessId
, LPWSAPROTOCOL_INFOW lpProtocolInfo
)
4075 return WS_DuplicateSocket(TRUE
, s
, dwProcessId
, lpProtocolInfo
);
4079 /***********************************************************************
4080 * WSAGetQOSByName (WS2_32.41)
4082 BOOL WINAPI
WSAGetQOSByName( SOCKET s
, WSABUF
*name
, QOS
*qos
)
4084 FIXME( "socket %#Ix, name %p, qos %p, stub!\n", s
, name
, qos
);
4089 /***********************************************************************
4090 * WSARecvDisconnect (WS2_32.68)
4092 int WINAPI
WSARecvDisconnect( SOCKET s
, WSABUF
*data
)
4094 TRACE( "socket %#Ix, data %p\n", s
, data
);
4096 return shutdown( s
, SD_RECEIVE
);
4100 static BOOL
protocol_matches_filter( const int *filter
, int protocol
)
4102 if (!filter
) return TRUE
;
4105 if (protocol
== *filter
++) return TRUE
;
4110 /*****************************************************************************
4111 * WSAEnumProtocolsA [WS2_32.@]
4113 * see function WSAEnumProtocolsW
4115 int WINAPI
WSAEnumProtocolsA( int *filter
, WSAPROTOCOL_INFOA
*protocols
, DWORD
*size
)
4119 TRACE("filter %p, protocols %p, size %p\n", filter
, protocols
, size
);
4121 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
4123 if (protocol_matches_filter( filter
, supported_protocols
[i
].iProtocol
))
4127 if (!protocols
|| *size
< count
* sizeof(WSAPROTOCOL_INFOA
))
4129 *size
= count
* sizeof(WSAPROTOCOL_INFOA
);
4130 WSASetLastError( WSAENOBUFS
);
4131 return SOCKET_ERROR
;
4135 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
4137 if (protocol_matches_filter( filter
, supported_protocols
[i
].iProtocol
))
4139 memcpy( &protocols
[count
], &supported_protocols
[i
], offsetof( WSAPROTOCOL_INFOW
, szProtocol
) );
4140 WideCharToMultiByte( CP_ACP
, 0, supported_protocols
[i
].szProtocol
, -1,
4141 protocols
[count
].szProtocol
, sizeof(protocols
[count
].szProtocol
), NULL
, NULL
);
4148 /*****************************************************************************
4149 * WSAEnumProtocolsW [WS2_32.@]
4151 * Retrieves information about specified set of active network protocols.
4154 * protocols [I] Pointer to null-terminated array of protocol id's. NULL
4155 * retrieves information on all available protocols.
4156 * buffer [I] Pointer to a buffer to be filled with WSAPROTOCOL_INFO
4158 * len [I/O] Pointer to a variable specifying buffer size. On output
4159 * the variable holds the number of bytes needed when the
4160 * specified size is too small.
4163 * Success: number of WSAPROTOCOL_INFO structures in buffer.
4164 * Failure: SOCKET_ERROR
4167 * NT4SP5 does not return SPX if protocols == NULL
4170 * - NT4SP5 returns in addition these list of NETBIOS protocols
4171 * (address family 17), each entry two times one for socket type 2 and 5
4173 * iProtocol szProtocol
4174 * 0x80000000 \Device\NwlnkNb
4175 * 0xfffffffa \Device\NetBT_CBENT7
4176 * 0xfffffffb \Device\Nbf_CBENT7
4177 * 0xfffffffc \Device\NetBT_NdisWan5
4178 * 0xfffffffd \Device\NetBT_El9202
4179 * 0xfffffffe \Device\Nbf_El9202
4180 * 0xffffffff \Device\Nbf_NdisWan4
4182 * - there is no check that the operating system supports the returned
4185 int WINAPI
WSAEnumProtocolsW( int *filter
, WSAPROTOCOL_INFOW
*protocols
, DWORD
*size
)
4189 TRACE("filter %p, protocols %p, size %p\n", filter
, protocols
, size
);
4191 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
4193 if (protocol_matches_filter( filter
, supported_protocols
[i
].iProtocol
))
4197 if (!protocols
|| *size
< count
* sizeof(WSAPROTOCOL_INFOW
))
4199 *size
= count
* sizeof(WSAPROTOCOL_INFOW
);
4200 WSASetLastError( WSAENOBUFS
);
4201 return SOCKET_ERROR
;
4205 for (i
= 0; i
< ARRAY_SIZE(supported_protocols
); ++i
)
4207 if (protocol_matches_filter( filter
, supported_protocols
[i
].iProtocol
))
4208 protocols
[count
++] = supported_protocols
[i
];