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
20 if ((DebugTraceLevel & MAX_TRACE) == 0)
24 AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n"));
28 AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size));
31 for (i = 0; i < Size; i++) {
34 DbgPrint("%02X ", (p[i]) & 0xFF);
41 inline DWORD TdiAddressSizeFromName(
44 * FUNCTION: Returns the size of a TDI style address equivalent to a
47 * Name = WinSock style name
49 * Size of TDI style address, 0 if Name is not valid
52 switch (Name->sa_family) {
54 return sizeof(TA_ADDRESS_IP);
55 /* FIXME: More to come */
57 AFD_DbgPrint(MIN_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
62 VOID TdiBuildAddressIPv4(
63 PTA_ADDRESS_IP Address,
66 * FUNCTION: Builds an IPv4 TDI style address
68 * Address = Address of buffer to place TDI style IPv4 address
69 * Name = Pointer to WinSock style IPv4 name
72 Address->TAAddressCount = 1;
73 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
74 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
75 Address->Address[0].Address[0].sin_port = ((LPSOCKADDR_IN)Name)->sin_port;
76 Address->Address[0].Address[0].in_addr = ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr;
80 NTSTATUS TdiBuildAddress(
84 * FUNCTION: Builds a TDI style address
86 * Address = Address of buffer to place TDI style address
87 * Name = Pointer to WinSock style name
92 NTSTATUS Status = STATUS_SUCCESS;
94 switch (Name->sa_family) {
96 TdiBuildAddressIPv4((PTA_ADDRESS_IP)Address, Name);
98 /* FIXME: More to come */
100 AFD_DbgPrint(MID_TRACE, ("Unknown address family (%d).\n", Name->sa_family));
101 Status = STATUS_INVALID_PARAMETER;
108 NTSTATUS TdiBuildName(
112 * FUNCTION: Builds a WinSock style address
114 * Name = Address of buffer to place WinSock style name
115 * Address = Pointer to TDI style address
117 * Status of operation
120 NTSTATUS Status = STATUS_SUCCESS;
122 switch (Address->AddressType) {
123 case TDI_ADDRESS_TYPE_IP:
124 Name->sa_family = AF_INET;
125 ((LPSOCKADDR_IN)Name)->sin_port =
126 ((PTDI_ADDRESS_IP)&Address->Address[0])->sin_port;
127 ((LPSOCKADDR_IN)Name)->sin_addr.S_un.S_addr =
128 ((PTDI_ADDRESS_IP)&Address->Address[0])->in_addr;
130 /* FIXME: More to come */
132 AFD_DbgPrint(MID_TRACE, ("Unknown TDI address type (%d).\n", Address->AddressType));
133 Status = STATUS_INVALID_PARAMETER;
141 NTSTATUS TdiBuildConnectionInfo(
142 PTDI_CONNECTION_INFORMATION *ConnectionInfo,
145 * FUNCTION: Builds a TDI connection information structure
147 * ConnectionInfo = Address of buffer to place connection information
148 * Name = Pointer to WinSock style name
150 * Status of operation
153 PTDI_CONNECTION_INFORMATION ConnInfo;
154 ULONG TdiAddressSize;
156 TdiAddressSize = TdiAddressSizeFromName(Name);
158 ConnInfo = (PTDI_CONNECTION_INFORMATION)
159 ExAllocatePool(NonPagedPool,
160 sizeof(TDI_CONNECTION_INFORMATION) +
163 return STATUS_INSUFFICIENT_RESOURCES;
165 RtlZeroMemory(ConnInfo,
166 sizeof(TDI_CONNECTION_INFORMATION) +
169 ConnInfo->RemoteAddressLength = TdiAddressSize;
170 ConnInfo->RemoteAddress = (PVOID)
171 (ConnInfo + sizeof(TDI_CONNECTION_INFORMATION));
173 TdiBuildAddress(ConnInfo->RemoteAddress, Name);
175 *ConnectionInfo = ConnInfo;
177 return STATUS_SUCCESS;
183 PDEVICE_OBJECT DeviceObject,
185 PIO_STATUS_BLOCK Iosb)
187 * FUNCTION: Calls a transport driver device
189 * Irp = Pointer to I/O Request Packet
190 * DeviceObject = Pointer to device object to call
191 * Event = An optional pointer to an event handle that will be
193 * Iosb = Pointer to an IO status block
195 * Status of operation
200 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
202 Status = IoCallDriver(DeviceObject, Irp);
203 if ((Status == STATUS_PENDING) && (Event != NULL)) {
204 AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
205 KeWaitForSingleObject(
211 Status = Iosb->Status;
214 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
220 NTSTATUS TdiOpenDevice(
221 PUNICODE_STRING DeviceName,
223 PFILE_FULL_EA_INFORMATION EaInfo,
225 PFILE_OBJECT *Object)
227 * FUNCTION: Opens a device
229 * DeviceName = Pointer to counted string with name of device
230 * EaLength = Length of EA information
231 * EaInfo = Pointer to buffer with EA information
232 * Handle = Address of buffer to place device handle
233 * Object = Address of buffer to place device object
235 * Status of operation
238 OBJECT_ATTRIBUTES Attr;
239 IO_STATUS_BLOCK Iosb;
242 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
244 InitializeObjectAttributes(&Attr, /* Attribute buffer */
245 DeviceName, /* Device name */
246 OBJ_CASE_INSENSITIVE, /* Attributes */
247 NULL, /* Root directory */
248 NULL); /* Security descriptor */
250 Status = ZwCreateFile(Handle, /* Return file handle */
251 GENERIC_READ | GENERIC_WRITE, /* Desired access */
252 &Attr, /* Object attributes */
253 &Iosb, /* IO status */
254 0, /* Initial allocation size */
255 FILE_ATTRIBUTE_NORMAL, /* File attributes */
256 FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */
257 FILE_OPEN_IF, /* Create disposition */
258 0, /* Create options */
259 EaInfo, /* EA buffer */
260 EaLength); /* EA length */
261 if (NT_SUCCESS(Status)) {
262 Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */
263 GENERIC_READ | GENERIC_WRITE, /* Access mode */
264 NULL, /* Object type */
265 KernelMode, /* Access mode */
266 (PVOID*)Object, /* Pointer to object */
267 NULL); /* Handle information */
268 if (!NT_SUCCESS(Status)) {
269 AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
272 AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X) Object (0x%X)\n",
276 AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
282 NTSTATUS TdiCloseDevice(
284 PFILE_OBJECT FileObject)
286 AFD_DbgPrint(MAX_TRACE, ("Called. Handle (0x%X) FileObject (0x%X)\n",
287 Handle, FileObject));
293 ObDereferenceObject(FileObject);
295 return STATUS_SUCCESS;
299 NTSTATUS TdiOpenAddressFileIPv4(
300 PUNICODE_STRING DeviceName,
302 PHANDLE AddressHandle,
303 PFILE_OBJECT *AddressObject)
305 * FUNCTION: Opens an IPv4 address file object
307 * DeviceName = Pointer to counted string with name of device
308 * Name = Pointer to socket name (IPv4 address family)
309 * AddressHandle = Address of buffer to place address file handle
310 * AddressObject = Address of buffer to place address file object
312 * Status of operation
315 PFILE_FULL_EA_INFORMATION EaInfo;
316 PTA_ADDRESS_IP Address;
320 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (0x%X)\n",
323 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
324 TDI_TRANSPORT_ADDRESS_LENGTH +
325 sizeof(TA_ADDRESS_IP);
326 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
328 return STATUS_INSUFFICIENT_RESOURCES;
330 RtlZeroMemory(EaInfo, EaLength);
331 EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
332 RtlCopyMemory(EaInfo->EaName,
334 TDI_TRANSPORT_ADDRESS_LENGTH);
335 EaInfo->EaValueLength = sizeof(TA_ADDRESS_IP);
336 Address = (PTA_ADDRESS_IP)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH);
337 TdiBuildAddressIPv4(Address, Name);
338 Status = TdiOpenDevice(DeviceName,
348 NTSTATUS TdiOpenAddressFile(
349 PUNICODE_STRING DeviceName,
351 PHANDLE AddressHandle,
352 PFILE_OBJECT *AddressObject)
354 * FUNCTION: Opens an address file object
356 * DeviceName = Pointer to counted string with name of device
357 * Name = Pointer to socket name
358 * AddressHandle = Address of buffer to place address file handle
359 * AddressObject = Address of buffer to place address file object
361 * Status of operation
366 switch (Name->sa_family) {
368 Status = TdiOpenAddressFileIPv4(
376 AFD_DbgPrint(MAX_TRACE, ("Unknown socket address family (0x%X)\n",
378 Status = STATUS_INVALID_PARAMETER;
385 NTSTATUS TdiOpenConnectionEndpointFile(
386 PUNICODE_STRING DeviceName,
387 PHANDLE ConnectionHandle,
388 PFILE_OBJECT *ConnectionObject)
390 * FUNCTION: Opens a connection endpoint file object
392 * DeviceName = Pointer to counted string with name of device
393 * ConnectionHandle = Address of buffer to place connection endpoint file handle
394 * ConnectionObject = Address of buffer to place connection endpoint file object
396 * Status of operation
399 PFILE_FULL_EA_INFORMATION EaInfo;
404 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
406 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
407 TDI_CONNECTION_CONTEXT_LENGTH +
410 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
412 return STATUS_INSUFFICIENT_RESOURCES;
414 RtlZeroMemory(EaInfo, EaLength);
415 EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
416 RtlCopyMemory(EaInfo->EaName,
417 TdiConnectionContext,
418 TDI_CONNECTION_CONTEXT_LENGTH);
419 EaInfo->EaValueLength = sizeof(PVOID);
420 ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH);
421 /* FIXME: Allocate context area */
423 Status = TdiOpenDevice(DeviceName,
434 PFILE_OBJECT ConnectionObject,
435 LPSOCKADDR RemoteAddress)
437 * FUNCTION: Connect a connection endpoint to a remote peer
439 * ConnectionObject = Pointer to connection endpoint file object
440 * RemoteAddress = Pointer to remote address
442 * Status of operation
445 PTDI_CONNECTION_INFORMATION RequestConnectionInfo;
446 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo;
447 PDEVICE_OBJECT DeviceObject;
448 IO_STATUS_BLOCK Iosb;
453 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
455 assert(ConnectionObject);
457 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
459 Status = TdiBuildConnectionInfo(&RequestConnectionInfo, RemoteAddress);
460 if (!NT_SUCCESS(Status))
463 /* Use same TDI address type for return connection information */
464 Status = TdiBuildConnectionInfo(&ReturnConnectionInfo, RemoteAddress);
465 if (!NT_SUCCESS(Status)) {
466 ExFreePool(RequestConnectionInfo);
470 KeInitializeEvent(&Event, NotificationEvent, FALSE);
472 Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */
473 DeviceObject, /* Device object */
474 ConnectionObject, /* File object */
478 ExFreePool(RequestConnectionInfo);
479 return STATUS_INSUFFICIENT_RESOURCES;
482 TdiBuildConnect(Irp, /* IRP */
483 DeviceObject, /* Device object */
484 ConnectionObject, /* File object */
485 NULL, /* Completion routine */
486 NULL, /* Completion routine context */
488 RequestConnectionInfo, /* Request connection information */
489 ReturnConnectionInfo); /* Return connection information */
491 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
493 ExFreePool(RequestConnectionInfo);
494 ExFreePool(ReturnConnectionInfo);
500 NTSTATUS TdiAssociateAddressFile(
501 HANDLE AddressHandle,
502 PFILE_OBJECT ConnectionObject)
504 * FUNCTION: Associates a connection endpoint to an address file object
506 * AddressHandle = Handle to address file object
507 * ConnectionObject = Connection endpoint file object
509 * Status of operation
512 PDEVICE_OBJECT DeviceObject;
513 IO_STATUS_BLOCK Iosb;
518 AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X) ConnectionObject (0x%X)\n",
519 AddressHandle, ConnectionObject));
521 assert(ConnectionObject);
523 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
525 KeInitializeEvent(&Event, NotificationEvent, FALSE);
527 Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, /* Sub function */
528 DeviceObject, /* Device object */
529 ConnectionObject, /* File object */
533 return STATUS_INSUFFICIENT_RESOURCES;
535 TdiBuildAssociateAddress(Irp,
542 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
548 NTSTATUS TdiSetEventHandler(
549 PFILE_OBJECT FileObject,
554 * FUNCTION: Sets or resets an event handler
556 * FileObject = Pointer to file object
557 * EventType = Event code
558 * Handler = Event handler to be called when the event occurs
559 * Context = Context input to handler when the event occurs
561 * Status of operation
563 * Specify NULL for Handler to stop calling event handler
566 PDEVICE_OBJECT DeviceObject;
567 IO_STATUS_BLOCK Iosb;
572 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
576 DeviceObject = IoGetRelatedDeviceObject(FileObject);
578 KeInitializeEvent(&Event, NotificationEvent, FALSE);
580 Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */
581 DeviceObject, /* Device object */
582 FileObject, /* File object */
586 return STATUS_INSUFFICIENT_RESOURCES;
590 TdiBuildSetEventHandler(Irp,
599 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
605 NTSTATUS TdiQueryDeviceControl(
606 PFILE_OBJECT FileObject,
609 ULONG InputBufferLength,
611 ULONG OutputBufferLength,
614 * FUNCTION: Queries a device for information
616 * FileObject = Pointer to file object
617 * IoControlCode = I/O control code
618 * InputBuffer = Pointer to buffer with input data
619 * InputBufferLength = Length of InputBuffer
620 * OutputBuffer = Address of buffer to place output data
621 * OutputBufferLength = Length of OutputBuffer
623 * Status of operation
626 PDEVICE_OBJECT DeviceObject;
627 IO_STATUS_BLOCK Iosb;
632 DeviceObject = IoGetRelatedDeviceObject(FileObject);
634 KeInitializeEvent(&Event, NotificationEvent, FALSE);
636 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
646 return STATUS_INSUFFICIENT_RESOURCES;
648 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
651 *Return = Iosb.Information;
657 NTSTATUS TdiQueryInformationEx(
658 PFILE_OBJECT FileObject,
667 * FUNCTION: Extended query for information
669 * FileObject = Pointer to file object
671 * Instance = Instance
672 * Class = Entity class
675 * OutputBuffer = Address of buffer to place data
676 * OutputLength = Address of buffer with length of OutputBuffer (updated)
678 * Status of operation
681 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;
683 RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
684 QueryInfo.ID.toi_entity.tei_entity = Entity;
685 QueryInfo.ID.toi_entity.tei_instance = Instance;
686 QueryInfo.ID.toi_class = Class;
687 QueryInfo.ID.toi_type = Type;
688 QueryInfo.ID.toi_id = Id;
690 return TdiQueryDeviceControl(FileObject, /* Transport/connection object */
691 IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */
692 &QueryInfo, /* Input buffer */
693 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */
694 OutputBuffer, /* Output buffer */
695 *OutputLength, /* Output buffer length */
696 OutputLength); /* Return information */
700 NTSTATUS TdiQueryAddress(
701 PFILE_OBJECT FileObject,
704 * FUNCTION: Queries for a local IP address
706 * FileObject = Pointer to file object
707 * Address = Address of buffer to place local address
709 * Status of operation
713 TDIEntityID *Entities;
716 IPSNMP_INFO SnmpInfo;
717 PIPADDR_ENTRY IpAddress;
719 NTSTATUS Status = STATUS_SUCCESS;
721 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
723 BufferSize = sizeof(TDIEntityID) * 20;
724 Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);
726 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
727 return STATUS_INSUFFICIENT_RESOURCES;
730 /* Query device for supported entities */
732 Status = TdiQueryInformationEx(FileObject, /* File object */
733 GENERIC_ENTITY, /* Entity */
734 TL_INSTANCE, /* Instance */
735 INFO_CLASS_GENERIC, /* Entity class */
736 INFO_TYPE_PROVIDER, /* Entity type */
737 ENTITY_LIST_ID, /* Entity id */
738 Entities, /* Output buffer */
739 &BufferSize); /* Output buffer size */
740 if (!NT_SUCCESS(Status)) {
741 AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
742 ExFreePool(Entities);
746 /* Locate an IP entity */
747 EntityCount = BufferSize / sizeof(TDIEntityID);
749 AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));
751 for (i = 0; i < EntityCount; i++) {
752 if (Entities[i].tei_entity == CL_NL_ENTITY) {
753 /* Query device for entity type */
755 BufferSize = sizeof(EntityType);
756 Status = TdiQueryInformationEx(FileObject, /* File object */
757 CL_NL_ENTITY, /* Entity */
758 Entities[i].tei_instance, /* Instance */
759 INFO_CLASS_GENERIC, /* Entity class */
760 INFO_TYPE_PROVIDER, /* Entity type */
761 ENTITY_TYPE_ID, /* Entity id */
762 &EntityType, /* Output buffer */
763 &BufferSize); /* Output buffer size */
764 if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) {
765 AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
769 /* Query device for SNMP information */
771 BufferSize = sizeof(SnmpInfo);
772 Status = TdiQueryInformationEx(FileObject, /* File object */
773 CL_NL_ENTITY, /* Entity */
774 Entities[i].tei_instance, /* Instance */
775 INFO_CLASS_PROTOCOL, /* Entity class */
776 INFO_TYPE_PROVIDER, /* Entity type */
777 IP_MIB_STATS_ID, /* Entity id */
778 &SnmpInfo, /* Output buffer */
779 &BufferSize); /* Output buffer size */
780 if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) {
781 AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
785 /* Query device for all IP addresses */
787 if (SnmpInfo.NumAddr != 0) {
788 BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
789 IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
791 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
795 Status = TdiQueryInformationEx(FileObject, /* File object */
796 CL_NL_ENTITY, /* Entity */
797 Entities[i].tei_instance, /* Instance */
798 INFO_CLASS_PROTOCOL, /* Entity class */
799 INFO_TYPE_PROVIDER, /* Entity type */
800 IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */
801 IpAddress, /* Output buffer */
802 &BufferSize); /* Output buffer size */
803 if (!NT_SUCCESS(Status)) {
804 AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
805 ExFreePool(IpAddress);
809 if (SnmpInfo.NumAddr != 1) {
810 /* Skip loopback address */
811 *Address = DN2H(((PIPADDR_ENTRY)((ULONG)IpAddress + sizeof(IPADDR_ENTRY)))->Addr);
813 /* Select the first address returned */
814 *Address = DN2H(IpAddress->Addr);
817 ExFreePool(IpAddress);
819 Status = STATUS_UNSUCCESSFUL;
825 ExFreePool(Entities);
827 AFD_DbgPrint(MAX_TRACE, ("Leaving\n"));
834 PFILE_OBJECT TransportObject,
838 * FUNCTION: Sends a block of data
840 * TransportObject = Pointer to transport object
841 * Buffer = Pointer to buffer with data to send
842 * BufferSize = Length of Buffer
844 * Status of operation
848 PTDI_CONNECTION_INFORMATION ConnectInfo;
849 PDEVICE_OBJECT DeviceObject;
850 IO_STATUS_BLOCK Iosb;
851 DWORD TdiAddressSize;
858 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
860 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
861 return STATUS_INVALID_PARAMETER;
864 TdiAddressSize = TdiAddressSizeFromName(Address);
866 ConnectInfo = (PTDI_CONNECTION_INFORMATION)
867 ExAllocatePool(NonPagedPool,
868 sizeof(TDI_CONNECTION_INFORMATION) +
872 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
873 return STATUS_INSUFFICIENT_RESOURCES;
876 RtlZeroMemory(ConnectInfo,
877 sizeof(TDI_CONNECTION_INFORMATION) +
880 ConnectInfo->RemoteAddressLength = TdiAddressSize;
881 ConnectInfo->RemoteAddress = (PVOID)
882 (ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION));
884 TdiBuildAddress(ConnectInfo->RemoteAddress, Address);
886 KeInitializeEvent(&Event, NotificationEvent, FALSE);
888 Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
889 DeviceObject, /* Device object */
890 TransportObject, /* File object */
894 AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
895 ExFreePool(ConnectInfo);
896 return STATUS_INSUFFICIENT_RESOURCES;
899 DisplayBuffer(Request->Buffers->buf, Request->Buffers->len);
902 /* FIXME: There may be more than one buffer */
903 BufferSize = Request->Buffers->len;
905 Request->Buffers->buf, /* Virtual address of buffer */
906 Request->Buffers->len, /* Length of buffer */
907 FALSE, /* Not secondary */
908 FALSE, /* Don't charge quota */
909 NULL); /* Don't use IRP */
911 AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
913 ExFreePool(ConnectInfo);
914 return STATUS_INSUFFICIENT_RESOURCES;
920 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
922 } except(EXCEPTION_EXECUTE_HANDLER) {
923 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
926 ExFreePool(ConnectInfo);
927 return STATUS_UNSUCCESSFUL;
931 BaseAddress = MmMapLockedPages(Mdl, KernelMode);
933 AFD_DbgPrint(MAX_TRACE, ("Mapped user mode buffer at 0x%X.\n", BaseAddress));
935 TdiBuildSendDatagram(Irp, /* I/O Request Packet */
936 DeviceObject, /* Device object */
937 TransportObject, /* File object */
938 NULL, /* Completion routine */
939 NULL, /* Completion context */
940 Mdl, /* Descriptor for data buffer */
941 BufferSize, /* Size of data to send */
942 ConnectInfo); /* Connection information */
944 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
946 MmUnmapLockedPages(BaseAddress, Mdl);
952 ExFreePool(ConnectInfo);
956 return STATUS_SUCCESS;
960 NTSTATUS TdiSendDatagram(
961 PFILE_OBJECT TransportObject,
966 * FUNCTION: Sends a datagram
968 * TransportObject = Pointer to transport object
969 * Address = Remote address to send data to
970 * Mdl = MDL of buffer to send
971 * BufferSize = Length of buffer
973 * Status of operation
976 PTDI_CONNECTION_INFORMATION ConnectInfo;
977 PDEVICE_OBJECT DeviceObject;
978 IO_STATUS_BLOCK Iosb;
979 DWORD TdiAddressSize;
984 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
986 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
987 return STATUS_INVALID_PARAMETER;
990 TdiAddressSize = TdiAddressSizeFromName(Address);
992 ConnectInfo = (PTDI_CONNECTION_INFORMATION)
993 ExAllocatePool(NonPagedPool,
994 sizeof(TDI_CONNECTION_INFORMATION) +
997 return STATUS_INSUFFICIENT_RESOURCES;
999 RtlZeroMemory(ConnectInfo,
1000 sizeof(TDI_CONNECTION_INFORMATION) +
1003 ConnectInfo->RemoteAddressLength = TdiAddressSize;
1004 ConnectInfo->RemoteAddress = (PVOID)
1005 (ConnectInfo + sizeof(TDI_CONNECTION_INFORMATION));
1007 TdiBuildAddress(ConnectInfo->RemoteAddress, Address);
1009 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1011 Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, /* Sub function */
1012 DeviceObject, /* Device object */
1013 TransportObject, /* File object */
1015 &Iosb); /* Status */
1017 AFD_DbgPrint(MIN_TRACE, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
1018 ExFreePool(ConnectInfo);
1019 return STATUS_INSUFFICIENT_RESOURCES;
1023 Mdl = IoAllocateMdl(Buffer, /* Virtual address of buffer */
1024 BufferSize, /* Length of buffer */
1025 FALSE, /* Not secondary */
1026 FALSE, /* Don't charge quota */
1027 NULL); /* Don't use IRP */
1029 AFD_DbgPrint(MIN_TRACE, ("IoAllocateMdl() failed.\n"));
1031 ExFreePool(ConnectInfo);
1032 return STATUS_INSUFFICIENT_RESOURCES;
1037 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
1039 } except(EXCEPTION_EXECUTE_HANDLER) {
1040 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
1042 ExFreePool(ConnectInfo);
1043 return STATUS_UNSUCCESSFUL;
1048 TdiBuildSendDatagram(Irp, /* I/O Request Packet */
1049 DeviceObject, /* Device object */
1050 TransportObject, /* File object */
1051 NULL, /* Completion routine */
1052 NULL, /* Completion context */
1053 Mdl, /* Descriptor for data buffer */
1054 BufferSize, /* Size of data to send */
1055 ConnectInfo); /* Connection information */
1057 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
1065 ExFreePool(ConnectInfo);
1071 NTSTATUS TdiReceiveDatagram(
1072 PFILE_OBJECT TransportObject,
1078 * FUNCTION: Receives a datagram
1080 * TransportObject = Pointer to transport object
1081 * From = Receive filter (NULL if none)
1082 * Address = Address of buffer to place remote address
1083 * Buffer = Address of buffer to place received data
1084 * BufferSize = Address of buffer with length of Buffer (updated)
1086 * Status of operation
1089 PTDI_CONNECTION_INFORMATION ReceiveInfo;
1090 PTDI_CONNECTION_INFORMATION ReturnInfo;
1091 PTA_ADDRESS_IP ReturnAddress;
1092 PDEVICE_OBJECT DeviceObject;
1093 IO_STATUS_BLOCK Iosb;
1094 DWORD TdiAddressSize;
1101 /* FIXME: Check that the socket type match the socket */
1104 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1105 if (!DeviceObject) {
1106 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
1107 return STATUS_INVALID_PARAMETER;
1110 /* FIXME: Get from socket information */
1111 TdiAddressSize = sizeof(TA_ADDRESS_IP);
1113 ReceiveInfo = (PTDI_CONNECTION_INFORMATION)
1114 ExAllocatePool(NonPagedPool,
1115 sizeof(TDI_CONNECTION_INFORMATION) +
1116 sizeof(TDI_CONNECTION_INFORMATION) +
1117 2 * TdiAddressSize);
1119 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1120 return STATUS_INSUFFICIENT_RESOURCES;
1123 RtlZeroMemory(ReceiveInfo,
1124 sizeof(TDI_CONNECTION_INFORMATION) +
1125 sizeof(TDI_CONNECTION_INFORMATION) +
1126 2 * TdiAddressSize);
1129 ReceiveInfo->RemoteAddressLength = TdiAddressSize;
1130 ReceiveInfo->RemoteAddress = (PVOID)
1131 (ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION));
1132 /* Filter datagrams */
1133 TdiBuildAddress(ReceiveInfo->RemoteAddress, From);
1135 /* Receive from any address */
1136 ReceiveInfo->RemoteAddressLength = 0;
1137 ReceiveInfo->RemoteAddress = NULL;
1140 ReturnInfo = (PTDI_CONNECTION_INFORMATION)
1141 (ReceiveInfo + sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize);
1142 ReturnInfo->RemoteAddressLength = TdiAddressSize;
1143 ReturnInfo->RemoteAddress = (PVOID)
1144 (ReturnInfo + sizeof(TDI_CONNECTION_INFORMATION));
1146 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1148 Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */
1149 DeviceObject, /* Device object */
1150 TransportObject, /* File object */
1152 &Iosb); /* Status */
1154 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1155 ExFreePool(ReceiveInfo);
1156 return STATUS_INSUFFICIENT_RESOURCES;
1159 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
1160 *BufferSize, /* Length of buffer */
1161 FALSE, /* Not secondary */
1162 FALSE, /* Don't charge quota */
1163 NULL); /* Don't use IRP */
1165 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1167 ExFreePool(ReceiveInfo);
1168 return STATUS_INSUFFICIENT_RESOURCES;
1174 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
1176 } except (EXCEPTION_EXECUTE_HANDLER) {
1177 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
1180 ExFreePool(ReceiveInfo);
1181 return STATUS_INSUFFICIENT_RESOURCES;
1185 TdiBuildReceiveDatagram(Irp, /* I/O Request Packet */
1186 DeviceObject, /* Device object */
1187 TransportObject, /* File object */
1188 NULL, /* Completion routine */
1189 NULL, /* Completion context */
1190 Mdl, /* Data buffer */
1191 *BufferSize, /* Size of data buffer */
1192 ReceiveInfo, /* Connection information */
1193 ReturnInfo, /* Connection information */
1194 TDI_RECEIVE_NORMAL); /* Flags */
1195 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
1196 if (NT_SUCCESS(Status)) {
1197 *BufferSize = Iosb.Information;
1198 TdiBuildName(Address, ReturnInfo->RemoteAddress);
1205 ExFreePool(ReceiveInfo);