ReactOS 0.4.16-dev-1946-g52006dd
netio.c
Go to the documentation of this file.
1/*
2 * PROJECT: NetIO driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: NT6 compatible NETIO.SYS driver: A BSD sockets like kernel
5 * internal interface for networking (TCP/IP, UDP/IP).
6 * COPYRIGHT: Copyright 2023-2025 Johannes Khoshnazar-Thoma <johannes@johannesthoma.com>
7 */
8
9/*
10Copyright © 2025 Johannes Khoshnazar-Thoma <johannes@johannesthoma.com>
11
12Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17*/
18
19/*
20 * [NETIO] NETIO.SYS driver
21 *
22 * This files adds the NETIO.SYS driver to ReactOS. It is not
23 * feature complete (meaning some functionality is unimplemented)
24 * but does its job quite good for what it originally was written
25 * for (which is getting WinDRBD working on ReactOS/Windows 2003 SP2).
26 *
27 * The driver re-uses parts of the AFD.SYS driver, namely those
28 * functions that ease communitating with the transport device
29 * interface (TDI). Other than that, following features are implemented
30 * and should work:
31 *
32 * * TCP/IP networking: connect, listen, accept, read, write
33 * * UDP/IP networking: write
34 *
35 * So in a nutshell TCP/IP support is completed, UDP support is
36 * partially complete and ICMP support does not exist yet.
37 * In particular the listen/accept mechanism allows one to write
38 * kernel side TCP servers that one can connect to via the internet.
39 */
40
41#include <ntifs.h>
42#include <netiodef.h>
43#include <ws2def.h>
44#include <wsk.h>
45#include <ndis.h>
46
47/* If you want to see the DPRINT() output in your debugger,
48 * remove the following line (or comment it out):
49 * Note that DPRINT1() is always printed to the debugger. */
50#define NDEBUG
51#include <reactos/debug.h>
52
53#include <tdi.h>
54#include <tcpioctl.h>
55#include <tdikrnl.h>
56#include <tdiinfo.h>
57#include <tdi_proto.h>
58#include <tdiconn.h>
59
60#define TAG_NETIO 'OIEN'
61
62#ifndef TAG_AFD_TDI_CONNECTION_INFORMATION
63#define TAG_AFD_TDI_CONNECTION_INFORMATION 'cTfA'
64#endif
65
66/* AFD Share Flags */
67#define AFD_SHARE_UNIQUE 0x0L
68#define AFD_SHARE_REUSE 0x1L
69#define AFD_SHARE_WILDCARD 0x2L
70#define AFD_SHARE_EXCLUSIVE 0x3L
71
72/* Function trace */
73// #define FUNCTION_TRACE DPRINT1("%s() ...\n", __FUNCTION__)
74#define FUNCTION_TRACE do { } while (0)
75
77{
79
80 ADDRESS_FAMILY family; /* AF_INET or AF_INET6 */
81 USHORT type; /* SOCK_DGRAM, SOCK_STREAM, ... */
82 ULONG proto; /* IPPROTO_UDP, IPPROTO_TCP */
83 ULONG WskFlags; /* WSK_FLAG_LISTEN_SOCKET, ... */
84 PVOID user_context; /* parameter for callbacks, opaque */
85 UNICODE_STRING TdiName; /* \\Devices\\Tcp, \\Devices\\Udp */
86
90
91 struct sockaddr RemoteAddress; /* Remember latest remote connection */
94
95 /* Those exist for connection oriented (TCP/IP) sockets only */
96 PFILE_OBJECT ConnectionFile; /* Returned by TdiOpenConnectionEndpointFile() */
97 HANDLE ConnectionHandle; /* Returned by TdiOpenConnectionEndpointFile() */
99
100 /* Incoming connection callback function */
103
104 UINT Flags; /* SO_REUSEADDR, ... see ws2def.h */
105 LONG RefCount; /* See ReferenceSocket/DereferenceSocket */
106
107 PIRP ListenIrp; /* must be cancelled on close */
109 HANDLE ListenThreadHandle; /* needed to restart listening */
113
114 /* AcceptSocket's keep a reference on their listen sockets so
115 * that the Address file will be closed only if there are no
116 * open connections any more.
117 */
119
120 /* DereferenceSocket() only works at PASSIVE_LEVEL. If > PASSIVE_LEVEL,
121 * it will put the socket on this list and wake the putsockets
122 * thread.
123 */
127
128typedef struct _NETIO_CONTEXT
129{
135
136static void
138{
140
141 InterlockedIncrement(&Socket->RefCount);
142}
143
144static void
146
147/* This function can be called several times on the same socket.
148 In particular it will be called by WskClose and later by the
149 DereferenceSocket() of the socket.
150 */
151
152static
154{
156
158
159 if (Socket->ListenSocket != NULL)
160 {
161 DereferenceSocket(Socket->ListenSocket);
162 Socket->ListenSocket = NULL;
163 }
164 if (Socket->ListenThreadHandle != NULL)
165 {
166 Socket->ListenThreadShouldRun = FALSE;
167 KeSetEvent(&Socket->StartListenEvent, IO_NO_INCREMENT, FALSE);
169 if (!NT_SUCCESS(status))
170 {
171 DPRINT1("KeWaitForSingleObject failed with status 0x%08x!\n", status);
172 }
173 ObDereferenceObject(Socket->ListenThread);
174 Socket->ListenThread = NULL;
175 Socket->ListenThreadHandle = NULL;
176 }
177 if (Socket->ListenIrp != NULL)
178 {
179 Socket->ListenCancelled = TRUE;
180 IoCancelIrp(Socket->ListenIrp);
181 Socket->ListenIrp = NULL;
182 }
183 if (Socket->ConnectionFile != NULL)
184 {
185 if (Socket->ConnectionFileAssociated)
186 {
187 /* This fails with error STATUS_CONNECTION_ACTIVE on Windows 2003 */
188 status = TdiDisassociateAddressFile(Socket->ConnectionFile);
189 if (!NT_SUCCESS(status))
190 {
191 DPRINT1("Warning: TdiDisassociateAddressFile returned status %08x\n", status);
192 }
193 Socket->ConnectionFileAssociated = FALSE;
194 }
195 ObDereferenceObject(Socket->ConnectionFile);
196 Socket->ConnectionFile = NULL;
197 }
198 if (Socket->ConnectionHandle != NULL)
199 {
200 ZwClose(Socket->ConnectionHandle);
201 Socket->ConnectionHandle = NULL;
202 }
203}
204
205static void
207{
208 SocketShutdown(Socket);
209
210 /* Especially listen sockets must keep the LocalAddressFile
211 * open when being closed and there are still accepted sockets
212 * somewhere. Else the accepted socket I/O will fail with
213 * STATUS_INVALID_DEVICE_STATE. So do not close the
214 * address file in Shutdown only close it here when all AcceptSockets
215 * are gone (AcceptSockets hold a reference to the listen socket).
216 */
217
218 if (Socket->LocalAddressFile != NULL)
219 {
220 ObDereferenceObject(Socket->LocalAddressFile);
221 Socket->LocalAddressFile = NULL;
222 }
223 if (Socket->LocalAddressHandle != NULL)
224 {
225 ZwClose(Socket->LocalAddressHandle);
226 Socket->LocalAddressHandle = NULL;
227 }
229}
230
231static void
233{
234 if (InterlockedDecrement(&Socket->RefCount) == 0)
235 {
236 SocketDestroy(Socket);
237 }
238}
239
245
247{
249 PWSK_SOCKET_INTERNAL SocketToDereference;
251 ULONG NumSocketDereferences;
252
254
256 {
258 if (!NT_SUCCESS(status))
259 {
260 DPRINT1("KeWaitForSingleObject failed with status 0x%08x!\n", status);
261 }
262
264 while (SocketsToDereference != NULL)
265 {
266 SocketToDereference = SocketsToDereference;
267 SocketsToDereference = SocketToDereference->NextSocketToDereference;
268 NumSocketDereferences = SocketToDereference->NumSocketDereferences;
269
270 while (NumSocketDereferences > 0)
271 {
272 SocketToDereference->NumSocketDereferences--;
273 NumSocketDereferences = SocketToDereference->NumSocketDereferences;
274
276 DereferenceSocketSynchronous(SocketToDereference);
278 }
279 }
281 }
282
284}
285
287{
289
293
295 if (!NT_SUCCESS(status))
296 {
297 DPRINT1("Could not start put sockets thread, status is %x\n", status);
298 }
299 return status;
300}
301
303{
306
307 /* eventually it will terminate, no need to wait for that. */
308}
309
310static void
312{
314
316
317 /* We are doing calls like ZwClose, TdiDisassociateAddressFile, ...
318 which require IRQL to be PASSIVE_LEVEL. So if we get here
319 when IRQL is greater than PASSIVE_LEVEL, defer the DereferenceSocket()
320 to a separate thread. */
321
323 {
325 if (Socket->NumSocketDereferences == 0)
326 {
327 Socket->NextSocketToDereference = SocketsToDereference;
328 SocketsToDereference = Socket;
329 Socket->NumSocketDereferences = 1;
330 }
331 else
332 {
333 Socket->NumSocketDereferences++;
334 }
336
338
339 return;
340 }
342}
343
346{
348
349 return STATUS_SUCCESS;
350}
351
352static NTSTATUS WSKAPI
360 _In_opt_ const VOID * Dispatch,
365
366static NTSTATUS NTAPI
368{
369 PNETIO_CONTEXT Context = (PNETIO_CONTEXT)ContextParam;
370 PIRP UserIrp = Context->UserIrp;
371
373
374 if (Irp->IoStatus.Status != STATUS_CANCELLED)
375 {
376 UserIrp->IoStatus.Status = Irp->IoStatus.Status;
377 UserIrp->IoStatus.Information = Irp->IoStatus.Information;
378 }
379
380 if (Context->PeerAddrRet != NULL)
381 {
383 (PSOCKADDR)(&((PTRANSPORT_ADDRESS)Context->PeerAddrRet->RemoteAddress)->Address[0].AddressType);
384
385 memcpy(&Context->socket->RemoteAddress, RemoteAddress, sizeof(Context->socket->RemoteAddress));
386 }
387 if (Irp->IoStatus.Status != STATUS_CANCELLED)
388 {
390 }
391
392 DereferenceSocket(Context->socket);
393 if (Context->TargetConnectionInfo != NULL)
394 {
396 }
397 if (Context->PeerAddrRet != NULL)
398 {
400 }
402
403 return STATUS_SUCCESS;
404}
405
406typedef struct _LISTEN_CONTEXT
407{
412
413static NTSTATUS NTAPI
415{
417
419
421
423}
424
431{
432 PIRP NewSocketIrp;
433 KEVENT CompletionEvent;
435
437
438 NewSocketIrp = IoAllocateIrp(1, FALSE);
439 if (NewSocketIrp == NULL)
440 {
441 DPRINT1("Out of memory?\n");
443 }
444 KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
445 IoSetCompletionRoutine(NewSocketIrp, CompletionFireEvent, &CompletionEvent, TRUE, TRUE, TRUE);
446 NewSocketIrp->Tail.Overlay.Thread = PsGetCurrentThread();
447
449 NULL, NULL, NULL, NULL, NULL, NewSocketIrp);
450
451 if (Status == STATUS_PENDING)
452 {
454 Status = NewSocketIrp->IoStatus.Status;
455 }
456
457 if (NT_SUCCESS(Status))
458 {
459 *TheSocket = (PWSK_SOCKET_INTERNAL)NewSocketIrp->IoStatus.Information;
460 }
461
462 IoFreeIrp(NewSocketIrp);
463 return Status;
464}
465
466static void QueueListening(_In_ PWSK_SOCKET_INTERNAL ListenSocket)
467{
469
470 KeSetEvent(&ListenSocket->StartListenEvent, IO_NO_INCREMENT, FALSE);
471}
472
473static NTSTATUS NTAPI
475{
476 PLISTEN_CONTEXT ListenContext = (PLISTEN_CONTEXT)Context;
477 PWSK_SOCKET_INTERNAL ListenSocket = ListenContext->ListenSocket;
479 PWSK_CLIENT_LISTEN_DISPATCH ListenDispatch =
481
482 /* A PTRANSPORT_ADDRESS address field has an additional
483 * AddressLength field so the struct sockaddr_in starts
484 * at the AddressType (the address family, 2 for AF_INET)
485 * field.
486 */
487
489 (PSOCKADDR)(&((PTRANSPORT_ADDRESS)ListenContext->ReturnConnectionInfo->RemoteAddress)->Address[0].AddressType);
493
495
496 if (ListenSocket->CallbackMask & WSK_EVENT_ACCEPT &&
497 ListenDispatch->WskAcceptEvent != NULL &&
498 ListenSocket->ListenIrp != NULL &&
499 !ListenSocket->ListenCancelled &&
500 Irp->IoStatus.Status != STATUS_CANCELLED)
501 {
502 ListenSocket->ListenIrp = NULL;
503
504 Status = ListenDispatch->WskAcceptEvent(ListenSocket->user_context,
505 0,
506 &ListenSocket->LocalAddress,
508 &AcceptSocket->Socket,
511
512 if (!NT_SUCCESS(Status))
513 {
514 DPRINT1("ListenDispatch->WskAcceptEvent returned non-successful status 0x%08x\n", Status);
515 }
516 else
517 {
518 memcpy(&AcceptSocket->RemoteAddress, RemoteAddress, sizeof(AcceptSocket->RemoteAddress));
519 }
520 }
521 else
522 {
523 DereferenceSocket(AcceptSocket); /* close the AcceptSocket */
524 }
525 ListenSocket->ListenIrp = NULL;
526
528 DereferenceSocket(ListenSocket);
529
532 ExFreePoolWithTag(ListenContext, TAG_NETIO);
533
534 /* And wait for the next incoming connection.
535 * This is done in a separate thread at IRQL = PASSIVE_LEVEL
536 */
537
538 QueueListening(ListenSocket);
539
540 return STATUS_SUCCESS;
541}
542
543static NTSTATUS
545{
546 PIRP tdiIrp;
550
552
553 if (ListenSocket->LocalAddressHandle == NULL)
554 {
555 DPRINT1("LocalAddressHandle is not set, need to bind your socket before listening\n");
557 }
558
559 status = CreateSocket(ListenSocket->family, ListenSocket->type, ListenSocket->proto, WSK_FLAG_CONNECTION_SOCKET, &AcceptSocket);
560 if (!NT_SUCCESS(status))
561 {
562 DPRINT1("Could not create AcceptSocket, status is 0x%08x\n", status);
563 return status;
564 }
565 AcceptSocket->ListenSocket = ListenSocket;
566 /* Dereferenced when the AcceptSocket is closed */
567 ReferenceSocket(AcceptSocket->ListenSocket);
568
571 if (lc == NULL)
572 {
573 goto err_out_free_accept_socket;
574 }
575 lc->ListenSocket = ListenSocket;
577
578 tdiIrp = NULL;
579
580 status = TdiAssociateAddressFile(ListenSocket->LocalAddressHandle, AcceptSocket->ConnectionFile);
581 if (!NT_SUCCESS(status))
582 {
583 goto err_out_free_lc;
584 }
585 AcceptSocket->ConnectionFileAssociated = TRUE;
586
589 if (lc->RequestConnectionInfo == NULL)
590 {
591 goto err_out_free_lc_and_disassociate;
592 }
594
597 if (lc->ReturnConnectionInfo == NULL)
598 {
599 goto err_out_free_lc_and_req_conn_info;
600 }
602
603 ReferenceSocket(ListenSocket);
605
606 ListenSocket->ListenCancelled = FALSE;
607 /* pass the ConnectionFile from accept socket, not from ListenSocket ... */
608 status = TdiListen(&tdiIrp, AcceptSocket->ConnectionFile, &lc->RequestConnectionInfo, &lc->ReturnConnectionInfo, ListenComplete, lc);
609
610 if (!NT_SUCCESS(status))
611 {
613 DereferenceSocket(ListenSocket);
615 goto err_out_free_lc_and_req_conn_info;
616 }
617 ListenSocket->ListenIrp = tdiIrp;
618
619 return STATUS_PENDING;
620
621err_out_free_lc_and_req_conn_info:
623
624err_out_free_lc_and_disassociate:
626 if (!NT_SUCCESS(status))
627 {
628 DPRINT1("Warning: TdiDisassociateAddressFile returned status %08x\n", status);
629 }
630 AcceptSocket->ConnectionFileAssociated = FALSE;
631
632err_out_free_lc:
634
635err_out_free_accept_socket:
637
638 return status;
639}
640
642{
645
647
648 while (ListenSocket->ListenThreadShouldRun)
649 {
651 if (!NT_SUCCESS(status))
652 {
653 DPRINT1("KeWaitForSingleObject failed with status 0x%08x!\n", status);
654 }
655 if (!ListenSocket->ListenThreadShouldRun)
656 {
657 break;
658 }
659 StartListening(ListenSocket);
660 }
662}
663
664static NTSTATUS WSKAPI
666 _In_ PWSK_SOCKET SocketParam,
670 _In_ SIZE_T InputSize,
672 _In_ SIZE_T OutputSize,
674 _Out_opt_ SIZE_T * OutputSizeReturned,
676{
677 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
679
681
682 if (Socket == NULL)
683 {
685 goto err_out;
686 }
688
689 switch (RequestType)
690 {
691 case WskSetOption:
692 switch (Level)
693 {
694 case SOL_SOCKET:
695 switch (ControlCode)
696 {
697 case SO_REUSEADDR: /* add more supported flags here */
698 if (InputBuffer == NULL)
699 {
700 DPRINT1("WskControlSocket: Need an InputBuffer for this operation\n");
702 break;
703 }
704 if (InputSize < sizeof(UINT))
705 {
706 DPRINT1("WskControlSocket: InputBuffer too small for this operation\n");
708 break;
709 }
711 if (enable != 0)
712 {
713 Socket->Flags |= ControlCode;
714 }
715 else
716 {
717 Socket->Flags &= ~ControlCode;
718 }
720 break;
721
722 /* Windows specific. This sets the mask for callback functions. */
724 if (InputBuffer == NULL)
725 {
726 DPRINT1("WskControlSocket: Need an InputBuffer for this operation\n");
728 break;
729 }
730 if (InputSize < sizeof(WSK_EVENT_CALLBACK_CONTROL))
731 {
732 DPRINT1("WskControlSocket: InputBuffer too small for this operation\n");
734 break;
735 }
737
738 if (((Socket->CallbackMask & WSK_EVENT_ACCEPT) == 0) &&
739 ((Control->EventMask & WSK_EVENT_ACCEPT) == WSK_EVENT_ACCEPT))
740 {
741 Socket->CallbackMask = Control->EventMask;
742 QueueListening(Socket);
743 }
744 else
745 {
746 Socket->CallbackMask = Control->EventMask;
747 }
748
750 break;
751
752 default:
753 DPRINT1("WskControlSocket: ControlCode %d Not implemented\n", ControlCode);
754 }
755 break;
756 default:
757 DPRINT1("WskControlSocket: Level %d Not implemented\n", Level);
758 }
759 break;
760
761 case WskGetOption:
762 case WskIoctl:
763 default:
764 DPRINT1("WskControlSocket: Option %d Not implemented\n", RequestType);
765 }
766
767err_out:
768 Irp->IoStatus.Status = status;
770
771 return STATUS_PENDING;
772}
773
774static NTSTATUS WSKAPI
776{
778 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
779
781
782 /* There might be a reference from (for example) a pending
783 * receive. Shutdown the socket here explicitly. We expect
784 * all pending I/O operations to be cancelled, then.
785 */
786
787 SocketShutdown(Socket);
788 DereferenceSocket(Socket);
789
790 Irp->IoStatus.Status = status;
792
793 return STATUS_PENDING;
794}
795
798{
800 ULONG Size;
801
803 FIELD_OFFSET(TA_ADDRESS, Address[sizeof(SocketAddress->sa_data)]);
804
806 if (ta == NULL)
807 {
808 DPRINT1("TdiTransportAddressFromSocketAddress: Out of memory\n");
809 return NULL;
810 }
811
812 ta->TAAddressCount = 1;
813 ta->Address[0].AddressLength = sizeof(SocketAddress->sa_data);
814 ta->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; /* AF_INET */
815
816 memcpy(&ta->Address[0].Address[0], &SocketAddress->sa_data, ta->Address[0].AddressLength);
817
818 return ta;
819}
820
823{
825 PTDI_CONNECTION_INFORMATION ConnectionInformation = NULL;
827
829 if (TargetAddress == NULL)
830 return NULL;
831
832 status = TdiBuildConnectionInfo(&ConnectionInformation, TargetAddress);
834
835 if (!NT_SUCCESS(status))
836 {
837 if (ConnectionInformation != NULL)
838 {
840 }
841 return NULL;
842 }
843 ConnectionInformation->OptionsLength = 0;
844 return ConnectionInformation;
845}
846
847static NTSTATUS WSKAPI
849{
851 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
852
854
857
858 if (ta == NULL)
859 {
861 goto err_out;
862 }
863 if (Socket->LocalAddressHandle != NULL)
864 {
866 goto err_out;
867 }
868
870 ta, AFD_SHARE_REUSE, &Socket->LocalAddressHandle, &Socket->LocalAddressFile);
871
873
874err_out:
875 Irp->IoStatus.Status = status;
877
878 return STATUS_PENDING;
879}
880
882{
886
887static NTSTATUS WSKAPI
889 _In_ PWSK_SOCKET SocketParam,
893 _In_ ULONG ControlInfoLength,
894 _In_reads_bytes_opt_(ControlInfoLength) PCMSGHDR ControlInfo,
896{
897 PIRP tdiIrp = NULL;
898 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
899 PTDI_CONNECTION_INFORMATION TargetConnectionInfo;
901 void *BufferData;
902 PNETIO_CONTEXT NetioContext;
903
905
907
909 NetioContext = ExAllocatePoolUninitialized(NonPagedPool, sizeof(*NetioContext), TAG_NETIO);
910 if (NetioContext == NULL)
911 {
912 goto err_out;
913 }
914 NetioContext->socket = Socket;
915 NetioContext->UserIrp = Irp;
916
918 if (TargetConnectionInfo == NULL)
919 {
920 goto err_out_free_nc;
921 }
922 NetioContext->TargetConnectionInfo = TargetConnectionInfo;
923 NetioContext->PeerAddrRet = NULL;
924
926 if (BufferData == NULL)
927 {
928 DPRINT1("Error mapping MDL\n");
929 goto err_out_free_nc_and_tci;
930 }
931
933 ReferenceSocket(Socket);
934
935 /* This will create a tdiIrp */
936 status = TdiSendDatagram(&tdiIrp, Socket->LocalAddressFile, ((char *)BufferData) + Buffer->Offset,
937 Buffer->Length, TargetConnectionInfo, NetioComplete, NetioContext);
938
939 /* If allocating tdiIrp fails we get here.
940 * Call the IoCompletion of the application's Irp so this Irp
941 * gets freed.
942 */
943 if (!NT_SUCCESS(status))
944 {
945 DereferenceSocket(Socket);
946 goto err_out_free_nc_and_tci; /* caller has to clean up mdl mapping */
947 }
948 return STATUS_PENDING;
949
950err_out_free_nc_and_tci:
952
953err_out_free_nc:
954 ExFreePoolWithTag(NetioContext, TAG_NETIO);
955
956err_out:
957 Irp->IoStatus.Status = status;
959
960 return status;
961}
962
963static NTSTATUS WSKAPI
965 _In_ PWSK_SOCKET SocketParam,
969 _Inout_ PULONG ControlLength,
970 _Out_writes_bytes_opt_(*ControlLength) PCMSGHDR ControlInfo,
971 _Out_opt_ PULONG ControlFlags, _Inout_ PIRP Irp)
972{
974
976 if (Irp != NULL)
977 {
978 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
980 }
982}
983
984static NTSTATUS WSKAPI
986{
988
990
992}
993
994static NTSTATUS WSKAPI
996{
998
1000
1002}
1003
1004static NTSTATUS WSKAPI
1006{
1008
1010 if (Irp != NULL)
1011 {
1012 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1014 }
1016}
1017
1018static NTSTATUS WSKAPI
1020{
1022
1023 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
1025
1027 if (Socket != NULL)
1028 {
1029 memcpy(RemoteAddress, &Socket->RemoteAddress, sizeof(*RemoteAddress));
1031 }
1032 Irp->IoStatus.Status = Status;
1034
1035 return STATUS_PENDING; /* Caller has to wait for his completion routine */
1036}
1037
1038static NTSTATUS WSKAPI
1052{
1054
1056 if (Irp != NULL)
1057 {
1058 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1060 }
1062}
1063
1064static NTSTATUS WSKAPI
1068 _In_ SIZE_T InputSize,
1070 _In_ SIZE_T OutputSize,
1072 _Out_opt_ SIZE_T * OutputSizeReturned, _Inout_opt_ PIRP Irp)
1073{
1075
1077 if (Irp != NULL)
1078 {
1079 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
1081 }
1083}
1084
1086 .WskControlSocket = WskControlSocket,
1087 .WskCloseSocket = WskCloseSocket,
1088 .WskBind = WskBind,
1089 .WskSendTo = WskSendTo,
1090 .WskReceiveFrom = WskReceiveFrom,
1091 .WskRelease = WskReleaseUdp,
1092 .WskGetLocalAddress = WskGetLocalAddress,
1093};
1094
1095/* Connection oriented routines (TCP/IP) */
1096
1097static NTSTATUS WSKAPI
1099{
1100 PTDI_CONNECTION_INFORMATION TargetConnectionInfo, PeerAddrRet;
1101 PIRP tdiIrp;
1102 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
1103 NTSTATUS status, status2;
1104 PNETIO_CONTEXT NetioContext;
1105
1107
1109
1111 if (Socket->LocalAddressHandle == NULL)
1112 {
1113 DPRINT1("LocalAddressHandle is not set, need to bind your socket before connecting\n");
1114 goto err_out;
1115 }
1116
1118 NetioContext = ExAllocatePoolUninitialized(NonPagedPool, sizeof(*NetioContext), TAG_NETIO);
1119 if (NetioContext == NULL)
1120 {
1121 goto err_out;
1122 }
1123 NetioContext->socket = Socket;
1124 NetioContext->UserIrp = Irp;
1125
1126 tdiIrp = NULL;
1127
1129 if (!NT_SUCCESS(status))
1130 {
1131 goto err_out_free_nc;
1132 }
1134
1135 TargetConnectionInfo = TdiConnectionInfoFromSocketAddress(RemoteAddress);
1136 if (TargetConnectionInfo == NULL)
1137 {
1138 goto err_out_free_nc_and_disassociate;
1139 }
1140 NetioContext->TargetConnectionInfo = TargetConnectionInfo;
1141
1142 PeerAddrRet = NULL;
1144 if (PeerAddrRet == NULL)
1145 {
1146 goto err_out_free_nc_and_tci;
1147 }
1148 PeerAddrRet->OptionsLength = 0;
1149 NetioContext->PeerAddrRet = PeerAddrRet;
1150
1152 ReferenceSocket(Socket);
1153
1154 status = TdiConnect(&tdiIrp, Socket->ConnectionFile, TargetConnectionInfo, PeerAddrRet, NetioComplete, NetioContext);
1155
1156 if (!NT_SUCCESS(status))
1157 {
1158 /* If allocating tdiIrp fails we get here.
1159 * Call the IoCompletion of the application's Irp so this Irp
1160 * gets freed.
1161 */
1162 ExFreePoolWithTag(PeerAddrRet, TAG_NETIO);
1163 DereferenceSocket(Socket);
1164 goto err_out_free_nc_and_tci;
1165 }
1166 return STATUS_PENDING;
1167
1168err_out_free_nc_and_tci:
1170
1171err_out_free_nc_and_disassociate:
1172 status2 = TdiDisassociateAddressFile(Socket->ConnectionFile);
1173 if (!NT_SUCCESS(status2))
1174 {
1175 DPRINT1("Warning: TdiDisassociateAddressFile returned status %08x\n", status);
1176 }
1178
1179err_out_free_nc:
1180 ExFreePoolWithTag(NetioContext, TAG_NETIO);
1181
1182err_out:
1183 Irp->IoStatus.Status = status;
1185
1186 return status;
1187}
1188
1189static NTSTATUS WSKAPI
1191 _In_ PWSK_SOCKET SocketParam,
1196{
1197 PIRP tdiIrp = NULL;
1198 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
1200 void *BufferData;
1201 PNETIO_CONTEXT NetioContext;
1202
1204
1207
1208 NetioContext = ExAllocatePoolUninitialized(NonPagedPool, sizeof(*NetioContext), TAG_NETIO);
1209 if (NetioContext == NULL)
1210 {
1211 goto err_out;
1212 }
1213 NetioContext->socket = Socket;
1214 NetioContext->UserIrp = Irp;
1215
1216 NetioContext->TargetConnectionInfo = NULL;
1217 NetioContext->PeerAddrRet = NULL;
1218
1220 if (BufferData == NULL)
1221 {
1222 DPRINT1("Error mapping MDL\n");
1223 goto err_out_free_nc;
1224 }
1225
1227 ReferenceSocket(Socket);
1228
1229 if (Direction == DIR_SEND)
1230 {
1231 /* This will create a tdiIrp */
1232 status = TdiSend(&tdiIrp, Socket->ConnectionFile, 0, ((char *)BufferData) + Buffer->Offset,
1233 Buffer->Length, NetioComplete, NetioContext);
1234 }
1235 else
1236 {
1237 status = TdiReceive(&tdiIrp, Socket->ConnectionFile, 0, ((char *)BufferData) + Buffer->Offset,
1238 Buffer->Length, NetioComplete, NetioContext);
1239 }
1240
1241 /* If allocating tdiIrp fails we get here.
1242 * Call the IoCompletion of the application's Irp so this Irp
1243 * gets freed.
1244 */
1245 if (!NT_SUCCESS(status))
1246 {
1247 goto err_out_free_nc; /* caller has to clean up mdl mapping */
1248 }
1249 return STATUS_PENDING;
1250
1251err_out_free_nc:
1252 ExFreePoolWithTag(NetioContext, TAG_NETIO);
1253
1254err_out:
1255 Irp->IoStatus.Status = status;
1257
1258 return status;
1259}
1260
1261static NTSTATUS WSKAPI
1263{
1265
1266 return WskStreamIo(SocketParam, Buffer, Flags, Irp, DIR_SEND);
1267}
1268
1269static NTSTATUS WSKAPI
1271{
1273
1274 return WskStreamIo(SocketParam, Buffer, Flags, Irp, DIR_RECEIVE);
1275}
1276
1277static NTSTATUS WSKAPI
1279{
1280 PWSK_SOCKET_INTERNAL Socket = CONTAINING_RECORD(SocketParam, WSK_SOCKET_INTERNAL, Socket);
1281
1283
1284 SocketShutdown(Socket);
1285
1287
1288 Irp->IoStatus.Status = STATUS_SUCCESS;
1290
1291 return STATUS_PENDING;
1292}
1293
1294
1296 .WskControlSocket = WskControlSocket,
1297 .WskCloseSocket = WskCloseSocket,
1298 .WskBind = WskBind,
1299 .WskConnect = WskConnect,
1300 .WskGetLocalAddress = WskGetLocalAddress,
1301 .WskGetRemoteAddress = WskGetRemoteAddress,
1302 .WskSend = WskSend,
1303 .WskReceive = WskReceive,
1304 .WskDisconnect = WskDisconnect,
1305 .WskRelease = WskReleaseTcp,
1306};
1307
1308static NTSTATUS WSKAPI
1316 _In_opt_ const VOID * Dispatch,
1321{
1322 PWSK_SOCKET_INTERNAL Socket;
1324
1326
1328
1329 if (AddressFamily != AF_INET)
1330 {
1331 DPRINT1("Address family %d not supported\n", AddressFamily);
1333 goto err_out;
1334 }
1335 switch (SocketType)
1336 {
1337 case SOCK_DGRAM:
1338 if (Protocol != IPPROTO_UDP)
1339 {
1340 DPRINT1("SOCK_DGRAM only supports IPPROTO_UDP\n");
1342 goto err_out;
1343 }
1345 {
1346 DPRINT1("SOCK_DGRAM flags must be WSK_FLAG_DATAGRAM_SOCKET\n");
1348 goto err_out;
1349 }
1350 break;
1351
1352 case SOCK_STREAM:
1353 if (Protocol != IPPROTO_TCP)
1354 {
1355 DPRINT1("SOCK_STREAM only supports IPPROTO_TCP\n");
1357 goto err_out;
1358 }
1360 {
1361 DPRINT1("SOCK_STREAM flags must be either WSK_FLAG_CONNECTION_SOCKET or WSK_FLAG_LISTEN_SOCKET\n");
1363 goto err_out;
1364 }
1365 break;
1366
1367 case SOCK_RAW:
1368 DPRINT1("SOCK_RAW not supported\n");
1370 goto err_out;
1371
1372 default:
1374 goto err_out;
1375 }
1376
1377 Socket = ExAllocatePoolZero(NonPagedPool, sizeof(*Socket), TAG_NETIO);
1378 if (Socket == NULL)
1379 {
1380 DPRINT1("WskSocket: Out of memory\n");
1382 goto err_out;
1383 }
1384 Socket->family = AddressFamily;
1385 Socket->type = SocketType;
1386 Socket->proto = Protocol;
1387 Socket->WskFlags = Flags;
1388 Socket->user_context = SocketContext;
1389 Socket->ListenDispatch = Dispatch;
1390 Socket->RefCount = 1; /* DereferenceSocket() is in WskCloseSocket */
1391
1392 switch (SocketType)
1393 {
1394 case SOCK_DGRAM:
1395 Socket->Socket.Dispatch = &UdpDispatch;
1396 RtlInitUnicodeString(&Socket->TdiName, L"\\Device\\Udp");
1397 break;
1398 case SOCK_STREAM:
1399 Socket->Socket.Dispatch = &TcpDispatch;
1400 RtlInitUnicodeString(&Socket->TdiName, L"\\Device\\Tcp");
1401
1403 {
1405 if (!NT_SUCCESS(status))
1406 {
1407 DPRINT1("Could not open TDI handle, status is %x\n", status);
1409 goto err_out;
1410 }
1411 }
1412 else
1413 {
1415 Socket->ListenThreadShouldRun = TRUE;
1416
1418 if (!NT_SUCCESS(status))
1419 {
1420 DPRINT1("Could not start listen thread, status is %x\n", status);
1422 goto err_out;
1423 }
1425 if (!NT_SUCCESS(status))
1426 {
1427 DPRINT1("Could not get a PKTHREAD object, status is %x\n", status);
1429 goto err_out;
1430 }
1431 ZwClose(Socket->ListenThreadHandle);
1432 }
1433
1434 if (Flags == WSK_FLAG_LISTEN_SOCKET && Socket->ListenDispatch == NULL)
1435 {
1436 DPRINT1("Warning: no callbacks given for listen socket\n");
1437 }
1438 break;
1439
1440 default:
1441 DPRINT1("Socket type not yet supported\n");
1443 goto err_out;
1444 }
1445
1446 Irp->IoStatus.Information = (ULONG_PTR)Socket;
1448
1449err_out:
1450 Irp->IoStatus.Status = status;
1452
1453 return STATUS_PENDING;
1454}
1455
1457 .Version = 0,
1458 .Reserved = 0,
1459 .WskSocket = WskSocket,
1460 .WskSocketConnect = WskSocketConnect,
1461 .WskControlClient = WskControlClient
1462};
1463
1466{
1468
1469 reg->ReservedRegistrationState = 0;
1470 reg->ReservedRegistrationContext = NULL;
1471 KeInitializeSpinLock(&reg->ReservedRegistrationLock);
1472
1473 return STATUS_SUCCESS;
1474}
1475
1478{
1480
1481 npi->Client = NULL;
1482 npi->Dispatch = &provider_dispatch;
1483
1485}
1486
1489{
1491
1493}
1494
1497{
1499
1500 reg->ReservedRegistrationState = 0;
1501 reg->ReservedRegistrationContext = NULL;
1502}
#define ExAllocatePoolUninitialized
unsigned char BOOLEAN
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
Definition: bufpool.h:45
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define L(x)
Definition: resources.c:13
static IO_COMPLETION_ROUTINE ListenComplete
Definition: listen.c:89
#define IPPROTO_TCP
Definition: ip.h:196
#define IPPROTO_UDP
Definition: ip.h:197
#define SOCK_STREAM
Definition: tcpip.h:118
#define IO_NETWORK_INCREMENT
Definition: tcpip.h:43
#define AF_INET
Definition: tcpip.h:117
#define ULONG_PTR
Definition: config.h:101
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define PKEVENT
Definition: env_spec_w32.h:70
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define NonPagedPool
Definition: env_spec_w32.h:307
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
Status
Definition: gdiplustypes.h:25
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean enable
Definition: glext.h:11120
static int reg
Definition: i386-dis.c:1290
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
@ NormalPagePriority
Definition: imports.h:54
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
IN PCO_ADDRESS_FAMILY AddressFamily
Definition: ndis.h:1906
#define KernelMode
Definition: asm.h:38
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
static void SocketShutdown(_In_ PWSK_SOCKET_INTERNAL Socket)
Definition: netio.c:153
static NTSTATUS WSKAPI WskControlClient(_In_ PWSK_CLIENT Client, _In_ ULONG ControlCode, _In_ SIZE_T InputSize, _In_reads_bytes_opt_(InputSize) PVOID InputBuffer, _In_ SIZE_T OutputSize, _Out_writes_bytes_opt_(OutputSize) PVOID OutputBuffer, _Out_opt_ SIZE_T *OutputSizeReturned, _Inout_opt_ PIRP Irp)
Definition: netio.c:1065
static NTSTATUS NTAPI CompletionFireEvent(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID Context)
Definition: netio.c:414
VOID WSKAPI WskDeregister(_In_ PWSK_REGISTRATION reg)
Definition: netio.c:1496
#define TAG_NETIO
Definition: netio.c:60
static WSK_PROVIDER_DATAGRAM_DISPATCH UdpDispatch
Definition: netio.c:1085
static NTSTATUS WSKAPI WskSend(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_BUF Buffer, _In_ ULONG Flags, _Inout_ PIRP Irp)
Definition: netio.c:1262
static void StopSocketDereferenceThread(void)
Definition: netio.c:302
static NTSTATUS WSKAPI WskCloseSocket(_In_ PWSK_SOCKET SocketParam, _Inout_ PIRP Irp)
Definition: netio.c:775
static NTSTATUS WSKAPI WskDisconnect(_In_ PWSK_SOCKET SocketParam, _In_opt_ PWSK_BUF Buffer, _In_ ULONG Flags, _Inout_ PIRP Irp)
Definition: netio.c:1278
static NTSTATUS WSKAPI WskControlSocket(_In_ PWSK_SOCKET SocketParam, _In_ WSK_CONTROL_SOCKET_TYPE RequestType, _In_ ULONG ControlCode, _In_ ULONG Level, _In_ SIZE_T InputSize, _In_reads_bytes_opt_(InputSize) PVOID InputBuffer, _In_ SIZE_T OutputSize, _Out_writes_bytes_opt_(OutputSize) PVOID OutputBuffer, _Out_opt_ SIZE_T *OutputSizeReturned, _Inout_opt_ PIRP Irp)
Definition: netio.c:665
static PTRANSPORT_ADDRESS TdiTransportAddressFromSocketAddress(_In_ PSOCKADDR SocketAddress)
Definition: netio.c:797
struct _LISTEN_CONTEXT LISTEN_CONTEXT
static HANDLE DereferenceSocketsThreadHandle
Definition: netio.c:244
struct _LISTEN_CONTEXT * PLISTEN_CONTEXT
static NTSTATUS StartSocketDereferenceThread(void)
Definition: netio.c:286
static volatile BOOLEAN DereferenceSocketsThreadShouldRun
Definition: netio.c:242
#define TAG_AFD_TDI_CONNECTION_INFORMATION
Definition: netio.c:63
static WSK_PROVIDER_DISPATCH provider_dispatch
Definition: netio.c:1456
static void DereferenceSocketSynchronous(_In_ PWSK_SOCKET_INTERNAL Socket)
Definition: netio.c:232
struct _NETIO_CONTEXT * PNETIO_CONTEXT
static NTSTATUS WSKAPI WskReleaseUdp(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_DATAGRAM_INDICATION DatagramIndication)
Definition: netio.c:985
static PWSK_SOCKET_INTERNAL SocketsToDereference
Definition: netio.c:240
NTSTATUS WSKAPI WskCaptureProviderNPI(_In_ PWSK_REGISTRATION reg, _In_ ULONG wait, _Out_ PWSK_PROVIDER_NPI npi)
Definition: netio.c:1477
static KEVENT DereferenceSocketsEvent
Definition: netio.c:243
static void DereferenceSocket(_In_ PWSK_SOCKET_INTERNAL Socket)
Definition: netio.c:311
static void ReferenceSocket(_In_ PWSK_SOCKET_INTERNAL Socket)
Definition: netio.c:137
#define FUNCTION_TRACE
Definition: netio.c:74
static NTSTATUS WSKAPI WskSendTo(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_BUF Buffer, _Reserved_ ULONG Flags, _In_opt_ PSOCKADDR RemoteAddress, _In_ ULONG ControlInfoLength, _In_reads_bytes_opt_(ControlInfoLength) PCMSGHDR ControlInfo, _Inout_ PIRP Irp)
Definition: netio.c:888
static NTSTATUS WSKAPI WskConnect(_In_ PWSK_SOCKET SocketParam, _In_ PSOCKADDR RemoteAddress, _Reserved_ ULONG Flags, _Inout_ PIRP Irp)
Definition: netio.c:1098
NTSTATUS WSKAPI WskRegister(_In_ PWSK_CLIENT_NPI client_npi, _Out_ PWSK_REGISTRATION reg)
Definition: netio.c:1465
static void QueueListening(_In_ PWSK_SOCKET_INTERNAL ListenSocket)
Definition: netio.c:466
static NTSTATUS WSKAPI WskStreamIo(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_BUF Buffer, _In_ ULONG Flags, _Inout_ PIRP Irp, _In_ enum direction Direction)
Definition: netio.c:1190
static void SocketDestroy(_In_ PWSK_SOCKET_INTERNAL Socket)
Definition: netio.c:206
static PTDI_CONNECTION_INFORMATION TdiConnectionInfoFromSocketAddress(_In_ PSOCKADDR SocketAddress)
Definition: netio.c:822
direction
Definition: netio.c:882
@ DIR_SEND
Definition: netio.c:883
@ DIR_RECEIVE
Definition: netio.c:884
static NTSTATUS WSKAPI WskReceive(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_BUF Buffer, _In_ ULONG Flags, _Inout_ PIRP Irp)
Definition: netio.c:1270
struct _WSK_SOCKET_INTERNAL * PWSK_SOCKET_INTERNAL
static NTSTATUS WSKAPI WskReceiveFrom(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_BUF Buffer, _Reserved_ ULONG Flags, _Out_opt_ PSOCKADDR RemoteAddress, _Inout_ PULONG ControlLength, _Out_writes_bytes_opt_(*ControlLength) PCMSGHDR ControlInfo, _Out_opt_ PULONG ControlFlags, _Inout_ PIRP Irp)
Definition: netio.c:964
static NTSTATUS WSKAPI WskReleaseTcp(_In_ PWSK_SOCKET SocketParam, _In_ PWSK_DATA_INDICATION DataIndication)
Definition: netio.c:995
VOID WSKAPI WskReleaseProviderNPI(_In_ PWSK_REGISTRATION reg)
Definition: netio.c:1488
static KSPIN_LOCK SocketsToDereferenceListLock
Definition: netio.c:241
struct _NETIO_CONTEXT NETIO_CONTEXT
static NTSTATUS WSKAPI WskBind(_In_ PWSK_SOCKET SocketParam, _In_ PSOCKADDR LocalAddress, _Reserved_ ULONG Flags, _Inout_ PIRP Irp)
Definition: netio.c:848
struct _WSK_SOCKET_INTERNAL WSK_SOCKET_INTERNAL
static NTSTATUS WSKAPI WskGetLocalAddress(_In_ PWSK_SOCKET SocketParam, _Out_ PSOCKADDR LocalAddress, _Inout_ PIRP Irp)
Definition: netio.c:1005
#define AFD_SHARE_REUSE
Definition: netio.c:68
static NTSTATUS StartListening(_In_ PWSK_SOCKET_INTERNAL ListenSocket)
Definition: netio.c:544
static NTSTATUS WSKAPI WskSocketConnect(_In_ PWSK_CLIENT Client, _In_ USHORT SocketType, _In_ ULONG Protocol, _In_ PSOCKADDR LocalAddress, _In_ PSOCKADDR RemoteAddress, _In_ ULONG Flags, _In_opt_ PVOID SocketContext, _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH *Dispatch, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PIRP Irp)
Definition: netio.c:1039
static NTSTATUS WSKAPI WskSocket(_In_ PWSK_CLIENT Client, _In_ ADDRESS_FAMILY AddressFamily, _In_ USHORT SocketType, _In_ ULONG Protocol, _In_ ULONG Flags, _In_opt_ PVOID SocketContext, _In_opt_ const VOID *Dispatch, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PIRP Irp)
Definition: netio.c:1309
static VOID NTAPI DereferenceSocketsThread(_In_opt_ void *p)
Definition: netio.c:246
static VOID NTAPI RequeueListenThread(_In_ PVOID p)
Definition: netio.c:641
static NTSTATUS WSKAPI WskGetRemoteAddress(_In_ PWSK_SOCKET SocketParam, _Out_ PSOCKADDR RemoteAddress, _Inout_ PIRP Irp)
Definition: netio.c:1019
static WSK_PROVIDER_CONNECTION_DISPATCH TcpDispatch
Definition: netio.c:1295
static NTSTATUS NTAPI NetioComplete(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_ PVOID ContextParam)
Definition: netio.c:367
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Outptr_
Definition: no_sal2.h:262
#define _Out_writes_bytes_opt_(s)
Definition: no_sal2.h:228
#define _Inout_opt_
Definition: no_sal2.h:216
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define _Reserved_
Definition: no_sal2.h:504
#define _In_reads_bytes_opt_(s)
Definition: no_sal2.h:224
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
@ NotificationEvent
@ SynchronizationEvent
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
BOOLEAN NTAPI IoCancelIrp(IN PIRP Irp)
Definition: irp.c:1101
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
NTSTATUS NTAPI PsTerminateSystemThread(IN NTSTATUS ExitStatus)
Definition: kill.c:1145
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: client.c:28
IO_STATUS_BLOCK IoStatus
PWSK_SOCKET_INTERNAL ListenSocket
Definition: netio.c:408
PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
Definition: netio.c:410
PWSK_SOCKET_INTERNAL AcceptSocket
Definition: netio.c:409
PTDI_CONNECTION_INFORMATION RequestConnectionInfo
Definition: netio.c:410
PTDI_CONNECTION_INFORMATION TargetConnectionInfo
Definition: netio.c:132
PTDI_CONNECTION_INFORMATION PeerAddrRet
Definition: netio.c:133
PIRP UserIrp
Definition: netio.c:130
PWSK_SOCKET_INTERNAL socket
Definition: netio.c:131
UCHAR Address[1]
Definition: tdi.h:340
USHORT AddressLength
Definition: tdi.h:338
USHORT AddressType
Definition: tdi.h:339
TA_ADDRESS Address[1]
Definition: tdi.h:377
LONG TAAddressCount
Definition: tdi.h:376
Definition: wsk.h:100
PFN_WSK_ACCEPT_EVENT WskAcceptEvent
Definition: wsk.h:527
ADDRESS_FAMILY family
Definition: netio.c:80
HANDLE LocalAddressHandle
Definition: netio.c:89
PKTHREAD ListenThread
Definition: netio.c:110
struct _WSK_SOCKET_INTERNAL * NextSocketToDereference
Definition: netio.c:124
struct sockaddr LocalAddress
Definition: netio.c:87
volatile BOOLEAN ListenThreadShouldRun
Definition: netio.c:112
struct _WSK_SOCKET_INTERNAL * ListenSocket
Definition: netio.c:118
PFILE_OBJECT LocalAddressFile
Definition: netio.c:88
UNICODE_STRING TdiName
Definition: netio.c:85
HANDLE ListenThreadHandle
Definition: netio.c:109
BOOLEAN ConnectionFileAssociated
Definition: netio.c:98
ULONG NumSocketDereferences
Definition: netio.c:125
const WSK_CLIENT_LISTEN_DISPATCH * ListenDispatch
Definition: netio.c:101
struct sockaddr RemoteAddress
Definition: netio.c:91
PFILE_OBJECT ConnectionFile
Definition: netio.c:96
HANDLE ConnectionHandle
Definition: netio.c:97
PVOID user_context
Definition: netio.c:84
WSK_SOCKET Socket
Definition: netio.c:78
volatile BOOLEAN ListenCancelled
Definition: netio.c:108
PFILE_OBJECT RemoteAddressFile
Definition: netio.c:92
KEVENT StartListenEvent
Definition: netio.c:111
HANDLE RemoteAddressHandle
Definition: netio.c:93
const VOID * Dispatch
Definition: wsk.h:96
Definition: ps.c:97
struct _TRANSPORT_ADDRESS * PTRANSPORT_ADDRESS
#define TDI_ADDRESS_TYPE_IP
Definition: tdi.h:345
NTSTATUS TdiOpenConnectionEndpointFile(PUNICODE_STRING DeviceName, PHANDLE ConnectionHandle, PFILE_OBJECT *ConnectionObject)
Opens a connection endpoint file object.
Definition: tdi.c:258
NTSTATUS TdiConnect(PIRP *PendingIrp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION ConnectionCallInfo, PTDI_CONNECTION_INFORMATION ConnectionReturnInfo, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Connect a connection endpoint to a remote peer.
Definition: tdi.c:311
NTSTATUS TdiBuildNullConnectionInfo(PTDI_CONNECTION_INFORMATION *ConnectionInfo, ULONG Type)
Builds a NULL TDI connection information structure.
Definition: tdiconn.c:181
NTSTATUS TdiListen(PIRP *Irp, PFILE_OBJECT ConnectionObject, PTDI_CONNECTION_INFORMATION *RequestConnectionInfo, PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Listen on a connection endpoint for a connection request from a remote peer.
Definition: tdi.c:463
NTSTATUS TdiAssociateAddressFile(HANDLE AddressHandle, PFILE_OBJECT ConnectionObject)
Associates a connection endpoint to an address file object.
Definition: tdi.c:366
NTSTATUS TdiBuildConnectionInfo(PTDI_CONNECTION_INFORMATION *ConnectionInfo, PTRANSPORT_ADDRESS Name)
Definition: tdiconn.c:247
NTSTATUS TdiDisassociateAddressFile(PFILE_OBJECT ConnectionObject)
Disassociates a connection endpoint from an address file object.
Definition: tdi.c:416
NTSTATUS TdiReceive(PIRP *Irp, PFILE_OBJECT ConnectionObject, USHORT Flags, PCHAR Buffer, UINT BufferLength, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Definition: tdi.c:999
NTSTATUS TdiSendDatagram(PIRP *Irp, PFILE_OBJECT TransportObject, PCHAR Buffer, UINT BufferLength, PTDI_CONNECTION_INFORMATION To, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Sends a datagram.
Definition: tdi.c:1170
NTSTATUS TdiOpenAddressFile(PUNICODE_STRING DeviceName, PTRANSPORT_ADDRESS Name, ULONG ShareType, PHANDLE AddressHandle, PFILE_OBJECT *AddressObject)
Opens an IPv4 address file object.
Definition: tdi.c:148
NTSTATUS TdiSend(PIRP *Irp, PFILE_OBJECT ConnectionObject, USHORT Flags, PCHAR Buffer, UINT BufferLength, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext)
Definition: tdi.c:923
static void CreateSocket(void)
Definition: telnetd.c:102
#define STATUS_PENDING
Definition: telnetd.h:14
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFQUEUE _In_ _Strict_type_match_ WDF_REQUEST_TYPE RequestType
Definition: wdfdevice.h:4239
WDF_EXTERN_C_START typedef _In_ WDFDEVICE _In_ WDFCONTEXT _In_ WDF_DMA_DIRECTION Direction
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
#define SOCK_RAW
Definition: winsock.h:331
#define SOCK_DGRAM
Definition: winsock.h:330
struct sockaddr * PSOCKADDR
Definition: winsock.h:479
#define SO_REUSEADDR
Definition: winsock.h:174
#define SOL_SOCKET
Definition: winsock.h:392
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
USHORT ADDRESS_FAMILY
Definition: ws2def.h:25
#define WSK_FLAG_LISTEN_SOCKET
Definition: wsk.h:45
#define SO_WSK_EVENT_CALLBACK
Definition: wsk.h:57
#define WSKAPI
Definition: wsk.h:35
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _In_opt_ PWSK_SOCKET _Outptr_result_maybenull_ PVOID * AcceptSocketContext
Definition: wsk.h:174
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR LocalAddress
Definition: wsk.h:171
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD OwningThread
Definition: wsk.h:190
#define WSK_FLAG_CONNECTION_SOCKET
Definition: wsk.h:46
WSK_CONTROL_SOCKET_TYPE
Definition: wsk.h:85
@ WskIoctl
Definition: wsk.h:88
@ WskGetOption
Definition: wsk.h:87
@ WskSetOption
Definition: wsk.h:86
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS _In_opt_ PETHREAD _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor
Definition: wsk.h:191
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH * Dispatch
Definition: wsk.h:188
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID SocketContext
Definition: wsk.h:187
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _In_opt_ PWSK_SOCKET AcceptSocket
Definition: wsk.h:173
#define WSK_FLAG_DATAGRAM_SOCKET
Definition: wsk.h:47
_In_ USHORT SocketType
Definition: wsk.h:182
#define WSK_EVENT_ACCEPT
Definition: wsk.h:59
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR RemoteAddress
Definition: wsk.h:172
struct _WSK_CLIENT_LISTEN_DISPATCH * PWSK_CLIENT_LISTEN_DISPATCH
_Must_inspect_result_ _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _In_opt_ PWSK_SOCKET _Outptr_result_maybenull_ PVOID _Outptr_result_maybenull_ const WSK_CLIENT_CONNECTION_DISPATCH ** AcceptSocketDispatch
Definition: wsk.h:175
_In_ USHORT _In_ ULONG _In_ PSOCKADDR _In_ PSOCKADDR _Reserved_ ULONG _In_opt_ PVOID _In_opt_ const WSK_CLIENT_CONNECTION_DISPATCH _In_opt_ PEPROCESS OwningProcess
Definition: wsk.h:189
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
#define IO_NO_INCREMENT
Definition: iotypes.h:598
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER _Outptr_ PVOID * TargetAddress
Definition: iotypes.h:1037
* PFILE_OBJECT
Definition: iotypes.h:1998
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:467
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define ObDereferenceObject
Definition: obfuncs.h:203