summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/testprot/tpdrvr/tpdrvr.c
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/testprot/tpdrvr/tpdrvr.c')
-rw-r--r--private/ntos/ndis/testprot/tpdrvr/tpdrvr.c1656
1 files changed, 1656 insertions, 0 deletions
diff --git a/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c b/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c
new file mode 100644
index 000000000..a40b385bc
--- /dev/null
+++ b/private/ntos/ndis/testprot/tpdrvr/tpdrvr.c
@@ -0,0 +1,1656 @@
+// -------------
+//
+// Copyright (c) 1990 Microsoft Corporation
+//
+// Module Name:
+//
+// tpdrvr.c
+//
+// Abstract:
+//
+// This module contains code which defines the Test Protocol
+// device object.
+//
+// Author:
+//
+// Tom Adams (tomad) 19-Apr-1991
+//
+// Environment:
+//
+// Kernel mode, FSD
+//
+// Revision History:
+//
+// Sanjeev Katariya Forced unload of driver thru the control panel was not working
+// Effected function : TpUnloadDriver()
+//
+// Tim Wynsma (timothyw) 4-27-94
+// Added performance tests
+// Tim Wynsma (timothyw) 6-08-94
+// Chgd perf tests to use client/server model
+//
+// --------------
+
+#include <ndis.h>
+
+#include "tpdefs.h"
+#include "media.h"
+#include "tpprocs.h"
+
+// the following function is prototyped in public\oak\inc\zwapi.h, but including that file
+// produces MANY compile errors.
+
+NTSYSAPI
+NTSTATUS
+NTAPI
+ZwCreateSymbolicLinkObject(
+ OUT PHANDLE LinkHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PUNICODE_STRING LinkTarget
+ );
+
+
+POPEN_BLOCK TpOpen = NULL;
+HANDLE SymbolicLinkHandle;
+
+//
+// The debugging longword, containing a bitmask as defined in common.h
+// If a bit is set, then debugging is turned on for that component.
+//
+
+#if DBG
+
+ULONG TpDebug = TP_DEBUG_NDIS_CALLS|TP_DEBUG_NDIS_ERROR|TP_DEBUG_STATISTICS|
+ TP_DEBUG_DATA|TP_DEBUG_DISPATCH|TP_DEBUG_IOCTL_ARGS|
+ TP_DEBUG_NT_STATUS|TP_DEBUG_DPC|TP_DEBUG_INITIALIZE|
+ TP_DEBUG_RESOURCES|TP_DEBUG_BREAKPOINT|TP_DEBUG_INFOLEVEL_1;
+
+BOOLEAN TpAssert = TRUE;
+
+#endif // DBG
+
+NDIS_PHYSICAL_ADDRESS HighestAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+//
+// Driver Entry function
+//
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+// ----------
+//
+// Routine Description:
+//
+// This routine performs initialization of the Test Protocol driver.
+// It creates the device objects for the driver and performs
+// other driver initialization.
+//
+// Arguments:
+//
+// DriverObject - Pointer to driver object created by the system.
+//
+// Return Value:
+//
+// The function value is the final status from the initialization operation.
+//
+// ----------
+
+{
+ STRING nameString;
+ PDEVICE_CONTEXT DeviceContext;
+ NTSTATUS Status;
+
+ //
+ // General Version Information
+ //
+ IF_TPDBG( TP_DEBUG_ALL )
+ {
+ TpPrint0("\nMAC NDIS 3.0 Tester - Test Driver Version 1.5.1\n\n");
+ }
+
+ //
+ // First initialize the DeviceContext struct,
+ //
+
+ RtlInitString( &nameString, DD_TP_DEVICE_NAME );
+
+ Status = TpCreateDeviceContext (DriverObject,
+ nameString,
+ &DeviceContext );
+
+ if (!NT_SUCCESS (Status))
+ {
+ TpPrint1 ("TPDRVR: failed to create device context: Status = %s\n",
+ TpGetStatus(Status));
+ return Status;
+ }
+ else
+ {
+ TpOpen = &DeviceContext->Open[0];
+ }
+
+ //
+ // Create symbolic link between the Dos Device name and Nt
+ // Device name for the test protocol driver.
+ //
+
+ Status = TpCreateSymbolicLinkObject( );
+
+ if (!NT_SUCCESS (Status))
+ {
+ TpPrint1 ("TPDRVR: failed to create symbolic link. Status = %s\n", TpGetStatus(Status));
+ return Status;
+ }
+
+ //
+ // then set up the EventQueue for any spurious event, indications,
+ // or completions. This should be ready at all times, from the
+ // time the test protocol is registered to the time it is unloaded.
+ //
+
+ Status = TpInitializeEventQueue( DeviceContext );
+
+ if (!NT_SUCCESS (Status)) {
+ TpPrint1 ("TPDRVR: failed to create initialize Event Queue. Status = %s\n",
+ TpGetStatus(Status));
+ return Status;
+ }
+
+ //
+ // make ourselves known to the NDIS wrapper.
+ //
+
+ Status = TpRegisterProtocol ( DeviceContext, &nameString );
+
+ if (!NT_SUCCESS(Status))
+ {
+ DeviceContext->Initialized = FALSE;
+
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint1("TPDRVR: TpRegisterProtocol failed. Status= %s\n", TpGetStatus(Status));
+ }
+ }
+ return Status;
+}
+
+
+
+NTSTATUS
+TpCreateDeviceContext(
+ IN PDRIVER_OBJECT DriverObject,
+ IN STRING DeviceName,
+ PDEVICE_CONTEXT *DeviceContext
+ )
+
+// -----------
+//
+// Routine Description:
+//
+// This routine creates and initializes a device context structure.
+//
+// Arguments:
+//
+// DriverObject - pointer to the IO subsystem supplied driver object.
+//
+// DeviceContext - Pointer to a pointer to a transport device context object.
+//
+// DeviceName - pointer to the name of the device this device object points to.
+//
+// Return Value:
+//
+// STATUS_SUCCESS if all is well; STATUS_INSUFFICIENT_RESOURCES otherwise.
+//
+// ------------
+
+{
+ NTSTATUS Status;
+ UNICODE_STRING unicodeString;
+ PDEVICE_OBJECT deviceObject;
+ PDEVICE_CONTEXT deviceContext;
+
+ //
+ // Convert the input name string to Unicode until it is actually
+ // passed as a Unicode string.
+ //
+
+ Status = RtlAnsiStringToUnicodeString( &unicodeString,
+ &DeviceName,
+ TRUE );
+ if ( !NT_SUCCESS( Status ))
+ {
+ return Status;
+ }
+
+ //
+ // Create the device object for Test Protocol.
+ //
+
+ Status = IoCreateDevice(DriverObject,
+ sizeof (DEVICE_CONTEXT) - sizeof (DEVICE_OBJECT),
+ &unicodeString,
+ FILE_DEVICE_TRANSPORT,
+ 0,
+ FALSE,
+ &deviceObject );
+
+ RtlFreeUnicodeString( &unicodeString );
+
+ if ( !NT_SUCCESS( Status ))
+ {
+ return Status;
+ }
+
+ deviceObject->Flags |= DO_DIRECT_IO;
+
+ //
+ // Initialize the driver object with this driver's entry points.
+ //
+
+ DriverObject->MajorFunction [IRP_MJ_CREATE] = TpDispatch;
+ DriverObject->MajorFunction [IRP_MJ_CLOSE] = TpDispatch;
+ DriverObject->MajorFunction [IRP_MJ_CLEANUP] = TpDispatch;
+ DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = TpDispatch;
+ DriverObject->DriverUnload = TpUnloadDriver;
+
+ deviceContext = (PDEVICE_CONTEXT)deviceObject;
+
+ //
+ // Now initialize the Device Context structure Signatures.
+ //
+
+ deviceContext->OpenSignature = OPEN_BLOCK_SIGNATURE;
+
+ deviceContext->Initialized = TRUE;
+
+ *DeviceContext = deviceContext;
+
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+TpCreateSymbolicLinkObject(
+ VOID
+ )
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttr;
+ STRING DosString;
+ STRING NtString;
+ UNICODE_STRING DosUnicodeString;
+ UNICODE_STRING NtUnicodeString;
+
+ RtlInitAnsiString( &DosString, "\\DosDevices\\Tpdrvr" );
+
+ Status = RtlAnsiStringToUnicodeString( &DosUnicodeString,
+ &DosString,
+ TRUE );
+ if ( !NT_SUCCESS( Status ))
+ {
+ return Status;
+ }
+
+ RtlInitAnsiString( &NtString, DD_TP_DEVICE_NAME );
+
+ Status = RtlAnsiStringToUnicodeString( &NtUnicodeString,
+ &NtString,
+ TRUE );
+ if ( !NT_SUCCESS( Status ))
+ {
+ return Status;
+ }
+
+ //
+ // Removed the OBJ_PERMANENT attribute since we should be able to load and
+ // unload this driver and create the necessary links at will. Buf Fix# 13183
+ //
+ InitializeObjectAttributes( &ObjectAttr,
+ &DosUnicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ Status = ZwCreateSymbolicLinkObject(&SymbolicLinkHandle,
+ SYMBOLIC_LINK_ALL_ACCESS,
+ &ObjectAttr,
+ &NtUnicodeString );
+
+ if ( Status != STATUS_SUCCESS )
+ {
+ return Status;
+ }
+
+ RtlFreeUnicodeString( &DosUnicodeString );
+ RtlFreeUnicodeString( &NtUnicodeString );
+
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+TpInitializeEventQueue(
+ IN PDEVICE_CONTEXT DeviceContext
+ )
+{
+ NTSTATUS Status;
+ ULONG i, j;
+
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ //
+ // Finally, allocate Event Queue header struct, and its spin lock.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&DeviceContext->Open[i].EventQueue,
+ sizeof( EVENT_QUEUE ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpInitializeEventQueue: failed to allocate EVENT_QUEUE struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( (PVOID)DeviceContext->Open[i].EventQueue,
+ sizeof( EVENT_QUEUE ) );
+ }
+
+ NdisAllocateSpinLock( &DeviceContext->Open[i].EventQueue->SpinLock );
+
+ //
+ // Initialize the Event Queue header, and each of the seperate events
+ // in the Event Queue array.
+ //
+
+ DeviceContext->Open[i].EventQueue->ReceiveIndicationCount = 0;
+ DeviceContext->Open[i].EventQueue->StatusIndicationCount = 0;
+ DeviceContext->Open[i].EventQueue->ExpectReceiveComplete = FALSE;
+ DeviceContext->Open[i].EventQueue->ExpectStatusComplete = FALSE;
+ DeviceContext->Open[i].EventQueue->Head = 0;
+ DeviceContext->Open[i].EventQueue->Tail = 0;
+
+ for ( j=0;j<MAX_EVENT;j++ )
+ {
+ DeviceContext->Open[i].EventQueue->Events[j].TpEventType = Unknown;
+ DeviceContext->Open[i].EventQueue->Events[j].Status = NDIS_STATUS_SUCCESS;
+ DeviceContext->Open[i].EventQueue->Events[j].Overflow = FALSE;
+ DeviceContext->Open[i].EventQueue->Events[j].EventInfo = NULL;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+TpRegisterProtocol (
+ IN PDEVICE_CONTEXT DeviceContext,
+ IN STRING *NameString
+ )
+
+// -----
+//
+// Routine Description:
+//
+// This routine introduces this transport to the NDIS interface.
+//
+// Arguments:
+//
+// DeviceObject - Pointer to the device object for this driver.
+//
+// NameString - The name of the device to be registered.
+//
+// Return Value:
+//
+// The function value is the status of the operation.
+// STATUS_SUCCESS if all goes well,
+// STATUS_UNSUCCESSFUL if we tried to register and couldn't,
+// STATUS_INSUFFICIENT_RESOURCES if we couldn't even try to register.
+//
+// -------------
+
+{
+ NDIS_STATUS Status;
+ USHORT i;
+
+ //
+ // Set up the characteristics of this protocol
+ //
+
+
+ Status = NdisAllocateMemory((PVOID *)&DeviceContext->ProtChars,
+ sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) + NameString->Length,
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_INITIALIZE)
+ {
+ TpPrint0 ("TpRegisterProtocol: insufficient memory to allocate Protocol descriptor.\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( DeviceContext->ProtChars,
+ sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) );
+ }
+
+ //
+ // Setup the Characteristics Block and register the protocol with
+ // the NDIS Wrapper.
+ //
+
+ DeviceContext->ProtChars->MajorNdisVersion = 3;
+ DeviceContext->ProtChars->MinorNdisVersion = 0;
+ DeviceContext->ProtChars->Name.Length = NameString->Length;
+ DeviceContext->ProtChars->Name.Buffer = (PVOID)NameString->Buffer;
+
+ DeviceContext->ProtChars->OpenAdapterCompleteHandler =
+ TestProtocolOpenComplete;
+ DeviceContext->ProtChars->CloseAdapterCompleteHandler =
+ TestProtocolCloseComplete;
+ DeviceContext->ProtChars->SendCompleteHandler = TestProtocolSendComplete;
+ DeviceContext->ProtChars->TransferDataCompleteHandler =
+ TestProtocolTransferDataComplete;
+ DeviceContext->ProtChars->ResetCompleteHandler =
+ TestProtocolResetComplete;
+ DeviceContext->ProtChars->RequestCompleteHandler =
+ TestProtocolRequestComplete;
+ DeviceContext->ProtChars->ReceiveHandler = TestProtocolReceive;
+ DeviceContext->ProtChars->ReceiveCompleteHandler =
+ TestProtocolReceiveComplete;
+ DeviceContext->ProtChars->StatusHandler = TestProtocolStatus;
+ DeviceContext->ProtChars->StatusCompleteHandler =
+ TestProtocolStatusComplete;
+
+ NdisRegisterProtocol ( &Status,
+ &DeviceContext->NdisProtocolHandle,
+ DeviceContext->ProtChars,
+ (UINT)sizeof( NDIS_PROTOCOL_CHARACTERISTICS ) + NameString->Length );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_INITIALIZE)
+ {
+ TpPrint1("TpRegisterProtocol: NdisRegisterProtocol failed: %s\n",
+ TpGetStatus( Status ));
+ }
+ NdisFreeMemory( DeviceContext->ProtChars,0,0 );
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ DeviceContext->Open[i].NdisProtocolHandle = DeviceContext->NdisProtocolHandle;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+TpDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+// -------
+//
+// Routine Description:
+//
+// This routine is the main dispatch routine for the Test Protocol
+// driver. It accepts an I/O Request Packet, performs the request,
+// and then returns with the appropriate status.
+//
+// Arguments:
+//
+// DeviceObject - Pointer to the device object for this driver.
+//
+// Irp - Pointer to the request packet representing the I/O request.
+//
+// Return Value:
+//
+// The function value is the status of the operation.
+//
+// -------
+
+{
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IrpSp;
+ PDEVICE_CONTEXT DeviceContext;
+
+ //
+ // Check to see if TP has been initialized; if not, don't allow any use.
+ //
+
+ DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
+ if ( !DeviceContext->Initialized )
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Make sure status information is consistent every time.
+ //
+
+ Irp->IoStatus.Status = NDIS_STATUS_PENDING;
+ Irp->IoStatus.Information = 0;
+
+ //
+ // Get a pointer to the current stack location in the IRP. This is where
+ // the function codes and parameters are stored.
+ //
+
+ IrpSp = IoGetCurrentIrpStackLocation( Irp );
+
+ //
+ // Case on the function that is being performed by the requestor. If the
+ // operation is a valid one for this device, then make it look like it was
+ // successfully completed, where possible.
+ //
+
+ switch ( IrpSp->MajorFunction )
+ {
+ //
+ // The Create function opens the Test Protocol driver and initializes
+ // the OpenBlock and its various data structures used to control the
+ // tests. Only one instance of TPCTL.EXE may have the driver open at
+ // any given time, all other open requests will fail with the error
+ // STATUS_DEVICE_ALREADY_ATTACHED
+ //
+ case IRP_MJ_CREATE:
+ IF_TPDBG(TP_DEBUG_DISPATCH)
+ {
+ TpPrint0("TpDispatch: IRP_MJ_CREATE.\n");
+ }
+ Status = TpOpenDriver( DeviceContext );
+ Irp->IoStatus.Status = Status;
+ break;
+
+ //
+ // The Close function closes the Test Protocol driver and deallocates
+ // the various data structures attached to the OpenBlock.
+ //
+ case IRP_MJ_CLOSE:
+ IF_TPDBG(TP_DEBUG_DISPATCH)
+ {
+ TpPrint0("TpDispatch: IRP_MJ_CLOSE.\n");
+ }
+ TpCloseDriver( DeviceContext );
+ Status = Irp->IoStatus.Status = STATUS_SUCCESS;
+ break;
+
+ //
+ // The DeviceControl function is the main path to the test protocol
+ // driver interface. Every Test Protocol request is has an Io Control
+ // code that is used by this function to determine the routine to
+ // call.
+ //
+ case IRP_MJ_DEVICE_CONTROL:
+ IF_TPDBG(TP_DEBUG_DISPATCH)
+ {
+ TpPrint0("TpDispatch: IRP_MJ_DEVICE_CONTROL.\n");
+ }
+ Status = TpIssueRequest( DeviceContext,Irp,IrpSp );
+ break;
+
+ //
+ // Handle the two stage IRP for a file close operation. When the first
+ // stage hits,
+ //
+ case IRP_MJ_CLEANUP:
+ IF_TPDBG( TP_DEBUG_DISPATCH )
+ {
+ TpPrint0("TpDispatch: IRP_MJ_CLEANUP.\n");
+ }
+ Status = TpCleanUpDriver( DeviceContext,Irp );
+ Irp->IoStatus.Status = Status;
+ break;
+
+ default:
+ IF_TPDBG( TP_DEBUG_DISPATCH )
+ {
+ TpPrint0("TpDispatch: OTHER (DEFAULT).\n");
+ }
+ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+
+ } // major function switch
+
+ //
+ // If the request did not pend, the complete it now, otherwise it
+ // will be completed when the pending routine finishes.
+ //
+
+ if ( Status == STATUS_PENDING )
+ {
+ IF_TPDBG( TP_DEBUG_DISPATCH )
+ {
+ TpPrint0("TpDispatch: request PENDING in handler.\n");
+ }
+ }
+ else if ( Status == STATUS_CANCELLED )
+ {
+ IF_TPDBG( TP_DEBUG_DISPATCH )
+ {
+ TpPrint0("TpDispatch: request CANCELLED by handler.\n");
+ }
+ }
+ else
+ {
+ IF_TPDBG(TP_DEBUG_DISPATCH)
+ {
+ TpPrint0("TpDispatch: request COMPLETED by handler.\n");
+ }
+ IoAcquireCancelSpinLock( &Irp->CancelIrql );
+ IoSetCancelRoutine( Irp,NULL );
+ IoReleaseCancelSpinLock( Irp->CancelIrql );
+
+ IoCompleteRequest( Irp,IO_NETWORK_INCREMENT );
+ }
+
+ //
+ // Return the immediate status code to the caller.
+ //
+
+ return Status;
+}
+
+
+
+NTSTATUS
+TpOpenDriver(
+ IN PDEVICE_CONTEXT DeviceContext
+ )
+
+{
+ NTSTATUS Status;
+ USHORT i;
+
+ //
+ // If the Device did not successfully initialize at boot time than
+ // fail this open.
+ //
+
+ if( DeviceContext->Initialized != TRUE )
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ //
+ // if the device has already been opened by an instance of TPCTL.EXE
+ // then fail this open.
+ //
+
+ if ( DeviceContext->Opened == TRUE )
+ {
+ return STATUS_DEVICE_ALREADY_ATTACHED;
+ }
+
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ //
+ // Allocate each of the instances of the OpenBlock.
+ //
+
+ Status = TpAllocateOpenArray( &DeviceContext->Open[i] );
+
+ if ( Status != STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint1("TpCreateDeviceContext: failed to allocate Open Array. Status = %s\n",
+ TpGetStatus(Status));
+ }
+
+ //
+ // If one of the allocation calls fails deallocate any of
+ // the structs that were just successfully allocated.
+ //
+
+ while ( i >= 0 )
+ {
+ TpDeallocateOpenArray( &DeviceContext->Open[i--] );
+ }
+ return Status;
+ }
+ }
+ DeviceContext->Opened = TRUE;
+
+ return STATUS_SUCCESS;
+}
+
+
+
+NTSTATUS
+TpCleanUpDriver(
+ IN PDEVICE_CONTEXT DeviceContext,
+ IN PIRP Irp
+ )
+
+// ----
+//
+// Routine Description:
+//
+//
+// Arguments:
+//
+//
+// Return Value:
+//
+// ----
+
+{
+ NDIS_STATUS Status;
+ USHORT i;
+
+ //
+ // Make this Irp Cancellable
+ //
+
+ NdisAcquireSpinLock( &DeviceContext->Open[0].SpinLock );
+
+ DeviceContext->Open[0].Irp = Irp;
+ DeviceContext->Open[0].IrpCancelled = FALSE;
+
+ IoAcquireCancelSpinLock( &Irp->CancelIrql );
+
+ if ( Irp->Cancel )
+ {
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ return STATUS_CANCELLED;
+ }
+
+ IoSetCancelRoutine( Irp,(PDRIVER_CANCEL)TpCancelIrp );
+
+ IoReleaseCancelSpinLock( Irp->CancelIrql );
+
+ NdisReleaseSpinLock( &DeviceContext->Open[0].SpinLock );
+
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ if ( DeviceContext->Open[i].OpenInstance != (UCHAR)-1 )
+ {
+ //
+ // Set the open instance's closing flag to true, then signal
+ // all the async test protocol routines to end.
+ //
+
+ DeviceContext->Open[i].Closing = TRUE;
+
+ if ( DeviceContext->Open[i].Stress->Stressing == TRUE )
+ {
+ DeviceContext->Open[i].Stress->StopStressing = TRUE;
+ }
+
+ if ( DeviceContext->Open[i].Send->Sending == TRUE )
+ {
+ DeviceContext->Open[i].Send->StopSending = TRUE;
+ }
+
+ if ( DeviceContext->Open[i].Receive->Receiving == TRUE )
+ {
+ DeviceContext->Open[i].Receive->StopReceiving = TRUE;
+ }
+
+ if ( DeviceContext->Open[i].PerformanceTest == TRUE)
+ {
+ DeviceContext->Open[i].Perform->Active = FALSE;
+ }
+
+ //
+ // Wait for all of the four asynchronous routines STRESS,
+ // SEND, PERFORMANCE, and RECEIVE to finish, then close the adapter.
+ //
+
+ while (( DeviceContext->Open[i].ReferenceCount > 0 ) &&
+ ( DeviceContext->Open[0].IrpCancelled != TRUE ))
+ {
+ /* NULL */ ;
+ }
+
+ //
+ // Now close each of the existing OpenInstances.
+ //
+
+ NdisCloseAdapter( &Status,
+ DeviceContext->Open[i].NdisBindingHandle );
+
+ if (( Status != NDIS_STATUS_SUCCESS ) &&
+ ( Status != NDIS_STATUS_PENDING ))
+ {
+ IF_TPDBG ( TP_DEBUG_NDIS_ERROR )
+ {
+ TpPrint2(
+ "TpCleanUpDriver: failed to close adapter for instance #%d. Status = %s\n",
+ i, TpGetStatus(Status));
+ }
+ }
+ else
+ {
+ // XXX: handle the close pending.
+
+ DeviceContext->Open[i].NdisBindingHandle = NULL;
+ DeviceContext->Open[i].OpenInstance = (UCHAR)-1;
+ DeviceContext->Open[i].Closing = FALSE;
+
+ NdisFreeMemory( DeviceContext->Open[i].AdapterName,0,0 );
+ DeviceContext->Open[i].AdapterName = NULL;
+
+ //
+ // We will also free the media block at this point because
+ // the info it contains may not hold for the next adapter
+ // open on this instance.
+ //
+
+ NdisFreeMemory( DeviceContext->Open[i].Media,0,0 );
+ DeviceContext->Open[i].Media = NULL;
+ }
+ }
+ }
+
+ //
+ // If this Irp has been cancelled return now, otherwise make it
+ // non cancellable.
+ //
+
+ NdisAcquireSpinLock( &DeviceContext->Open[0].SpinLock );
+
+ if ( DeviceContext->Open[0].IrpCancelled == TRUE )
+ {
+ return STATUS_CANCELLED;
+ }
+ else
+ {
+ IoAcquireCancelSpinLock( &Irp->CancelIrql );
+ IoSetCancelRoutine( Irp,NULL );
+ IoReleaseCancelSpinLock( Irp->CancelIrql );
+ }
+
+ NdisReleaseSpinLock( &DeviceContext->Open[0].SpinLock );
+
+ //
+ // Deallocate each of the instances of the OpenBlock.
+ //
+
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ TpDeallocateOpenArray( &DeviceContext->Open[i] );
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+
+VOID
+TpCloseDriver(
+ IN PDEVICE_CONTEXT DeviceContext
+ )
+
+// ----
+//
+// Routine Description:
+//
+//
+// Arguments:
+//
+//
+// Return Value:
+//
+// ----
+
+{
+ DeviceContext->Opened = FALSE;
+}
+
+
+
+VOID
+TpUnloadDriver(
+ IN PDRIVER_OBJECT DriverObject
+ )
+{
+ USHORT i;
+ PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)DriverObject->DeviceObject;
+
+ TpPrint0("TpUnloadDriver called.\n");
+
+ //
+ // Fixed error for deallocation of memory contigent to having been opened
+ // Bug# 13183
+ //
+ if ( DeviceContext->Opened == TRUE )
+ {
+ //
+ // for each of the open instances in the open array.
+ //
+ for ( i=0;i<NUM_OPEN_INSTANCES;i++ )
+ {
+ //
+ // Deallocate each of the instances of the OpenBlock.
+ //
+ TpDeallocateOpenArray( &DeviceContext->Open[i] );
+ }
+ }
+
+ //
+ // Close the Dos Symbolic link to remove traces of the device
+ //
+ ZwClose( SymbolicLinkHandle );
+
+ //
+ // Then delete the device object from the system. Fixed for Bug#: 13183
+ //
+ IoDeleteDevice( (PDEVICE_OBJECT)DeviceContext );
+
+ TpPrint0("TpUnloadDriver completed.\n");
+}
+
+
+
+BOOLEAN
+TpAddReference(
+ IN POPEN_BLOCK OpenP
+ )
+
+// ---
+//
+// Routine Description:
+//
+// Add a reference to an open block, to prevent it being removed
+// by TpCloseDriver.
+//
+// Arguments:
+//
+// OpenP - The open block holding the adapter information to add the
+// reference to.
+//
+// Return Value:
+//
+// TRUE if the reference is added.
+// FALSE if the open is already closing.
+//
+// ----
+
+{
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->Closing )
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ return FALSE;
+ }
+ ++OpenP->ReferenceCount;
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ return TRUE;
+}
+
+
+
+VOID
+TpRemoveReference(
+ IN POPEN_BLOCK OpenP
+ )
+
+// --
+//
+// Routine Description:
+//
+// Remove a reference to an adapter. If the count goes to
+// zero, then the adapter may be closed if requested.
+//
+// Arguments:
+//
+// Argument - The open block holding the adapter information to
+// remove the reference from.
+//
+// Return Value:
+//
+// None.
+//
+// --
+
+{
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+ --OpenP->ReferenceCount;
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+}
+
+
+
+NTSTATUS
+TpAllocateOpenArray(
+ POPEN_BLOCK OpenP
+ )
+
+// -----
+//
+// Routine Description:
+//
+// This routine allocates the various data structures and spinlocks
+// in the OpenBlock.
+//
+// Arguments:
+//
+// OpenP - a pointer to the OpenBlock containing the data structures which
+// will be allocated during this routine.
+//
+// Return Value:
+//
+// NTSTATUS - STATUS_SUCCESS if all the memory and spinlocks are allocated
+// else STATUS_INSUFFICIENT_RESOURCES if an allocation of memory
+// fails.
+//
+// ----------
+
+{
+ NDIS_STATUS Status;
+ ULONG i;
+
+ //
+ // Initialize the Open Block fields,
+ //
+
+ OpenP->NdisBindingHandle = NULL;
+ OpenP->OpenInstance = (UCHAR)-1;
+ OpenP->Closing = FALSE;
+ OpenP->AdapterName = NULL;
+ OpenP->ReferenceCount = 0;
+ OpenP->MediumIndex = 0xFFFFFFFF;
+
+ OpenP->Media = NULL;
+ OpenP->GlobalCounters = NULL;
+ OpenP->Environment = NULL;
+
+ OpenP->Stress = NULL;
+ OpenP->Send = NULL;
+ OpenP->Receive = NULL;
+
+ OpenP->OpenReqHndl = NULL;
+ OpenP->CloseReqHndl = NULL;
+ OpenP->ResetReqHndl = NULL;
+ OpenP->RequestReqHndl = NULL;
+ OpenP->StressReqHndl = NULL;
+
+ OpenP->IrpCancelled = FALSE;
+ OpenP->Irp = NULL;
+
+ OpenP->Signature = OPEN_BLOCK_SIGNATURE;
+ OpenP->PerformanceTest = FALSE;
+
+
+ //
+ // and set the station address for this open instance to nulls.
+ //
+
+ for ( i=0;i<ADDRESS_LENGTH;i++ )
+ {
+ OpenP->StationAddress[i] = 0x00;
+ }
+
+ //
+ // Allocate the Environment struct
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Environment,
+ sizeof( ENVIRONMENT_VARIABLES ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate Environment struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Environment,sizeof( ENVIRONMENT_VARIABLES ));
+ }
+
+ //
+ // Then initialize the Environment Variables to the default settings.
+ //
+
+ OpenP->Environment->WindowSize = WINDOW_SIZE;
+ OpenP->Environment->RandomBufferNumber = BUFFER_NUMBER;
+ OpenP->Environment->StressDelayInterval = DELAY_INTERVAL;
+ OpenP->Environment->UpForAirDelay = UP_FOR_AIR_DELAY;
+ OpenP->Environment->StandardDelay = STANDARD_DELAY;
+
+ //
+ // Allocate the Stress struct and the pend counters and stress results
+ // counters attached to it.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Stress,
+ sizeof( STRESS_BLOCK ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate STRESS_BLOCK struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Stress,sizeof( STRESS_BLOCK ));
+ }
+
+ //
+ // Initialize the Stress Block and set the request pending counters
+ // and the stress results structs to null.
+ //
+
+ OpenP->Stress->Stressing = FALSE;
+ OpenP->Stress->StressStarted = FALSE;
+ OpenP->Stress->StopStressing = TRUE;
+ OpenP->Stress->StressFinal = FALSE;
+ OpenP->Stress->StressEnded = TRUE;
+ OpenP->Stress->Client = NULL;
+ OpenP->Stress->Server = NULL;
+ OpenP->Stress->Arguments = NULL;
+ OpenP->Stress->DataBuffer[0] = NULL;
+ OpenP->Stress->DataBuffer[1] = NULL;
+ OpenP->Stress->DataBufferMdl[0] = NULL;
+ OpenP->Stress->DataBufferMdl[1] = NULL;
+ OpenP->Stress->PoolInitialized = FALSE;
+ OpenP->Stress->PacketHandle = NULL;
+ OpenP->Stress->StressIrp = NULL;
+
+ //
+ // allocate the pend counter, we need to create this here because
+ // it will be used in starting all instances of the stress test.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Pend,
+ sizeof( PENDING ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate PEND_COUNTER struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Stress->Pend,sizeof( PENDING ));
+ }
+
+ NdisAllocateSpinLock( &OpenP->Stress->Pend->SpinLock );
+
+ TpInitializePending( OpenP->Stress->Pend );
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Stress->Results,
+ sizeof( STRESS_RESULTS ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate Stress Results struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Stress->Results,sizeof( STRESS_RESULTS ));
+ TpInitializeStressResults( OpenP->Stress->Results );
+ }
+
+ //
+ // Initialize the timer to regulate when to call each of the routines.
+ //
+
+ KeInitializeTimer( &OpenP->Stress->TpStressTimer );
+ KeInitializeTimer( &OpenP->Stress->TpStressReg2Timer );
+
+ //
+ // Now allocate the Send and Receive structs.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Send,
+ sizeof( SEND_BLOCK ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate SEND_BLOCK struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( OpenP->Send,sizeof( SEND_BLOCK ));
+ }
+
+ //
+ // Initialize the Send Block fields and set the SEND destination
+ // address and resend address to nulls.
+ //
+
+ OpenP->Send->Sending = FALSE;
+ OpenP->Send->StopSending = TRUE;
+ OpenP->Send->ResendPackets = FALSE;
+ OpenP->Send->PacketSize = 0;
+ OpenP->Send->NumberOfPackets = 0;
+ OpenP->Send->PacketsSent = 0;
+ OpenP->Send->PacketsPending = 0;
+ OpenP->Send->PacketHandle = NULL;
+ OpenP->Send->Counters = NULL;
+ OpenP->Send->SendIrp = NULL;
+
+ KeInitializeTimer( &OpenP->Send->SendTimer );
+
+ for ( i=0;i<ADDRESS_LENGTH;i++ )
+ {
+ OpenP->Send->DestAddress[i] = 0x00;
+ OpenP->Send->ResendAddress[i] = 0x00;
+ }
+
+ //
+ // Allocate the Send PacketPool.
+ //
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Send->PacketHandle,
+ NUMBER_OF_POOL_PACKETS,
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: could not allocate Packet Pool\n");
+ }
+ return Status;
+ }
+
+ //
+ // Now allocate the SEND Counters and initialize them to zero.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Send->Counters,
+ sizeof( INSTANCE_COUNTERS ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate counters.\n");
+ }
+ return NDIS_STATUS_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( (PVOID)OpenP->Send->Counters,
+ sizeof( INSTANCE_COUNTERS ) );
+ }
+
+ //
+ // Initialize the DPC used to call SendDpc, and SendEndDpc.
+ //
+
+ KeInitializeDpc(&OpenP->Send->SendDpc,
+ TpFuncSendDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Send->SendEndDpc,
+ TpFuncSendEndDpc,
+ (PVOID)OpenP );
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Receive,
+ sizeof( RECEIVE_BLOCK ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate RECEIVE_BLOCK struct\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory((PVOID)OpenP->Receive,sizeof( RECEIVE_BLOCK ));
+ }
+
+ //
+ // Initialize the Receive Block fields.
+ //
+
+ OpenP->Receive->Receiving = FALSE;
+ OpenP->Receive->StopReceiving = TRUE;
+ OpenP->Receive->PacketsPending = 0;
+ OpenP->Receive->PacketHandle = NULL;
+ OpenP->Receive->Counters = NULL;
+ OpenP->Receive->ReceiveIrp = NULL;
+
+ KeInitializeTimer( &OpenP->Receive->ReceiveTimer );
+ KeInitializeTimer( &OpenP->Receive->ResendTimer);
+
+ //
+ // Create a PacketPool, and initialize it, we will need this in case
+ // we receive any RESEND packets (FUNC2_PACKET).
+ //
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Receive->PacketHandle,
+ NUMBER_OF_POOL_PACKETS,
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint1("TpAllocateOpenArray: could not allocate Packet Pool: return %s.\n",
+ TpGetStatus(Status));
+ }
+ return Status;
+ }
+
+ //
+ // Now allocate the COUNTERS structure and set the counters to zero.
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Receive->Counters,
+ sizeof( INSTANCE_COUNTERS ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG ( TP_DEBUG_RESOURCES )
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate counters.\n");
+ }
+ return NDIS_STATUS_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( (PVOID)OpenP->Receive->Counters,
+ sizeof( INSTANCE_COUNTERS ) );
+ }
+
+ //
+ // Initialize the DPCs used to call ReceiveDpc and ReceiveEndDpc.
+ //
+
+ KeInitializeDpc(&OpenP->Receive->ReceiveDpc,
+ TpFuncReceiveDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Receive->ReceiveEndDpc,
+ TpFuncReceiveEndDpc,
+ (PVOID)OpenP );
+
+ KeInitializeDpc(&OpenP->Receive->ResendDpc,
+ TpFuncResendDpc,
+ (PVOID)OpenP );
+
+ //
+ // the performance structure is not allocated here, but is allocated and freed
+ // within the performance functions themselves
+ //
+
+// OpenP->Perform = NULL;
+
+ //
+ // now deal with the PAUSE Block
+ //
+
+ Status = NdisAllocateMemory((PVOID *)&OpenP->Pause,
+ sizeof( PAUSE_BLOCK ),
+ 0,
+ HighestAddress );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: failed to allocate PAUSE_BLOCK struct.\n");
+ }
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ NdisZeroMemory( (PVOID)OpenP->Pause,
+ sizeof( PAUSE_BLOCK ) );
+ }
+
+ //
+ // Initialize the Pause Block fields.
+ //
+
+ OpenP->Pause->GoReceived = FALSE;
+
+ for ( i=0;i<ADDRESS_LENGTH;i++ )
+ {
+ OpenP->Pause->RemoteAddress[i] = 0x00;
+ }
+
+ OpenP->Pause->TestSignature = 0xFFFFFFFF;
+ OpenP->Pause->PacketType = (UCHAR)-1;
+ OpenP->Pause->UniqueSignature = 0xFFFFFFFF;
+ OpenP->Pause->TimeOut = 0;
+
+ NdisAllocateSpinLock( &OpenP->Pause->SpinLock );
+ OpenP->Pause->PoolAllocated = FALSE;
+
+ //
+ // and Allocate the PacketPool.
+ //
+
+ NdisAllocatePacketPool( &Status,
+ &OpenP->Pause->PacketHandle,
+ 10,
+ sizeof( PROTOCOL_RESERVED ) );
+
+ if ( Status != NDIS_STATUS_SUCCESS )
+ {
+ IF_TPDBG (TP_DEBUG_RESOURCES)
+ {
+ TpPrint0("TpAllocateOpenArray: could not allocate Packet Pool.\n");
+ }
+ return Status;
+ }
+ else
+ {
+ OpenP->Pause->PoolAllocated = TRUE;
+ }
+
+ //
+ // Then allocate the Open Blocks open spin lock.
+ //
+
+ NdisAllocateSpinLock( &OpenP->SpinLock );
+
+ return STATUS_SUCCESS;
+}
+
+
+
+VOID
+TpDeallocateOpenArray(
+ POPEN_BLOCK OpenP
+ )
+
+// -------
+//
+// Routine Description:
+//
+// This routine deallocates the various data structures and spinlocks
+// in the OpenBlock that are used to control the tests.
+//
+// Arguments:
+//
+// OpenP - a pointer to the OpenBlock containing the data structures which
+// will be deallocated during this routine.
+//
+// Return Value:
+//
+// None.
+//
+// -------
+
+{
+ NdisFreeSpinLock( &OpenP->SpinLock );
+
+ if ( OpenP->AdapterName != NULL )
+ {
+ NdisFreeMemory( OpenP->AdapterName,0,0 );
+ }
+
+ if ( OpenP->Environment != NULL )
+ {
+ NdisFreeMemory( OpenP->Environment,0,0 );
+ }
+
+ if ( OpenP->Stress->Pend != NULL )
+ {
+ NdisFreeMemory( OpenP->Stress->Pend,0,0 );
+ NdisFreeSpinLock( &OpenP->Stress->Pend->SpinLock );
+ }
+
+ if ( OpenP->Stress->Results != NULL )
+ {
+ NdisFreeMemory( OpenP->Stress->Results,0,0 );
+ }
+
+ if ( OpenP->Send != NULL )
+ {
+ NdisFreePacketPool( OpenP->Send->PacketHandle );
+ NdisFreeMemory( (PVOID)OpenP->Send->Counters,0,0 );
+ NdisFreeMemory( OpenP->Send,0,0 );
+ }
+
+ if ( OpenP->Receive != NULL )
+ {
+ NdisFreePacketPool( OpenP->Receive->PacketHandle );
+ NdisFreeMemory( (PVOID)OpenP->Receive->Counters,0,0 );
+ NdisFreeMemory( OpenP->Receive,0,0 );
+ }
+
+ if ( OpenP->Pause != NULL )
+ {
+ if ( OpenP->Pause->PoolAllocated == TRUE )
+ {
+ NdisFreePacketPool( OpenP->Pause->PacketHandle );
+ }
+ NdisFreeSpinLock( &OpenP->Pause->SpinLock );
+ NdisFreeMemory( OpenP->Pause,0,0 );
+ }
+}
+
+
+
+VOID
+TpCancelIrp(
+ IN PDEVICE_CONTEXT DeviceContext,
+ IN PIRP Irp
+ )
+
+// ----------
+//
+// Routine Description:
+//
+// Arguments:
+//
+// DeviceObject - Pointer to device object for this driver.
+//
+// Irp - Pointer to the request packet representing the I/O request
+// to cancel.
+//
+// Return Value:
+//
+// None.
+//
+// ----------
+
+{
+ POPEN_BLOCK OpenP;
+ PIO_STACK_LOCATION IrpSp;
+
+ IrpSp = IoGetCurrentIrpStackLocation( Irp );
+
+ OpenP = (POPEN_BLOCK)Irp->IoStatus.Information;
+
+ IoSetCancelRoutine( Irp,NULL );
+
+ IoReleaseCancelSpinLock( Irp->CancelIrql );
+
+ NdisAcquireSpinLock( &OpenP->SpinLock );
+
+ if ((( Irp == OpenP->Stress->StressIrp ) ||
+ ( Irp == OpenP->Send->SendIrp )) ||
+ ( Irp == OpenP->Receive->ReceiveIrp ) ||
+ ( OpenP->PerformanceTest && (Irp == OpenP->Perform->PerformIrp)))
+ {
+ //
+ // These Irps will handle the cancel and clean up themselves
+ // so just return
+ //
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ return;
+ }
+ else if ( Irp == OpenP->Irp )
+ {
+ //
+ // We have found one of the General Case Irp to be cancelled.
+ // first set the flag that this Irp has been cancelled, them
+ // complete it.
+ //
+
+ OpenP->IrpCancelled = TRUE;
+ OpenP->Irp = NULL;
+
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+
+ IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
+ }
+ else
+ {
+ NdisReleaseSpinLock( &OpenP->SpinLock );
+ }
+}
+
+
+