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
)ExAllocatePoolWithTag(NonPagedPool
,
203 return STATUS_INSUFFICIENT_RESOURCES
;
205 RtlZeroMemory(EaInfo
, EaLength
);
206 EaInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
207 /* Don't copy the terminating 0; we have already zeroed it */
208 RtlCopyMemory(EaInfo
->EaName
,
210 TDI_TRANSPORT_ADDRESS_LENGTH
);
211 EaInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
213 (PTRANSPORT_ADDRESS
)(EaInfo
->EaName
+ TDI_TRANSPORT_ADDRESS_LENGTH
+ 1); /* 0-terminated */
214 TaCopyTransportAddressInPlace( Address
, Name
);
216 Status
= TdiOpenDevice(DeviceName
,
222 ExFreePoolWithTag(EaInfo
, TAG_AFD_EA_INFO
);
226 NTSTATUS
TdiQueryMaxDatagramLength(
227 PFILE_OBJECT FileObject
,
228 PUINT MaxDatagramLength
)
231 PTDI_MAX_DATAGRAM_INFO Buffer
;
232 NTSTATUS Status
= STATUS_SUCCESS
;
234 Buffer
= ExAllocatePoolWithTag(NonPagedPool
,
235 sizeof(TDI_MAX_DATAGRAM_INFO
),
236 TAG_AFD_DATA_BUFFER
);
238 if (!Buffer
) return STATUS_NO_MEMORY
;
240 Mdl
= IoAllocateMdl(Buffer
, sizeof(TDI_MAX_DATAGRAM_INFO
), FALSE
, FALSE
, NULL
);
243 ExFreePoolWithTag(Buffer
, TAG_AFD_DATA_BUFFER
);
244 return STATUS_NO_MEMORY
;
249 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
251 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
253 Status
= _SEH2_GetExceptionCode();
257 if (!NT_SUCCESS(Status
))
259 AFD_DbgPrint(MIN_TRACE
,("Failed to lock pages\n"));
261 ExFreePoolWithTag(Buffer
, TAG_AFD_DATA_BUFFER
);
265 Status
= TdiQueryInformation(FileObject
,
266 TDI_QUERY_MAX_DATAGRAM_INFO
,
268 if (!NT_SUCCESS(Status
))
270 ExFreePoolWithTag(Buffer
, TAG_AFD_DATA_BUFFER
);
274 *MaxDatagramLength
= Buffer
->MaxDatagramSize
;
276 ExFreePoolWithTag(Buffer
, TAG_AFD_DATA_BUFFER
);
278 return STATUS_SUCCESS
;
281 NTSTATUS
TdiOpenConnectionEndpointFile(
282 PUNICODE_STRING DeviceName
,
283 PHANDLE ConnectionHandle
,
284 PFILE_OBJECT
*ConnectionObject
)
286 * FUNCTION: Opens a connection endpoint file object
288 * DeviceName = Pointer to counted string with name of device
289 * ConnectionHandle = Address of buffer to place connection endpoint file handle
290 * ConnectionObject = Address of buffer to place connection endpoint file object
292 * Status of operation
295 PFILE_FULL_EA_INFORMATION EaInfo
;
300 AFD_DbgPrint(MAX_TRACE
, ("Called. DeviceName (%wZ)\n", DeviceName
));
302 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
303 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) +
304 TDI_CONNECTION_CONTEXT_LENGTH
+
307 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePoolWithTag(NonPagedPool
,
311 return STATUS_INSUFFICIENT_RESOURCES
;
313 RtlZeroMemory(EaInfo
, EaLength
);
314 EaInfo
->EaNameLength
= TDI_CONNECTION_CONTEXT_LENGTH
;
315 /* Don't copy the terminating 0; we have already zeroed it */
316 RtlCopyMemory(EaInfo
->EaName
,
317 TdiConnectionContext
,
318 TDI_CONNECTION_CONTEXT_LENGTH
);
319 EaInfo
->EaValueLength
= sizeof(PVOID
);
320 ContextArea
= (PVOID
*)(EaInfo
->EaName
+ TDI_CONNECTION_CONTEXT_LENGTH
+ 1); /* 0-terminated */
321 /* FIXME: Allocate context area */
323 Status
= TdiOpenDevice(DeviceName
,
329 ExFreePoolWithTag(EaInfo
, TAG_AFD_EA_INFO
);
336 PFILE_OBJECT ConnectionObject
,
337 PTDI_CONNECTION_INFORMATION ConnectionCallInfo
,
338 PTDI_CONNECTION_INFORMATION ConnectionReturnInfo
,
339 PIO_COMPLETION_ROUTINE CompletionRoutine
,
340 PVOID CompletionContext
)
342 * FUNCTION: Connect a connection endpoint to a remote peer
344 * ConnectionObject = Pointer to connection endpoint file object
345 * RemoteAddress = Pointer to remote address
347 * Status of operation
350 PDEVICE_OBJECT DeviceObject
;
352 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
354 ASSERT(*Irp
== NULL
);
356 if (!ConnectionObject
) {
357 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
358 return STATUS_INVALID_PARAMETER
;
361 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
363 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
364 return STATUS_INVALID_PARAMETER
;
367 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_CONNECT
, /* Sub function */
368 DeviceObject
, /* Device object */
369 ConnectionObject
, /* File object */
373 return STATUS_INSUFFICIENT_RESOURCES
;
376 TdiBuildConnect(*Irp
, /* IRP */
377 DeviceObject
, /* Device object */
378 ConnectionObject
, /* File object */
379 CompletionRoutine
, /* Completion routine */
380 CompletionContext
, /* Completion routine context */
382 ConnectionCallInfo
, /* Request connection information */
383 ConnectionReturnInfo
); /* Return connection information */
385 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
387 return STATUS_PENDING
;
391 NTSTATUS
TdiAssociateAddressFile(
392 HANDLE AddressHandle
,
393 PFILE_OBJECT ConnectionObject
)
395 * FUNCTION: Associates a connection endpoint to an address file object
397 * AddressHandle = Handle to address file object
398 * ConnectionObject = Connection endpoint file object
400 * Status of operation
403 PDEVICE_OBJECT DeviceObject
;
404 IO_STATUS_BLOCK Iosb
;
408 AFD_DbgPrint(MAX_TRACE
, ("Called. AddressHandle (%p) ConnectionObject (%p)\n",
409 AddressHandle
, ConnectionObject
));
411 if (!ConnectionObject
) {
412 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
413 return STATUS_INVALID_PARAMETER
;
416 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
418 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
419 return STATUS_INVALID_PARAMETER
;
422 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
424 Irp
= TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS
, /* Sub function */
425 DeviceObject
, /* Device object */
426 ConnectionObject
, /* File object */
430 return STATUS_INSUFFICIENT_RESOURCES
;
432 TdiBuildAssociateAddress(Irp
,
439 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
442 NTSTATUS
TdiDisassociateAddressFile(
443 PFILE_OBJECT ConnectionObject
)
445 * FUNCTION: Disassociates a connection endpoint from an address file object
447 * ConnectionObject = Connection endpoint file object
449 * Status of operation
452 PDEVICE_OBJECT DeviceObject
;
453 IO_STATUS_BLOCK Iosb
;
457 AFD_DbgPrint(MAX_TRACE
, ("Called. ConnectionObject (%p)\n", ConnectionObject
));
459 if (!ConnectionObject
) {
460 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
461 return STATUS_INVALID_PARAMETER
;
464 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
466 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
467 return STATUS_INVALID_PARAMETER
;
470 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
472 Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS
, /* Sub function */
473 DeviceObject
, /* Device object */
474 ConnectionObject
, /* File object */
478 return STATUS_INSUFFICIENT_RESOURCES
;
480 TdiBuildDisassociateAddress(Irp
,
486 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
491 PFILE_OBJECT ConnectionObject
,
492 PTDI_CONNECTION_INFORMATION
*RequestConnectionInfo
,
493 PTDI_CONNECTION_INFORMATION
*ReturnConnectionInfo
,
494 PIO_COMPLETION_ROUTINE CompletionRoutine
,
495 PVOID CompletionContext
)
497 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
499 * CompletionRoutine = Routine to be called when IRP is completed
500 * CompletionContext = Context for CompletionRoutine
502 * Status of operation
503 * May return STATUS_PENDING
506 PDEVICE_OBJECT DeviceObject
;
508 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
510 ASSERT(*Irp
== NULL
);
512 if (!ConnectionObject
) {
513 AFD_DbgPrint(MIN_TRACE
, ("Bad connection object.\n"));
514 return STATUS_INVALID_PARAMETER
;
517 DeviceObject
= IoGetRelatedDeviceObject(ConnectionObject
);
519 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
520 return STATUS_INVALID_PARAMETER
;
523 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_LISTEN
, /* Sub function */
524 DeviceObject
, /* Device object */
525 ConnectionObject
, /* File object */
529 return STATUS_INSUFFICIENT_RESOURCES
;
531 TdiBuildListen(*Irp
, /* IRP */
532 DeviceObject
, /* Device object */
533 ConnectionObject
, /* File object */
534 CompletionRoutine
, /* Completion routine */
535 CompletionContext
, /* Completion routine context */
537 *RequestConnectionInfo
, /* Request connection information */
538 *ReturnConnectionInfo
); /* Return connection information */
540 TdiCall(*Irp
, DeviceObject
, NULL
/* Don't wait for completion */, NULL
);
542 return STATUS_PENDING
;
546 NTSTATUS
TdiSetEventHandler(
547 PFILE_OBJECT FileObject
,
552 * FUNCTION: Sets or resets an event handler
554 * FileObject = Pointer to file object
555 * EventType = Event code
556 * Handler = Event handler to be called when the event occurs
557 * Context = Context input to handler when the event occurs
559 * Status of operation
561 * Specify NULL for Handler to stop calling event handler
564 PDEVICE_OBJECT DeviceObject
;
565 IO_STATUS_BLOCK Iosb
;
569 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
572 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
573 return STATUS_INVALID_PARAMETER
;
576 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
578 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
579 return STATUS_INVALID_PARAMETER
;
582 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
584 Irp
= TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER
, /* Sub function */
585 DeviceObject
, /* Device object */
586 FileObject
, /* File object */
590 return STATUS_INSUFFICIENT_RESOURCES
;
594 TdiBuildSetEventHandler(Irp
,
603 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
607 NTSTATUS
TdiQueryDeviceControl(
608 PFILE_OBJECT FileObject
,
611 ULONG InputBufferLength
,
613 ULONG OutputBufferLength
,
616 * FUNCTION: Queries a device for information
618 * FileObject = Pointer to file object
619 * IoControlCode = I/O control code
620 * InputBuffer = Pointer to buffer with input data
621 * InputBufferLength = Length of InputBuffer
622 * OutputBuffer = Address of buffer to place output data
623 * OutputBufferLength = Length of OutputBuffer
625 * Status of operation
628 PDEVICE_OBJECT DeviceObject
;
629 IO_STATUS_BLOCK Iosb
;
635 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
636 return STATUS_INVALID_PARAMETER
;
639 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
641 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
642 return STATUS_INVALID_PARAMETER
;
645 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
647 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
,
657 return STATUS_INSUFFICIENT_RESOURCES
;
659 Status
= TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
662 *Return
= Iosb
.Information
;
668 NTSTATUS
TdiQueryInformation(
669 PFILE_OBJECT FileObject
,
673 * FUNCTION: Query for information
675 * FileObject = Pointer to file object
676 * QueryType = Query type
677 * MdlBuffer = Pointer to MDL buffer specific for query type
679 * Status of operation
682 PDEVICE_OBJECT DeviceObject
;
683 IO_STATUS_BLOCK Iosb
;
688 AFD_DbgPrint(MIN_TRACE
, ("Bad file object.\n"));
689 return STATUS_INVALID_PARAMETER
;
692 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
694 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
695 return STATUS_INVALID_PARAMETER
;
698 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
700 Irp
= TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION
, /* Sub function */
701 DeviceObject
, /* Device object */
702 ConnectionObject
, /* File object */
706 return STATUS_INSUFFICIENT_RESOURCES
;
709 TdiBuildQueryInformation(Irp
,
717 return TdiCall(Irp
, DeviceObject
, &Event
, &Iosb
);
720 NTSTATUS
TdiQueryInformationEx(
721 PFILE_OBJECT FileObject
,
730 * FUNCTION: Extended query for information
732 * FileObject = Pointer to file object
734 * Instance = Instance
735 * Class = Entity class
738 * OutputBuffer = Address of buffer to place data
739 * OutputLength = Address of buffer with length of OutputBuffer (updated)
741 * Status of operation
744 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
746 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
747 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
748 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
749 QueryInfo
.ID
.toi_class
= Class
;
750 QueryInfo
.ID
.toi_type
= Type
;
751 QueryInfo
.ID
.toi_id
= Id
;
753 return TdiQueryDeviceControl(FileObject
, /* Transport/connection object */
754 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
755 &QueryInfo
, /* Input buffer */
756 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
757 OutputBuffer
, /* Output buffer */
758 *OutputLength
, /* Output buffer length */
759 OutputLength
); /* Return information */
762 NTSTATUS
TdiQueryAddress(
763 PFILE_OBJECT FileObject
,
766 * FUNCTION: Queries for a local IP address
768 * FileObject = Pointer to file object
769 * Address = Address of buffer to place local address
771 * Status of operation
775 TDIEntityID
*Entities
;
779 PIPADDR_ENTRY IpAddress
;
781 NTSTATUS Status
= STATUS_SUCCESS
;
783 AFD_DbgPrint(MAX_TRACE
, ("Called\n"));
785 BufferSize
= sizeof(TDIEntityID
) * 20;
786 Entities
= (TDIEntityID
*)ExAllocatePoolWithTag(NonPagedPool
,
788 TAG_AFD_TRANSPORT_ADDRESS
);
790 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
791 return STATUS_INSUFFICIENT_RESOURCES
;
794 /* Query device for supported entities */
796 Status
= TdiQueryInformationEx(FileObject
, /* File object */
797 GENERIC_ENTITY
, /* Entity */
798 TL_INSTANCE
, /* Instance */
799 INFO_CLASS_GENERIC
, /* Entity class */
800 INFO_TYPE_PROVIDER
, /* Entity type */
801 ENTITY_LIST_ID
, /* Entity id */
802 Entities
, /* Output buffer */
803 &BufferSize
); /* Output buffer size */
804 if (!NT_SUCCESS(Status
)) {
805 AFD_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
806 ExFreePoolWithTag(Entities
, TAG_AFD_TRANSPORT_ADDRESS
);
810 /* Locate an IP entity */
811 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
813 AFD_DbgPrint(MAX_TRACE
, ("EntityCount = %u\n", EntityCount
));
815 for (i
= 0; i
< EntityCount
; i
++) {
816 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
) {
817 /* Query device for entity type */
819 BufferSize
= sizeof(EntityType
);
820 Status
= TdiQueryInformationEx(FileObject
, /* File object */
821 CL_NL_ENTITY
, /* Entity */
822 Entities
[i
].tei_instance
, /* Instance */
823 INFO_CLASS_GENERIC
, /* Entity class */
824 INFO_TYPE_PROVIDER
, /* Entity type */
825 ENTITY_TYPE_ID
, /* Entity id */
826 &EntityType
, /* Output buffer */
827 &BufferSize
); /* Output buffer size */
828 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
)) {
829 AFD_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
833 /* Query device for SNMP information */
835 BufferSize
= sizeof(SnmpInfo
);
836 Status
= TdiQueryInformationEx(FileObject
, /* File object */
837 CL_NL_ENTITY
, /* Entity */
838 Entities
[i
].tei_instance
, /* Instance */
839 INFO_CLASS_PROTOCOL
, /* Entity class */
840 INFO_TYPE_PROVIDER
, /* Entity type */
841 IP_MIB_STATS_ID
, /* Entity id */
842 &SnmpInfo
, /* Output buffer */
843 &BufferSize
); /* Output buffer size */
844 if (!NT_SUCCESS(Status
) || (SnmpInfo
.ipsi_numaddr
== 0)) {
845 AFD_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
849 /* Query device for all IP addresses */
851 if (SnmpInfo
.ipsi_numaddr
!= 0) {
852 BufferSize
= SnmpInfo
.ipsi_numaddr
* sizeof(IPADDR_ENTRY
);
853 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePoolWithTag(NonPagedPool
,
855 TAG_AFD_SNMP_ADDRESS_INFO
);
857 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
861 Status
= TdiQueryInformationEx(FileObject
, /* File object */
862 CL_NL_ENTITY
, /* Entity */
863 Entities
[i
].tei_instance
, /* Instance */
864 INFO_CLASS_PROTOCOL
, /* Entity class */
865 INFO_TYPE_PROVIDER
, /* Entity type */
866 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
867 IpAddress
, /* Output buffer */
868 &BufferSize
); /* Output buffer size */
869 if (!NT_SUCCESS(Status
)) {
870 AFD_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
871 ExFreePoolWithTag(IpAddress
, TAG_AFD_SNMP_ADDRESS_INFO
);
875 if (SnmpInfo
.ipsi_numaddr
!= 1) {
876 /* Skip loopback address */
877 *Address
= DN2H(IpAddress
[1].Addr
);
879 /* Select the first address returned */
880 *Address
= DN2H(IpAddress
->Addr
);
883 ExFreePoolWithTag(IpAddress
, TAG_AFD_SNMP_ADDRESS_INFO
);
885 Status
= STATUS_UNSUCCESSFUL
;
891 ExFreePoolWithTag(Entities
, TAG_AFD_TRANSPORT_ADDRESS
);
893 AFD_DbgPrint(MAX_TRACE
, ("Leaving\n"));
900 PFILE_OBJECT TransportObject
,
904 PIO_COMPLETION_ROUTINE CompletionRoutine
,
905 PVOID CompletionContext
)
907 PDEVICE_OBJECT DeviceObject
;
910 ASSERT(*Irp
== NULL
);
912 if (!TransportObject
) {
913 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
914 return STATUS_INVALID_PARAMETER
;
917 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
919 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
920 return STATUS_INVALID_PARAMETER
;
923 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND
, /* Sub function */
924 DeviceObject
, /* Device object */
925 TransportObject
, /* File object */
930 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
931 return STATUS_INSUFFICIENT_RESOURCES
;
934 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
936 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
937 BufferLength
, /* Length of buffer */
938 FALSE
, /* Not secondary */
939 FALSE
, /* Don't charge quota */
940 NULL
); /* Don't use IRP */
942 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
943 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
945 return STATUS_INSUFFICIENT_RESOURCES
;
949 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoReadAccess
);
950 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
951 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
953 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
955 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
958 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
960 TdiBuildSend(*Irp
, /* I/O Request Packet */
961 DeviceObject
, /* Device object */
962 TransportObject
, /* File object */
963 CompletionRoutine
, /* Completion routine */
964 CompletionContext
, /* Completion context */
965 Mdl
, /* Data buffer */
967 BufferLength
); /* Length of data */
969 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
970 /* Does not block... The MDL is deleted in the receive completion
973 return STATUS_PENDING
;
978 PFILE_OBJECT TransportObject
,
982 PIO_COMPLETION_ROUTINE CompletionRoutine
,
983 PVOID CompletionContext
)
985 PDEVICE_OBJECT DeviceObject
;
988 ASSERT(*Irp
== NULL
);
990 if (!TransportObject
) {
991 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
992 return STATUS_INVALID_PARAMETER
;
995 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
997 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
998 return STATUS_INVALID_PARAMETER
;
1001 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE
, /* Sub function */
1002 DeviceObject
, /* Device object */
1003 TransportObject
, /* File object */
1008 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1009 return STATUS_INSUFFICIENT_RESOURCES
;
1012 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1014 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1015 BufferLength
, /* Length of buffer */
1016 FALSE
, /* Not secondary */
1017 FALSE
, /* Don't charge quota */
1018 NULL
); /* Don't use IRP */
1020 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1021 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1023 return STATUS_INSUFFICIENT_RESOURCES
;
1027 AFD_DbgPrint(MID_TRACE
, ("probe and lock\n"));
1028 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1029 AFD_DbgPrint(MID_TRACE
, ("probe and lock done\n"));
1030 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1031 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1033 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1035 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1038 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1040 TdiBuildReceive(*Irp
, /* I/O Request Packet */
1041 DeviceObject
, /* Device object */
1042 TransportObject
, /* File object */
1043 CompletionRoutine
, /* Completion routine */
1044 CompletionContext
, /* Completion context */
1045 Mdl
, /* Data buffer */
1047 BufferLength
); /* Length of data */
1050 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1051 /* Does not block... The MDL is deleted in the receive completion
1054 return STATUS_PENDING
;
1058 NTSTATUS
TdiReceiveDatagram(
1060 PFILE_OBJECT TransportObject
,
1064 PTDI_CONNECTION_INFORMATION Addr
,
1065 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1066 PVOID CompletionContext
)
1068 * FUNCTION: Receives a datagram
1070 * TransportObject = Pointer to transport object
1071 * From = Receive filter (NULL if none)
1072 * Address = Address of buffer to place remote address
1073 * Buffer = Address of buffer to place received data
1074 * BufferSize = Address of buffer with length of Buffer (updated)
1076 * Status of operation
1079 PDEVICE_OBJECT DeviceObject
;
1082 ASSERT(*Irp
== NULL
);
1084 if (!TransportObject
) {
1085 AFD_DbgPrint(MIN_TRACE
, ("Bad tranport object.\n"));
1086 return STATUS_INVALID_PARAMETER
;
1089 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1090 if (!DeviceObject
) {
1091 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1092 return STATUS_INVALID_PARAMETER
;
1095 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM
, /* Sub function */
1096 DeviceObject
, /* Device object */
1097 TransportObject
, /* File object */
1102 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1103 return STATUS_INSUFFICIENT_RESOURCES
;
1106 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1108 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1109 BufferLength
, /* Length of buffer */
1110 FALSE
, /* Not secondary */
1111 FALSE
, /* Don't charge quota */
1112 NULL
); /* Don't use IRP */
1114 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1115 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1117 return STATUS_INSUFFICIENT_RESOURCES
;
1121 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoModifyAccess
);
1122 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1123 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1125 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1127 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1130 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1132 TdiBuildReceiveDatagram(*Irp
, /* I/O Request Packet */
1133 DeviceObject
, /* Device object */
1134 TransportObject
, /* File object */
1135 CompletionRoutine
, /* Completion routine */
1136 CompletionContext
, /* Completion context */
1137 Mdl
, /* Data buffer */
1141 Flags
); /* Length of data */
1143 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1144 /* Does not block... The MDL is deleted in the receive completion
1147 return STATUS_PENDING
;
1151 NTSTATUS
TdiSendDatagram(
1153 PFILE_OBJECT TransportObject
,
1156 PTDI_CONNECTION_INFORMATION Addr
,
1157 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1158 PVOID CompletionContext
)
1160 * FUNCTION: Sends a datagram
1162 * TransportObject = Pointer to transport object
1163 * From = Send filter (NULL if none)
1164 * Address = Address of buffer to place remote address
1165 * Buffer = Address of buffer to place send data
1166 * BufferSize = Address of buffer with length of Buffer (updated)
1168 * Status of operation
1171 PDEVICE_OBJECT DeviceObject
;
1174 ASSERT(*Irp
== NULL
);
1176 if (!TransportObject
) {
1177 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1178 return STATUS_INVALID_PARAMETER
;
1181 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1183 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1184 if (!DeviceObject
) {
1185 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1186 return STATUS_INVALID_PARAMETER
;
1189 if (BufferLength
== 0)
1191 AFD_DbgPrint(MID_TRACE
, ("Succeeding send with length 0.\n"));
1192 return STATUS_SUCCESS
;
1195 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM
, /* Sub function */
1196 DeviceObject
, /* Device object */
1197 TransportObject
, /* File object */
1202 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1203 return STATUS_INSUFFICIENT_RESOURCES
;
1206 AFD_DbgPrint(MID_TRACE
, ("Allocating irp for %p:%u\n", Buffer
,BufferLength
));
1208 Mdl
= IoAllocateMdl(Buffer
, /* Virtual address */
1209 BufferLength
, /* Length of buffer */
1210 FALSE
, /* Not secondary */
1211 FALSE
, /* Don't charge quota */
1212 NULL
); /* Don't use IRP */
1215 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1216 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1218 return STATUS_INSUFFICIENT_RESOURCES
;
1222 MmProbeAndLockPages(Mdl
, (*Irp
)->RequestorMode
, IoReadAccess
);
1223 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1224 AFD_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
1226 IoCompleteRequest(*Irp
, IO_NO_INCREMENT
);
1228 _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES
);
1231 AFD_DbgPrint(MID_TRACE
,("AFD>>> Got an MDL: %p\n", Mdl
));
1233 TdiBuildSendDatagram(*Irp
, /* I/O Request Packet */
1234 DeviceObject
, /* Device object */
1235 TransportObject
, /* File object */
1236 CompletionRoutine
, /* Completion routine */
1237 CompletionContext
, /* Completion context */
1238 Mdl
, /* Data buffer */
1239 BufferLength
, /* Bytes to send */
1240 Addr
); /* Address */
1242 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1243 /* Does not block... The MDL is deleted in the send completion
1246 return STATUS_PENDING
;
1249 NTSTATUS
TdiDisconnect(
1251 PFILE_OBJECT TransportObject
,
1252 PLARGE_INTEGER Time
,
1254 PIO_COMPLETION_ROUTINE CompletionRoutine
,
1255 PVOID CompletionContext
,
1256 PTDI_CONNECTION_INFORMATION RequestConnectionInfo
,
1257 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
) {
1258 PDEVICE_OBJECT DeviceObject
;
1260 if (!TransportObject
) {
1261 AFD_DbgPrint(MIN_TRACE
, ("Bad transport object.\n"));
1262 return STATUS_INVALID_PARAMETER
;
1265 AFD_DbgPrint(MID_TRACE
,("Called(TransportObject %p)\n", TransportObject
));
1267 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
1268 if (!DeviceObject
) {
1269 AFD_DbgPrint(MIN_TRACE
, ("Bad device object.\n"));
1270 return STATUS_INVALID_PARAMETER
;
1273 *Irp
= TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT
, /* Sub function */
1274 DeviceObject
, /* Device object */
1275 TransportObject
, /* File object */
1280 AFD_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
1281 return STATUS_INSUFFICIENT_RESOURCES
;
1284 TdiBuildDisconnect(*Irp
, /* I/O Request Packet */
1285 DeviceObject
, /* Device object */
1286 TransportObject
, /* File object */
1287 CompletionRoutine
, /* Completion routine */
1288 CompletionContext
, /* Completion context */
1290 Flags
, /* Disconnect flags */
1291 RequestConnectionInfo
, /* Indication of who to disconnect */
1292 ReturnConnectionInfo
); /* Indication of who disconnected */
1294 TdiCall(*Irp
, DeviceObject
, NULL
, NULL
);
1296 return STATUS_PENDING
;