2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TDI test driver
5 * PURPOSE: Testing TDI drivers
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 26-Nov-2003 Vizzini Updated to run properly on Win2ksp4
13 #include <pseh/pseh2.h>
18 /* See debug.h for debug/trace constants */
19 ULONG DebugTraceLevel
= -1;
24 HANDLE TdiTransport
= 0;
25 PFILE_OBJECT TdiTransportObject
= NULL
;
34 PDEVICE_OBJECT DeviceObject
,
35 PIO_STATUS_BLOCK IoStatusBlock
,
38 * FUNCTION: Calls a transport driver device
40 * Irp = Pointer to I/O Request Packet
41 * DeviceObject = Pointer to device object to call
42 * IoStatusBlock = Address of buffer with I/O status block
43 * CanCancel = TRUE if the IRP can be cancelled, FALSE if not
47 * All requests are completed synchronously. A request may be cancelled
53 Events
[0] = &StopEvent
;
56 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
57 Irp
->UserEvent
= &Event
;
58 Irp
->UserIosb
= IoStatusBlock
;
60 Status
= IoCallDriver(DeviceObject
, Irp
);
62 if (Status
== STATUS_PENDING
)
66 Status
= KeWaitForMultipleObjects(2, (PVOID
)Events
, WaitAny
, Executive
, KernelMode
, FALSE
, NULL
, NULL
);
68 if (KeReadStateEvent(&StopEvent
) != 0)
72 TDI_DbgPrint(MAX_TRACE
, ("Cancelled IRP.\n"));
76 TDI_DbgPrint(MIN_TRACE
, ("Could not cancel IRP.\n"));
78 return STATUS_CANCELLED
;
82 Status
= KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
85 return (Status
== STATUS_SUCCESS
)? IoStatusBlock
->Status
: STATUS_SUCCESS
;
89 NTSTATUS
TdiOpenDevice(
92 PFILE_FULL_EA_INFORMATION EaInfo
,
96 * FUNCTION: Opens a device
98 * Protocol = Pointer to buffer 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 RtlInitUnicodeString(&Name
, Protocol
);
113 InitializeObjectAttributes(
114 &Attr
, /* Attribute buffer */
115 &Name
, /* Device name */
116 OBJ_CASE_INSENSITIVE
, /* Attributes */
117 NULL
, /* Root directory */
118 NULL
); /* Security descriptor */
120 Status
= ZwCreateFile(
121 Handle
, /* Return file handle */
122 GENERIC_READ
| GENERIC_WRITE
, /* Desired access */
123 &Attr
, /* Object attributes */
124 &Iosb
, /* IO status */
125 0, /* Initial allocation size */
126 FILE_ATTRIBUTE_NORMAL
, /* File attributes */
127 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* Share access */
128 FILE_OPEN_IF
, /* Create disposition */
129 0, /* Create options */
130 EaInfo
, /* EA buffer */
131 EaLength
); /* EA length */
133 if (NT_SUCCESS(Status
))
135 Status
= ObReferenceObjectByHandle(
136 *Handle
, /* Handle to open file */
137 GENERIC_READ
| GENERIC_WRITE
, /* Access mode */
138 NULL
, /* Object type */
139 KernelMode
, /* Access mode */
140 (PVOID
*)Object
, /* Pointer to object */
141 NULL
); /* Handle information */
143 if (!NT_SUCCESS(Status
))
145 TDI_DbgPrint(MIN_TRACE
, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status
));
151 TDI_DbgPrint(MIN_TRACE
, ("ZwCreateFile() failed with status (0x%X)\n", Status
));
158 NTSTATUS
TdiCloseDevice(
160 PFILE_OBJECT FileObject
)
163 ObDereferenceObject(FileObject
);
168 return STATUS_SUCCESS
;
172 NTSTATUS
TdiOpenTransport(
176 PFILE_OBJECT
*TransportObject
)
178 * FUNCTION: Opens a transport driver
180 * Protocol = Pointer to buffer with name of device
181 * Port = Port number to use
182 * Transport = Address of buffer to place transport device handle
183 * TransportObject = Address of buffer to place transport object
185 * Status of operation
188 PFILE_FULL_EA_INFORMATION EaInfo
;
189 PTA_IP_ADDRESS Address
;
193 /* EaName must be 0-termed, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
194 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) + TDI_TRANSPORT_ADDRESS_LENGTH
+ sizeof(TA_IP_ADDRESS
) + 1;
195 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
199 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
200 return STATUS_INSUFFICIENT_RESOURCES
;
203 RtlZeroMemory(EaInfo
, EaLength
);
205 EaInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
207 /* don't copy the 0; we have already zeroed it */
208 RtlCopyMemory(EaInfo
->EaName
, TdiTransportAddress
, TDI_TRANSPORT_ADDRESS_LENGTH
);
210 EaInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
211 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ TDI_TRANSPORT_ADDRESS_LENGTH
+ 1); // 0-term
212 Address
->TAAddressCount
= 1;
213 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
214 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
215 Address
->Address
[0].Address
[0].sin_port
= WH2N(Port
);
216 Address
->Address
[0].Address
[0].in_addr
= 0;
218 Status
= TdiOpenDevice(Protocol
, EaLength
, EaInfo
, Transport
, TransportObject
);
226 NTSTATUS
TdiQueryDeviceControl(
227 PFILE_OBJECT FileObject
,
230 ULONG InputBufferLength
,
232 ULONG OutputBufferLength
,
235 * FUNCTION: Queries a device for information
237 * FileObject = Pointer to device object
238 * IoControlCode = I/O control code
239 * InputBuffer = Pointer to buffer with input data
240 * InputBufferLength = Length of InputBuffer
241 * OutputBuffer = Address of buffer to place output data
242 * OutputBufferLength = Length of OutputBuffer
244 * Status of operation
247 PDEVICE_OBJECT DeviceObject
;
248 PIO_STACK_LOCATION IoStack
;
249 IO_STATUS_BLOCK Iosb
;
253 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
254 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceObject
, InputBuffer
, InputBufferLength
, OutputBuffer
,
255 OutputBufferLength
, FALSE
, NULL
, NULL
);
259 TDI_DbgPrint(MIN_TRACE
, ("IoBuildDeviceIoControlRequest() failed.\n"));
260 return STATUS_INSUFFICIENT_RESOURCES
;
263 IoStack
= IoGetNextIrpStackLocation(Irp
);
264 IoStack
->DeviceObject
= DeviceObject
;
265 IoStack
->FileObject
= FileObject
;
266 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, FALSE
);
269 *Return
= Iosb
.Information
;
275 NTSTATUS
TdiQueryInformationEx(
276 PFILE_OBJECT FileObject
,
285 * FUNCTION: Extended query for information
287 * FileObject = Pointer to transport object
289 * Instance = Instance
290 * Class = Entity class
293 * OutputBuffer = Address of buffer to place data
294 * OutputLength = Address of buffer with length of OutputBuffer (updated)
296 * Status of operation
299 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
301 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
302 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
303 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
304 QueryInfo
.ID
.toi_class
= Class
;
305 QueryInfo
.ID
.toi_type
= Type
;
306 QueryInfo
.ID
.toi_id
= Id
;
308 return TdiQueryDeviceControl(
309 FileObject
, /* Transport/connection object */
310 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
311 &QueryInfo
, /* Input buffer */
312 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
313 OutputBuffer
, /* Output buffer */
314 *OutputLength
, /* Output buffer length */
315 OutputLength
); /* Return information */
319 NTSTATUS
TdiQueryAddress(
320 PFILE_OBJECT FileObject
,
323 * FUNCTION: Queries for a local IP address
325 * FileObject = Pointer to file object
326 * Address = Address of buffer to place local address
328 * Status of operation
332 TDIEntityID
*Entities
;
335 IPSNMP_INFO SnmpInfo
;
336 PIPADDR_ENTRY IpAddress
;
338 NTSTATUS Status
= STATUS_SUCCESS
;
340 TDI_DbgPrint(MAX_TRACE
, ("Called\n"));
342 BufferSize
= sizeof(TDIEntityID
) * 20;
343 Entities
= (TDIEntityID
*)ExAllocatePool(NonPagedPool
, BufferSize
);
347 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
348 return STATUS_INSUFFICIENT_RESOURCES
;
351 /* Query device for supported entities */
352 Status
= TdiQueryInformationEx(
353 FileObject
, /* File object */
354 GENERIC_ENTITY
, /* Entity */
355 TL_INSTANCE
, /* Instance */
356 INFO_CLASS_GENERIC
, /* Entity class */
357 INFO_TYPE_PROVIDER
, /* Entity type */
358 ENTITY_LIST_ID
, /* Entity id */
359 Entities
, /* Output buffer */
360 &BufferSize
); /* Output buffer size */
362 if (!NT_SUCCESS(Status
))
364 TDI_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
365 ExFreePool(Entities
);
369 /* Locate an IP entity */
370 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
372 TDI_DbgPrint(MAX_TRACE
, ("EntityCount = %d\n", EntityCount
));
374 for (i
= 0; i
< EntityCount
; i
++)
376 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
)
378 /* Query device for entity type */
379 BufferSize
= sizeof(EntityType
);
380 Status
= TdiQueryInformationEx(
381 FileObject
, /* File object */
382 CL_NL_ENTITY
, /* Entity */
383 Entities
[i
].tei_instance
, /* Instance */
384 INFO_CLASS_GENERIC
, /* Entity class */
385 INFO_TYPE_PROVIDER
, /* Entity type */
386 ENTITY_TYPE_ID
, /* Entity id */
387 &EntityType
, /* Output buffer */
388 &BufferSize
); /* Output buffer size */
390 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
))
392 TDI_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
396 /* Query device for SNMP information */
397 BufferSize
= sizeof(SnmpInfo
);
398 Status
= TdiQueryInformationEx(
399 FileObject
, /* File object */
400 CL_NL_ENTITY
, /* Entity */
401 Entities
[i
].tei_instance
, /* Instance */
402 INFO_CLASS_PROTOCOL
, /* Entity class */
403 INFO_TYPE_PROVIDER
, /* Entity type */
404 IP_MIB_STATS_ID
, /* Entity id */
405 &SnmpInfo
, /* Output buffer */
406 &BufferSize
); /* Output buffer size */
408 if (!NT_SUCCESS(Status
) || (SnmpInfo
.NumAddr
== 0))
410 TDI_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
414 /* Query device for all IP addresses */
415 if (SnmpInfo
.NumAddr
!= 0)
417 BufferSize
= SnmpInfo
.NumAddr
* sizeof(IPADDR_ENTRY
);
418 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePool(NonPagedPool
, BufferSize
);
421 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
425 Status
= TdiQueryInformationEx(
426 FileObject
, /* File object */
427 CL_NL_ENTITY
, /* Entity */
428 Entities
[i
].tei_instance
, /* Instance */
429 INFO_CLASS_PROTOCOL
, /* Entity class */
430 INFO_TYPE_PROVIDER
, /* Entity type */
431 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
432 IpAddress
, /* Output buffer */
433 &BufferSize
); /* Output buffer size */
435 if (!NT_SUCCESS(Status
))
437 TDI_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
438 ExFreePool(IpAddress
);
442 if (SnmpInfo
.NumAddr
!= 1)
444 /* Skip loopback address */
445 *Address
= DN2H(((PIPADDR_ENTRY
)((ULONG
)IpAddress
+ sizeof(IPADDR_ENTRY
)))->Addr
);
449 /* Select the first address returned */
450 *Address
= DN2H(IpAddress
->Addr
);
452 ExFreePool(IpAddress
);
457 Status
= STATUS_UNSUCCESSFUL
;
463 ExFreePool(Entities
);
465 TDI_DbgPrint(MAX_TRACE
, ("Leaving\n"));
471 NTSTATUS
TdiSendDatagram(
472 PFILE_OBJECT TransportObject
,
478 * FUNCTION: Sends a datagram
480 * TransportObject = Pointer to transport object
482 * Address = Remote address
483 * Buffer = Pointer to buffer with data to send
484 * BufferSize = Length of Buffer
486 * Status of operation
491 PDEVICE_OBJECT DeviceObject
;
492 PTDI_CONNECTION_INFORMATION ConnectInfo
;
494 PTDI_ADDRESS_IP IpAddress
;
495 IO_STATUS_BLOCK Iosb
;
498 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
499 ConnectInfo
= (PTDI_CONNECTION_INFORMATION
)
500 ExAllocatePool(NonPagedPool
,
501 sizeof(TDI_CONNECTION_INFORMATION
) +
502 sizeof(TA_IP_ADDRESS
));
505 return STATUS_INSUFFICIENT_RESOURCES
;
507 RtlZeroMemory(ConnectInfo
, sizeof(TDI_CONNECTION_INFORMATION
) + sizeof(TA_IP_ADDRESS
));
509 ConnectInfo
->RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
510 ConnectInfo
->RemoteAddress
= (PUCHAR
) ((ULONG
)ConnectInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
512 TA
= (PTA_IP_ADDRESS
)(ConnectInfo
->RemoteAddress
);
513 TA
->TAAddressCount
= 1;
514 TA
->Address
[0].AddressLength
= sizeof(TDI_ADDRESS_IP
);
515 TA
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
516 IpAddress
= (PTDI_ADDRESS_IP
)(TA
->Address
[0].Address
);
517 IpAddress
->sin_port
= WH2N(Port
);
518 IpAddress
->in_addr
= DH2N(Address
);
519 Irp
= TdiBuildInternalDeviceControlIrp(
520 TDI_SEND_DATAGRAM
, /* Sub function */
521 DeviceObject
, /* Device object */
522 TransportObject
, /* File object */
524 NULL
); /* Return buffer */
528 TDI_DbgPrint(MIN_TRACE
, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
529 ExFreePool(ConnectInfo
);
530 return STATUS_INSUFFICIENT_RESOURCES
;
534 Buffer
, /* Virtual address of buffer */
535 BufferSize
, /* Length of buffer */
536 FALSE
, /* Not secondary */
537 FALSE
, /* Don't charge quota */
538 NULL
); /* Don't use IRP */
542 TDI_DbgPrint(MIN_TRACE
, ("IoAllocateMdl() failed.\n"));
544 ExFreePool(ConnectInfo
);
545 return STATUS_INSUFFICIENT_RESOURCES
;
550 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
554 TDI_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
557 ExFreePool(ConnectInfo
);
558 return STATUS_UNSUCCESSFUL
;
561 TdiBuildSendDatagram(
562 Irp
, /* I/O Request Packet */
563 DeviceObject
, /* Device object */
564 TransportObject
, /* File object */
565 NULL
, /* Completion routine */
566 NULL
, /* Completion context */
567 Mdl
, /* Descriptor for data buffer */
568 BufferSize
, /* Size of data to send */
569 ConnectInfo
); /* Connection information */
571 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, FALSE
);
573 ExFreePool(ConnectInfo
);
579 NTSTATUS
TdiReceiveDatagram(
580 PFILE_OBJECT TransportObject
,
586 * FUNCTION: Receives a datagram
588 * TransportObject = Pointer to transport object
589 * Port = Port to receive on
590 * Address = Address of buffer to place remote address
591 * Buffer = Address of buffer to place received data
592 * BufferSize = Address of buffer with length of Buffer (updated)
594 * Status of operation
597 PTDI_CONNECTION_INFORMATION ReceiveInfo
;
598 PTDI_CONNECTION_INFORMATION ReturnInfo
;
599 PTA_IP_ADDRESS ReturnAddress
;
600 PDEVICE_OBJECT DeviceObject
;
601 PTDI_ADDRESS_IP IpAddress
;
602 IO_STATUS_BLOCK Iosb
;
608 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
610 return STATUS_INVALID_PARAMETER
;
612 ReceiveInfo
= (PTDI_CONNECTION_INFORMATION
) ExAllocatePool(NonPagedPool
,
613 sizeof(TDI_CONNECTION_INFORMATION
) +
614 sizeof(TDI_CONNECTION_INFORMATION
) +
615 sizeof(TA_IP_ADDRESS
));
618 return STATUS_INSUFFICIENT_RESOURCES
;
620 MdlBuffer
= ExAllocatePool(PagedPool
, *BufferSize
);
622 return STATUS_INSUFFICIENT_RESOURCES
;
624 RtlZeroMemory(ReceiveInfo
, sizeof(TDI_CONNECTION_INFORMATION
) + sizeof(TDI_CONNECTION_INFORMATION
) +
625 sizeof(TA_IP_ADDRESS
));
627 RtlCopyMemory(MdlBuffer
, Buffer
, *BufferSize
);
629 /* Receive from any address */
630 ReceiveInfo
->RemoteAddressLength
= 0;
631 ReceiveInfo
->RemoteAddress
= NULL
;
633 ReturnInfo
= (PTDI_CONNECTION_INFORMATION
) ((ULONG
)ReceiveInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
634 ReturnInfo
->RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
635 ReturnInfo
->RemoteAddress
= (PUCHAR
) ((ULONG
)ReturnInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
637 ReturnAddress
= (PTA_IP_ADDRESS
)(ReturnInfo
->RemoteAddress
);
638 ReturnAddress
->TAAddressCount
= 1;
639 ReturnAddress
->Address
[0].AddressLength
= sizeof(TDI_ADDRESS_IP
);
640 ReturnAddress
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
642 IpAddress
= (PTDI_ADDRESS_IP
)(ReturnAddress
->Address
[0].Address
);
643 IpAddress
->sin_port
= WH2N(Port
);
644 IpAddress
->in_addr
= DH2N(LocalAddress
);
646 Irp
= TdiBuildInternalDeviceControlIrp(
647 TDI_RECEIVE_DATAGRAM
, /* Sub function */
648 DeviceObject
, /* Device object */
649 TransportObject
, /* File object */
651 NULL
); /* Return buffer */
655 ExFreePool(MdlBuffer
);
656 ExFreePool(ReceiveInfo
);
657 return STATUS_INSUFFICIENT_RESOURCES
;
661 MdlBuffer
, /* Virtual address */
662 *BufferSize
, /* Length of buffer */
663 FALSE
, /* Not secondary */
664 FALSE
, /* Don't charge quota */
665 NULL
); /* Don't use IRP */
670 ExFreePool(MdlBuffer
);
671 ExFreePool(ReceiveInfo
);
672 return STATUS_INSUFFICIENT_RESOURCES
;
677 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
679 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
681 TDI_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
684 ExFreePool(MdlBuffer
);
685 ExFreePool(ReceiveInfo
);
686 return STATUS_INSUFFICIENT_RESOURCES
;
689 TdiBuildReceiveDatagram(
690 Irp
, /* I/O Request Packet */
691 DeviceObject
, /* Device object */
692 TransportObject
, /* File object */
693 NULL
, /* Completion routine */
694 NULL
, /* Completion context */
695 Mdl
, /* Data buffer */
696 *BufferSize
, /* Size of data buffer */
697 ReceiveInfo
, /* Connection information */
698 ReturnInfo
, /* Connection information */
699 TDI_RECEIVE_NORMAL
); /* Flags */
701 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, TRUE
);
703 if (NT_SUCCESS(Status
))
705 RtlCopyMemory(Buffer
, MdlBuffer
, Iosb
.Information
);
706 *BufferSize
= Iosb
.Information
;
707 *Address
= DN2H(IpAddress
->in_addr
);
710 ExFreePool(MdlBuffer
);
711 ExFreePool(ReceiveInfo
);
720 * FUNCTION: Send thread
722 * Context = Pointer to context information
724 * Transmits an UDP packet every two seconds to ourselves on the chosen port
729 LARGE_INTEGER Timeout
;
730 NTSTATUS Status
= STATUS_SUCCESS
;
731 UCHAR Data
[40] = "Testing one, two, three, ...";
735 Timeout
.QuadPart
= 10000000L; /* Second factor */
736 Timeout
.QuadPart
*= 2; /* Number of seconds */
737 Timeout
.QuadPart
= -(Timeout
.QuadPart
); /* Relative time */
739 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
741 Events
[0] = &StopEvent
;
744 while (NT_SUCCESS(Status
))
746 /* Wait until timeout or stop flag is set */
747 KeWaitForMultipleObjects( 2, (PVOID
)Events
, WaitAny
, Executive
, KernelMode
, FALSE
, &Timeout
, NULL
);
749 if (KeReadStateEvent(&StopEvent
) != 0)
751 TDI_DbgPrint(MAX_TRACE
, ("Received terminate signal...\n"));
755 DbgPrint("Sending data - '%s'\n", Data
);
757 Status
= TdiSendDatagram(TdiTransportObject
, TEST_PORT
, LocalAddress
, Data
, sizeof(Data
));
759 if (!NT_SUCCESS(Status
))
760 DbgPrint("Failed sending data (Status = 0x%X)\n", Status
);
764 TDI_DbgPrint(MAX_TRACE
, ("Terminating send thread...\n"));
766 PsTerminateSystemThread(STATUS_SUCCESS
);
770 VOID
TdiReceiveThread(
773 * FUNCTION: Receive thread
775 * Context = Pointer to context information
777 * Waits until an UDP packet is received on the chosen endpoint and displays the data
783 NTSTATUS Status
= STATUS_SUCCESS
;
787 while (NT_SUCCESS(Status
))
790 RtlZeroMemory(Data
, Size
);
792 Status
= TdiReceiveDatagram(TdiTransportObject
, TEST_PORT
, &Address
, Data
, &Size
);
794 if (NT_SUCCESS(Status
))
796 DbgPrint("Received data - '%s'\n", Data
);
799 if (Status
!= STATUS_CANCELLED
)
801 TDI_DbgPrint(MIN_TRACE
, ("Receive error (Status = 0x%X).\n", Status
));
805 TDI_DbgPrint(MAX_TRACE
, ("IRP was cancelled.\n"));
810 TDI_DbgPrint(MAX_TRACE
, ("Terminating receive thread...\n"));
812 PsTerminateSystemThread(STATUS_SUCCESS
);
819 * FUNCTION: Open thread
821 * Context = Pointer to context information (event)
826 TDI_DbgPrint(MAX_TRACE
, ("Called.\n"));
830 Status
= TdiOpenTransport(UDP_DEVICE_NAME
, TEST_PORT
, &TdiTransport
, &TdiTransportObject
);
832 if (NT_SUCCESS(Status
))
834 Status
= TdiQueryAddress(TdiTransportObject
, &LocalAddress
);
836 if (NT_SUCCESS(Status
))
839 DbgPrint("Using local IP address 0x%X\n", LocalAddress
);
843 TDI_DbgPrint(MIN_TRACE
, ("Unable to determine local IP address.\n"));
847 TDI_DbgPrint(MIN_TRACE
, ("Cannot open transport (Status = 0x%X).\n", Status
));
849 TDI_DbgPrint(MAX_TRACE
, ("Setting close event.\n"));
851 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
853 TDI_DbgPrint(MIN_TRACE
, ("Leaving.\n"));
858 PDRIVER_OBJECT DriverObject
)
860 * FUNCTION: Unload routine
862 * DriverObject = Pointer to a driver object for this driver
865 PVOID ReceiveThreadObject
= 0;
866 PVOID SendThreadObject
= 0;
868 TDI_DbgPrint(MAX_TRACE
, ("Setting stop flag\n"));
870 /* Get pointers to the thread objects */
871 ObReferenceObjectByHandle(SendThread
, THREAD_ALL_ACCESS
, NULL
, KernelMode
, &SendThreadObject
, NULL
);
872 ObReferenceObjectByHandle(ReceiveThread
, THREAD_ALL_ACCESS
, NULL
, KernelMode
, &ReceiveThreadObject
, NULL
);
874 KeSetEvent(&StopEvent
, 0, FALSE
);
876 /* Wait for send thread to stop */
877 KeWaitForSingleObject(SendThreadObject
, Executive
, KernelMode
, FALSE
, NULL
);
879 /* Wait for receive thread to stop */
880 KeWaitForSingleObject(ReceiveThreadObject
, Executive
, KernelMode
, FALSE
, NULL
);
883 TdiCloseDevice(TdiTransport
, TdiTransportObject
);
890 PDRIVER_OBJECT DriverObject
,
891 PUNICODE_STRING RegistryPath
)
893 * FUNCTION: Main driver entry point
895 * DriverObject = Pointer to a driver object for this driver
896 * RegistryPath = Registry node for configuration parameters
898 * Status of driver initialization
903 WORK_QUEUE_ITEM WorkItem
;
905 KeInitializeEvent(&StopEvent
, NotificationEvent
, FALSE
);
907 /* Call TdiOpenThread() */
908 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
909 ExInitializeWorkItem(&WorkItem
, (PWORKER_THREAD_ROUTINE
)TdiOpenThread
, &Event
);
910 ExQueueWorkItem(&WorkItem
, DelayedWorkQueue
);
911 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, TRUE
, NULL
);
913 /* Create a UDP send thread that sends a dgram every 2 seconds */
914 Status
= PsCreateSystemThread(
915 &SendThread
, /* Thread handle */
916 0, /* Desired access */
917 NULL
, /* Object attributes */
918 NULL
, /* Process handle */
919 NULL
, /* Client id */
920 (PKSTART_ROUTINE
)TdiSendThread
, /* Start routine */
921 NULL
); /* Start context */
923 if (!NT_SUCCESS(Status
))
925 TDI_DbgPrint(MIN_TRACE
, ("PsCreateSystemThread() failed for send thread (Status = 0x%X).\n", Status
));
926 return STATUS_INSUFFICIENT_RESOURCES
;
929 /* Create a UDP receive thread */
930 Status
= PsCreateSystemThread(
931 &ReceiveThread
, /* Thread handle */
932 0, /* Desired access */
933 NULL
, /* Object attributes */
934 NULL
, /* Process handle */
935 NULL
, /* Client id */
936 (PKSTART_ROUTINE
)TdiReceiveThread
, /* Start routine */
937 NULL
); /* Start context */
939 if (!NT_SUCCESS(Status
))
941 TDI_DbgPrint(MIN_TRACE
, ("PsCreateSystemThread() failed for receive thread (Status = 0x%X).\n", Status
));
943 return STATUS_INSUFFICIENT_RESOURCES
;
946 DriverObject
->DriverUnload
= (PDRIVER_UNLOAD
)TdiUnload
;
948 return STATUS_SUCCESS
;