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
18 static VOID
DisplayBuffer(
25 if ((DebugTraceLevel
& MAX_TRACE
) == 0)
29 AFD_DbgPrint(MIN_TRACE
, ("Cannot display null buffer.\n"));
33 AFD_DbgPrint(MID_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 = %p\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(Event
,
79 Status
= Iosb
->Status
;
82 AFD_DbgPrint(MAX_TRACE
, ("Status (0x%X).\n", Status
));
88 static NTSTATUS
TdiOpenDevice(
89 PUNICODE_STRING DeviceName
,
91 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
;
112 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ, %u)\n", DeviceName
, ShareType
));
114 /* Determine the share access */
115 if (ShareType
!= AFD_SHARE_REUSE
)
117 /* Exclusive access */
123 ShareAccess
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
126 InitializeObjectAttributes(&Attr
, /* Attribute buffer */
127 DeviceName
, /* Device name */
128 OBJ_CASE_INSENSITIVE
| /* Attributes */
130 NULL
, /* Root directory */
131 NULL
); /* Security descriptor */
133 Status
= ZwCreateFile(Handle
, /* Return file handle */
134 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, /* Desired access */
135 &Attr
, /* Object attributes */
136 &Iosb
, /* IO status */
137 0, /* Initial allocation size */
138 FILE_ATTRIBUTE_NORMAL
, /* File attributes */
139 ShareAccess
, /* Share access */
140 FILE_OPEN_IF
, /* Create disposition */
141 0, /* Create options */
142 EaInfo
, /* EA buffer */
143 EaLength
); /* EA length */
144 if (NT_SUCCESS(Status
)) {
145 Status
= ObReferenceObjectByHandle(*Handle
, /* Handle to open file */
146 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, /* Access mode */
147 *IoFileObjectType
, /* Object type */
148 KernelMode
, /* Access mode */
149 (PVOID
*)Object
, /* Pointer to object */
150 NULL
); /* Handle information */
151 if (!NT_SUCCESS(Status
)) {
152 AFD_DbgPrint(MIN_TRACE
, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status
));
155 AFD_DbgPrint(MAX_TRACE
, ("Got handle (%p) Object (%p)\n",
159 AFD_DbgPrint(MIN_TRACE
, ("ZwCreateFile() failed with status (0x%X)\n", Status
));
162 if (!NT_SUCCESS(Status
)) {
163 *Handle
= INVALID_HANDLE_VALUE
;
170 NTSTATUS
TdiOpenAddressFile(
171 PUNICODE_STRING DeviceName
,
172 PTRANSPORT_ADDRESS Name
,
174 PHANDLE AddressHandle
,
175 PFILE_OBJECT
*AddressObject
)
177 * FUNCTION: Opens an IPv4 address file object
179 * DeviceName = Pointer to counted string with name of device
180 * Name = Pointer to socket name (IPv4 address family)
181 * AddressHandle = Address of buffer to place address file handle
182 * AddressObject = Address of buffer to place address file object
184 * Status of operation
187 PFILE_FULL_EA_INFORMATION EaInfo
;
190 PTRANSPORT_ADDRESS Address
;
192 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ) Name (%p)\n",
195 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
196 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
197 TDI_TRANSPORT_ADDRESS_LENGTH
+
198 TaLengthOfTransportAddress( Name
) + 1;
199 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
201 return STATUS_INSUFFICIENT_RESOURCES
;
203 RtlZeroMemory(EaInfo
, EaLength
);
204 EaInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
205 /* Don't copy the terminating 0; we have already zeroed it */
206 RtlCopyMemory(EaInfo
->EaName
,
208 TDI_TRANSPORT_ADDRESS_LENGTH
);
209 EaInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
211 (PTRANSPORT_ADDRESS
)(EaInfo
->EaName
+ TDI_TRANSPORT_ADDRESS_LENGTH
+ 1); /* 0-terminated */
212 TaCopyTransportAddressInPlace( Address
, Name
);
214 Status
= TdiOpenDevice(DeviceName
,
224 NTSTATUS
TdiQueryMaxDatagramLength(
225 PFILE_OBJECT FileObject
,
226 PUINT MaxDatagramLength
)
229 PTDI_MAX_DATAGRAM_INFO Buffer
;
230 NTSTATUS Status
= STATUS_SUCCESS
;
232 Buffer
= ExAllocatePool(NonPagedPool
, sizeof(TDI_MAX_DATAGRAM_INFO
));
233 if (!Buffer
) return STATUS_NO_MEMORY
;
235 Mdl
= IoAllocateMdl(Buffer
, sizeof(TDI_MAX_DATAGRAM_INFO
), FALSE
, FALSE
, NULL
);
239 return STATUS_NO_MEMORY
;
244 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
248 Status
= _SEH2_GetExceptionCode();
252 if (!NT_SUCCESS(Status
))
254 AFD_DbgPrint(MIN_TRACE
,("Failed to lock pages\n"));
260 Status
= TdiQueryInformation(FileObject
,
261 TDI_QUERY_MAX_DATAGRAM_INFO
,
263 if (!NT_SUCCESS(Status
))
269 *MaxDatagramLength
= Buffer
->MaxDatagramSize
;
273 return STATUS_SUCCESS
;
276 NTSTATUS
TdiOpenConnectionEndpointFile(
277 PUNICODE_STRING DeviceName
,
278 PHANDLE ConnectionHandle
,
279 PFILE_OBJECT
*ConnectionObject
)
281 * FUNCTION: Opens a connection endpoint file object
283 * DeviceName = Pointer to counted string with name of device
284 * ConnectionHandle = Address of buffer to place connection endpoint file handle
285 * ConnectionObject = Address of buffer to place connection endpoint file object
287 * Status of operation
290 PFILE_FULL_EA_INFORMATION EaInfo
;
295 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ)\n", DeviceName
));
297 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
298 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
299 TDI_CONNECTION_CONTEXT_LENGTH
+
302 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
304 return STATUS_INSUFFICIENT_RESOURCES
;
306 RtlZeroMemory(EaInfo
, EaLength
);
307 EaInfo
->EaNameLength
= TDI_CONNECTION_CONTEXT_LENGTH
;
308 /* Don't copy the terminating 0; we have already zeroed it */
309 RtlCopyMemory(EaInfo
->EaName
,
310 TdiConnectionContext
,
311 TDI_CONNECTION_CONTEXT_LENGTH
);
312 EaInfo
->EaValueLength
= sizeof(PVOID
);
313 ContextArea
= (PVOID
*)(EaInfo
->EaName
+ TDI_CONNECTION_CONTEXT_LENGTH
+ 1); /* 0-terminated */
314 /* FIXME: Allocate context area */
316 Status
= TdiOpenDevice(DeviceName
,
329 PFILE_OBJECT ConnectionObject
,
330 PTDI_CONNECTION_INFORMATION ConnectionCallInfo
,
331 PTDI_CONNECTION_INFORMATION ConnectionReturnInfo
,
332 PIO_COMPLETION_ROUTINE CompletionRoutine
,
333 PVOID CompletionContext
)
335 * FUNCTION: Connect a connection endpoint to a remote peer
337 * ConnectionObject = Pointer to connection endpoint file object
338 * RemoteAddress = Pointer to remote address
340 * Status of operation
343 PDEVICE_OBJECT DeviceObject
;
345 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
347 ASSERT(*Irp
== NULL
);
349 if (!ConnectionObject
) {
350 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
351 return STATUS_INVALID_PARAMETER
;
354 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
356 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
357 return STATUS_INVALID_PARAMETER
;
360 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_CONNECT
, /* Sub function */
361 DeviceObject
, /* Device object */
362 ConnectionObject
, /* File object */
366 return STATUS_INSUFFICIENT_RESOURCES
;
369 TdiBuildConnect(*Irp
, /* IRP */
370 DeviceObject
, /* Device object */
371 ConnectionObject
, /* File object */
372 CompletionRoutine
, /* Completion routine */
373 CompletionContext
, /* Completion routine context */
375 ConnectionCallInfo
, /* Request connection information */
376 ConnectionReturnInfo
); /* Return connection information */
378 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
380 return STATUS_PENDING
;
384 NTSTATUS
TdiAssociateAddressFile(
385 HANDLE AddressHandle
,
386 PFILE_OBJECT ConnectionObject
)
388 * FUNCTION: Associates a connection endpoint to an address file object
390 * AddressHandle = Handle to address file object
391 * ConnectionObject = Connection endpoint file object
393 * Status of operation
396 PDEVICE_OBJECT DeviceObject
;
397 IO_STATUS_BLOCK Iosb
;
401 AFD_DbgPrint(MAX_TRACE
, ("Called. AddressHandle (%p) ConnectionObject (%p)\n",
402 AddressHandle
, ConnectionObject
));
404 if (!ConnectionObject
) {
405 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
406 return STATUS_INVALID_PARAMETER
;
409 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
411 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
412 return STATUS_INVALID_PARAMETER
;
415 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
417 Irp
= TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS
, /* Sub function */
418 DeviceObject
, /* Device object */
419 ConnectionObject
, /* File object */
423 return STATUS_INSUFFICIENT_RESOURCES
;
425 TdiBuildAssociateAddress(Irp
,
432 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
435 NTSTATUS
TdiDisassociateAddressFile(
436 PFILE_OBJECT ConnectionObject
)
438 * FUNCTION: Disassociates a connection endpoint from an address file object
440 * ConnectionObject = Connection endpoint file object
442 * Status of operation
445 PDEVICE_OBJECT DeviceObject
;
446 IO_STATUS_BLOCK Iosb
;
450 AFD_DbgPrint(MAX_TRACE
, ("Called. ConnectionObject (%p)\n", ConnectionObject
));
452 if (!ConnectionObject
) {
453 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
454 return STATUS_INVALID_PARAMETER
;
457 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
459 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
460 return STATUS_INVALID_PARAMETER
;
463 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
465 Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS
, /* Sub function */
466 DeviceObject
, /* Device object */
467 ConnectionObject
, /* File object */
471 return STATUS_INSUFFICIENT_RESOURCES
;
473 TdiBuildDisassociateAddress(Irp
,
479 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
484 PFILE_OBJECT ConnectionObject
,
485 PTDI_CONNECTION_INFORMATION
*RequestConnectionInfo
,
486 PTDI_CONNECTION_INFORMATION
*ReturnConnectionInfo
,
487 PIO_COMPLETION_ROUTINE CompletionRoutine
,
488 PVOID CompletionContext
)
490 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
492 * CompletionRoutine = Routine to be called when IRP is completed
493 * CompletionContext = Context for CompletionRoutine
495 * Status of operation
496 * May return STATUS_PENDING
499 PDEVICE_OBJECT DeviceObject
;
501 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
503 ASSERT(*Irp
== NULL
);
505 if (!ConnectionObject
) {
506 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
507 return STATUS_INVALID_PARAMETER
;
510 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
512 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
513 return STATUS_INVALID_PARAMETER
;
516 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_LISTEN
, /* Sub function */
517 DeviceObject
, /* Device object */
518 ConnectionObject
, /* File object */
522 return STATUS_INSUFFICIENT_RESOURCES
;
524 TdiBuildListen(*Irp
, /* IRP */
525 DeviceObject
, /* Device object */
526 ConnectionObject
, /* File object */
527 CompletionRoutine
, /* Completion routine */
528 CompletionContext
, /* Completion routine context */
530 *RequestConnectionInfo
, /* Request connection information */
531 *ReturnConnectionInfo
); /* Return connection information */
533 TdiCall(*Irp
, DeviceObject
, NULL
/* Don't wait for completion */, NULL
);
535 return STATUS_PENDING
;
539 NTSTATUS
TdiSetEventHandler(
540 PFILE_OBJECT FileObject
,
545 * FUNCTION: Sets or resets an event handler
547 * FileObject = Pointer to file object
548 * EventType = Event code
549 * Handler = Event handler to be called when the event occurs
550 * Context = Context input to handler when the event occurs
552 * Status of operation
554 * Specify NULL for Handler to stop calling event handler
557 PDEVICE_OBJECT DeviceObject
;
558 IO_STATUS_BLOCK Iosb
;
562 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
565 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
566 return STATUS_INVALID_PARAMETER
;
569 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
571 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
572 return STATUS_INVALID_PARAMETER
;
575 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
577 Irp
= TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER
, /* Sub function */
578 DeviceObject
, /* Device object */
579 FileObject
, /* File object */
583 return STATUS_INSUFFICIENT_RESOURCES
;
587 TdiBuildSetEventHandler(Irp
,
596 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
600 NTSTATUS
TdiQueryDeviceControl(
601 PFILE_OBJECT FileObject
,
604 ULONG InputBufferLength
,
606 ULONG OutputBufferLength
,
609 * FUNCTION: Queries a device for information
611 * FileObject = Pointer to file object
612 * IoControlCode = I/O control code
613 * InputBuffer = Pointer to buffer with input data
614 * InputBufferLength = Length of InputBuffer
615 * OutputBuffer = Address of buffer to place output data
616 * OutputBufferLength = Length of OutputBuffer
618 * Status of operation
621 PDEVICE_OBJECT DeviceObject
;
622 IO_STATUS_BLOCK Iosb
;
628 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
629 return STATUS_INVALID_PARAMETER
;
632 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
634 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
635 return STATUS_INVALID_PARAMETER
;
638 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
640 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
650 return STATUS_INSUFFICIENT_RESOURCES
;
652 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
655 *Return
= Iosb
.Information
;
661 NTSTATUS
TdiQueryInformation(
662 PFILE_OBJECT FileObject
,
666 * FUNCTION: Query for information
668 * FileObject = Pointer to file object
669 * QueryType = Query type
670 * MdlBuffer = Pointer to MDL buffer specific for query type
672 * Status of operation
675 PDEVICE_OBJECT DeviceObject
;
676 IO_STATUS_BLOCK Iosb
;
681 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
682 return STATUS_INVALID_PARAMETER
;
685 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
687 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
688 return STATUS_INVALID_PARAMETER
;
691 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
693 Irp
= TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION
, /* Sub function */
694 DeviceObject
, /* Device object */
695 ConnectionObject
, /* File object */
699 return STATUS_INSUFFICIENT_RESOURCES
;
702 TdiBuildQueryInformation(Irp
,
710 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
713 NTSTATUS
TdiQueryInformationEx(
714 PFILE_OBJECT FileObject
,
723 * FUNCTION: Extended query for information
725 * FileObject = Pointer to file object
727 * Instance = Instance
728 * Class = Entity class
731 * OutputBuffer = Address of buffer to place data
732 * OutputLength = Address of buffer with length of OutputBuffer (updated)
734 * Status of operation
737 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
739 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
740 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
741 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
742 QueryInfo
.ID
.toi_class
= Class
;
743 QueryInfo
.ID
.toi_type
= Type
;
744 QueryInfo
.ID
.toi_id
= Id
;
746 return TdiQueryDeviceControl(FileObject
, /* Transport/connection object */
747 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
748 &QueryInfo
, /* Input buffer */
749 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
750 OutputBuffer
, /* Output buffer */
751 *OutputLength
, /* Output buffer length */
752 OutputLength
); /* Return information */
755 NTSTATUS
TdiQueryAddress(
756 PFILE_OBJECT FileObject
,
759 * FUNCTION: Queries for a local IP address
761 * FileObject = Pointer to file object
762 * Address = Address of buffer to place local address
764 * Status of operation
768 TDIEntityID
*Entities
;
772 PIPADDR_ENTRY IpAddress
;
774 NTSTATUS Status
= STATUS_SUCCESS
;
776 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
778 BufferSize
= sizeof(TDIEntityID
) * 20;
779 Entities
= (TDIEntityID
*)ExAllocatePool(NonPagedPool
, BufferSize
);
781 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
782 return STATUS_INSUFFICIENT_RESOURCES
;
785 /* Query device for supported entities */
787 Status
= TdiQueryInformationEx(FileObject
, /* File object */
788 GENERIC_ENTITY
, /* Entity */
789 TL_INSTANCE
, /* Instance */
790 INFO_CLASS_GENERIC
, /* Entity class */
791 INFO_TYPE_PROVIDER
, /* Entity type */
792 ENTITY_LIST_ID
, /* Entity id */
793 Entities
, /* Output buffer */
794 &BufferSize
); /* Output buffer size */
795 if (!NT_SUCCESS(Status
)) {
796 AFD_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
797 ExFreePool(Entities
);
801 /* Locate an IP entity */
802 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
804 AFD_DbgPrint(MAX_TRACE
, ("EntityCount = %u\n", EntityCount
));
806 for (i
= 0; i
< EntityCount
; i
++) {
807 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
) {
808 /* Query device for entity type */
810 BufferSize
= sizeof(EntityType
);
811 Status
= TdiQueryInformationEx(FileObject
, /* File object */
812 CL_NL_ENTITY
, /* Entity */
813 Entities
[i
].tei_instance
, /* Instance */
814 INFO_CLASS_GENERIC
, /* Entity class */
815 INFO_TYPE_PROVIDER
, /* Entity type */
816 ENTITY_TYPE_ID
, /* Entity id */
817 &EntityType
, /* Output buffer */
818 &BufferSize
); /* Output buffer size */
819 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
)) {
820 AFD_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
824 /* Query device for SNMP information */
826 BufferSize
= sizeof(SnmpInfo
);
827 Status
= TdiQueryInformationEx(FileObject
, /* File object */
828 CL_NL_ENTITY
, /* Entity */
829 Entities
[i
].tei_instance
, /* Instance */
830 INFO_CLASS_PROTOCOL
, /* Entity class */
831 INFO_TYPE_PROVIDER
, /* Entity type */
832 IP_MIB_STATS_ID
, /* Entity id */
833 &SnmpInfo
, /* Output buffer */
834 &BufferSize
); /* Output buffer size */
835 if (!NT_SUCCESS(Status
) || (SnmpInfo
.ipsi_numaddr
== 0)) {
836 AFD_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
840 /* Query device for all IP addresses */
842 if (SnmpInfo
.ipsi_numaddr
!= 0) {
843 BufferSize
= SnmpInfo
.ipsi_numaddr
* sizeof(IPADDR_ENTRY
);
844 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePool(NonPagedPool
, BufferSize
);
846 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
850 Status
= TdiQueryInformationEx(FileObject
, /* File object */
851 CL_NL_ENTITY
, /* Entity */
852 Entities
[i
].tei_instance
, /* Instance */
853 INFO_CLASS_PROTOCOL
, /* Entity class */
854 INFO_TYPE_PROVIDER
, /* Entity type */
855 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
856 IpAddress
, /* Output buffer */
857 &BufferSize
); /* Output buffer size */
858 if (!NT_SUCCESS(Status
)) {
859 AFD_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
860 ExFreePool(IpAddress
);
864 if (SnmpInfo
.ipsi_numaddr
!= 1) {
865 /* Skip loopback address */
866 *Address
= DN2H(IpAddress
[1].Addr
);
868 /* Select the first address returned */
869 *Address
= DN2H(IpAddress
->Addr
);
872 ExFreePool(IpAddress
);
874 Status
= STATUS_UNSUCCESSFUL
;
880 ExFreePool(Entities
);
882 AFD_DbgPrint(MAX_TRACE
, ("Leaving\n"));
889 PFILE_OBJECT TransportObject
,
893 PIO_COMPLETION_ROUTINE CompletionRoutine
,
894 PVOID CompletionContext
)
896 PDEVICE_OBJECT DeviceObject
;
899 ASSERT(*Irp
== NULL
);
901 if (!TransportObject
) {
902 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
903 return STATUS_INVALID_PARAMETER
;
906 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
908 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
909 return STATUS_INVALID_PARAMETER
;
912 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND
, /* Sub function */
913 DeviceObject
, /* Device object */
914 TransportObject
, /* File object */
919 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
920 return STATUS_INSUFFICIENT_RESOURCES
;
923 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
925 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
926 BufferLength
, /* Length of buffer */
927 FALSE
, /* Not secondary */
928 FALSE
, /* Don't charge quota */
929 NULL
); /* Don't use IRP */
931 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
932 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
934 return STATUS_INSUFFICIENT_RESOURCES
;
938 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
939 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
940 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
942 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
944 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
947 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
949 TdiBuildSend(*Irp
, /* I/O Request Packet */
950 DeviceObject
, /* Device object */
951 TransportObject
, /* File object */
952 CompletionRoutine
, /* Completion routine */
953 CompletionContext
, /* Completion context */
954 Mdl
, /* Data buffer */
956 BufferLength
); /* Length of data */
958 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
959 /* Does not block... The MDL is deleted in the receive completion
962 return STATUS_PENDING
;
967 PFILE_OBJECT TransportObject
,
971 PIO_COMPLETION_ROUTINE CompletionRoutine
,
972 PVOID CompletionContext
)
974 PDEVICE_OBJECT DeviceObject
;
977 ASSERT(*Irp
== NULL
);
979 if (!TransportObject
) {
980 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
981 return STATUS_INVALID_PARAMETER
;
984 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
986 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
987 return STATUS_INVALID_PARAMETER
;
990 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE
, /* Sub function */
991 DeviceObject
, /* Device object */
992 TransportObject
, /* File object */
997 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
998 return STATUS_INSUFFICIENT_RESOURCES
;
1001 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1003 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1004 BufferLength
, /* Length of buffer */
1005 FALSE
, /* Not secondary */
1006 FALSE
, /* Don't charge quota */
1007 NULL
); /* Don't use IRP */
1009 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1010 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1012 return STATUS_INSUFFICIENT_RESOURCES
;
1016 AFD_DbgPrint(MID_TRACE
, ("probe and lock\n"));
1017 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1018 AFD_DbgPrint(MID_TRACE
, ("probe and lock done\n"));
1019 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1020 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1022 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1024 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1027 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1029 TdiBuildReceive(*Irp
, /* I/O Request Packet */
1030 DeviceObject
, /* Device object */
1031 TransportObject
, /* File object */
1032 CompletionRoutine
, /* Completion routine */
1033 CompletionContext
, /* Completion context */
1034 Mdl
, /* Data buffer */
1036 BufferLength
); /* Length of data */
1039 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1040 /* Does not block... The MDL is deleted in the receive completion
1043 return STATUS_PENDING
;
1047 NTSTATUS
TdiReceiveDatagram(
1049 PFILE_OBJECT TransportObject
,
1053 PTDI_CONNECTION_INFORMATION Addr
,
1054 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1055 PVOID CompletionContext
)
1057 * FUNCTION: Receives a datagram
1059 * TransportObject = Pointer to transport object
1060 * From = Receive filter (NULL if none)
1061 * Address = Address of buffer to place remote address
1062 * Buffer = Address of buffer to place received data
1063 * BufferSize = Address of buffer with length of Buffer (updated)
1065 * Status of operation
1068 PDEVICE_OBJECT DeviceObject
;
1071 ASSERT(*Irp
== NULL
);
1073 if (!TransportObject
) {
1074 AFD_DbgPrint(MIN_TRACE
, ("Bad tranport object.\n"));
1075 return STATUS_INVALID_PARAMETER
;
1078 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1079 if (!DeviceObject
) {
1080 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1081 return STATUS_INVALID_PARAMETER
;
1084 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM
, /* Sub function */
1085 DeviceObject
, /* Device object */
1086 TransportObject
, /* File object */
1091 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1092 return STATUS_INSUFFICIENT_RESOURCES
;
1095 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1097 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1098 BufferLength
, /* Length of buffer */
1099 FALSE
, /* Not secondary */
1100 FALSE
, /* Don't charge quota */
1101 NULL
); /* Don't use IRP */
1103 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1104 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1106 return STATUS_INSUFFICIENT_RESOURCES
;
1110 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1111 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1112 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1114 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1116 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1119 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1121 TdiBuildReceiveDatagram(*Irp
, /* I/O Request Packet */
1122 DeviceObject
, /* Device object */
1123 TransportObject
, /* File object */
1124 CompletionRoutine
, /* Completion routine */
1125 CompletionContext
, /* Completion context */
1126 Mdl
, /* Data buffer */
1130 Flags
); /* Length of data */
1132 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1133 /* Does not block... The MDL is deleted in the receive completion
1136 return STATUS_PENDING
;
1140 NTSTATUS
TdiSendDatagram(
1142 PFILE_OBJECT TransportObject
,
1145 PTDI_CONNECTION_INFORMATION Addr
,
1146 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1147 PVOID CompletionContext
)
1149 * FUNCTION: Sends a datagram
1151 * TransportObject = Pointer to transport object
1152 * From = Send filter (NULL if none)
1153 * Address = Address of buffer to place remote address
1154 * Buffer = Address of buffer to place send data
1155 * BufferSize = Address of buffer with length of Buffer (updated)
1157 * Status of operation
1160 PDEVICE_OBJECT DeviceObject
;
1163 ASSERT(*Irp
== NULL
);
1165 if (!TransportObject
) {
1166 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1167 return STATUS_INVALID_PARAMETER
;
1170 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1172 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1173 if (!DeviceObject
) {
1174 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1175 return STATUS_INVALID_PARAMETER
;
1178 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM
, /* Sub function */
1179 DeviceObject
, /* Device object */
1180 TransportObject
, /* File object */
1185 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1186 return STATUS_INSUFFICIENT_RESOURCES
;
1189 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1191 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1192 BufferLength
, /* Length of buffer */
1193 FALSE
, /* Not secondary */
1194 FALSE
, /* Don't charge quota */
1195 NULL
); /* Don't use IRP */
1198 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1199 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1201 return STATUS_INSUFFICIENT_RESOURCES
;
1205 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1206 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1207 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1209 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1211 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1214 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1216 TdiBuildSendDatagram(*Irp
, /* I/O Request Packet */
1217 DeviceObject
, /* Device object */
1218 TransportObject
, /* File object */
1219 CompletionRoutine
, /* Completion routine */
1220 CompletionContext
, /* Completion context */
1221 Mdl
, /* Data buffer */
1222 BufferLength
, /* Bytes to send */
1223 Addr
); /* Address */
1225 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1226 /* Does not block... The MDL is deleted in the send completion
1229 return STATUS_PENDING
;
1232 NTSTATUS
TdiDisconnect(
1234 PFILE_OBJECT TransportObject
,
1235 PLARGE_INTEGER Time
,
1237 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1238 PVOID CompletionContext
,
1239 PTDI_CONNECTION_INFORMATION RequestConnectionInfo
,
1240 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
) {
1241 PDEVICE_OBJECT DeviceObject
;
1243 if (!TransportObject
) {
1244 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1245 return STATUS_INVALID_PARAMETER
;
1248 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1250 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1251 if (!DeviceObject
) {
1252 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1253 return STATUS_INVALID_PARAMETER
;
1256 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT
, /* Sub function */
1257 DeviceObject
, /* Device object */
1258 TransportObject
, /* File object */
1263 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1264 return STATUS_INSUFFICIENT_RESOURCES
;
1267 TdiBuildDisconnect(*Irp
, /* I/O Request Packet */
1268 DeviceObject
, /* Device object */
1269 TransportObject
, /* File object */
1270 CompletionRoutine
, /* Completion routine */
1271 CompletionContext
, /* Completion context */
1273 Flags
, /* Disconnect flags */
1274 RequestConnectionInfo
, /* Indication of who to disconnect */
1275 ReturnConnectionInfo
); /* Indication of who disconnected */
1277 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1279 return STATUS_PENDING
;