amstream: Implement AMAudioStream::NewSegment.
[wine/zf.git] / dlls / netio.sys / netio.c
blobc9203f37adab29b8839cc9e337d9e666a11e986e
1 /*
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
21 #include <stdarg.h>
23 #define NONAMELESSUNION
24 #define NONAMELESSSTRUCT
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winioctl.h"
30 #include "winternl.h"
31 #include "ddk/wdm.h"
32 #include "ddk/wsk.h"
33 #include "wine/debug.h"
34 #include "winsock2.h"
35 #include "ws2tcpip.h"
37 #include "wine/heap.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(netio);
41 struct _WSK_CLIENT
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;
51 void *client_context;
52 char addr_buffer[2 * (sizeof(SOCKADDR) + 16)];
53 SOCKET acceptor;
56 #define MAX_PENDING_IO 10
58 struct wsk_pending_io
60 OVERLAPPED ovr;
61 TP_WAIT *tp_wait;
62 IRP *irp;
65 struct wsk_socket_internal
67 WSK_SOCKET wsk_socket;
68 SOCKET s;
69 const void *client_dispatch;
70 void *client_context;
71 ULONG flags;
72 ADDRESS_FAMILY address_family;
73 USHORT socket_type;
74 ULONG protocol;
76 CRITICAL_SECTION cs_socket;
78 struct wsk_pending_io pending_io[MAX_PENDING_IO];
80 union
82 struct listen_socket_callback_context listen_socket_callback_context;
84 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)
97 switch (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;
129 default:
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;
162 unsigned int i;
164 for (i = 0; i < ARRAY_SIZE(socket->pending_io); ++i)
165 if (!io[i].irp)
166 break;
168 if (i == ARRAY_SIZE(socket->pending_io))
170 FIXME("Pending io requests count exceeds limit.\n");
171 return NULL;
174 io[i].irp = irp;
176 if (io[i].tp_wait)
177 return &io[i];
179 io[i].ovr.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
180 io[i].tp_wait = CreateThreadpoolWait(socket_async_callback, socket, NULL);
182 return &io[i];
185 static struct wsk_pending_io *find_pending_io(struct wsk_socket_internal *socket, TP_WAIT *tp_wait)
187 unsigned int i;
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);
196 return NULL;
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);
205 io->irp = NULL;
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);
223 NTSTATUS status;
224 unsigned int i;
226 TRACE("socket %p, irp %p.\n", socket, irp);
228 lock_socket(s);
230 for (i = 0; i < ARRAY_SIZE(s->pending_io); ++i)
232 struct wsk_pending_io *io = &s->pending_io[i];
234 if (io->tp_wait)
236 CancelIoEx((HANDLE)s->s, &io->ovr);
237 SetThreadpoolWait(io->tp_wait, NULL, NULL);
238 unlock_socket(s);
239 WaitForThreadpoolWaitCallbacks(io->tp_wait, FALSE);
240 lock_socket(s);
241 CloseThreadpoolWait(io->tp_wait);
242 CloseHandle(io->ovr.hEvent);
245 if (io->irp)
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;
254 unlock_socket(s);
255 DeleteCriticalSection(&s->cs_socket);
256 heap_free(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);
267 NTSTATUS status;
269 TRACE("socket %p, local_address %p, flags %#x, irp %p.\n",
270 socket, local_address, flags, irp);
272 if (!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());
279 else
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))))
296 ERR("No memory.\n");
297 dispatch_pending_io(io, STATUS_NO_MEMORY, 0);
299 else
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;
323 DWORD size;
325 TRACE("instance %p, socket %p, wait %p, wait_result %#x.\n", instance, socket, wait, wait_result);
327 lock_socket(socket);
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);
335 else
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;
348 DWORD size;
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());
354 return FALSE;
356 return TRUE;
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;
367 SOCKET acceptor;
368 DWORD size;
369 int error;
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);
376 if (!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;
385 lock_socket(s);
386 if (!(io = allocate_pending_io(s, accept_callback, irp)))
388 irp->IoStatus.Information = 0;
389 dispatch_irp(irp, STATUS_UNSUCCESSFUL);
390 unlock_socket(s);
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))
396 == INVALID_SOCKET)
398 dispatch_pending_io(io, sock_error_to_ntstatus(WSAGetLastError()), 0);
399 unlock_socket(s);
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);
417 else
419 closesocket(acceptor);
420 context->acceptor = 0;
421 dispatch_pending_io(io, sock_error_to_ntstatus(error), 0);
423 unlock_socket(s);
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 =
447 wsk_control_socket,
448 wsk_close_socket,
450 wsk_bind,
451 wsk_accept,
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;
475 DWORD length, flags;
477 TRACE("instance %p, socket %p, wait %p, wait_result %#x.\n", instance, socket, wait, wait_result);
479 lock_socket(socket);
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);
484 else
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;
494 DWORD wsa_flags;
495 WSABUF wsa_buf;
496 DWORD length;
497 int error;
499 TRACE("socket %p, buffer %p, flags %#x, irp %p, is_send %#x.\n",
500 socket, wsk_buf, flags, irp, is_send);
502 if (!irp)
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;
516 if (flags)
517 FIXME("flags %#x not implemented.\n", flags);
519 lock_socket(s);
520 if (!(io = allocate_pending_io(s, send_receive_callback, irp)))
522 irp->IoStatus.Information = 0;
523 dispatch_irp(irp, STATUS_UNSUCCESSFUL);
524 unlock_socket(s);
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;
532 wsa_flags = 0;
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);
543 else
545 dispatch_pending_io(io, sock_error_to_ntstatus(error), 0);
547 unlock_socket(s);
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 =
606 wsk_control_socket,
607 wsk_close_socket,
609 wsk_bind,
610 wsk_connect,
611 wsk_get_local_address,
612 wsk_get_remote_address,
613 wsk_send,
614 wsk_receive,
615 wsk_disconnect,
616 wsk_release,
617 wsk_connext_ex,
618 wsk_send_ex,
619 wsk_receive_ex,
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;
627 NTSTATUS status;
628 SOCKET s;
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);
635 if (!irp)
636 return STATUS_INVALID_PARAMETER;
638 if (!client)
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());
646 goto done;
649 if (!(socket = heap_alloc_zero(sizeof(*socket))))
651 status = STATUS_NO_MEMORY;
652 closesocket(s);
653 goto done;
656 socket->s = s;
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;
664 switch (flags)
666 case WSK_FLAG_LISTEN_SOCKET:
667 socket->wsk_socket.Dispatch = &wsk_provider_listen_dispatch;
668 break;
670 case WSK_FLAG_CONNECTION_SOCKET:
671 socket->wsk_socket.Dispatch = &wsk_provider_connection_dispatch;
672 break;
674 default:
675 FIXME("Flags %#x not implemented.\n", flags);
676 closesocket(s);
677 heap_free(socket);
678 status = STATUS_NOT_IMPLEMENTED;
679 goto done;
682 socket_init(socket);
684 irp->IoStatus.Information = (ULONG_PTR)&socket->wsk_socket;
685 status = STATUS_SUCCESS;
687 done:
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,
708 IRP *irp
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;
723 ULONG namespace;
724 GUID *provider;
725 ADDRINFOEXW *hints;
726 ADDRINFOEXW **result;
727 IRP *irp;
730 static void WINAPI get_address_info_callback(TP_CALLBACK_INSTANCE *instance, void *context_)
732 struct wsk_get_address_info_context *context = context_;
733 INT ret;
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));
743 heap_free(context);
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;
751 NTSTATUS status;
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);
758 if (!irp)
759 return STATUS_INVALID_PARAMETER;
761 if (!(context = heap_alloc(sizeof(*context))))
763 ERR("No memory.\n");
764 status = STATUS_NO_MEMORY;
765 dispatch_irp(irp, status);
766 return 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;
775 context->irp = irp;
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);
782 heap_free(context);
783 return 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,
811 wsk_socket,
812 wsk_socket_connect,
813 wsk_control_client,
814 wsk_get_address_info,
815 wsk_free_address_info,
816 wsk_get_name_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 );
841 WSADATA data;
843 WSK_CLIENT *client;
845 TRACE("wsk_client_npi %p, wsk_registration %p.\n", wsk_client_npi, wsk_registration);
847 if (!(client = heap_alloc(sizeof(*client))))
849 ERR("No memory.\n");
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;