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_STATUS_BLOCK Iosb
,
333 PIO_COMPLETION_ROUTINE CompletionRoutine
,
334 PVOID CompletionContext
)
336 * FUNCTION: Connect a connection endpoint to a remote peer
338 * ConnectionObject = Pointer to connection endpoint file object
339 * RemoteAddress = Pointer to remote address
341 * Status of operation
344 PDEVICE_OBJECT DeviceObject
;
346 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
348 ASSERT(*Irp
== NULL
);
350 if (!ConnectionObject
) {
351 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
352 return STATUS_INVALID_PARAMETER
;
355 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
357 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
358 return STATUS_INVALID_PARAMETER
;
361 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_CONNECT
, /* Sub function */
362 DeviceObject
, /* Device object */
363 ConnectionObject
, /* File object */
367 return STATUS_INSUFFICIENT_RESOURCES
;
370 TdiBuildConnect(*Irp
, /* IRP */
371 DeviceObject
, /* Device object */
372 ConnectionObject
, /* File object */
373 CompletionRoutine
, /* Completion routine */
374 CompletionContext
, /* Completion routine context */
376 ConnectionCallInfo
, /* Request connection information */
377 ConnectionReturnInfo
); /* Return connection information */
379 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
381 return STATUS_PENDING
;
385 NTSTATUS
TdiAssociateAddressFile(
386 HANDLE AddressHandle
,
387 PFILE_OBJECT ConnectionObject
)
389 * FUNCTION: Associates a connection endpoint to an address file object
391 * AddressHandle = Handle to address file object
392 * ConnectionObject = Connection endpoint file object
394 * Status of operation
397 PDEVICE_OBJECT DeviceObject
;
398 IO_STATUS_BLOCK Iosb
;
402 AFD_DbgPrint(MAX_TRACE
, ("Called. AddressHandle (%p) ConnectionObject (%p)\n",
403 AddressHandle
, ConnectionObject
));
405 if (!ConnectionObject
) {
406 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
407 return STATUS_INVALID_PARAMETER
;
410 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
412 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
413 return STATUS_INVALID_PARAMETER
;
416 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
418 Irp
= TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS
, /* Sub function */
419 DeviceObject
, /* Device object */
420 ConnectionObject
, /* File object */
424 return STATUS_INSUFFICIENT_RESOURCES
;
426 TdiBuildAssociateAddress(Irp
,
433 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
436 NTSTATUS
TdiDisassociateAddressFile(
437 PFILE_OBJECT ConnectionObject
)
439 * FUNCTION: Disassociates a connection endpoint from an address file object
441 * ConnectionObject = Connection endpoint file object
443 * Status of operation
446 PDEVICE_OBJECT DeviceObject
;
447 IO_STATUS_BLOCK Iosb
;
451 AFD_DbgPrint(MAX_TRACE
, ("Called. ConnectionObject (%p)\n", ConnectionObject
));
453 if (!ConnectionObject
) {
454 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
455 return STATUS_INVALID_PARAMETER
;
458 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
460 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
461 return STATUS_INVALID_PARAMETER
;
464 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
466 Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS
, /* Sub function */
467 DeviceObject
, /* Device object */
468 ConnectionObject
, /* File object */
472 return STATUS_INSUFFICIENT_RESOURCES
;
474 TdiBuildDisassociateAddress(Irp
,
480 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
485 PFILE_OBJECT ConnectionObject
,
486 PTDI_CONNECTION_INFORMATION
*RequestConnectionInfo
,
487 PTDI_CONNECTION_INFORMATION
*ReturnConnectionInfo
,
488 PIO_STATUS_BLOCK Iosb
,
489 PIO_COMPLETION_ROUTINE CompletionRoutine
,
490 PVOID CompletionContext
)
492 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
494 * CompletionRoutine = Routine to be called when IRP is completed
495 * CompletionContext = Context for CompletionRoutine
497 * Status of operation
498 * May return STATUS_PENDING
501 PDEVICE_OBJECT DeviceObject
;
503 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
505 ASSERT(*Irp
== NULL
);
507 if (!ConnectionObject
) {
508 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
509 return STATUS_INVALID_PARAMETER
;
512 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
514 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
515 return STATUS_INVALID_PARAMETER
;
518 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_LISTEN
, /* Sub function */
519 DeviceObject
, /* Device object */
520 ConnectionObject
, /* File object */
524 return STATUS_INSUFFICIENT_RESOURCES
;
526 TdiBuildListen(*Irp
, /* IRP */
527 DeviceObject
, /* Device object */
528 ConnectionObject
, /* File object */
529 CompletionRoutine
, /* Completion routine */
530 CompletionContext
, /* Completion routine context */
532 *RequestConnectionInfo
, /* Request connection information */
533 *ReturnConnectionInfo
); /* Return connection information */
535 TdiCall(*Irp
, DeviceObject
, NULL
/* Don't wait for completion */, Iosb
);
537 return STATUS_PENDING
;
541 NTSTATUS
TdiSetEventHandler(
542 PFILE_OBJECT FileObject
,
547 * FUNCTION: Sets or resets an event handler
549 * FileObject = Pointer to file object
550 * EventType = Event code
551 * Handler = Event handler to be called when the event occurs
552 * Context = Context input to handler when the event occurs
554 * Status of operation
556 * Specify NULL for Handler to stop calling event handler
559 PDEVICE_OBJECT DeviceObject
;
560 IO_STATUS_BLOCK Iosb
;
564 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
567 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
568 return STATUS_INVALID_PARAMETER
;
571 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
573 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
574 return STATUS_INVALID_PARAMETER
;
577 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
579 Irp
= TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER
, /* Sub function */
580 DeviceObject
, /* Device object */
581 FileObject
, /* File object */
585 return STATUS_INSUFFICIENT_RESOURCES
;
589 TdiBuildSetEventHandler(Irp
,
598 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
602 NTSTATUS
TdiQueryDeviceControl(
603 PFILE_OBJECT FileObject
,
606 ULONG InputBufferLength
,
608 ULONG OutputBufferLength
,
611 * FUNCTION: Queries a device for information
613 * FileObject = Pointer to file object
614 * IoControlCode = I/O control code
615 * InputBuffer = Pointer to buffer with input data
616 * InputBufferLength = Length of InputBuffer
617 * OutputBuffer = Address of buffer to place output data
618 * OutputBufferLength = Length of OutputBuffer
620 * Status of operation
623 PDEVICE_OBJECT DeviceObject
;
624 IO_STATUS_BLOCK Iosb
;
630 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
631 return STATUS_INVALID_PARAMETER
;
634 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
636 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
637 return STATUS_INVALID_PARAMETER
;
640 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
642 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
652 return STATUS_INSUFFICIENT_RESOURCES
;
654 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
657 *Return
= Iosb
.Information
;
663 NTSTATUS
TdiQueryInformation(
664 PFILE_OBJECT FileObject
,
668 * FUNCTION: Query for information
670 * FileObject = Pointer to file object
671 * QueryType = Query type
672 * MdlBuffer = Pointer to MDL buffer specific for query type
674 * Status of operation
677 PDEVICE_OBJECT DeviceObject
;
678 IO_STATUS_BLOCK Iosb
;
683 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
684 return STATUS_INVALID_PARAMETER
;
687 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
689 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
690 return STATUS_INVALID_PARAMETER
;
693 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
695 Irp
= TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION
, /* Sub function */
696 DeviceObject
, /* Device object */
697 ConnectionObject
, /* File object */
701 return STATUS_INSUFFICIENT_RESOURCES
;
704 TdiBuildQueryInformation(Irp
,
712 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
715 NTSTATUS
TdiQueryInformationEx(
716 PFILE_OBJECT FileObject
,
725 * FUNCTION: Extended query for information
727 * FileObject = Pointer to file object
729 * Instance = Instance
730 * Class = Entity class
733 * OutputBuffer = Address of buffer to place data
734 * OutputLength = Address of buffer with length of OutputBuffer (updated)
736 * Status of operation
739 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
741 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
742 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
743 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
744 QueryInfo
.ID
.toi_class
= Class
;
745 QueryInfo
.ID
.toi_type
= Type
;
746 QueryInfo
.ID
.toi_id
= Id
;
748 return TdiQueryDeviceControl(FileObject
, /* Transport/connection object */
749 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
750 &QueryInfo
, /* Input buffer */
751 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
752 OutputBuffer
, /* Output buffer */
753 *OutputLength
, /* Output buffer length */
754 OutputLength
); /* Return information */
757 NTSTATUS
TdiQueryAddress(
758 PFILE_OBJECT FileObject
,
761 * FUNCTION: Queries for a local IP address
763 * FileObject = Pointer to file object
764 * Address = Address of buffer to place local address
766 * Status of operation
770 TDIEntityID
*Entities
;
773 IPSNMP_INFO SnmpInfo
;
774 PIPADDR_ENTRY IpAddress
;
776 NTSTATUS Status
= STATUS_SUCCESS
;
778 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
780 BufferSize
= sizeof(TDIEntityID
) * 20;
781 Entities
= (TDIEntityID
*)ExAllocatePool(NonPagedPool
, BufferSize
);
783 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
784 return STATUS_INSUFFICIENT_RESOURCES
;
787 /* Query device for supported entities */
789 Status
= TdiQueryInformationEx(FileObject
, /* File object */
790 GENERIC_ENTITY
, /* Entity */
791 TL_INSTANCE
, /* Instance */
792 INFO_CLASS_GENERIC
, /* Entity class */
793 INFO_TYPE_PROVIDER
, /* Entity type */
794 ENTITY_LIST_ID
, /* Entity id */
795 Entities
, /* Output buffer */
796 &BufferSize
); /* Output buffer size */
797 if (!NT_SUCCESS(Status
)) {
798 AFD_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
799 ExFreePool(Entities
);
803 /* Locate an IP entity */
804 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
806 AFD_DbgPrint(MAX_TRACE
, ("EntityCount = %u\n", EntityCount
));
808 for (i
= 0; i
< EntityCount
; i
++) {
809 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
) {
810 /* Query device for entity type */
812 BufferSize
= sizeof(EntityType
);
813 Status
= TdiQueryInformationEx(FileObject
, /* File object */
814 CL_NL_ENTITY
, /* Entity */
815 Entities
[i
].tei_instance
, /* Instance */
816 INFO_CLASS_GENERIC
, /* Entity class */
817 INFO_TYPE_PROVIDER
, /* Entity type */
818 ENTITY_TYPE_ID
, /* Entity id */
819 &EntityType
, /* Output buffer */
820 &BufferSize
); /* Output buffer size */
821 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
)) {
822 AFD_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
826 /* Query device for SNMP information */
828 BufferSize
= sizeof(SnmpInfo
);
829 Status
= TdiQueryInformationEx(FileObject
, /* File object */
830 CL_NL_ENTITY
, /* Entity */
831 Entities
[i
].tei_instance
, /* Instance */
832 INFO_CLASS_PROTOCOL
, /* Entity class */
833 INFO_TYPE_PROVIDER
, /* Entity type */
834 IP_MIB_STATS_ID
, /* Entity id */
835 &SnmpInfo
, /* Output buffer */
836 &BufferSize
); /* Output buffer size */
837 if (!NT_SUCCESS(Status
) || (SnmpInfo
.NumAddr
== 0)) {
838 AFD_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
842 /* Query device for all IP addresses */
844 if (SnmpInfo
.NumAddr
!= 0) {
845 BufferSize
= SnmpInfo
.NumAddr
* sizeof(IPADDR_ENTRY
);
846 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePool(NonPagedPool
, BufferSize
);
848 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
852 Status
= TdiQueryInformationEx(FileObject
, /* File object */
853 CL_NL_ENTITY
, /* Entity */
854 Entities
[i
].tei_instance
, /* Instance */
855 INFO_CLASS_PROTOCOL
, /* Entity class */
856 INFO_TYPE_PROVIDER
, /* Entity type */
857 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
858 IpAddress
, /* Output buffer */
859 &BufferSize
); /* Output buffer size */
860 if (!NT_SUCCESS(Status
)) {
861 AFD_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
862 ExFreePool(IpAddress
);
866 if (SnmpInfo
.NumAddr
!= 1) {
867 /* Skip loopback address */
868 *Address
= DN2H(IpAddress
[1].Addr
);
870 /* Select the first address returned */
871 *Address
= DN2H(IpAddress
->Addr
);
874 ExFreePool(IpAddress
);
876 Status
= STATUS_UNSUCCESSFUL
;
882 ExFreePool(Entities
);
884 AFD_DbgPrint(MAX_TRACE
, ("Leaving\n"));
891 PFILE_OBJECT TransportObject
,
895 PIO_STATUS_BLOCK Iosb
,
896 PIO_COMPLETION_ROUTINE CompletionRoutine
,
897 PVOID CompletionContext
)
899 PDEVICE_OBJECT DeviceObject
;
902 ASSERT(*Irp
== NULL
);
904 if (!TransportObject
) {
905 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
906 return STATUS_INVALID_PARAMETER
;
909 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
911 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
912 return STATUS_INVALID_PARAMETER
;
915 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND
, /* Sub function */
916 DeviceObject
, /* Device object */
917 TransportObject
, /* File object */
922 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
923 return STATUS_INSUFFICIENT_RESOURCES
;
926 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
928 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
929 BufferLength
, /* Length of buffer */
930 FALSE
, /* Not secondary */
931 FALSE
, /* Don't charge quota */
932 NULL
); /* Don't use IRP */
934 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
935 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
937 return STATUS_INSUFFICIENT_RESOURCES
;
941 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
942 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
943 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
945 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
947 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
950 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
952 TdiBuildSend(*Irp
, /* I/O Request Packet */
953 DeviceObject
, /* Device object */
954 TransportObject
, /* File object */
955 CompletionRoutine
, /* Completion routine */
956 CompletionContext
, /* Completion context */
957 Mdl
, /* Data buffer */
959 BufferLength
); /* Length of data */
961 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
962 /* Does not block... The MDL is deleted in the receive completion
965 return STATUS_PENDING
;
970 PFILE_OBJECT TransportObject
,
974 PIO_STATUS_BLOCK Iosb
,
975 PIO_COMPLETION_ROUTINE CompletionRoutine
,
976 PVOID CompletionContext
)
978 PDEVICE_OBJECT DeviceObject
;
981 ASSERT(*Irp
== NULL
);
983 if (!TransportObject
) {
984 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
985 return STATUS_INVALID_PARAMETER
;
988 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
990 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
991 return STATUS_INVALID_PARAMETER
;
994 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE
, /* Sub function */
995 DeviceObject
, /* Device object */
996 TransportObject
, /* File object */
1001 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1002 return STATUS_INSUFFICIENT_RESOURCES
;
1005 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1007 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1008 BufferLength
, /* Length of buffer */
1009 FALSE
, /* Not secondary */
1010 FALSE
, /* Don't charge quota */
1011 NULL
); /* Don't use IRP */
1013 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1014 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1016 return STATUS_INSUFFICIENT_RESOURCES
;
1020 AFD_DbgPrint(MID_TRACE
, ("probe and lock\n"));
1021 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1022 AFD_DbgPrint(MID_TRACE
, ("probe and lock done\n"));
1023 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1024 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1026 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1028 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1031 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1033 TdiBuildReceive(*Irp
, /* I/O Request Packet */
1034 DeviceObject
, /* Device object */
1035 TransportObject
, /* File object */
1036 CompletionRoutine
, /* Completion routine */
1037 CompletionContext
, /* Completion context */
1038 Mdl
, /* Data buffer */
1040 BufferLength
); /* Length of data */
1043 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1044 /* Does not block... The MDL is deleted in the receive completion
1047 return STATUS_PENDING
;
1051 NTSTATUS
TdiReceiveDatagram(
1053 PFILE_OBJECT TransportObject
,
1057 PTDI_CONNECTION_INFORMATION Addr
,
1058 PIO_STATUS_BLOCK Iosb
,
1059 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1060 PVOID CompletionContext
)
1062 * FUNCTION: Receives a datagram
1064 * TransportObject = Pointer to transport object
1065 * From = Receive filter (NULL if none)
1066 * Address = Address of buffer to place remote address
1067 * Buffer = Address of buffer to place received data
1068 * BufferSize = Address of buffer with length of Buffer (updated)
1070 * Status of operation
1073 PDEVICE_OBJECT DeviceObject
;
1076 ASSERT(*Irp
== NULL
);
1078 if (!TransportObject
) {
1079 AFD_DbgPrint(MIN_TRACE
, ("Bad tranport object.\n"));
1080 return STATUS_INVALID_PARAMETER
;
1083 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1084 if (!DeviceObject
) {
1085 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1086 return STATUS_INVALID_PARAMETER
;
1089 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM
, /* Sub function */
1090 DeviceObject
, /* Device object */
1091 TransportObject
, /* File object */
1096 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1097 return STATUS_INSUFFICIENT_RESOURCES
;
1100 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1102 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1103 BufferLength
, /* Length of buffer */
1104 FALSE
, /* Not secondary */
1105 FALSE
, /* Don't charge quota */
1106 NULL
); /* Don't use IRP */
1108 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1109 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1111 return STATUS_INSUFFICIENT_RESOURCES
;
1115 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1116 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1117 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1119 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1121 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1124 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1126 TdiBuildReceiveDatagram(*Irp
, /* I/O Request Packet */
1127 DeviceObject
, /* Device object */
1128 TransportObject
, /* File object */
1129 CompletionRoutine
, /* Completion routine */
1130 CompletionContext
, /* Completion context */
1131 Mdl
, /* Data buffer */
1135 Flags
); /* Length of data */
1137 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1138 /* Does not block... The MDL is deleted in the receive completion
1141 return STATUS_PENDING
;
1145 NTSTATUS
TdiSendDatagram(
1147 PFILE_OBJECT TransportObject
,
1150 PTDI_CONNECTION_INFORMATION Addr
,
1151 PIO_STATUS_BLOCK Iosb
,
1152 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1153 PVOID CompletionContext
)
1155 * FUNCTION: Sends a datagram
1157 * TransportObject = Pointer to transport object
1158 * From = Send filter (NULL if none)
1159 * Address = Address of buffer to place remote address
1160 * Buffer = Address of buffer to place send data
1161 * BufferSize = Address of buffer with length of Buffer (updated)
1163 * Status of operation
1166 PDEVICE_OBJECT DeviceObject
;
1169 ASSERT(*Irp
== NULL
);
1171 if (!TransportObject
) {
1172 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1173 return STATUS_INVALID_PARAMETER
;
1176 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1178 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1179 if (!DeviceObject
) {
1180 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1181 return STATUS_INVALID_PARAMETER
;
1184 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM
, /* Sub function */
1185 DeviceObject
, /* Device object */
1186 TransportObject
, /* File object */
1191 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1192 return STATUS_INSUFFICIENT_RESOURCES
;
1195 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1197 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1198 BufferLength
, /* Length of buffer */
1199 FALSE
, /* Not secondary */
1200 FALSE
, /* Don't charge quota */
1201 NULL
); /* Don't use IRP */
1204 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1205 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1207 return STATUS_INSUFFICIENT_RESOURCES
;
1211 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1212 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1213 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1215 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1217 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1220 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1222 TdiBuildSendDatagram(*Irp
, /* I/O Request Packet */
1223 DeviceObject
, /* Device object */
1224 TransportObject
, /* File object */
1225 CompletionRoutine
, /* Completion routine */
1226 CompletionContext
, /* Completion context */
1227 Mdl
, /* Data buffer */
1228 BufferLength
, /* Bytes to send */
1229 Addr
); /* Address */
1231 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1232 /* Does not block... The MDL is deleted in the send completion
1235 return STATUS_PENDING
;
1238 NTSTATUS
TdiDisconnect(
1240 PFILE_OBJECT TransportObject
,
1241 PLARGE_INTEGER Time
,
1243 PIO_STATUS_BLOCK Iosb
,
1244 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1245 PVOID CompletionContext
,
1246 PTDI_CONNECTION_INFORMATION RequestConnectionInfo
,
1247 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
) {
1248 PDEVICE_OBJECT DeviceObject
;
1250 if (!TransportObject
) {
1251 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1252 return STATUS_INVALID_PARAMETER
;
1255 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1257 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1258 if (!DeviceObject
) {
1259 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1260 return STATUS_INVALID_PARAMETER
;
1263 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT
, /* Sub function */
1264 DeviceObject
, /* Device object */
1265 TransportObject
, /* File object */
1270 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1271 return STATUS_INSUFFICIENT_RESOURCES
;
1274 TdiBuildDisconnect(*Irp
, /* I/O Request Packet */
1275 DeviceObject
, /* Device object */
1276 TransportObject
, /* File object */
1277 CompletionRoutine
, /* Completion routine */
1278 CompletionContext
, /* Completion context */
1280 Flags
, /* Disconnect flags */
1281 RequestConnectionInfo
, /* Indication of who to disconnect */
1282 ReturnConnectionInfo
); /* Indication of who disconnected */
1284 TdiCall(*Irp
, DeviceObject
, NULL
, Iosb
);
1286 return STATUS_PENDING
;