2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
5 * PURPOSE: Transport Driver Interface functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
11 #include <pseh/pseh2.h>
14 #include "tdi_proto.h"
18 static VOID
DisplayBuffer(
25 if ((DebugTraceLevel
& MAX_TRACE
) == 0)
29 AFD_DbgPrint(MIN_TRACE
, ("Cannot display null buffer.\n"));
33 AFD_DbgPrint(MIN_TRACE
, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer
, Size
));
36 for (i
= 0; i
< Size
; i
++) {
39 DbgPrint("%02X ", (p
[i
]) & 0xFF);
46 static NTSTATUS
TdiCall(
48 PDEVICE_OBJECT DeviceObject
,
50 PIO_STATUS_BLOCK Iosb
)
52 * FUNCTION: Calls a transport driver device
54 * Irp = Pointer to I/O Request Packet
55 * DeviceObject = Pointer to device object to call
56 * Event = An optional pointer to an event handle that will be
58 * Iosb = Pointer to an IO status block
65 AFD_DbgPrint(MID_TRACE
, ("Called\n"));
67 AFD_DbgPrint(MID_TRACE
, ("Irp->UserEvent = %x\n", Irp
->UserEvent
));
69 Status
= IoCallDriver(DeviceObject
, Irp
);
70 AFD_DbgPrint(MID_TRACE
, ("IoCallDriver: %08x\n", Status
));
72 if ((Status
== STATUS_PENDING
) && (Event
!= NULL
)) {
73 AFD_DbgPrint(MAX_TRACE
, ("Waiting on transport.\n"));
74 KeWaitForSingleObject(
80 Status
= Iosb
->Status
;
83 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
89 static NTSTATUS
TdiOpenDevice(
90 PUNICODE_STRING DeviceName
,
92 PFILE_FULL_EA_INFORMATION EaInfo
,
96 * FUNCTION: Opens a device
98 * DeviceName = Pointer to counted string with name of device
99 * EaLength = Length of EA information
100 * EaInfo = Pointer to buffer with EA information
101 * Handle = Address of buffer to place device handle
102 * Object = Address of buffer to place device object
104 * Status of operation
107 OBJECT_ATTRIBUTES Attr
;
108 IO_STATUS_BLOCK Iosb
;
111 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ)\n", DeviceName
));
113 InitializeObjectAttributes(&Attr
, /* Attribute buffer */
114 DeviceName
, /* Device name */
115 OBJ_CASE_INSENSITIVE
| /* Attributes */
117 NULL
, /* Root directory */
118 NULL
); /* Security descriptor */
120 Status
= ZwCreateFile(Handle
, /* Return file handle */
121 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, /* Desired access */
122 &Attr
, /* Object attributes */
123 &Iosb
, /* IO status */
124 0, /* Initial allocation size */
125 FILE_ATTRIBUTE_NORMAL
, /* File attributes */
126 0, /* Share access */
127 FILE_OPEN_IF
, /* Create disposition */
128 0, /* Create options */
129 EaInfo
, /* EA buffer */
130 EaLength
); /* EA length */
131 if (NT_SUCCESS(Status
)) {
132 Status
= ObReferenceObjectByHandle(*Handle
, /* Handle to open file */
133 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, /* Access mode */
134 IoFileObjectType
, /* Object type */
135 KernelMode
, /* Access mode */
136 (PVOID
*)Object
, /* Pointer to object */
137 NULL
); /* Handle information */
138 if (!NT_SUCCESS(Status
)) {
139 AFD_DbgPrint(MIN_TRACE
, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status
));
142 AFD_DbgPrint(MAX_TRACE
, ("Got handle (0x%X) Object (0x%X)\n",
146 AFD_DbgPrint(MIN_TRACE
, ("ZwCreateFile() failed with status (0x%X)\n", Status
));
149 if (!NT_SUCCESS(Status
)) {
150 *Handle
= INVALID_HANDLE_VALUE
;
157 NTSTATUS
TdiOpenAddressFile(
158 PUNICODE_STRING DeviceName
,
159 PTRANSPORT_ADDRESS Name
,
160 PHANDLE AddressHandle
,
161 PFILE_OBJECT
*AddressObject
)
163 * FUNCTION: Opens an IPv4 address file object
165 * DeviceName = Pointer to counted string with name of device
166 * Name = Pointer to socket name (IPv4 address family)
167 * AddressHandle = Address of buffer to place address file handle
168 * AddressObject = Address of buffer to place address file object
170 * Status of operation
173 PFILE_FULL_EA_INFORMATION EaInfo
;
176 PTRANSPORT_ADDRESS Address
;
178 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ) Name (0x%X)\n",
181 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
182 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
183 TDI_TRANSPORT_ADDRESS_LENGTH
+
184 TaLengthOfTransportAddress( Name
) + 1;
185 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
187 return STATUS_INSUFFICIENT_RESOURCES
;
189 RtlZeroMemory(EaInfo
, EaLength
);
190 EaInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
191 /* Don't copy the terminating 0; we have already zeroed it */
192 RtlCopyMemory(EaInfo
->EaName
,
194 TDI_TRANSPORT_ADDRESS_LENGTH
);
195 EaInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
197 (PTRANSPORT_ADDRESS
)(EaInfo
->EaName
+ TDI_TRANSPORT_ADDRESS_LENGTH
+ 1); /* 0-terminated */
198 TaCopyTransportAddressInPlace( Address
, Name
);
200 Status
= TdiOpenDevice(DeviceName
,
210 NTSTATUS
TdiOpenConnectionEndpointFile(
211 PUNICODE_STRING DeviceName
,
212 PHANDLE ConnectionHandle
,
213 PFILE_OBJECT
*ConnectionObject
)
215 * FUNCTION: Opens a connection endpoint file object
217 * DeviceName = Pointer to counted string with name of device
218 * ConnectionHandle = Address of buffer to place connection endpoint file handle
219 * ConnectionObject = Address of buffer to place connection endpoint file object
221 * Status of operation
224 PFILE_FULL_EA_INFORMATION EaInfo
;
229 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ)\n", DeviceName
));
231 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
232 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
233 TDI_CONNECTION_CONTEXT_LENGTH
+
236 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
238 return STATUS_INSUFFICIENT_RESOURCES
;
240 RtlZeroMemory(EaInfo
, EaLength
);
241 EaInfo
->EaNameLength
= TDI_CONNECTION_CONTEXT_LENGTH
;
242 /* Don't copy the terminating 0; we have already zeroed it */
243 RtlCopyMemory(EaInfo
->EaName
,
244 TdiConnectionContext
,
245 TDI_CONNECTION_CONTEXT_LENGTH
);
246 EaInfo
->EaValueLength
= sizeof(PVOID
);
247 ContextArea
= (PVOID
*)(EaInfo
->EaName
+ TDI_CONNECTION_CONTEXT_LENGTH
+ 1); /* 0-terminated */
248 /* FIXME: Allocate context area */
250 Status
= TdiOpenDevice(DeviceName
,
262 PFILE_OBJECT ConnectionObject
,
263 PTDI_CONNECTION_INFORMATION ConnectionCallInfo
,
264 PTDI_CONNECTION_INFORMATION ConnectionReturnInfo
,
265 PIO_STATUS_BLOCK Iosb
,
266 PIO_COMPLETION_ROUTINE CompletionRoutine
,
267 PVOID CompletionContext
)
269 * FUNCTION: Connect a connection endpoint to a remote peer
271 * ConnectionObject = Pointer to connection endpoint file object
272 * RemoteAddress = Pointer to remote address
274 * Status of operation
277 PDEVICE_OBJECT DeviceObject
;
280 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
282 if (!ConnectionObject
) {
283 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
285 return STATUS_INVALID_PARAMETER
;
288 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
290 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
292 return STATUS_INVALID_PARAMETER
;
295 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_CONNECT
, /* Sub function */
296 DeviceObject
, /* Device object */
297 ConnectionObject
, /* File object */
301 return STATUS_INSUFFICIENT_RESOURCES
;
304 TdiBuildConnect(*Irp
, /* IRP */
305 DeviceObject
, /* Device object */
306 ConnectionObject
, /* File object */
307 CompletionRoutine
, /* Completion routine */
308 CompletionContext
, /* Completion routine context */
310 ConnectionCallInfo
, /* Request connection information */
311 ConnectionReturnInfo
); /* Return connection information */
313 Status
= TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
319 NTSTATUS
TdiAssociateAddressFile(
320 HANDLE AddressHandle
,
321 PFILE_OBJECT ConnectionObject
)
323 * FUNCTION: Associates a connection endpoint to an address file object
325 * AddressHandle = Handle to address file object
326 * ConnectionObject = Connection endpoint file object
328 * Status of operation
331 PDEVICE_OBJECT DeviceObject
;
332 IO_STATUS_BLOCK Iosb
;
337 AFD_DbgPrint(MAX_TRACE
, ("Called. AddressHandle (0x%X) ConnectionObject (0x%X)\n",
338 AddressHandle
, ConnectionObject
));
340 if (!ConnectionObject
) {
341 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
342 return STATUS_INVALID_PARAMETER
;
345 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
347 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
348 return STATUS_INVALID_PARAMETER
;
351 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
353 Irp
= TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS
, /* Sub function */
354 DeviceObject
, /* Device object */
355 ConnectionObject
, /* File object */
359 return STATUS_INSUFFICIENT_RESOURCES
;
361 TdiBuildAssociateAddress(Irp
,
368 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
376 PFILE_OBJECT ConnectionObject
,
377 PTDI_CONNECTION_INFORMATION
*RequestConnectionInfo
,
378 PTDI_CONNECTION_INFORMATION
*ReturnConnectionInfo
,
379 PIO_STATUS_BLOCK Iosb
,
380 PIO_COMPLETION_ROUTINE CompletionRoutine
,
381 PVOID CompletionContext
)
383 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
385 * CompletionRoutine = Routine to be called when IRP is completed
386 * CompletionContext = Context for CompletionRoutine
388 * Status of operation
389 * May return STATUS_PENDING
392 PDEVICE_OBJECT DeviceObject
;
395 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
397 if (!ConnectionObject
) {
398 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
400 return STATUS_INVALID_PARAMETER
;
403 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
405 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
407 return STATUS_INVALID_PARAMETER
;
410 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_LISTEN
, /* Sub function */
411 DeviceObject
, /* Device object */
412 ConnectionObject
, /* File object */
416 return STATUS_INSUFFICIENT_RESOURCES
;
418 TdiBuildListen(*Irp
, /* IRP */
419 DeviceObject
, /* Device object */
420 ConnectionObject
, /* File object */
421 CompletionRoutine
, /* Completion routine */
422 CompletionContext
, /* Completion routine context */
424 *RequestConnectionInfo
, /* Request connection information */
425 *ReturnConnectionInfo
); /* Return connection information */
427 Status
= TdiCall(*Irp
, DeviceObject
, NULL
/* Don't wait for completion */, Iosb
);
433 NTSTATUS
TdiSetEventHandler(
434 PFILE_OBJECT FileObject
,
439 * FUNCTION: Sets or resets an event handler
441 * FileObject = Pointer to file object
442 * EventType = Event code
443 * Handler = Event handler to be called when the event occurs
444 * Context = Context input to handler when the event occurs
446 * Status of operation
448 * Specify NULL for Handler to stop calling event handler
451 PDEVICE_OBJECT DeviceObject
;
452 IO_STATUS_BLOCK Iosb
;
457 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
460 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
461 return STATUS_INVALID_PARAMETER
;
464 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
466 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
467 return STATUS_INVALID_PARAMETER
;
470 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
472 Irp
= TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER
, /* Sub function */
473 DeviceObject
, /* Device object */
474 FileObject
, /* File object */
478 return STATUS_INSUFFICIENT_RESOURCES
;
482 TdiBuildSetEventHandler(Irp
,
491 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
497 NTSTATUS
TdiQueryDeviceControl(
498 PFILE_OBJECT FileObject
,
501 ULONG InputBufferLength
,
503 ULONG OutputBufferLength
,
506 * FUNCTION: Queries a device for information
508 * FileObject = Pointer to file object
509 * IoControlCode = I/O control code
510 * InputBuffer = Pointer to buffer with input data
511 * InputBufferLength = Length of InputBuffer
512 * OutputBuffer = Address of buffer to place output data
513 * OutputBufferLength = Length of OutputBuffer
515 * Status of operation
518 PDEVICE_OBJECT DeviceObject
;
519 IO_STATUS_BLOCK Iosb
;
525 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
526 return STATUS_INVALID_PARAMETER
;
529 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
531 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
532 return STATUS_INVALID_PARAMETER
;
535 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
537 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
547 return STATUS_INSUFFICIENT_RESOURCES
;
549 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
552 *Return
= Iosb
.Information
;
558 NTSTATUS
TdiQueryInformation(
559 PFILE_OBJECT FileObject
,
563 * FUNCTION: Query for information
565 * FileObject = Pointer to file object
566 * QueryType = Query type
567 * MdlBuffer = Pointer to MDL buffer specific for query type
569 * Status of operation
572 PDEVICE_OBJECT DeviceObject
;
573 IO_STATUS_BLOCK Iosb
;
579 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
580 return STATUS_INVALID_PARAMETER
;
583 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
585 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
586 return STATUS_INVALID_PARAMETER
;
589 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
591 Irp
= TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION
, /* Sub function */
592 DeviceObject
, /* Device object */
593 ConnectionObject
, /* File object */
597 return STATUS_INSUFFICIENT_RESOURCES
;
600 TdiBuildQueryInformation(
609 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
614 NTSTATUS
TdiQueryInformationEx(
615 PFILE_OBJECT FileObject
,
624 * FUNCTION: Extended query for information
626 * FileObject = Pointer to file object
628 * Instance = Instance
629 * Class = Entity class
632 * OutputBuffer = Address of buffer to place data
633 * OutputLength = Address of buffer with length of OutputBuffer (updated)
635 * Status of operation
638 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
640 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
641 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
642 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
643 QueryInfo
.ID
.toi_class
= Class
;
644 QueryInfo
.ID
.toi_type
= Type
;
645 QueryInfo
.ID
.toi_id
= Id
;
647 return TdiQueryDeviceControl(FileObject
, /* Transport/connection object */
648 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
649 &QueryInfo
, /* Input buffer */
650 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
651 OutputBuffer
, /* Output buffer */
652 *OutputLength
, /* Output buffer length */
653 OutputLength
); /* Return information */
656 NTSTATUS
TdiQueryAddress(
657 PFILE_OBJECT FileObject
,
660 * FUNCTION: Queries for a local IP address
662 * FileObject = Pointer to file object
663 * Address = Address of buffer to place local address
665 * Status of operation
669 TDIEntityID
*Entities
;
672 IPSNMP_INFO SnmpInfo
;
673 PIPADDR_ENTRY IpAddress
;
675 NTSTATUS Status
= STATUS_SUCCESS
;
677 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
679 BufferSize
= sizeof(TDIEntityID
) * 20;
680 Entities
= (TDIEntityID
*)ExAllocatePool(NonPagedPool
, BufferSize
);
682 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
683 return STATUS_INSUFFICIENT_RESOURCES
;
686 /* Query device for supported entities */
688 Status
= TdiQueryInformationEx(FileObject
, /* File object */
689 GENERIC_ENTITY
, /* Entity */
690 TL_INSTANCE
, /* Instance */
691 INFO_CLASS_GENERIC
, /* Entity class */
692 INFO_TYPE_PROVIDER
, /* Entity type */
693 ENTITY_LIST_ID
, /* Entity id */
694 Entities
, /* Output buffer */
695 &BufferSize
); /* Output buffer size */
696 if (!NT_SUCCESS(Status
)) {
697 AFD_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
698 ExFreePool(Entities
);
702 /* Locate an IP entity */
703 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
705 AFD_DbgPrint(MAX_TRACE
, ("EntityCount = %d\n", EntityCount
));
707 for (i
= 0; i
< EntityCount
; i
++) {
708 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
) {
709 /* Query device for entity type */
711 BufferSize
= sizeof(EntityType
);
712 Status
= TdiQueryInformationEx(FileObject
, /* File object */
713 CL_NL_ENTITY
, /* Entity */
714 Entities
[i
].tei_instance
, /* Instance */
715 INFO_CLASS_GENERIC
, /* Entity class */
716 INFO_TYPE_PROVIDER
, /* Entity type */
717 ENTITY_TYPE_ID
, /* Entity id */
718 &EntityType
, /* Output buffer */
719 &BufferSize
); /* Output buffer size */
720 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
)) {
721 AFD_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
725 /* Query device for SNMP information */
727 BufferSize
= sizeof(SnmpInfo
);
728 Status
= TdiQueryInformationEx(FileObject
, /* File object */
729 CL_NL_ENTITY
, /* Entity */
730 Entities
[i
].tei_instance
, /* Instance */
731 INFO_CLASS_PROTOCOL
, /* Entity class */
732 INFO_TYPE_PROVIDER
, /* Entity type */
733 IP_MIB_STATS_ID
, /* Entity id */
734 &SnmpInfo
, /* Output buffer */
735 &BufferSize
); /* Output buffer size */
736 if (!NT_SUCCESS(Status
) || (SnmpInfo
.NumAddr
== 0)) {
737 AFD_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
741 /* Query device for all IP addresses */
743 if (SnmpInfo
.NumAddr
!= 0) {
744 BufferSize
= SnmpInfo
.NumAddr
* sizeof(IPADDR_ENTRY
);
745 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePool(NonPagedPool
, BufferSize
);
747 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
751 Status
= TdiQueryInformationEx(FileObject
, /* File object */
752 CL_NL_ENTITY
, /* Entity */
753 Entities
[i
].tei_instance
, /* Instance */
754 INFO_CLASS_PROTOCOL
, /* Entity class */
755 INFO_TYPE_PROVIDER
, /* Entity type */
756 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
757 IpAddress
, /* Output buffer */
758 &BufferSize
); /* Output buffer size */
759 if (!NT_SUCCESS(Status
)) {
760 AFD_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
761 ExFreePool(IpAddress
);
765 if (SnmpInfo
.NumAddr
!= 1) {
766 /* Skip loopback address */
767 PIPADDR_ENTRY IpAddressEntry
= (PIPADDR_ENTRY
)
768 ((PCHAR
)IpAddress
) + sizeof(IPADDR_ENTRY
);
769 *Address
= DN2H(IpAddressEntry
->Addr
);
771 /* Select the first address returned */
772 *Address
= DN2H(IpAddress
->Addr
);
775 ExFreePool(IpAddress
);
777 Status
= STATUS_UNSUCCESSFUL
;
783 ExFreePool(Entities
);
785 AFD_DbgPrint(MAX_TRACE
, ("Leaving\n"));
792 PFILE_OBJECT TransportObject
,
796 PIO_STATUS_BLOCK Iosb
,
797 PIO_COMPLETION_ROUTINE CompletionRoutine
,
798 PVOID CompletionContext
)
800 PDEVICE_OBJECT DeviceObject
;
801 NTSTATUS Status
= STATUS_SUCCESS
;
804 if (!TransportObject
) {
805 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
807 return STATUS_INVALID_PARAMETER
;
810 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
812 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
814 return STATUS_INVALID_PARAMETER
;
817 *Irp
= TdiBuildInternalDeviceControlIrp
818 ( TDI_SEND
, /* Sub function */
819 DeviceObject
, /* Device object */
820 TransportObject
, /* File object */
825 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
826 return STATUS_INSUFFICIENT_RESOURCES
;
829 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %x:%d\n", Buffer
,BufferLength
));
831 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
832 BufferLength
, /* Length of buffer */
833 FALSE
, /* Not secondary */
834 FALSE
, /* Don't charge quota */
835 NULL
); /* Don't use IRP */
837 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
838 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
840 return STATUS_INSUFFICIENT_RESOURCES
;
844 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
845 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
846 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
848 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
850 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
853 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %x\n", Mdl
));
855 TdiBuildSend(*Irp
, /* I/O Request Packet */
856 DeviceObject
, /* Device object */
857 TransportObject
, /* File object */
858 CompletionRoutine
, /* Completion routine */
859 CompletionContext
, /* Completion context */
860 Mdl
, /* Data buffer */
862 BufferLength
); /* Length of data */
864 Status
= TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
865 /* Does not block... The MDL is deleted in the receive completion
873 PFILE_OBJECT TransportObject
,
877 PIO_STATUS_BLOCK Iosb
,
878 PIO_COMPLETION_ROUTINE CompletionRoutine
,
879 PVOID CompletionContext
)
881 NTSTATUS Status
= STATUS_SUCCESS
;
882 PDEVICE_OBJECT DeviceObject
;
885 if (!TransportObject
) {
886 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
888 return STATUS_INVALID_PARAMETER
;
891 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
893 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
895 return STATUS_INVALID_PARAMETER
;
898 *Irp
= TdiBuildInternalDeviceControlIrp
899 ( TDI_RECEIVE
, /* Sub function */
900 DeviceObject
, /* Device object */
901 TransportObject
, /* File object */
906 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
907 return STATUS_INSUFFICIENT_RESOURCES
;
910 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %x:%d\n", Buffer
,BufferLength
));
912 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
913 BufferLength
, /* Length of buffer */
914 FALSE
, /* Not secondary */
915 FALSE
, /* Don't charge quota */
916 NULL
); /* Don't use IRP */
918 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
919 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
921 return STATUS_INSUFFICIENT_RESOURCES
;
925 AFD_DbgPrint(MIN_TRACE
, ("probe and lock\n"));
926 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
927 AFD_DbgPrint(MIN_TRACE
, ("probe and lock done\n"));
928 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
929 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
931 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
933 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
936 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %x\n", Mdl
));
938 TdiBuildReceive(*Irp
, /* I/O Request Packet */
939 DeviceObject
, /* Device object */
940 TransportObject
, /* File object */
941 CompletionRoutine
, /* Completion routine */
942 CompletionContext
, /* Completion context */
943 Mdl
, /* Data buffer */
945 BufferLength
); /* Length of data */
948 Status
= TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
949 /* Does not block... The MDL is deleted in the receive completion
952 AFD_DbgPrint(MID_TRACE
,("Status %x Information %d\n",
953 Status
, Iosb
->Information
));
959 NTSTATUS
TdiReceiveDatagram(
961 PFILE_OBJECT TransportObject
,
965 PTDI_CONNECTION_INFORMATION Addr
,
966 PIO_STATUS_BLOCK Iosb
,
967 PIO_COMPLETION_ROUTINE CompletionRoutine
,
968 PVOID CompletionContext
)
970 * FUNCTION: Receives a datagram
972 * TransportObject = Pointer to transport object
973 * From = Receive filter (NULL if none)
974 * Address = Address of buffer to place remote address
975 * Buffer = Address of buffer to place received data
976 * BufferSize = Address of buffer with length of Buffer (updated)
978 * Status of operation
981 PDEVICE_OBJECT DeviceObject
;
985 if (!TransportObject
) {
986 AFD_DbgPrint(MIN_TRACE
, ("Bad tranport object.\n"));
988 return STATUS_INVALID_PARAMETER
;
991 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
993 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
995 return STATUS_INVALID_PARAMETER
;
998 *Irp
= TdiBuildInternalDeviceControlIrp
999 ( TDI_RECEIVE_DATAGRAM
, /* Sub function */
1000 DeviceObject
, /* Device object */
1001 TransportObject
, /* File object */
1003 Iosb
); /* Status */
1006 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1007 return STATUS_INSUFFICIENT_RESOURCES
;
1010 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %x:%d\n", Buffer
,BufferLength
));
1012 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1013 BufferLength
, /* Length of buffer */
1014 FALSE
, /* Not secondary */
1015 FALSE
, /* Don't charge quota */
1016 NULL
); /* Don't use IRP */
1018 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1019 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1021 return STATUS_INSUFFICIENT_RESOURCES
;
1025 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1026 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1027 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1029 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1031 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1034 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %x\n", Mdl
));
1036 TdiBuildReceiveDatagram
1037 (*Irp
, /* I/O Request Packet */
1038 DeviceObject
, /* Device object */
1039 TransportObject
, /* File object */
1040 CompletionRoutine
, /* Completion routine */
1041 CompletionContext
, /* Completion context */
1042 Mdl
, /* Data buffer */
1046 Flags
); /* Length of data */
1048 Status
= TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1049 /* Does not block... The MDL is deleted in the receive completion
1056 NTSTATUS
TdiSendDatagram(
1058 PFILE_OBJECT TransportObject
,
1061 PTDI_CONNECTION_INFORMATION Addr
,
1062 PIO_STATUS_BLOCK Iosb
,
1063 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1064 PVOID CompletionContext
)
1066 * FUNCTION: Sends a datagram
1068 * TransportObject = Pointer to transport object
1069 * From = Send filter (NULL if none)
1070 * Address = Address of buffer to place remote address
1071 * Buffer = Address of buffer to place send data
1072 * BufferSize = Address of buffer with length of Buffer (updated)
1074 * Status of operation
1077 PDEVICE_OBJECT DeviceObject
;
1081 if (!TransportObject
) {
1082 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1084 return STATUS_INVALID_PARAMETER
;
1087 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %x)\n", TransportObject
));
1089 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1090 if (!DeviceObject
) {
1091 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1093 return STATUS_INVALID_PARAMETER
;
1096 *Irp
= TdiBuildInternalDeviceControlIrp
1097 ( TDI_SEND_DATAGRAM
, /* Sub function */
1098 DeviceObject
, /* Device object */
1099 TransportObject
, /* File object */
1101 Iosb
); /* Status */
1104 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1105 return STATUS_INSUFFICIENT_RESOURCES
;
1108 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %x:%d\n", Buffer
,BufferLength
));
1110 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1111 BufferLength
, /* Length of buffer */
1112 FALSE
, /* Not secondary */
1113 FALSE
, /* Don't charge quota */
1114 NULL
); /* Don't use IRP */
1117 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1118 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1120 return STATUS_INSUFFICIENT_RESOURCES
;
1124 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1125 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1126 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1128 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1130 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1133 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %x\n", Mdl
));
1135 TdiBuildSendDatagram
1136 (*Irp
, /* I/O Request Packet */
1137 DeviceObject
, /* Device object */
1138 TransportObject
, /* File object */
1139 CompletionRoutine
, /* Completion routine */
1140 CompletionContext
, /* Completion context */
1141 Mdl
, /* Data buffer */
1142 BufferLength
, /* Bytes to send */
1143 Addr
); /* Address */
1145 Status
= TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1146 /* Does not block... The MDL is deleted in the send completion
1152 NTSTATUS
TdiDisconnect(
1153 PFILE_OBJECT TransportObject
,
1154 PLARGE_INTEGER Time
,
1156 PIO_STATUS_BLOCK Iosb
,
1157 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1158 PVOID CompletionContext
,
1159 PTDI_CONNECTION_INFORMATION RequestConnectionInfo
,
1160 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
) {
1161 PDEVICE_OBJECT DeviceObject
;
1166 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1168 if (!TransportObject
) {
1169 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1170 return STATUS_INVALID_PARAMETER
;
1173 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %x)\n", TransportObject
));
1175 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1176 if (!DeviceObject
) {
1177 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1178 return STATUS_INVALID_PARAMETER
;
1181 Irp
= TdiBuildInternalDeviceControlIrp
1182 ( TDI_SEND_DATAGRAM
, /* Sub function */
1183 DeviceObject
, /* Device object */
1184 TransportObject
, /* File object */
1186 Iosb
); /* Status */
1189 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1190 return STATUS_INSUFFICIENT_RESOURCES
;
1194 (Irp
, /* I/O Request Packet */
1195 DeviceObject
, /* Device object */
1196 TransportObject
, /* File object */
1197 CompletionRoutine
, /* Completion routine */
1198 CompletionContext
, /* Completion context */
1200 Flags
, /* Disconnect flags */
1201 RequestConnectionInfo
, /* Indication of who to disconnect */
1202 ReturnConnectionInfo
); /* Indication of who disconnected */
1204 Status
= TdiCall(Irp
, DeviceObject
, &Event
, Iosb
);