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
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
27 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
37 #include "wine/heap.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(netio
);
43 WSK_REGISTRATION
*registration
;
44 WSK_CLIENT_NPI
*client_npi
;
47 struct listen_socket_callback_context
49 SOCKADDR
*remote_address
;
50 const void *client_dispatch
;
52 char addr_buffer
[2 * (sizeof(SOCKADDR
) + 16)];
56 #define MAX_PENDING_IO 10
65 struct wsk_socket_internal
67 WSK_SOCKET wsk_socket
;
69 const void *client_dispatch
;
72 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 const WSK_PROVIDER_CONNECTION_DISPATCH wsk_provider_connection_dispatch
;
90 static inline struct wsk_socket_internal
*wsk_socket_internal_from_wsk_socket(WSK_SOCKET
*wsk_socket
)
92 return CONTAINING_RECORD(wsk_socket
, struct wsk_socket_internal
, wsk_socket
);
95 static NTSTATUS
sock_error_to_ntstatus(DWORD err
)
99 case 0: return STATUS_SUCCESS
;
100 case WSAEBADF
: return STATUS_INVALID_HANDLE
;
101 case WSAEACCES
: return STATUS_ACCESS_DENIED
;
102 case WSAEFAULT
: return STATUS_NO_MEMORY
;
103 case WSAEINVAL
: return STATUS_INVALID_PARAMETER
;
104 case WSAEMFILE
: return STATUS_TOO_MANY_OPENED_FILES
;
105 case WSAEWOULDBLOCK
: return STATUS_CANT_WAIT
;
106 case WSAEINPROGRESS
: return STATUS_PENDING
;
107 case WSAEALREADY
: return STATUS_NETWORK_BUSY
;
108 case WSAENOTSOCK
: return STATUS_OBJECT_TYPE_MISMATCH
;
109 case WSAEDESTADDRREQ
: return STATUS_INVALID_PARAMETER
;
110 case WSAEMSGSIZE
: return STATUS_BUFFER_OVERFLOW
;
111 case WSAEPROTONOSUPPORT
:
112 case WSAESOCKTNOSUPPORT
:
113 case WSAEPFNOSUPPORT
:
114 case WSAEAFNOSUPPORT
:
115 case WSAEPROTOTYPE
: return STATUS_NOT_SUPPORTED
;
116 case WSAENOPROTOOPT
: return STATUS_INVALID_PARAMETER
;
117 case WSAEOPNOTSUPP
: return STATUS_NOT_IMPLEMENTED
;
118 case WSAEADDRINUSE
: return STATUS_ADDRESS_ALREADY_ASSOCIATED
;
119 case WSAEADDRNOTAVAIL
: return STATUS_INVALID_PARAMETER
;
120 case WSAECONNREFUSED
: return STATUS_CONNECTION_REFUSED
;
121 case WSAESHUTDOWN
: return STATUS_PIPE_DISCONNECTED
;
122 case WSAENOTCONN
: return STATUS_CONNECTION_DISCONNECTED
;
123 case WSAETIMEDOUT
: return STATUS_IO_TIMEOUT
;
124 case WSAENETUNREACH
: return STATUS_NETWORK_UNREACHABLE
;
125 case WSAENETDOWN
: return STATUS_NETWORK_BUSY
;
126 case WSAECONNRESET
: return STATUS_CONNECTION_RESET
;
127 case WSAECONNABORTED
: return STATUS_CONNECTION_ABORTED
;
128 case WSAHOST_NOT_FOUND
: return STATUS_NOT_FOUND
;
130 FIXME("Unmapped error %u.\n", err
);
131 return STATUS_UNSUCCESSFUL
;
135 static inline void lock_socket(struct wsk_socket_internal
*socket
)
137 EnterCriticalSection(&socket
->cs_socket
);
140 static inline void unlock_socket(struct wsk_socket_internal
*socket
)
142 LeaveCriticalSection(&socket
->cs_socket
);
145 static void socket_init(struct wsk_socket_internal
*socket
)
147 InitializeCriticalSection(&socket
->cs_socket
);
150 static void dispatch_irp(IRP
*irp
, NTSTATUS status
)
152 irp
->IoStatus
.u
.Status
= status
;
153 --irp
->CurrentLocation
;
154 --irp
->Tail
.Overlay
.s
.u2
.CurrentStackLocation
;
155 IoCompleteRequest(irp
, IO_NO_INCREMENT
);
158 static struct wsk_pending_io
*allocate_pending_io(struct wsk_socket_internal
*socket
,
159 PTP_WAIT_CALLBACK socket_async_callback
, IRP
*irp
)
161 struct wsk_pending_io
*io
= socket
->pending_io
;
164 for (i
= 0; i
< ARRAY_SIZE(socket
->pending_io
); ++i
)
168 if (i
== ARRAY_SIZE(socket
->pending_io
))
170 FIXME("Pending io requests count exceeds limit.\n");
179 io
[i
].ovr
.hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
180 io
[i
].tp_wait
= CreateThreadpoolWait(socket_async_callback
, socket
, NULL
);
185 static struct wsk_pending_io
*find_pending_io(struct wsk_socket_internal
*socket
, TP_WAIT
*tp_wait
)
189 for (i
= 0; i
< ARRAY_SIZE(socket
->pending_io
); ++i
)
191 if (socket
->pending_io
[i
].tp_wait
== tp_wait
)
192 return &socket
->pending_io
[i
];
195 FIXME("Pending io not found for tp_wait %p.\n", tp_wait
);
199 static void dispatch_pending_io(struct wsk_pending_io
*io
, NTSTATUS status
, ULONG_PTR information
)
201 TRACE("io %p, status %#x, information %#lx.\n", io
, status
, information
);
203 io
->irp
->IoStatus
.Information
= information
;
204 dispatch_irp(io
->irp
, status
);
208 static NTSTATUS WINAPI
wsk_control_socket(WSK_SOCKET
*socket
, WSK_CONTROL_SOCKET_TYPE request_type
,
209 ULONG control_code
, ULONG level
, SIZE_T input_size
, void *input_buffer
, SIZE_T output_size
,
210 void *output_buffer
, SIZE_T
*output_size_returned
, IRP
*irp
)
212 FIXME("socket %p, request_type %u, control_code %#x, level %u, input_size %lu, input_buffer %p, "
213 "output_size %lu, output_buffer %p, output_size_returned %p, irp %p stub.\n",
214 socket
, request_type
, control_code
, level
, input_size
, input_buffer
, output_size
,
215 output_buffer
, output_size_returned
, irp
);
217 return STATUS_NOT_IMPLEMENTED
;
220 static NTSTATUS WINAPI
wsk_close_socket(WSK_SOCKET
*socket
, IRP
*irp
)
222 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
226 TRACE("socket %p, irp %p.\n", socket
, irp
);
230 for (i
= 0; i
< ARRAY_SIZE(s
->pending_io
); ++i
)
232 struct wsk_pending_io
*io
= &s
->pending_io
[i
];
236 CancelIoEx((HANDLE
)s
->s
, &io
->ovr
);
237 SetThreadpoolWait(io
->tp_wait
, NULL
, NULL
);
239 WaitForThreadpoolWaitCallbacks(io
->tp_wait
, FALSE
);
241 CloseThreadpoolWait(io
->tp_wait
);
242 CloseHandle(io
->ovr
.hEvent
);
246 dispatch_pending_io(io
, STATUS_CANCELLED
, 0);
249 if (s
->flags
& WSK_FLAG_LISTEN_SOCKET
&& s
->callback_context
.listen_socket_callback_context
.acceptor
)
250 closesocket(s
->callback_context
.listen_socket_callback_context
.acceptor
);
252 status
= closesocket(s
->s
) ? sock_error_to_ntstatus(WSAGetLastError()) : STATUS_SUCCESS
;
255 DeleteCriticalSection(&s
->cs_socket
);
258 irp
->IoStatus
.Information
= 0;
259 dispatch_irp(irp
, status
);
261 return status
? status
: STATUS_PENDING
;
264 static NTSTATUS WINAPI
wsk_bind(WSK_SOCKET
*socket
, SOCKADDR
*local_address
, ULONG flags
, IRP
*irp
)
266 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
269 TRACE("socket %p, local_address %p, flags %#x, irp %p.\n",
270 socket
, local_address
, flags
, irp
);
273 return STATUS_INVALID_PARAMETER
;
275 if (bind(s
->s
, local_address
, sizeof(*local_address
)))
276 status
= sock_error_to_ntstatus(WSAGetLastError());
277 else if (s
->flags
& WSK_FLAG_LISTEN_SOCKET
&& listen(s
->s
, SOMAXCONN
))
278 status
= sock_error_to_ntstatus(WSAGetLastError());
280 status
= STATUS_SUCCESS
;
282 TRACE("status %#x.\n", status
);
283 irp
->IoStatus
.Information
= 0;
284 dispatch_irp(irp
, status
);
285 return STATUS_PENDING
;
288 static void create_accept_socket(struct wsk_socket_internal
*socket
, struct wsk_pending_io
*io
)
290 struct listen_socket_callback_context
*context
291 = &socket
->callback_context
.listen_socket_callback_context
;
292 struct wsk_socket_internal
*accept_socket
;
294 if (!(accept_socket
= heap_alloc_zero(sizeof(*accept_socket
))))
297 dispatch_pending_io(io
, STATUS_NO_MEMORY
, 0);
301 TRACE("accept_socket %p.\n", accept_socket
);
302 accept_socket
->wsk_socket
.Dispatch
= &wsk_provider_connection_dispatch
;
303 accept_socket
->s
= context
->acceptor
;
304 accept_socket
->client_dispatch
= context
->client_dispatch
;
305 accept_socket
->client_context
= context
->client_context
;
306 accept_socket
->socket_type
= socket
->socket_type
;
307 accept_socket
->address_family
= socket
->address_family
;
308 accept_socket
->protocol
= socket
->protocol
;
309 accept_socket
->flags
= WSK_FLAG_CONNECTION_SOCKET
;
310 socket_init(accept_socket
);
311 /* TODO: fill local and remote addresses. */
313 dispatch_pending_io(io
, STATUS_SUCCESS
, (ULONG_PTR
)&accept_socket
->wsk_socket
);
317 static void WINAPI
accept_callback(TP_CALLBACK_INSTANCE
*instance
, void *socket_
, TP_WAIT
*wait
,
318 TP_WAIT_RESULT wait_result
)
320 struct listen_socket_callback_context
*context
;
321 struct wsk_socket_internal
*socket
= socket_
;
322 struct wsk_pending_io
*io
;
325 TRACE("instance %p, socket %p, wait %p, wait_result %#x.\n", instance
, socket
, wait
, wait_result
);
328 context
= &socket
->callback_context
.listen_socket_callback_context
;
329 io
= find_pending_io(socket
, wait
);
331 if (GetOverlappedResult((HANDLE
)socket
->s
, &io
->ovr
, &size
, FALSE
))
333 create_accept_socket(socket
, io
);
337 closesocket(context
->acceptor
);
338 context
->acceptor
= 0;
339 dispatch_pending_io(io
, io
->ovr
.Internal
, 0);
341 unlock_socket(socket
);
344 static BOOL WINAPI
init_accept_functions(INIT_ONCE
*once
, void *param
, void **context
)
346 GUID acceptex_guid
= WSAID_ACCEPTEX
;
347 SOCKET s
= (SOCKET
)param
;
350 if (WSAIoctl(s
, SIO_GET_EXTENSION_FUNCTION_POINTER
, &acceptex_guid
, sizeof(acceptex_guid
),
351 &pAcceptEx
, sizeof(pAcceptEx
), &size
, NULL
, NULL
))
353 ERR("Could not get AcceptEx address, error %u.\n", WSAGetLastError());
359 static NTSTATUS WINAPI
wsk_accept(WSK_SOCKET
*listen_socket
, ULONG flags
, void *accept_socket_context
,
360 const WSK_CLIENT_CONNECTION_DISPATCH
*accept_socket_dispatch
, SOCKADDR
*local_address
,
361 SOCKADDR
*remote_address
, IRP
*irp
)
363 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(listen_socket
);
364 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
365 struct listen_socket_callback_context
*context
;
366 struct wsk_pending_io
*io
;
371 TRACE("listen_socket %p, flags %#x, accept_socket_context %p, accept_socket_dispatch %p, "
372 "local_address %p, remote_address %p, irp %p.\n",
373 listen_socket
, flags
, accept_socket_context
, accept_socket_dispatch
, local_address
,
374 remote_address
, irp
);
377 return STATUS_INVALID_PARAMETER
;
379 if (!InitOnceExecuteOnce(&init_once
, init_accept_functions
, (void *)s
->s
, NULL
))
381 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
382 return STATUS_PENDING
;
386 if (!(io
= allocate_pending_io(s
, accept_callback
, irp
)))
388 irp
->IoStatus
.Information
= 0;
389 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
391 return STATUS_PENDING
;
394 context
= &s
->callback_context
.listen_socket_callback_context
;
395 if ((acceptor
= WSASocketW(s
->address_family
, s
->socket_type
, s
->protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
))
398 dispatch_pending_io(io
, sock_error_to_ntstatus(WSAGetLastError()), 0);
400 return STATUS_PENDING
;
403 context
->remote_address
= remote_address
;
404 context
->client_dispatch
= accept_socket_dispatch
;
405 context
->client_context
= accept_socket_context
;
406 context
->acceptor
= acceptor
;
408 if (pAcceptEx(s
->s
, acceptor
, context
->addr_buffer
, 0,
409 sizeof(SOCKADDR
) + 16, sizeof(SOCKADDR
) + 16, &size
, &io
->ovr
))
411 create_accept_socket(s
, io
);
413 else if ((error
= WSAGetLastError()) == ERROR_IO_PENDING
)
415 SetThreadpoolWait(io
->tp_wait
, io
->ovr
.hEvent
, NULL
);
419 closesocket(acceptor
);
420 context
->acceptor
= 0;
421 dispatch_pending_io(io
, sock_error_to_ntstatus(error
), 0);
425 return STATUS_PENDING
;
428 static NTSTATUS WINAPI
wsk_inspect_complete(WSK_SOCKET
*listen_socket
, WSK_INSPECT_ID
*inspect_id
,
429 WSK_INSPECT_ACTION action
, IRP
*irp
)
431 FIXME("listen_socket %p, inspect_id %p, action %u, irp %p stub.\n",
432 listen_socket
, inspect_id
, action
, irp
);
434 return STATUS_NOT_IMPLEMENTED
;
437 static NTSTATUS WINAPI
wsk_get_local_address(WSK_SOCKET
*socket
, SOCKADDR
*local_address
, IRP
*irp
)
439 FIXME("socket %p, local_address %p, irp %p stub.\n", socket
, local_address
, irp
);
441 return STATUS_NOT_IMPLEMENTED
;
444 static const WSK_PROVIDER_LISTEN_DISPATCH wsk_provider_listen_dispatch
=
452 wsk_inspect_complete
,
453 wsk_get_local_address
,
456 static NTSTATUS WINAPI
wsk_connect(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, ULONG flags
, IRP
*irp
)
458 FIXME("socket %p, remote_address %p, flags %#x, irp %p stub.\n", socket
, remote_address
, flags
, irp
);
460 return STATUS_NOT_IMPLEMENTED
;
463 static NTSTATUS WINAPI
wsk_get_remote_address(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, IRP
*irp
)
465 FIXME("socket %p, remote_address %p, irp %p stub.\n", socket
, remote_address
, irp
);
467 return STATUS_NOT_IMPLEMENTED
;
470 static void WINAPI
send_receive_callback(TP_CALLBACK_INSTANCE
*instance
, void *socket_
, TP_WAIT
*wait
,
471 TP_WAIT_RESULT wait_result
)
473 struct wsk_socket_internal
*socket
= socket_
;
474 struct wsk_pending_io
*io
;
477 TRACE("instance %p, socket %p, wait %p, wait_result %#x.\n", instance
, socket
, wait
, wait_result
);
480 io
= find_pending_io(socket
, wait
);
482 if (WSAGetOverlappedResult(socket
->s
, &io
->ovr
, &length
, FALSE
, &flags
))
483 dispatch_pending_io(io
, STATUS_SUCCESS
, length
);
485 dispatch_pending_io(io
, io
->ovr
.Internal
, 0);
487 unlock_socket(socket
);
490 static NTSTATUS WINAPI
do_send_receive(WSK_SOCKET
*socket
, WSK_BUF
*wsk_buf
, ULONG flags
, IRP
*irp
, BOOL is_send
)
492 struct wsk_socket_internal
*s
= wsk_socket_internal_from_wsk_socket(socket
);
493 struct wsk_pending_io
*io
;
499 TRACE("socket %p, buffer %p, flags %#x, irp %p, is_send %#x.\n",
500 socket
, wsk_buf
, flags
, irp
, is_send
);
503 return STATUS_INVALID_PARAMETER
;
505 if (!wsk_buf
->Mdl
&& wsk_buf
->Length
)
506 return STATUS_INVALID_PARAMETER
;
508 if (wsk_buf
->Mdl
&& wsk_buf
->Mdl
->Next
)
510 FIXME("Chained MDLs are not supported.\n");
511 irp
->IoStatus
.Information
= 0;
512 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
513 return STATUS_PENDING
;
517 FIXME("flags %#x not implemented.\n", flags
);
520 if (!(io
= allocate_pending_io(s
, send_receive_callback
, irp
)))
522 irp
->IoStatus
.Information
= 0;
523 dispatch_irp(irp
, STATUS_UNSUCCESSFUL
);
525 return STATUS_PENDING
;
528 wsa_buf
.len
= wsk_buf
->Length
;
529 wsa_buf
.buf
= wsk_buf
->Mdl
? (CHAR
*)wsk_buf
->Mdl
->StartVa
530 + wsk_buf
->Mdl
->ByteOffset
+ wsk_buf
->Offset
: NULL
;
534 if (!(is_send
? WSASend(s
->s
, &wsa_buf
, 1, &length
, wsa_flags
, &io
->ovr
, NULL
)
535 : WSARecv(s
->s
, &wsa_buf
, 1, &length
, &wsa_flags
, &io
->ovr
, NULL
)))
537 dispatch_pending_io(io
, STATUS_SUCCESS
, length
);
539 else if ((error
= WSAGetLastError()) == WSA_IO_PENDING
)
541 SetThreadpoolWait(io
->tp_wait
, io
->ovr
.hEvent
, NULL
);
545 dispatch_pending_io(io
, sock_error_to_ntstatus(error
), 0);
549 return STATUS_PENDING
;
552 static NTSTATUS WINAPI
wsk_send(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
554 TRACE("socket %p, buffer %p, flags %#x, irp %p.\n", socket
, buffer
, flags
, irp
);
556 return do_send_receive(socket
, buffer
, flags
, irp
, TRUE
);
559 static NTSTATUS WINAPI
wsk_receive(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
561 TRACE("socket %p, buffer %p, flags %#x, irp %p.\n", socket
, buffer
, flags
, irp
);
563 return do_send_receive(socket
, buffer
, flags
, irp
, FALSE
);
566 static NTSTATUS WINAPI
wsk_disconnect(WSK_SOCKET
*socket
, WSK_BUF
*buffer
, ULONG flags
, IRP
*irp
)
568 FIXME("socket %p, buffer %p, flags %#x, irp %p stub.\n", socket
, buffer
, flags
, irp
);
570 return STATUS_NOT_IMPLEMENTED
;
573 static NTSTATUS WINAPI
wsk_release(WSK_SOCKET
*socket
, WSK_DATA_INDICATION
*data_indication
)
575 FIXME("socket %p, data_indication %p stub.\n", socket
, data_indication
);
577 return STATUS_NOT_IMPLEMENTED
;
580 static NTSTATUS WINAPI
wsk_connext_ex(WSK_SOCKET
*socket
, SOCKADDR
*remote_address
, WSK_BUF
*buffer
,
581 ULONG flags
, IRP
*irp
)
583 FIXME("socket %p, remote_address %p, buffer %p, flags %#x, irp %p stub.\n",
584 socket
, remote_address
, buffer
, flags
, irp
);
586 return STATUS_NOT_IMPLEMENTED
;
589 static NTSTATUS WINAPI
wsk_send_ex(void)
591 FIXME("stub (no prototype, will crash).\n");
593 return STATUS_NOT_IMPLEMENTED
;
596 static NTSTATUS WINAPI
wsk_receive_ex(void)
598 FIXME("stub (no prototype, will crash).\n");
600 return STATUS_NOT_IMPLEMENTED
;
603 static const WSK_PROVIDER_CONNECTION_DISPATCH wsk_provider_connection_dispatch
=
611 wsk_get_local_address
,
612 wsk_get_remote_address
,
622 static NTSTATUS WINAPI
wsk_socket(WSK_CLIENT
*client
, ADDRESS_FAMILY address_family
, USHORT socket_type
,
623 ULONG protocol
, ULONG flags
, void *socket_context
, const void *dispatch
, PEPROCESS owning_process
,
624 PETHREAD owning_thread
, SECURITY_DESCRIPTOR
*security_descriptor
, IRP
*irp
)
626 struct wsk_socket_internal
*socket
;
630 TRACE("client %p, address_family %#x, socket_type %#x, protocol %#x, flags %#x, socket_context %p, dispatch %p, "
631 "owning_process %p, owning_thread %p, security_descriptor %p, irp %p.\n",
632 client
, address_family
, socket_type
, protocol
, flags
, socket_context
, dispatch
, owning_process
,
633 owning_thread
, security_descriptor
, irp
);
636 return STATUS_INVALID_PARAMETER
;
639 return STATUS_INVALID_HANDLE
;
641 irp
->IoStatus
.Information
= 0;
643 if ((s
= WSASocketW(address_family
, socket_type
, protocol
, NULL
, 0, WSA_FLAG_OVERLAPPED
)) == INVALID_SOCKET
)
645 status
= sock_error_to_ntstatus(WSAGetLastError());
649 if (!(socket
= heap_alloc_zero(sizeof(*socket
))))
651 status
= STATUS_NO_MEMORY
;
657 socket
->client_dispatch
= dispatch
;
658 socket
->client_context
= socket_context
;
659 socket
->socket_type
= socket_type
;
660 socket
->flags
= flags
;
661 socket
->address_family
= address_family
;
662 socket
->protocol
= protocol
;
666 case WSK_FLAG_LISTEN_SOCKET
:
667 socket
->wsk_socket
.Dispatch
= &wsk_provider_listen_dispatch
;
670 case WSK_FLAG_CONNECTION_SOCKET
:
671 socket
->wsk_socket
.Dispatch
= &wsk_provider_connection_dispatch
;
675 FIXME("Flags %#x not implemented.\n", flags
);
678 status
= STATUS_NOT_IMPLEMENTED
;
684 irp
->IoStatus
.Information
= (ULONG_PTR
)&socket
->wsk_socket
;
685 status
= STATUS_SUCCESS
;
688 dispatch_irp(irp
, status
);
689 return status
? status
: STATUS_PENDING
;
692 static NTSTATUS WINAPI
wsk_socket_connect(WSK_CLIENT
*client
, USHORT socket_type
, ULONG protocol
,
693 SOCKADDR
*local_address
, SOCKADDR
*remote_address
, ULONG flags
, void *socket_context
,
694 const WSK_CLIENT_CONNECTION_DISPATCH
*dispatch
, PEPROCESS owning_process
, PETHREAD owning_thread
,
695 SECURITY_DESCRIPTOR
*security_descriptor
, IRP
*irp
)
697 FIXME("client %p, socket_type %#x, protocol %#x, local_address %p, remote_address %p, "
698 "flags %#x, socket_context %p, dispatch %p, owning_process %p, owning_thread %p, "
699 "security_descriptor %p, irp %p stub.\n",
700 client
, socket_type
, protocol
, local_address
, remote_address
, flags
, socket_context
,
701 dispatch
, owning_process
, owning_thread
, security_descriptor
, irp
);
703 return STATUS_NOT_IMPLEMENTED
;
706 static NTSTATUS WINAPI
wsk_control_client(WSK_CLIENT
*client
, ULONG control_code
, SIZE_T input_size
,
707 void *input_buffer
, SIZE_T output_size
, void *output_buffer
, SIZE_T
*output_size_returned
,
711 FIXME("client %p, control_code %#x, input_size %lu, input_buffer %p, output_size %lu, "
712 "output_buffer %p, output_size_returned %p, irp %p, stub.\n",
713 client
, control_code
, input_size
, input_buffer
, output_size
, output_buffer
,
714 output_size_returned
, irp
);
716 return STATUS_NOT_IMPLEMENTED
;
719 struct wsk_get_address_info_context
721 UNICODE_STRING
*node_name
;
722 UNICODE_STRING
*service_name
;
726 ADDRINFOEXW
**result
;
730 static void WINAPI
get_address_info_callback(TP_CALLBACK_INSTANCE
*instance
, void *context_
)
732 struct wsk_get_address_info_context
*context
= context_
;
735 TRACE("instance %p, context %p.\n", instance
, context
);
737 ret
= GetAddrInfoExW( context
->node_name
? context
->node_name
->Buffer
: NULL
,
738 context
->service_name
? context
->service_name
->Buffer
: NULL
, context
->namespace,
739 context
->provider
, context
->hints
, context
->result
, NULL
, NULL
, NULL
, NULL
);
741 context
->irp
->IoStatus
.Information
= 0;
742 dispatch_irp(context
->irp
, sock_error_to_ntstatus(ret
));
746 static NTSTATUS WINAPI
wsk_get_address_info(WSK_CLIENT
*client
, UNICODE_STRING
*node_name
,
747 UNICODE_STRING
*service_name
, ULONG name_space
, GUID
*provider
, ADDRINFOEXW
*hints
,
748 ADDRINFOEXW
**result
, PEPROCESS owning_process
, PETHREAD owning_thread
, IRP
*irp
)
750 struct wsk_get_address_info_context
*context
;
753 TRACE("client %p, node_name %p, service_name %p, name_space %#x, provider %p, hints %p, "
754 "result %p, owning_process %p, owning_thread %p, irp %p.\n",
755 client
, node_name
, service_name
, name_space
, provider
, hints
, result
,
756 owning_process
, owning_thread
, irp
);
759 return STATUS_INVALID_PARAMETER
;
761 if (!(context
= heap_alloc(sizeof(*context
))))
764 status
= STATUS_NO_MEMORY
;
765 dispatch_irp(irp
, status
);
769 context
->node_name
= node_name
;
770 context
->service_name
= service_name
;
771 context
->namespace = name_space
;
772 context
->provider
= provider
;
773 context
->hints
= hints
;
774 context
->result
= result
;
777 if (!TrySubmitThreadpoolCallback(get_address_info_callback
, context
, NULL
))
779 ERR("Could not submit thread pool callback.\n");
780 status
= STATUS_UNSUCCESSFUL
;
781 dispatch_irp(irp
, status
);
785 TRACE("Submitted threadpool callback, context %p.\n", context
);
786 return STATUS_PENDING
;
789 static void WINAPI
wsk_free_address_info(WSK_CLIENT
*client
, ADDRINFOEXW
*addr_info
)
791 TRACE("client %p, addr_info %p.\n", client
, addr_info
);
793 FreeAddrInfoExW(addr_info
);
796 static NTSTATUS WINAPI
wsk_get_name_info(WSK_CLIENT
*client
, SOCKADDR
*sock_addr
, ULONG sock_addr_length
,
797 UNICODE_STRING
*node_name
, UNICODE_STRING
*service_name
, ULONG flags
, PEPROCESS owning_process
,
798 PETHREAD owning_thread
, IRP
*irp
)
800 FIXME("client %p, sock_addr %p, sock_addr_length %u, node_name %p, service_name %p, "
801 "flags %#x, owning_process %p, owning_thread %p, irp %p stub.\n",
802 client
, sock_addr
, sock_addr_length
, node_name
, service_name
, flags
,
803 owning_process
, owning_thread
, irp
);
805 return STATUS_NOT_IMPLEMENTED
;
808 static const WSK_PROVIDER_DISPATCH wsk_dispatch
=
810 MAKE_WSK_VERSION(1, 0), 0,
814 wsk_get_address_info
,
815 wsk_free_address_info
,
819 NTSTATUS WINAPI
WskCaptureProviderNPI(WSK_REGISTRATION
*wsk_registration
, ULONG wait_timeout
,
820 WSK_PROVIDER_NPI
*wsk_provider_npi
)
822 WSK_CLIENT
*client
= wsk_registration
->ReservedRegistrationContext
;
824 TRACE("wsk_registration %p, wait_timeout %u, wsk_provider_npi %p.\n",
825 wsk_registration
, wait_timeout
, wsk_provider_npi
);
827 wsk_provider_npi
->Client
= client
;
828 wsk_provider_npi
->Dispatch
= &wsk_dispatch
;
829 return STATUS_SUCCESS
;
832 void WINAPI
WskReleaseProviderNPI(WSK_REGISTRATION
*wsk_registration
)
834 TRACE("wsk_registration %p.\n", wsk_registration
);
838 NTSTATUS WINAPI
WskRegister(WSK_CLIENT_NPI
*wsk_client_npi
, WSK_REGISTRATION
*wsk_registration
)
840 static const WORD version
= MAKEWORD( 2, 2 );
845 TRACE("wsk_client_npi %p, wsk_registration %p.\n", wsk_client_npi
, wsk_registration
);
847 if (!(client
= heap_alloc(sizeof(*client
))))
850 return STATUS_NO_MEMORY
;
853 client
->registration
= wsk_registration
;
854 client
->client_npi
= wsk_client_npi
;
855 wsk_registration
->ReservedRegistrationContext
= client
;
857 if (WSAStartup(version
, &data
))
858 return STATUS_INTERNAL_ERROR
;
860 return STATUS_SUCCESS
;
863 void WINAPI
WskDeregister(WSK_REGISTRATION
*wsk_registration
)
865 TRACE("wsk_registration %p.\n", wsk_registration
);
867 heap_free(wsk_registration
->ReservedRegistrationContext
);
870 static void WINAPI
driver_unload(DRIVER_OBJECT
*driver
)
872 TRACE("driver %p.\n", driver
);
875 NTSTATUS WINAPI
DriverEntry(DRIVER_OBJECT
*driver
, UNICODE_STRING
*path
)
877 TRACE("driver %p, path %s.\n", driver
, debugstr_w(path
->Buffer
));
879 driver
->DriverUnload
= driver_unload
;
880 return STATUS_SUCCESS
;