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
17 /* See debug.h for debug/trace constants */
18 ULONG DebugTraceLevel
= -1;
23 HANDLE TdiTransport
= 0;
24 PFILE_OBJECT TdiTransportObject
= NULL
;
33 PDEVICE_OBJECT DeviceObject
,
34 PIO_STATUS_BLOCK IoStatusBlock
,
37 * FUNCTION: Calls a transport driver device
39 * Irp = Pointer to I/O Request Packet
40 * DeviceObject = Pointer to device object to call
41 * IoStatusBlock = Address of buffer with I/O status block
42 * CanCancel = TRUE if the IRP can be cancelled, FALSE if not
46 * All requests are completed synchronously. A request may be cancelled
52 Events
[0] = &StopEvent
;
55 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
56 Irp
->UserEvent
= &Event
;
57 Irp
->UserIosb
= IoStatusBlock
;
59 Status
= IoCallDriver(DeviceObject
, Irp
);
61 if (Status
== STATUS_PENDING
)
65 Status
= KeWaitForMultipleObjects(2, (PVOID
)Events
, WaitAny
, Executive
, KernelMode
, FALSE
, NULL
, NULL
);
67 if (KeReadStateEvent(&StopEvent
) != 0)
71 TDI_DbgPrint(MAX_TRACE
, ("Cancelled IRP.\n"));
75 TDI_DbgPrint(MIN_TRACE
, ("Could not cancel IRP.\n"));
77 return STATUS_CANCELLED
;
81 Status
= KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
84 return (Status
== STATUS_SUCCESS
)? IoStatusBlock
->Status
: STATUS_SUCCESS
;
88 NTSTATUS
TdiOpenDevice(
91 PFILE_FULL_EA_INFORMATION EaInfo
,
95 * FUNCTION: Opens a device
97 * Protocol = Pointer to buffer with name of device
98 * EaLength = Length of EA information
99 * EaInfo = Pointer to buffer with EA information
100 * Handle = Address of buffer to place device handle
101 * Object = Address of buffer to place device object
103 * Status of operation
106 OBJECT_ATTRIBUTES Attr
;
107 IO_STATUS_BLOCK Iosb
;
111 RtlInitUnicodeString(&Name
, Protocol
);
112 InitializeObjectAttributes(
113 &Attr
, /* Attribute buffer */
114 &Name
, /* Device name */
115 OBJ_CASE_INSENSITIVE
, /* Attributes */
116 NULL
, /* Root directory */
117 NULL
); /* Security descriptor */
119 Status
= ZwCreateFile(
120 Handle
, /* Return file handle */
121 GENERIC_READ
| GENERIC_WRITE
, /* Desired access */
122 &Attr
, /* Object attributes */
123 &Iosb
, /* IO status */
124 0, /* Initial allocation size */
125 FILE_ATTRIBUTE_NORMAL
, /* File attributes */
126 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* Share access */
127 FILE_OPEN_IF
, /* Create disposition */
128 0, /* Create options */
129 EaInfo
, /* EA buffer */
130 EaLength
); /* EA length */
132 if (NT_SUCCESS(Status
))
134 Status
= ObReferenceObjectByHandle(
135 *Handle
, /* Handle to open file */
136 GENERIC_READ
| GENERIC_WRITE
, /* Access mode */
137 NULL
, /* Object type */
138 KernelMode
, /* Access mode */
139 (PVOID
*)Object
, /* Pointer to object */
140 NULL
); /* Handle information */
142 if (!NT_SUCCESS(Status
))
144 TDI_DbgPrint(MIN_TRACE
, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status
));
150 TDI_DbgPrint(MIN_TRACE
, ("ZwCreateFile() failed with status (0x%X)\n", Status
));
157 NTSTATUS
TdiCloseDevice(
159 PFILE_OBJECT FileObject
)
162 ObDereferenceObject(FileObject
);
167 return STATUS_SUCCESS
;
171 NTSTATUS
TdiOpenTransport(
175 PFILE_OBJECT
*TransportObject
)
177 * FUNCTION: Opens a transport driver
179 * Protocol = Pointer to buffer with name of device
180 * Port = Port number to use
181 * Transport = Address of buffer to place transport device handle
182 * TransportObject = Address of buffer to place transport object
184 * Status of operation
187 PFILE_FULL_EA_INFORMATION EaInfo
;
188 PTA_IP_ADDRESS Address
;
192 /* EaName must be 0-termed, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
193 EaLength
= sizeof(FILE_FULL_EA_INFORMATION
) + TDI_TRANSPORT_ADDRESS_LENGTH
+ sizeof(TA_IP_ADDRESS
) + 1;
194 EaInfo
= (PFILE_FULL_EA_INFORMATION
)ExAllocatePool(NonPagedPool
, EaLength
);
198 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
199 return STATUS_INSUFFICIENT_RESOURCES
;
202 RtlZeroMemory(EaInfo
, EaLength
);
204 EaInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
206 /* don't copy the 0; we have already zeroed it */
207 RtlCopyMemory(EaInfo
->EaName
, TdiTransportAddress
, TDI_TRANSPORT_ADDRESS_LENGTH
);
209 EaInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
210 Address
= (PTA_IP_ADDRESS
)(EaInfo
->EaName
+ TDI_TRANSPORT_ADDRESS_LENGTH
+ 1); // 0-term
211 Address
->TAAddressCount
= 1;
212 Address
->Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
213 Address
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
214 Address
->Address
[0].Address
[0].sin_port
= WH2N(Port
);
215 Address
->Address
[0].Address
[0].in_addr
= 0;
217 Status
= TdiOpenDevice(Protocol
, EaLength
, EaInfo
, Transport
, TransportObject
);
225 NTSTATUS
TdiQueryDeviceControl(
226 PFILE_OBJECT FileObject
,
229 ULONG InputBufferLength
,
231 ULONG OutputBufferLength
,
234 * FUNCTION: Queries a device for information
236 * FileObject = Pointer to device object
237 * IoControlCode = I/O control code
238 * InputBuffer = Pointer to buffer with input data
239 * InputBufferLength = Length of InputBuffer
240 * OutputBuffer = Address of buffer to place output data
241 * OutputBufferLength = Length of OutputBuffer
243 * Status of operation
246 PDEVICE_OBJECT DeviceObject
;
247 PIO_STACK_LOCATION IoStack
;
248 IO_STATUS_BLOCK Iosb
;
252 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
253 Irp
= IoBuildDeviceIoControlRequest(IoControlCode
, DeviceObject
, InputBuffer
, InputBufferLength
, OutputBuffer
,
254 OutputBufferLength
, FALSE
, NULL
, NULL
);
258 TDI_DbgPrint(MIN_TRACE
, ("IoBuildDeviceIoControlRequest() failed.\n"));
259 return STATUS_INSUFFICIENT_RESOURCES
;
262 IoStack
= IoGetNextIrpStackLocation(Irp
);
263 IoStack
->DeviceObject
= DeviceObject
;
264 IoStack
->FileObject
= FileObject
;
265 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, FALSE
);
268 *Return
= Iosb
.Information
;
274 NTSTATUS
TdiQueryInformationEx(
275 PFILE_OBJECT FileObject
,
284 * FUNCTION: Extended query for information
286 * FileObject = Pointer to transport object
288 * Instance = Instance
289 * Class = Entity class
292 * OutputBuffer = Address of buffer to place data
293 * OutputLength = Address of buffer with length of OutputBuffer (updated)
295 * Status of operation
298 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo
;
300 RtlZeroMemory(&QueryInfo
, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
));
301 QueryInfo
.ID
.toi_entity
.tei_entity
= Entity
;
302 QueryInfo
.ID
.toi_entity
.tei_instance
= Instance
;
303 QueryInfo
.ID
.toi_class
= Class
;
304 QueryInfo
.ID
.toi_type
= Type
;
305 QueryInfo
.ID
.toi_id
= Id
;
307 return TdiQueryDeviceControl(
308 FileObject
, /* Transport/connection object */
309 IOCTL_TCP_QUERY_INFORMATION_EX
, /* Control code */
310 &QueryInfo
, /* Input buffer */
311 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX
), /* Input buffer length */
312 OutputBuffer
, /* Output buffer */
313 *OutputLength
, /* Output buffer length */
314 OutputLength
); /* Return information */
318 NTSTATUS
TdiQueryAddress(
319 PFILE_OBJECT FileObject
,
322 * FUNCTION: Queries for a local IP address
324 * FileObject = Pointer to file object
325 * Address = Address of buffer to place local address
327 * Status of operation
331 TDIEntityID
*Entities
;
334 IPSNMP_INFO SnmpInfo
;
335 PIPADDR_ENTRY IpAddress
;
337 NTSTATUS Status
= STATUS_SUCCESS
;
339 TDI_DbgPrint(MAX_TRACE
, ("Called\n"));
341 BufferSize
= sizeof(TDIEntityID
) * 20;
342 Entities
= (TDIEntityID
*)ExAllocatePool(NonPagedPool
, BufferSize
);
346 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
347 return STATUS_INSUFFICIENT_RESOURCES
;
350 /* Query device for supported entities */
351 Status
= TdiQueryInformationEx(
352 FileObject
, /* File object */
353 GENERIC_ENTITY
, /* Entity */
354 TL_INSTANCE
, /* Instance */
355 INFO_CLASS_GENERIC
, /* Entity class */
356 INFO_TYPE_PROVIDER
, /* Entity type */
357 ENTITY_LIST_ID
, /* Entity id */
358 Entities
, /* Output buffer */
359 &BufferSize
); /* Output buffer size */
361 if (!NT_SUCCESS(Status
))
363 TDI_DbgPrint(MIN_TRACE
, ("Unable to get list of supported entities (Status = 0x%X).\n", Status
));
364 ExFreePool(Entities
);
368 /* Locate an IP entity */
369 EntityCount
= BufferSize
/ sizeof(TDIEntityID
);
371 TDI_DbgPrint(MAX_TRACE
, ("EntityCount = %d\n", EntityCount
));
373 for (i
= 0; i
< EntityCount
; i
++)
375 if (Entities
[i
].tei_entity
== CL_NL_ENTITY
)
377 /* Query device for entity type */
378 BufferSize
= sizeof(EntityType
);
379 Status
= TdiQueryInformationEx(
380 FileObject
, /* File object */
381 CL_NL_ENTITY
, /* Entity */
382 Entities
[i
].tei_instance
, /* Instance */
383 INFO_CLASS_GENERIC
, /* Entity class */
384 INFO_TYPE_PROVIDER
, /* Entity type */
385 ENTITY_TYPE_ID
, /* Entity id */
386 &EntityType
, /* Output buffer */
387 &BufferSize
); /* Output buffer size */
389 if (!NT_SUCCESS(Status
) || (EntityType
!= CL_NL_IP
))
391 TDI_DbgPrint(MIN_TRACE
, ("Unable to get entity of type IP (Status = 0x%X).\n", Status
));
395 /* Query device for SNMP information */
396 BufferSize
= sizeof(SnmpInfo
);
397 Status
= TdiQueryInformationEx(
398 FileObject
, /* File object */
399 CL_NL_ENTITY
, /* Entity */
400 Entities
[i
].tei_instance
, /* Instance */
401 INFO_CLASS_PROTOCOL
, /* Entity class */
402 INFO_TYPE_PROVIDER
, /* Entity type */
403 IP_MIB_STATS_ID
, /* Entity id */
404 &SnmpInfo
, /* Output buffer */
405 &BufferSize
); /* Output buffer size */
407 if (!NT_SUCCESS(Status
) || (SnmpInfo
.NumAddr
== 0))
409 TDI_DbgPrint(MIN_TRACE
, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status
));
413 /* Query device for all IP addresses */
414 if (SnmpInfo
.NumAddr
!= 0)
416 BufferSize
= SnmpInfo
.NumAddr
* sizeof(IPADDR_ENTRY
);
417 IpAddress
= (PIPADDR_ENTRY
)ExAllocatePool(NonPagedPool
, BufferSize
);
420 TDI_DbgPrint(MIN_TRACE
, ("Insufficient resources.\n"));
424 Status
= TdiQueryInformationEx(
425 FileObject
, /* File object */
426 CL_NL_ENTITY
, /* Entity */
427 Entities
[i
].tei_instance
, /* Instance */
428 INFO_CLASS_PROTOCOL
, /* Entity class */
429 INFO_TYPE_PROVIDER
, /* Entity type */
430 IP_MIB_ADDRTABLE_ENTRY_ID
, /* Entity id */
431 IpAddress
, /* Output buffer */
432 &BufferSize
); /* Output buffer size */
434 if (!NT_SUCCESS(Status
))
436 TDI_DbgPrint(MIN_TRACE
, ("Unable to get IP address (Status = 0x%X).\n", Status
));
437 ExFreePool(IpAddress
);
441 if (SnmpInfo
.NumAddr
!= 1)
443 /* Skip loopback address */
444 *Address
= DN2H(((PIPADDR_ENTRY
)((ULONG
)IpAddress
+ sizeof(IPADDR_ENTRY
)))->Addr
);
448 /* Select the first address returned */
449 *Address
= DN2H(IpAddress
->Addr
);
451 ExFreePool(IpAddress
);
456 Status
= STATUS_UNSUCCESSFUL
;
462 ExFreePool(Entities
);
464 TDI_DbgPrint(MAX_TRACE
, ("Leaving\n"));
470 NTSTATUS
TdiSendDatagram(
471 PFILE_OBJECT TransportObject
,
477 * FUNCTION: Sends a datagram
479 * TransportObject = Pointer to transport object
481 * Address = Remote address
482 * Buffer = Pointer to buffer with data to send
483 * BufferSize = Length of Buffer
485 * Status of operation
490 PDEVICE_OBJECT DeviceObject
;
491 PTDI_CONNECTION_INFORMATION ConnectInfo
;
493 PTDI_ADDRESS_IP IpAddress
;
494 IO_STATUS_BLOCK Iosb
;
497 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
498 ConnectInfo
= (PTDI_CONNECTION_INFORMATION
)
499 ExAllocatePool(NonPagedPool
,
500 sizeof(TDI_CONNECTION_INFORMATION
) +
501 sizeof(TA_IP_ADDRESS
));
504 return STATUS_INSUFFICIENT_RESOURCES
;
506 RtlZeroMemory(ConnectInfo
, sizeof(TDI_CONNECTION_INFORMATION
) + sizeof(TA_IP_ADDRESS
));
508 ConnectInfo
->RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
509 ConnectInfo
->RemoteAddress
= (PUCHAR
) ((ULONG
)ConnectInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
511 TA
= (PTA_IP_ADDRESS
)(ConnectInfo
->RemoteAddress
);
512 TA
->TAAddressCount
= 1;
513 TA
->Address
[0].AddressLength
= sizeof(TDI_ADDRESS_IP
);
514 TA
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
515 IpAddress
= (PTDI_ADDRESS_IP
)(TA
->Address
[0].Address
);
516 IpAddress
->sin_port
= WH2N(Port
);
517 IpAddress
->in_addr
= DH2N(Address
);
518 Irp
= TdiBuildInternalDeviceControlIrp(
519 TDI_SEND_DATAGRAM
, /* Sub function */
520 DeviceObject
, /* Device object */
521 TransportObject
, /* File object */
523 NULL
); /* Return buffer */
527 TDI_DbgPrint(MIN_TRACE
, ("TdiBuildInternalDeviceControlIrp() failed.\n"));
528 ExFreePool(ConnectInfo
);
529 return STATUS_INSUFFICIENT_RESOURCES
;
533 Buffer
, /* Virtual address of buffer */
534 BufferSize
, /* Length of buffer */
535 FALSE
, /* Not secondary */
536 FALSE
, /* Don't charge quota */
537 NULL
); /* Don't use IRP */
541 TDI_DbgPrint(MIN_TRACE
, ("IoAllocateMdl() failed.\n"));
543 ExFreePool(ConnectInfo
);
544 return STATUS_INSUFFICIENT_RESOURCES
;
551 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
554 except(EXCEPTION_EXECUTE_HANDLER
)
556 TDI_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
559 ExFreePool(ConnectInfo
);
560 return STATUS_UNSUCCESSFUL
;
564 TdiBuildSendDatagram(
565 Irp
, /* I/O Request Packet */
566 DeviceObject
, /* Device object */
567 TransportObject
, /* File object */
568 NULL
, /* Completion routine */
569 NULL
, /* Completion context */
570 Mdl
, /* Descriptor for data buffer */
571 BufferSize
, /* Size of data to send */
572 ConnectInfo
); /* Connection information */
574 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, FALSE
);
576 ExFreePool(ConnectInfo
);
582 NTSTATUS
TdiReceiveDatagram(
583 PFILE_OBJECT TransportObject
,
589 * FUNCTION: Receives a datagram
591 * TransportObject = Pointer to transport object
592 * Port = Port to receive on
593 * Address = Address of buffer to place remote address
594 * Buffer = Address of buffer to place received data
595 * BufferSize = Address of buffer with length of Buffer (updated)
597 * Status of operation
600 PTDI_CONNECTION_INFORMATION ReceiveInfo
;
601 PTDI_CONNECTION_INFORMATION ReturnInfo
;
602 PTA_IP_ADDRESS ReturnAddress
;
603 PDEVICE_OBJECT DeviceObject
;
604 PTDI_ADDRESS_IP IpAddress
;
605 IO_STATUS_BLOCK Iosb
;
611 DeviceObject
= IoGetRelatedDeviceObject(TransportObject
);
613 return STATUS_INVALID_PARAMETER
;
615 ReceiveInfo
= (PTDI_CONNECTION_INFORMATION
) ExAllocatePool(NonPagedPool
,
616 sizeof(TDI_CONNECTION_INFORMATION
) +
617 sizeof(TDI_CONNECTION_INFORMATION
) +
618 sizeof(TA_IP_ADDRESS
));
621 return STATUS_INSUFFICIENT_RESOURCES
;
623 MdlBuffer
= ExAllocatePool(PagedPool
, *BufferSize
);
625 return STATUS_INSUFFICIENT_RESOURCES
;
627 RtlZeroMemory(ReceiveInfo
, sizeof(TDI_CONNECTION_INFORMATION
) + sizeof(TDI_CONNECTION_INFORMATION
) +
628 sizeof(TA_IP_ADDRESS
));
630 RtlCopyMemory(MdlBuffer
, Buffer
, *BufferSize
);
632 /* Receive from any address */
633 ReceiveInfo
->RemoteAddressLength
= 0;
634 ReceiveInfo
->RemoteAddress
= NULL
;
636 ReturnInfo
= (PTDI_CONNECTION_INFORMATION
) ((ULONG
)ReceiveInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
637 ReturnInfo
->RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
638 ReturnInfo
->RemoteAddress
= (PUCHAR
) ((ULONG
)ReturnInfo
+ sizeof(TDI_CONNECTION_INFORMATION
));
640 ReturnAddress
= (PTA_IP_ADDRESS
)(ReturnInfo
->RemoteAddress
);
641 ReturnAddress
->TAAddressCount
= 1;
642 ReturnAddress
->Address
[0].AddressLength
= sizeof(TDI_ADDRESS_IP
);
643 ReturnAddress
->Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
645 IpAddress
= (PTDI_ADDRESS_IP
)(ReturnAddress
->Address
[0].Address
);
646 IpAddress
->sin_port
= WH2N(Port
);
647 IpAddress
->in_addr
= DH2N(LocalAddress
);
649 Irp
= TdiBuildInternalDeviceControlIrp(
650 TDI_RECEIVE_DATAGRAM
, /* Sub function */
651 DeviceObject
, /* Device object */
652 TransportObject
, /* File object */
654 NULL
); /* Return buffer */
658 ExFreePool(MdlBuffer
);
659 ExFreePool(ReceiveInfo
);
660 return STATUS_INSUFFICIENT_RESOURCES
;
664 MdlBuffer
, /* Virtual address */
665 *BufferSize
, /* Length of buffer */
666 FALSE
, /* Not secondary */
667 FALSE
, /* Don't charge quota */
668 NULL
); /* Don't use IRP */
673 ExFreePool(MdlBuffer
);
674 ExFreePool(ReceiveInfo
);
675 return STATUS_INSUFFICIENT_RESOURCES
;
682 MmProbeAndLockPages(Mdl
, KernelMode
, IoModifyAccess
);
685 except (EXCEPTION_EXECUTE_HANDLER
)
687 TDI_DbgPrint(MIN_TRACE
, ("MmProbeAndLockPages() failed.\n"));
690 ExFreePool(MdlBuffer
);
691 ExFreePool(ReceiveInfo
);
692 return STATUS_INSUFFICIENT_RESOURCES
;
696 TdiBuildReceiveDatagram(
697 Irp
, /* I/O Request Packet */
698 DeviceObject
, /* Device object */
699 TransportObject
, /* File object */
700 NULL
, /* Completion routine */
701 NULL
, /* Completion context */
702 Mdl
, /* Data buffer */
703 *BufferSize
, /* Size of data buffer */
704 ReceiveInfo
, /* Connection information */
705 ReturnInfo
, /* Connection information */
706 TDI_RECEIVE_NORMAL
); /* Flags */
708 Status
= TdiCall(Irp
, DeviceObject
, &Iosb
, TRUE
);
710 if (NT_SUCCESS(Status
))
712 RtlCopyMemory(Buffer
, MdlBuffer
, Iosb
.Information
);
713 *BufferSize
= Iosb
.Information
;
714 *Address
= DN2H(IpAddress
->in_addr
);
717 ExFreePool(MdlBuffer
);
718 ExFreePool(ReceiveInfo
);
727 * FUNCTION: Send thread
729 * Context = Pointer to context information
731 * Transmits an UDP packet every two seconds to ourselves on the chosen port
736 LARGE_INTEGER Timeout
;
737 NTSTATUS Status
= STATUS_SUCCESS
;
738 UCHAR Data
[40] = "Testing one, two, three, ...";
742 Timeout
.QuadPart
= 10000000L; /* Second factor */
743 Timeout
.QuadPart
*= 2; /* Number of seconds */
744 Timeout
.QuadPart
= -(Timeout
.QuadPart
); /* Relative time */
746 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
748 Events
[0] = &StopEvent
;
751 while (NT_SUCCESS(Status
))
753 /* Wait until timeout or stop flag is set */
754 KeWaitForMultipleObjects( 2, (PVOID
)Events
, WaitAny
, Executive
, KernelMode
, FALSE
, &Timeout
, NULL
);
756 if (KeReadStateEvent(&StopEvent
) != 0)
758 TDI_DbgPrint(MAX_TRACE
, ("Received terminate signal...\n"));
762 DbgPrint("Sending data - '%s'\n", Data
);
764 Status
= TdiSendDatagram(TdiTransportObject
, TEST_PORT
, LocalAddress
, Data
, sizeof(Data
));
766 if (!NT_SUCCESS(Status
))
767 DbgPrint("Failed sending data (Status = 0x%X)\n", Status
);
771 TDI_DbgPrint(MAX_TRACE
, ("Terminating send thread...\n"));
773 PsTerminateSystemThread(STATUS_SUCCESS
);
777 VOID
TdiReceiveThread(
780 * FUNCTION: Receive thread
782 * Context = Pointer to context information
784 * Waits until an UDP packet is received on the chosen endpoint and displays the data
790 NTSTATUS Status
= STATUS_SUCCESS
;
794 while (NT_SUCCESS(Status
))
797 RtlZeroMemory(Data
, Size
);
799 Status
= TdiReceiveDatagram(TdiTransportObject
, TEST_PORT
, &Address
, Data
, &Size
);
801 if (NT_SUCCESS(Status
))
803 DbgPrint("Received data - '%s'\n", Data
);
806 if (Status
!= STATUS_CANCELLED
)
808 TDI_DbgPrint(MIN_TRACE
, ("Receive error (Status = 0x%X).\n", Status
));
812 TDI_DbgPrint(MAX_TRACE
, ("IRP was cancelled.\n"));
817 TDI_DbgPrint(MAX_TRACE
, ("Terminating receive thread...\n"));
819 PsTerminateSystemThread(STATUS_SUCCESS
);
826 * FUNCTION: Open thread
828 * Context = Pointer to context information (event)
833 TDI_DbgPrint(MAX_TRACE
, ("Called.\n"));
837 Status
= TdiOpenTransport(UDP_DEVICE_NAME
, TEST_PORT
, &TdiTransport
, &TdiTransportObject
);
839 if (NT_SUCCESS(Status
))
841 Status
= TdiQueryAddress(TdiTransportObject
, &LocalAddress
);
843 if (NT_SUCCESS(Status
))
846 DbgPrint("Using local IP address 0x%X\n", LocalAddress
);
850 TDI_DbgPrint(MIN_TRACE
, ("Unable to determine local IP address.\n"));
854 TDI_DbgPrint(MIN_TRACE
, ("Cannot open transport (Status = 0x%X).\n", Status
));
856 TDI_DbgPrint(MAX_TRACE
, ("Setting close event.\n"));
858 KeSetEvent((PKEVENT
)Context
, 0, FALSE
);
860 TDI_DbgPrint(MIN_TRACE
, ("Leaving.\n"));
865 PDRIVER_OBJECT DriverObject
)
867 * FUNCTION: Unload routine
869 * DriverObject = Pointer to a driver object for this driver
872 PVOID ReceiveThreadObject
= 0;
873 PVOID SendThreadObject
= 0;
875 TDI_DbgPrint(MAX_TRACE
, ("Setting stop flag\n"));
877 /* Get pointers to the thread objects */
878 ObReferenceObjectByHandle(SendThread
, THREAD_ALL_ACCESS
, NULL
, KernelMode
, &SendThreadObject
, NULL
);
879 ObReferenceObjectByHandle(ReceiveThread
, THREAD_ALL_ACCESS
, NULL
, KernelMode
, &ReceiveThreadObject
, NULL
);
881 KeSetEvent(&StopEvent
, 0, FALSE
);
883 /* Wait for send thread to stop */
884 KeWaitForSingleObject(SendThreadObject
, Executive
, KernelMode
, FALSE
, NULL
);
886 /* Wait for receive thread to stop */
887 KeWaitForSingleObject(ReceiveThreadObject
, Executive
, KernelMode
, FALSE
, NULL
);
890 TdiCloseDevice(TdiTransport
, TdiTransportObject
);
899 PDRIVER_OBJECT DriverObject
,
900 PUNICODE_STRING RegistryPath
)
902 * FUNCTION: Main driver entry point
904 * DriverObject = Pointer to a driver object for this driver
905 * RegistryPath = Registry node for configuration parameters
907 * Status of driver initialization
912 WORK_QUEUE_ITEM WorkItem
;
914 KeInitializeEvent(&StopEvent
, NotificationEvent
, FALSE
);
916 /* Call TdiOpenThread() */
917 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
918 ExInitializeWorkItem(&WorkItem
, (PWORKER_THREAD_ROUTINE
)TdiOpenThread
, &Event
);
919 ExQueueWorkItem(&WorkItem
, DelayedWorkQueue
);
920 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, TRUE
, NULL
);
922 /* Create a UDP send thread that sends a dgram every 2 seconds */
923 Status
= PsCreateSystemThread(
924 &SendThread
, /* Thread handle */
925 0, /* Desired access */
926 NULL
, /* Object attributes */
927 NULL
, /* Process handle */
928 NULL
, /* Client id */
929 (PKSTART_ROUTINE
)TdiSendThread
, /* Start routine */
930 NULL
); /* Start context */
932 if (!NT_SUCCESS(Status
))
934 TDI_DbgPrint(MIN_TRACE
, ("PsCreateSystemThread() failed for send thread (Status = 0x%X).\n", Status
));
935 return STATUS_INSUFFICIENT_RESOURCES
;
938 /* Create a UDP receive thread */
939 Status
= PsCreateSystemThread(
940 &ReceiveThread
, /* Thread handle */
941 0, /* Desired access */
942 NULL
, /* Object attributes */
943 NULL
, /* Process handle */
944 NULL
, /* Client id */
945 (PKSTART_ROUTINE
)TdiReceiveThread
, /* Start routine */
946 NULL
); /* Start context */
948 if (!NT_SUCCESS(Status
))
950 TDI_DbgPrint(MIN_TRACE
, ("PsCreateSystemThread() failed for receive thread (Status = 0x%X).\n", Status
));
952 return STATUS_INSUFFICIENT_RESOURCES
;
955 DriverObject
->DriverUnload
= (PDRIVER_UNLOAD
)TdiUnload
;
957 return STATUS_SUCCESS
;