Fixed a race condition on unload, other minor clean-up, now loads and runs correctly on win2ksp4 checked w/ full verifier

svn path=/trunk/; revision=6800
This commit is contained in:
Vizzini 2003-11-26 09:12:07 +00:00
parent d50eee1838
commit fcfd77241a
2 changed files with 38 additions and 43 deletions

View file

@ -19,7 +19,7 @@
#ifdef DBG #ifdef DBG
extern DWORD DebugTraceLevel; extern ULONG DebugTraceLevel;
#ifdef _MSC_VER #ifdef _MSC_VER

View file

@ -4,8 +4,10 @@
* FILE: tditest.c * FILE: tditest.c
* PURPOSE: Testing TDI drivers * PURPOSE: Testing TDI drivers
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Vizzini (vizzini@plasmic.com)
* REVISIONS: * REVISIONS:
* CSH 01/08-2000 Created * CSH 01/08-2000 Created
* 26-Nov-2003 Vizzini Updated to run properly on Win2ksp4
*/ */
#include <tditest.h> #include <tditest.h>
@ -24,12 +26,7 @@ ULONG LocalAddress;
BOOLEAN OpenError; BOOLEAN OpenError;
KEVENT StopEvent; KEVENT StopEvent;
HANDLE SendThread; HANDLE SendThread;
KEVENT SendThreadEvent;
HANDLE ReceiveThread; HANDLE ReceiveThread;
KEVENT ReceiveThreadEvent;
PVOID ReceiveThreadObject;
PVOID SendThreadObject;
NTSTATUS TdiCall( NTSTATUS TdiCall(
PIRP Irp, PIRP Irp,
@ -65,7 +62,7 @@ NTSTATUS TdiCall(
{ {
if (CanCancel) if (CanCancel)
{ {
Status = KeWaitForMultipleObjects(2, (PVOID)&Events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); Status = KeWaitForMultipleObjects(2, (PVOID)Events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
if (KeReadStateEvent(&StopEvent) != 0) if (KeReadStateEvent(&StopEvent) != 0)
{ {
@ -112,13 +109,15 @@ NTSTATUS TdiOpenDevice(
NTSTATUS Status; NTSTATUS Status;
RtlInitUnicodeString(&Name, Protocol); RtlInitUnicodeString(&Name, Protocol);
InitializeObjectAttributes(&Attr, /* Attribute buffer */ InitializeObjectAttributes(
&Attr, /* Attribute buffer */
&Name, /* Device name */ &Name, /* Device name */
OBJ_CASE_INSENSITIVE, /* Attributes */ OBJ_CASE_INSENSITIVE, /* Attributes */
NULL, /* Root directory */ NULL, /* Root directory */
NULL); /* Security descriptor */ NULL); /* Security descriptor */
Status = ZwCreateFile(Handle, /* Return file handle */ Status = ZwCreateFile(
Handle, /* Return file handle */
GENERIC_READ | GENERIC_WRITE, /* Desired access */ GENERIC_READ | GENERIC_WRITE, /* Desired access */
&Attr, /* Object attributes */ &Attr, /* Object attributes */
&Iosb, /* IO status */ &Iosb, /* IO status */
@ -132,7 +131,8 @@ NTSTATUS TdiOpenDevice(
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */ Status = ObReferenceObjectByHandle(
*Handle, /* Handle to open file */
GENERIC_READ | GENERIC_WRITE, /* Access mode */ GENERIC_READ | GENERIC_WRITE, /* Access mode */
NULL, /* Object type */ NULL, /* Object type */
KernelMode, /* Access mode */ KernelMode, /* Access mode */
@ -189,7 +189,7 @@ NTSTATUS TdiOpenTransport(
NTSTATUS Status; NTSTATUS Status;
ULONG EaLength; ULONG EaLength;
/* EaName *must* be 0-termed, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */ /* EaName must be 0-termed, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
EaLength = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS) + 1; EaLength = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS) + 1;
EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength); EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
@ -304,7 +304,8 @@ NTSTATUS TdiQueryInformationEx(
QueryInfo.ID.toi_type = Type; QueryInfo.ID.toi_type = Type;
QueryInfo.ID.toi_id = Id; QueryInfo.ID.toi_id = Id;
return TdiQueryDeviceControl(FileObject, /* Transport/connection object */ return TdiQueryDeviceControl(
FileObject, /* Transport/connection object */
IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */ IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */
&QueryInfo, /* Input buffer */ &QueryInfo, /* Input buffer */
sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */ sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */
@ -347,7 +348,8 @@ NTSTATUS TdiQueryAddress(
} }
/* Query device for supported entities */ /* Query device for supported entities */
Status = TdiQueryInformationEx(FileObject, /* File object */ Status = TdiQueryInformationEx(
FileObject, /* File object */
GENERIC_ENTITY, /* Entity */ GENERIC_ENTITY, /* Entity */
TL_INSTANCE, /* Instance */ TL_INSTANCE, /* Instance */
INFO_CLASS_GENERIC, /* Entity class */ INFO_CLASS_GENERIC, /* Entity class */
@ -374,7 +376,8 @@ NTSTATUS TdiQueryAddress(
{ {
/* Query device for entity type */ /* Query device for entity type */
BufferSize = sizeof(EntityType); BufferSize = sizeof(EntityType);
Status = TdiQueryInformationEx(FileObject, /* File object */ Status = TdiQueryInformationEx(
FileObject, /* File object */
CL_NL_ENTITY, /* Entity */ CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */ Entities[i].tei_instance, /* Instance */
INFO_CLASS_GENERIC, /* Entity class */ INFO_CLASS_GENERIC, /* Entity class */
@ -391,7 +394,8 @@ NTSTATUS TdiQueryAddress(
/* Query device for SNMP information */ /* Query device for SNMP information */
BufferSize = sizeof(SnmpInfo); BufferSize = sizeof(SnmpInfo);
Status = TdiQueryInformationEx(FileObject, /* File object */ Status = TdiQueryInformationEx(
FileObject, /* File object */
CL_NL_ENTITY, /* Entity */ CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */ Entities[i].tei_instance, /* Instance */
INFO_CLASS_PROTOCOL, /* Entity class */ INFO_CLASS_PROTOCOL, /* Entity class */
@ -417,7 +421,8 @@ NTSTATUS TdiQueryAddress(
break; break;
} }
Status = TdiQueryInformationEx(FileObject, /* File object */ Status = TdiQueryInformationEx(
FileObject, /* File object */
CL_NL_ENTITY, /* Entity */ CL_NL_ENTITY, /* Entity */
Entities[i].tei_instance, /* Instance */ Entities[i].tei_instance, /* Instance */
INFO_CLASS_PROTOCOL, /* Entity class */ INFO_CLASS_PROTOCOL, /* Entity class */
@ -746,7 +751,7 @@ VOID TdiSendThread(
while (NT_SUCCESS(Status)) while (NT_SUCCESS(Status))
{ {
/* Wait until timeout or stop flag is set */ /* Wait until timeout or stop flag is set */
KeWaitForMultipleObjects( 2, (PVOID)&Events, WaitAny, Executive, KernelMode, FALSE, &Timeout, NULL); KeWaitForMultipleObjects( 2, (PVOID)Events, WaitAny, Executive, KernelMode, FALSE, &Timeout, NULL);
if (KeReadStateEvent(&StopEvent) != 0) if (KeReadStateEvent(&StopEvent) != 0)
{ {
@ -765,8 +770,6 @@ VOID TdiSendThread(
TDI_DbgPrint(MAX_TRACE, ("Terminating send thread...\n")); TDI_DbgPrint(MAX_TRACE, ("Terminating send thread...\n"));
KeSetEvent(&SendThreadEvent, 0, FALSE);
PsTerminateSystemThread(STATUS_SUCCESS); PsTerminateSystemThread(STATUS_SUCCESS);
} }
@ -813,8 +816,6 @@ VOID TdiReceiveThread(
TDI_DbgPrint(MAX_TRACE, ("Terminating receive thread...\n")); TDI_DbgPrint(MAX_TRACE, ("Terminating receive thread...\n"));
KeSetEvent(&ReceiveThreadEvent, 0, FALSE);
PsTerminateSystemThread(STATUS_SUCCESS); PsTerminateSystemThread(STATUS_SUCCESS);
} }
@ -868,19 +869,25 @@ VOID TdiUnload(
* DriverObject = Pointer to a driver object for this driver * DriverObject = Pointer to a driver object for this driver
*/ */
{ {
PVOID ReceiveThreadObject = 0;
PVOID SendThreadObject = 0;
TDI_DbgPrint(MAX_TRACE, ("Setting stop flag\n")); TDI_DbgPrint(MAX_TRACE, ("Setting stop flag\n"));
/* Get pointers to the thread objects */
ObReferenceObjectByHandle(SendThread, THREAD_ALL_ACCESS, NULL, KernelMode, &SendThreadObject, NULL);
ObReferenceObjectByHandle(ReceiveThread, THREAD_ALL_ACCESS, NULL, KernelMode, &ReceiveThreadObject, NULL);
ASSERT(ReceiveThreadObject);
ASSERT(SendThreadObject);
KeSetEvent(&StopEvent, 0, FALSE); KeSetEvent(&StopEvent, 0, FALSE);
/* Wait for send thread to stop */ /* Wait for send thread to stop */
KeWaitForSingleObject(&SendThreadEvent, Executive, KernelMode, FALSE, NULL); KeWaitForSingleObject(SendThreadObject, Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(SendThreadObject);
/* Wait for receive thread to stop */ /* Wait for receive thread to stop */
KeWaitForSingleObject(&ReceiveThreadEvent, Executive, KernelMode, FALSE, NULL); KeWaitForSingleObject(ReceiveThreadObject, Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(ReceiveThreadObject);
/* Close device */ /* Close device */
TdiCloseDevice(TdiTransport, TdiTransportObject); TdiCloseDevice(TdiTransport, TdiTransportObject);
@ -908,8 +915,6 @@ DriverEntry(
WORK_QUEUE_ITEM WorkItem; WORK_QUEUE_ITEM WorkItem;
KeInitializeEvent(&StopEvent, NotificationEvent, FALSE); KeInitializeEvent(&StopEvent, NotificationEvent, FALSE);
KeInitializeEvent(&SendThreadEvent, NotificationEvent, FALSE);
KeInitializeEvent(&ReceiveThreadEvent, NotificationEvent, FALSE);
/* Call TdiOpenThread() */ /* Call TdiOpenThread() */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE); KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
@ -918,7 +923,8 @@ DriverEntry(
KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, NULL); KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, NULL);
/* Create a UDP send thread that sends a dgram every 2 seconds */ /* Create a UDP send thread that sends a dgram every 2 seconds */
Status = PsCreateSystemThread(&SendThread, /* Thread handle */ Status = PsCreateSystemThread(
&SendThread, /* Thread handle */
0, /* Desired access */ 0, /* Desired access */
NULL, /* Object attributes */ NULL, /* Object attributes */
NULL, /* Process handle */ NULL, /* Process handle */
@ -932,11 +938,9 @@ DriverEntry(
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* Get a pointer to the thread object */
ObReferenceObjectByHandle(SendThread, THREAD_ALL_ACCESS, NULL, KernelMode, &SendThreadObject, NULL);
/* Create a UDP receive thread */ /* Create a UDP receive thread */
Status = PsCreateSystemThread(&ReceiveThread, /* Thread handle */ Status = PsCreateSystemThread(
&ReceiveThread, /* Thread handle */
0, /* Desired access */ 0, /* Desired access */
NULL, /* Object attributes */ NULL, /* Object attributes */
NULL, /* Process handle */ NULL, /* Process handle */
@ -948,18 +952,9 @@ DriverEntry(
{ {
TDI_DbgPrint(MIN_TRACE, ("PsCreateSystemThread() failed for receive thread (Status = 0x%X).\n", Status)); TDI_DbgPrint(MIN_TRACE, ("PsCreateSystemThread() failed for receive thread (Status = 0x%X).\n", Status));
ZwClose(SendThread); ZwClose(SendThread);
ObDereferenceObject(SendThreadObject); /* deref the extra ref we took above */
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* Get a pointer to the thread object */
ObReferenceObjectByHandle(ReceiveThread, THREAD_ALL_ACCESS, NULL, KernelMode, &ReceiveThreadObject, NULL);
/* Don't need these for anything, so we might as well close them now.
The threads will call PsTerminateSystemThread themselves when they are done */
ZwClose(SendThread);
ZwClose(ReceiveThread);
DriverObject->DriverUnload = (PDRIVER_UNLOAD)TdiUnload; DriverObject->DriverUnload = (PDRIVER_UNLOAD)TdiUnload;
return STATUS_SUCCESS; return STATUS_SUCCESS;