2 * WSK (Winsock Kernel) driver library.
4 * Copyright 2020 Paul Gofman <pgofman@codeweavers.com> for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WIN32_NO_STATUS
30 #include "wine/debug.h"
34 #include "wine/heap.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(netio
);
40 WSK_REGISTRATION
*registration
;
41 WSK_CLIENT_NPI
*client_npi
;
44 struct listen_socket_callback_context
46 SOCKADDR
*local_address
;
47 SOCKADDR
*remote_address
;
48 const void *client_dispatch
;
50 char addr_buffer
[2 * (sizeof(SOCKADDR
) + 16)];
54 #define MAX_PENDING_IO 10
64 struct wsk_socket_internal
66 WSK_SOCKET wsk_socket
;
68 const void *client_dispatch
;
71 ADDRESS_FAMILY address_family
;
76 CRITICAL_SECTION cs_socket
;
78 struct wsk_pending_io pending_io
[MAX_PENDING_IO
];
82 struct listen_socket_callback_context listen_socket_callback_context
;
87 static LPFN_ACCEPTEX pAcceptEx
;
88 static LPFN_GETACCEPTEXSOCKADDRS pGetAcceptExSockaddrs
;
89 static LPFN_CONNECTEX pConnectEx
;
91 static const WSK_PROVIDER_CONNECTION_DISPATCH wsk_provider_connection_dispatch
;
93 static inline struct wsk_socket_internal
*wsk_socket_internal_from_wsk_socket(WSK_SOCKET
*wsk_socket
)
95 return CONTAINING_RECORD(wsk_socket
, struct wsk_socket_internal
, wsk_socket
);
98 static NTSTATUS
sock_error_to_ntstatus(DWORD err
)
102 case 0: return STATUS_SUCCESS
;
103 case WSAEBADF
: return STATUS_INVALID_HANDLE
;
104 case WSAEACCES
: return STATUS_ACCESS_DENIED
;
105 case WSAEFAULT
: return STATUS_NO_MEMORY
;
106 case WSAEINVAL
: return STATUS_INVALID_PARAMETER
;
107 case WSAEMFILE
: return STATUS_TOO_MANY_OPENED_FILES
;
108 case WSAEWOULDBLOCK
: return STATUS_CANT_WAIT
;
109 case WSAEINPROGRESS
: return STATUS_PENDING
;
110 case WSAEALREADY
: return STATUS_NETWORK_BUSY
;
111 case WSAENOTSOCK
: return STATUS_OBJECT_TYPE_MISMATCH
;
112 case WSAEDESTADDRREQ
: return STATUS_INVALID_PARAMETER
;
113 case WSAEMSGSIZE
: return STATUS_BUFFER_OVERFLOW
;
114 case WSAEPROTONOSUPPORT
:
115 case WSAESOCKTNOSUPPORT
:
116 case WSAEPFNOSUPPORT
:
117 case WSAEAFNOSUPPORT
:
118 case WSAEPROTOTYPE
: return STATUS_NOT_SUPPORTED
;
119 case WSAENOPROTOOPT
: return STATUS_INVALID_PARAMETER
;
120 case WSAEOPNOTSUPP
: return STATUS_NOT_IMPLEMENTED
;
121 case WSAEADDRINUSE
: return STATUS_ADDRESS_ALREADY_ASSOCIATED
;
122 case WSAEADDRNOTAVAIL
: return STATUS_INVALID_PARAMETER
;
123 case WSAECONNREFUSED
: return STATUS_CONNECTION_REFUSED
;
124 case WSAESHUTDOWN
: return STATUS_PIPE_DISCONNECTED
;
125 case WSAENOTCONN
: return STATUS_CONNECTION_DISCONNECTED
;
126 case WSAETIMEDOUT
: return STATUS_IO_TIMEOUT
;
127 case WSAENETUNREACH
: return STATUS_NETWORK_UNREACHABLE
;
128 case WSAENETDOWN
: return STATUS_NETWORK_BUSY
;
129 case WSAECONNRESET
: return STATUS_CONNECTION_RESET
;
130 case WSAECONNABORTED
: return STATUS_CONNECTION_ABORTED
;
131 case WSAHOST_NOT_FOUND
: return STATUS_NOT_FOUND
;
133 FIXME("Unmapped error %lu.\n", err
);
134 return STATUS_UNSUCCESSFUL
;
138 static inline void lock_socket(struct wsk_socket_internal
*socket
)
140 EnterCriticalSection(&socket
->cs_socket
);
143 static inline void unlock_socket(struct wsk_socket_internal
*socket
)
145 LeaveCriticalSection(&socket
->cs_socket
);
148 static void socket_init(struct wsk_socket_internal
*socket
)
150 InitializeCriticalSection(&socket
->cs_socket
);
153 static void dispatch_irp(IRP
*irp
, NTSTATUS status
)
155 irp
->IoStatus
.Status
= status
;
156 --irp
->CurrentLocation
;
157 --irp
->Tail
.Overlay
.CurrentStackLocation
;
158 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
161 static struct wsk_pending_io
*allocate_pending_io(struct wsk_socket_internal
*socket
,
162 PTP_WAIT_CALLBACK socket_async_callback
, IRP
*irp
)
164 struct wsk_pending_io
*io
= socket
->pending_io
;
165 unsigned int i
, io_index
;
168 for (i
= 0; i
< ARRAY_SIZE(socket
->pending_io
); ++i
)
172 if (io
[i
].callback
== socket_async_callback
)
185 FIXME("Pending io requests count exceeds limit.\n");
189 io
[io_index
].irp
= irp
;
191 if (io
[io_index
].tp_wait
)
192 CloseThreadpoolWait(io
[io_index
].tp_wait
);
194 io
[io_index
].ovr
.hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
196 io
[io_index
].tp_wait
= CreateThreadpoolWait(socket_async_callback
, socket
, NULL
);
197 io
[io_index
].callback
= socket_async_callback
;
199 return &io
[io_index
];
202 static struct wsk_pending_io
*find_pending_io(struct wsk_socket_internal
*socket
, TP_WAIT
*tp_wait
)
206 for (i
= 0; i
< ARRAY_SIZE(socket
->pending_io
); ++i
)
208 if (socket
->pending_io
[i
].tp_wait
== tp_wait
)
209 return &socket
->pending_io
[i
];
212 FIXME("Pending io not found for tp_wait %p.\n", tp_wait
);
216 static void dispatch_pending_io(struct wsk_pending_io
*io
, NTSTATUS status
, ULONG_PTR information
)
218 TRACE("io %p, status %#lx, information %#Ix.\n", io
, status
, information
);
220 io
->irp
->IoStatus
.Information
= information
;
221 dispatch_irp(io
->irp
, status
);
225 static NTSTATUS WINAPI
wsk_control_socket(WSK_SOCKET
*socket
, WSK_CONTROL_SOCKET_TYPE request_type
,
226 ULONG control_code
, ULONG level
, SIZE_T input_size
, void *input_buffer
, SIZE_T output_size
,
227 void *output_buffer
, SIZE_T
*output_size_returned
, IRP
*irp
)
229 FIXME("socket %p, request_type %u, control_code %#lx, level %lu, input_size %Iu, input_buffer %p, "
230 "output_size %Iu, output_buffer %p, output_size_returned %p, irp %p stub.\n",
231 socket
, request_type
, control_code
, level
, input_size
, input_buffer
, output_size
,
232 output_buffer
, output_size_returned
, irp
);
234 return STATUS_NOT_IMPLEMENTED
;
237 static NTSTATUS WINAPI
wsk_close_socket(WSK_SOCKET
*socket
, IRP
*irp
)
239 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
243 TRACE("socket %p, irp %p.\n", socket
, irp
);
247 for (i
= 0; i
< ARRAY_SIZE(s
->pending_io
); ++i
)
249 struct wsk_pending_io
*io
= &s
->pending_io
[i
];
253 CancelIoEx((HANDLE
)s
->s
, &io
->ovr
);
254 SetThreadpoolWait(io
->tp_wait
, NULL
, NULL
);
256 WaitForThreadpoolWaitCallbacks(io
->tp_wait
, FALSE
);
258 CloseThreadpoolWait(io
->tp_wait
);
259 CloseHandle(io
->ovr
.hEvent
);
263 dispatch_pending_io(io
, STATUS_CANCELLED
, 0);
266 if (s
->flags
& WSK_FLAG_LISTEN_SOCKET
&& s
->callback_context
.listen_socket_callback_context
.acceptor
)
267 closesocket(s
->callback_context
.listen_socket_callback_context
.acceptor
);
269 status
= closesocket(s
->s
) ? sock_error_to_ntstatus(WSAGetLastError()) : STATUS_SUCCESS
;
272 DeleteCriticalSection(&s
->cs_socket
);
275 irp
->IoStatus
.Information
= 0;
276 dispatch_irp(irp
, status
);
278 return status
? status
: STATUS_PENDING
;
281 static NTSTATUS WINAPI
wsk_bind(WSK_SOCKET
*socket
, SOCKADDR
*local_address
, ULONG flags
, IRP
*irp
)
283 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
286 TRACE("socket %p, local_address %p, flags %#lx, irp %p.\n",
287 socket
, local_address
, flags
, irp
);
290 return STATUS_INVALID_PARAMETER
;
292 if (bind(s
->s
, local_address
, sizeof(*local_address
)))
293 status
= sock_error_to_ntstatus(WSAGetLastError());
294 else if (s
->flags
& WSK_FLAG_LISTEN_SOCKET
&& listen(s
->s
, SOMAXCONN
))
295 status
= sock_error_to_ntstatus(WSAGetLastError());
297 status
= STATUS_SUCCESS
;
299 if (status
== STATUS_SUCCESS
)
302 TRACE("status %#lx.\n", status
);
303 irp
->IoStatus
.Information
= 0;
304 dispatch_irp(irp
, status
);
305 return STATUS_PENDING
;
308 static void create_accept_socket(struct wsk_socket_internal
*socket
, struct wsk_pending_io
*io
)
310 struct listen_socket_callback_context
*context
311 = &socket
->callback_context
.listen_socket_callback_context
;
312 INT local_address_len
, remote_address_len
;
313 SOCKADDR
*local_address
, *remote_address
;
314 struct wsk_socket_internal
*accept_socket
;
316 if (!(accept_socket
= heap_alloc_zero(sizeof(*accept_socket
))))
319 dispatch_pending_io(io
, STATUS_NO_MEMORY
, 0);
323 TRACE("accept_socket %p.\n", accept_socket
);
324 accept_socket
->wsk_socket
.Dispatch
= &wsk_provider_connection_dispatch
;
325 accept_socket
->s
= context
->acceptor
;
326 accept_socket
->client_dispatch
= context
->client_dispatch
;
327 accept_socket
->client_context
= context
->client_context
;
328 accept_socket
->socket_type
= socket
->socket_type
;
329 accept_socket
->address_family
= socket
->address_family
;
330 accept_socket
->protocol
= socket
->protocol
;
331 accept_socket
->flags
= WSK_FLAG_CONNECTION_SOCKET
;
332 socket_init(accept_socket
);
334 pGetAcceptExSockaddrs(context
->addr_buffer
, 0, sizeof(SOCKADDR
) + 16, sizeof(SOCKADDR
) + 16,
335 &local_address
, &local_address_len
, &remote_address
, &remote_address_len
);
337 if (context
->local_address
)
338 memcpy(context
->local_address
, local_address
,
339 min(sizeof(*context
->local_address
), local_address_len
));
341 if (context
->remote_address
)
342 memcpy(context
->remote_address
, remote_address
,
343 min(sizeof(*context
->remote_address
), remote_address_len
));
345 dispatch_pending_io(io
, STATUS_SUCCESS
, (ULONG_PTR
)&accept_socket
->wsk_socket
);
349 static void WINAPI
accept_callback(TP_CALLBACK_INSTANCE
*instance
, void *socket_
, TP_WAIT
*wait
,
350 TP_WAIT_RESULT wait_result
)
352 struct listen_socket_callback_context
*context
;
353 struct wsk_socket_internal
*socket
= socket_
;
354 struct wsk_pending_io
*io
;
357 TRACE("instance %p, socket %p, wait %p, wait_result %#lx.\n", instance
, socket
, wait
, wait_result
);
360 context
= &socket
->callback_context
.listen_socket_callback_context
;
361 io
= find_pending_io(socket
, wait
);
363 if (GetOverlappedResult((HANDLE
)socket
->s
, &io
->ovr
, &size
, FALSE
))
365 create_accept_socket(socket
, io
);
369 closesocket(context
->acceptor
);
370 context
->acceptor
= 0;
371 dispatch_pending_io(io
, io
->ovr
.Internal
, 0);
373 unlock_socket(socket
);
376 static BOOL WINAPI
init_accept_functions(INIT_ONCE
*once
, void *param
, void **context
)
378 GUID get_acceptex_guid
= WSAID_GETACCEPTEXSOCKADDRS
;
379 GUID acceptex_guid
= WSAID_ACCEPTEX
;
380 SOCKET s
= (SOCKET
)param
;
383 if (WSAIoctl(s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, &acceptex_guid
, sizeof(acceptex_guid
),
384 &pAcceptEx
, sizeof(pAcceptEx
), &size
, NULL
, NULL
))
386 ERR("Could not get AcceptEx address, error %u.\n", WSAGetLastError());
390 if (WSAIoctl(s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, &get_acceptex_guid
, sizeof(get_acceptex_guid
),
391 &pGetAcceptExSockaddrs
, sizeof(pGetAcceptExSockaddrs
), &size
, NULL
, NULL
))
393 ERR("Could not get AcceptEx address, error %u.\n", WSAGetLastError());
400 static NTSTATUS WINAPI
wsk_accept(WSK_SOCKET
*listen_socket
, ULONG flags
, void *accept_socket_context
,
401 const WSK_CLIENT_CONNECTION_DISPATCH
*accept_socket_dispatch
, SOCKADDR
*local_address
,
402 SOCKADDR
*remote_address
, IRP
*irp
)
404 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(listen_socket
);
405 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
406 struct listen_socket_callback_context
*context
;
407 struct wsk_pending_io
*io
;
412 TRACE("listen_socket %p, flags %#lx, accept_socket_context %p, accept_socket_dispatch %p, "
413 "local_address %p, remote_address %p, irp %p.\n",
414 listen_socket
, flags
, accept_socket_context
, accept_socket_dispatch
, local_address
,
415 remote_address
, irp
);
418 return STATUS_INVALID_PARAMETER
;
420 if (!InitOnceExecuteOnce(&init_once
, init_accept_functions
, (void *)s
->s
, NULL
))
422 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
423 return STATUS_PENDING
;
427 if (!(io
= allocate_pending_io(s
, accept_callback
, irp
)))
429 irp
->IoStatus
.Information
= 0;
430 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
432 return STATUS_PENDING
;
435 context
= &s
->callback_context
.listen_socket_callback_context
;
436 if ((acceptor
= WSASocketW(s
->address_family
, s
->socket_type
, s
->protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
))
439 dispatch_pending_io(io
, sock_error_to_ntstatus(WSAGetLastError()), 0);
441 return STATUS_PENDING
;
444 context
->local_address
= local_address
;
445 context
->remote_address
= remote_address
;
446 context
->client_dispatch
= accept_socket_dispatch
;
447 context
->client_context
= accept_socket_context
;
448 context
->acceptor
= acceptor
;
450 if (pAcceptEx(s
->s
, acceptor
, context
->addr_buffer
, 0,
451 sizeof(SOCKADDR
) + 16, sizeof(SOCKADDR
) + 16, &size
, &io
->ovr
))
453 create_accept_socket(s
, io
);
455 else if ((error
= WSAGetLastError()) == ERROR_IO_PENDING
)
457 SetThreadpoolWait(io
->tp_wait
, io
->ovr
.hEvent
, NULL
);
461 closesocket(acceptor
);
462 context
->acceptor
= 0;
463 dispatch_pending_io(io
, sock_error_to_ntstatus(error
), 0);
467 return STATUS_PENDING
;
470 static NTSTATUS WINAPI
wsk_inspect_complete(WSK_SOCKET
*listen_socket
, WSK_INSPECT_ID
*inspect_id
,
471 WSK_INSPECT_ACTION action
, IRP
*irp
)
473 FIXME("listen_socket %p, inspect_id %p, action %u, irp %p stub.\n",
474 listen_socket
, inspect_id
, action
, irp
);
476 return STATUS_NOT_IMPLEMENTED
;
479 static NTSTATUS WINAPI
wsk_get_local_address(WSK_SOCKET
*socket
, SOCKADDR
*local_address
, IRP
*irp
)
481 FIXME("socket %p, local_address %p, irp %p stub.\n", socket
, local_address
, irp
);
483 return STATUS_NOT_IMPLEMENTED
;
486 static const WSK_PROVIDER_LISTEN_DISPATCH wsk_provider_listen_dispatch
=
494 wsk_inspect_complete
,
495 wsk_get_local_address
,
498 static void WINAPI
connect_callback(TP_CALLBACK_INSTANCE
*instance
, void *socket_
, TP_WAIT
*wait
,
499 TP_WAIT_RESULT wait_result
)
501 struct wsk_socket_internal
*socket
= socket_
;
502 struct wsk_pending_io
*io
;
505 TRACE("instance %p, socket %p, wait %p, wait_result %#lx.\n", instance
, socket
, wait
, wait_result
);
508 io
= find_pending_io(socket
, wait
);
510 GetOverlappedResult((HANDLE
)socket
->s
, &io
->ovr
, &size
, FALSE
);
511 dispatch_pending_io(io
, io
->ovr
.Internal
, 0);
512 unlock_socket(socket
);
515 static BOOL WINAPI
init_connect_functions(INIT_ONCE
*once
, void *param
, void **context
)
517 GUID connectex_guid
= WSAID_CONNECTEX
;
518 SOCKET s
= (SOCKET
)param
;
521 if (WSAIoctl(s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, &connectex_guid
, sizeof(connectex_guid
),
522 &pConnectEx
, sizeof(pConnectEx
), &size
, NULL
, NULL
))
524 ERR("Could not get AcceptEx address, error %u.\n", WSAGetLastError());
530 static NTSTATUS WINAPI
wsk_connect(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, ULONG flags
, IRP
*irp
)
532 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
533 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
534 struct wsk_pending_io
*io
;
537 TRACE("socket %p, remote_address %p, flags %#lx, irp %p.\n",
538 socket
, remote_address
, flags
, irp
);
541 return STATUS_INVALID_PARAMETER
;
543 if (!InitOnceExecuteOnce(&init_once
, init_connect_functions
, (void *)s
->s
, NULL
))
545 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
546 return STATUS_PENDING
;
551 if (!(io
= allocate_pending_io(s
, connect_callback
, irp
)))
553 irp
->IoStatus
.Information
= 0;
554 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
556 return STATUS_PENDING
;
561 dispatch_pending_io(io
, STATUS_INVALID_DEVICE_STATE
, 0);
563 return STATUS_INVALID_DEVICE_STATE
;
566 if (pConnectEx(s
->s
, remote_address
, sizeof(*remote_address
), NULL
, 0, NULL
, &io
->ovr
))
567 dispatch_pending_io(io
, STATUS_SUCCESS
, 0);
568 else if ((error
= WSAGetLastError()) == ERROR_IO_PENDING
)
569 SetThreadpoolWait(io
->tp_wait
, io
->ovr
.hEvent
, NULL
);
571 dispatch_pending_io(io
, sock_error_to_ntstatus(error
), 0);
575 return STATUS_PENDING
;
578 static NTSTATUS WINAPI
wsk_get_remote_address(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, IRP
*irp
)
580 FIXME("socket %p, remote_address %p, irp %p stub.\n", socket
, remote_address
, irp
);
582 return STATUS_NOT_IMPLEMENTED
;
585 static void WINAPI
send_receive_callback(TP_CALLBACK_INSTANCE
*instance
, void *socket_
, TP_WAIT
*wait
,
586 TP_WAIT_RESULT wait_result
)
588 struct wsk_socket_internal
*socket
= socket_
;
589 struct wsk_pending_io
*io
;
592 TRACE("instance %p, socket %p, wait %p, wait_result %#lx.\n", instance
, socket
, wait
, wait_result
);
595 io
= find_pending_io(socket
, wait
);
597 if (WSAGetOverlappedResult(socket
->s
, &io
->ovr
, &length
, FALSE
, &flags
))
598 dispatch_pending_io(io
, STATUS_SUCCESS
, length
);
600 dispatch_pending_io(io
, io
->ovr
.Internal
, 0);
602 unlock_socket(socket
);
605 static NTSTATUS
do_send_receive(WSK_SOCKET
*socket
, WSK_BUF
*wsk_buf
, ULONG flags
, IRP
*irp
, BOOL is_send
)
607 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
608 struct wsk_pending_io
*io
;
614 TRACE("socket %p, buffer %p, flags %#lx, irp %p, is_send %#x.\n",
615 socket
, wsk_buf
, flags
, irp
, is_send
);
618 return STATUS_INVALID_PARAMETER
;
620 if (!wsk_buf
->Mdl
&& wsk_buf
->Length
)
621 return STATUS_INVALID_PARAMETER
;
623 if (wsk_buf
->Mdl
&& wsk_buf
->Mdl
->Next
)
625 FIXME("Chained MDLs are not supported.\n");
626 irp
->IoStatus
.Information
= 0;
627 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
628 return STATUS_PENDING
;
632 FIXME("flags %#lx not implemented.\n", flags
);
635 if (!(io
= allocate_pending_io(s
, send_receive_callback
, irp
)))
637 irp
->IoStatus
.Information
= 0;
638 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
640 return STATUS_PENDING
;
643 wsa_buf
.len
= wsk_buf
->Length
;
644 wsa_buf
.buf
= wsk_buf
->Mdl
? (CHAR
*)wsk_buf
->Mdl
->StartVa
645 + wsk_buf
->Mdl
->ByteOffset
+ wsk_buf
->Offset
: NULL
;
649 if (!(is_send
? WSASend(s
->s
, &wsa_buf
, 1, &length
, wsa_flags
, &io
->ovr
, NULL
)
650 : WSARecv(s
->s
, &wsa_buf
, 1, &length
, &wsa_flags
, &io
->ovr
, NULL
)))
652 dispatch_pending_io(io
, STATUS_SUCCESS
, length
);
654 else if ((error
= WSAGetLastError()) == WSA_IO_PENDING
)
656 SetThreadpoolWait(io
->tp_wait
, io
->ovr
.hEvent
, NULL
);
660 dispatch_pending_io(io
, sock_error_to_ntstatus(error
), 0);
664 return STATUS_PENDING
;
667 static NTSTATUS WINAPI
wsk_send(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
669 TRACE("socket %p, buffer %p, flags %#lx, irp %p.\n", socket
, buffer
, flags
, irp
);
671 return do_send_receive(socket
, buffer
, flags
, irp
, TRUE
);
674 static NTSTATUS WINAPI
wsk_receive(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
676 TRACE("socket %p, buffer %p, flags %#lx, irp %p.\n", socket
, buffer
, flags
, irp
);
678 return do_send_receive(socket
, buffer
, flags
, irp
, FALSE
);
681 static NTSTATUS WINAPI
wsk_disconnect(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
683 FIXME("socket %p, buffer %p, flags %#lx, irp %p stub.\n", socket
, buffer
, flags
, irp
);
685 return STATUS_NOT_IMPLEMENTED
;
688 static NTSTATUS WINAPI
wsk_release(WSK_SOCKET
*socket
, WSK_DATA_INDICATION
*data_indication
)
690 FIXME("socket %p, data_indication %p stub.\n", socket
, data_indication
);
692 return STATUS_NOT_IMPLEMENTED
;
695 static NTSTATUS WINAPI
wsk_connext_ex(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, WSK_BUF
*buffer
,
696 ULONG flags
, IRP
*irp
)
698 FIXME("socket %p, remote_address %p, buffer %p, flags %#lx, irp %p stub.\n",
699 socket
, remote_address
, buffer
, flags
, irp
);
701 return STATUS_NOT_IMPLEMENTED
;
704 static NTSTATUS WINAPI
wsk_send_ex(void)
706 FIXME("stub (no prototype, will crash).\n");
708 return STATUS_NOT_IMPLEMENTED
;
711 static NTSTATUS WINAPI
wsk_receive_ex(void)
713 FIXME("stub (no prototype, will crash).\n");
715 return STATUS_NOT_IMPLEMENTED
;
718 static const WSK_PROVIDER_CONNECTION_DISPATCH wsk_provider_connection_dispatch
=
726 wsk_get_local_address
,
727 wsk_get_remote_address
,
737 static NTSTATUS WINAPI
wsk_socket(WSK_CLIENT
*client
, ADDRESS_FAMILY address_family
, USHORT socket_type
,
738 ULONG protocol
, ULONG flags
, void *socket_context
, const void *dispatch
, PEPROCESS owning_process
,
739 PETHREAD owning_thread
, SECURITY_DESCRIPTOR
*security_descriptor
, IRP
*irp
)
741 struct wsk_socket_internal
*socket
;
745 TRACE("client %p, address_family %#x, socket_type %#x, protocol %#lx, flags %#lx, socket_context %p, dispatch %p, "
746 "owning_process %p, owning_thread %p, security_descriptor %p, irp %p.\n",
747 client
, address_family
, socket_type
, protocol
, flags
, socket_context
, dispatch
, owning_process
,
748 owning_thread
, security_descriptor
, irp
);
751 return STATUS_INVALID_PARAMETER
;
754 return STATUS_INVALID_HANDLE
;
756 irp
->IoStatus
.Information
= 0;
758 if ((s
= WSASocketW(address_family
, socket_type
, protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
)) == INVALID_SOCKET
)
760 status
= sock_error_to_ntstatus(WSAGetLastError());
764 if (!(socket
= heap_alloc_zero(sizeof(*socket
))))
766 status
= STATUS_NO_MEMORY
;
772 socket
->client_dispatch
= dispatch
;
773 socket
->client_context
= socket_context
;
774 socket
->socket_type
= socket_type
;
775 socket
->flags
= flags
;
776 socket
->address_family
= address_family
;
777 socket
->protocol
= protocol
;
781 case WSK_FLAG_LISTEN_SOCKET
:
782 socket
->wsk_socket
.Dispatch
= &wsk_provider_listen_dispatch
;
785 case WSK_FLAG_CONNECTION_SOCKET
:
786 socket
->wsk_socket
.Dispatch
= &wsk_provider_connection_dispatch
;
790 FIXME("Flags %#lx not implemented.\n", flags
);
793 status
= STATUS_NOT_IMPLEMENTED
;
799 irp
->IoStatus
.Information
= (ULONG_PTR
)&socket
->wsk_socket
;
800 status
= STATUS_SUCCESS
;
803 dispatch_irp(irp
, status
);
804 return status
? status
: STATUS_PENDING
;
807 static NTSTATUS WINAPI
wsk_socket_connect(WSK_CLIENT
*client
, USHORT socket_type
, ULONG protocol
,
808 SOCKADDR
*local_address
, SOCKADDR
*remote_address
, ULONG flags
, void *socket_context
,
809 const WSK_CLIENT_CONNECTION_DISPATCH
*dispatch
, PEPROCESS owning_process
, PETHREAD owning_thread
,
810 SECURITY_DESCRIPTOR
*security_descriptor
, IRP
*irp
)
812 FIXME("client %p, socket_type %#x, protocol %#lx, local_address %p, remote_address %p, "
813 "flags %#lx, socket_context %p, dispatch %p, owning_process %p, owning_thread %p, "
814 "security_descriptor %p, irp %p stub.\n",
815 client
, socket_type
, protocol
, local_address
, remote_address
, flags
, socket_context
,
816 dispatch
, owning_process
, owning_thread
, security_descriptor
, irp
);
818 return STATUS_NOT_IMPLEMENTED
;
821 static NTSTATUS WINAPI
wsk_control_client(WSK_CLIENT
*client
, ULONG control_code
, SIZE_T input_size
,
822 void *input_buffer
, SIZE_T output_size
, void *output_buffer
, SIZE_T
*output_size_returned
,
826 FIXME("client %p, control_code %#lx, input_size %Iu, input_buffer %p, output_size %Iu, "
827 "output_buffer %p, output_size_returned %p, irp %p, stub.\n",
828 client
, control_code
, input_size
, input_buffer
, output_size
, output_buffer
,
829 output_size_returned
, irp
);
831 return STATUS_NOT_IMPLEMENTED
;
834 struct wsk_get_address_info_context
836 UNICODE_STRING
*node_name
;
837 UNICODE_STRING
*service_name
;
841 ADDRINFOEXW
**result
;
845 static void WINAPI
get_address_info_callback(TP_CALLBACK_INSTANCE
*instance
, void *context_
)
847 struct wsk_get_address_info_context
*context
= context_
;
850 TRACE("instance %p, context %p.\n", instance
, context
);
852 ret
= GetAddrInfoExW( context
->node_name
? context
->node_name
->Buffer
: NULL
,
853 context
->service_name
? context
->service_name
->Buffer
: NULL
, context
->namespace,
854 context
->provider
, context
->hints
, context
->result
, NULL
, NULL
, NULL
, NULL
);
856 context
->irp
->IoStatus
.Information
= 0;
857 dispatch_irp(context
->irp
, sock_error_to_ntstatus(ret
));
861 static NTSTATUS WINAPI
wsk_get_address_info(WSK_CLIENT
*client
, UNICODE_STRING
*node_name
,
862 UNICODE_STRING
*service_name
, ULONG name_space
, GUID
*provider
, ADDRINFOEXW
*hints
,
863 ADDRINFOEXW
**result
, PEPROCESS owning_process
, PETHREAD owning_thread
, IRP
*irp
)
865 struct wsk_get_address_info_context
*context
;
868 TRACE("client %p, node_name %p, service_name %p, name_space %#lx, provider %p, hints %p, "
869 "result %p, owning_process %p, owning_thread %p, irp %p.\n",
870 client
, node_name
, service_name
, name_space
, provider
, hints
, result
,
871 owning_process
, owning_thread
, irp
);
874 return STATUS_INVALID_PARAMETER
;
876 if (!(context
= heap_alloc(sizeof(*context
))))
879 status
= STATUS_NO_MEMORY
;
880 dispatch_irp(irp
, status
);
884 context
->node_name
= node_name
;
885 context
->service_name
= service_name
;
886 context
->namespace = name_space
;
887 context
->provider
= provider
;
888 context
->hints
= hints
;
889 context
->result
= result
;
892 if (!TrySubmitThreadpoolCallback(get_address_info_callback
, context
, NULL
))
894 ERR("Could not submit thread pool callback.\n");
895 status
= STATUS_UNSUCCESSFUL
;
896 dispatch_irp(irp
, status
);
900 TRACE("Submitted threadpool callback, context %p.\n", context
);
901 return STATUS_PENDING
;
904 static void WINAPI
wsk_free_address_info(WSK_CLIENT
*client
, ADDRINFOEXW
*addr_info
)
906 TRACE("client %p, addr_info %p.\n", client
, addr_info
);
908 FreeAddrInfoExW(addr_info
);
911 static NTSTATUS WINAPI
wsk_get_name_info(WSK_CLIENT
*client
, SOCKADDR
*sock_addr
, ULONG sock_addr_length
,
912 UNICODE_STRING
*node_name
, UNICODE_STRING
*service_name
, ULONG flags
, PEPROCESS owning_process
,
913 PETHREAD owning_thread
, IRP
*irp
)
915 FIXME("client %p, sock_addr %p, sock_addr_length %lu, node_name %p, service_name %p, "
916 "flags %#lx, owning_process %p, owning_thread %p, irp %p stub.\n",
917 client
, sock_addr
, sock_addr_length
, node_name
, service_name
, flags
,
918 owning_process
, owning_thread
, irp
);
920 return STATUS_NOT_IMPLEMENTED
;
923 static const WSK_PROVIDER_DISPATCH wsk_dispatch
=
925 MAKE_WSK_VERSION(1, 0), 0,
929 wsk_get_address_info
,
930 wsk_free_address_info
,
934 NTSTATUS WINAPI
WskCaptureProviderNPI(WSK_REGISTRATION
*wsk_registration
, ULONG wait_timeout
,
935 WSK_PROVIDER_NPI
*wsk_provider_npi
)
937 WSK_CLIENT
*client
= wsk_registration
->ReservedRegistrationContext
;
939 TRACE("wsk_registration %p, wait_timeout %lu, wsk_provider_npi %p.\n",
940 wsk_registration
, wait_timeout
, wsk_provider_npi
);
942 wsk_provider_npi
->Client
= client
;
943 wsk_provider_npi
->Dispatch
= &wsk_dispatch
;
944 return STATUS_SUCCESS
;
947 void WINAPI
WskReleaseProviderNPI(WSK_REGISTRATION
*wsk_registration
)
949 TRACE("wsk_registration %p.\n", wsk_registration
);
953 NTSTATUS WINAPI
WskRegister(WSK_CLIENT_NPI
*wsk_client_npi
, WSK_REGISTRATION
*wsk_registration
)
955 static const WORD version
= MAKEWORD( 2, 2 );
960 TRACE("wsk_client_npi %p, wsk_registration %p.\n", wsk_client_npi
, wsk_registration
);
962 if (!(client
= heap_alloc(sizeof(*client
))))
965 return STATUS_NO_MEMORY
;
968 client
->registration
= wsk_registration
;
969 client
->client_npi
= wsk_client_npi
;
970 wsk_registration
->ReservedRegistrationContext
= client
;
972 if (WSAStartup(version
, &data
))
973 return STATUS_INTERNAL_ERROR
;
975 return STATUS_SUCCESS
;
978 void WINAPI
WskDeregister(WSK_REGISTRATION
*wsk_registration
)
980 TRACE("wsk_registration %p.\n", wsk_registration
);
982 heap_free(wsk_registration
->ReservedRegistrationContext
);
985 static void WINAPI
driver_unload(DRIVER_OBJECT
*driver
)
987 TRACE("driver %p.\n", driver
);
990 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
992 TRACE("driver %p, path %s.\n", driver
, debugstr_w(path
->Buffer
));
994 driver
->DriverUnload
= driver_unload
;
995 return STATUS_SUCCESS
;