summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isnp/spx/spxdrvr.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/tdi/isnp/spx/spxdrvr.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/tdi/isnp/spx/spxdrvr.c')
-rw-r--r--private/ntos/tdi/isnp/spx/spxdrvr.c1008
1 files changed, 1008 insertions, 0 deletions
diff --git a/private/ntos/tdi/isnp/spx/spxdrvr.c b/private/ntos/tdi/isnp/spx/spxdrvr.c
new file mode 100644
index 000000000..0e9935d1a
--- /dev/null
+++ b/private/ntos/tdi/isnp/spx/spxdrvr.c
@@ -0,0 +1,1008 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ spxdrvr.c
+
+Abstract:
+
+ This module contains the DriverEntry and other initialization
+ code for the SPX/SPXII module of the ISN transport.
+
+Author:
+
+ Adam Barr (adamba) Original Version
+ Nikhil Kamkolkar (nikhilk) 11-November-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Sanjay Anand (SanjayAn) 14-July-1995
+ Bug fixes - tagged [SA]
+
+--*/
+
+#include "precomp.h"
+#pragma hdrstop
+
+// Define module number for event logging entries
+#define FILENUM SPXDRVR
+
+// Forward declaration of various routines used in this module.
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath);
+
+NTSTATUS
+SpxDispatchOpenClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+SpxDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+SpxDispatchInternal (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+NTSTATUS
+SpxDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+VOID
+SpxUnload(
+ IN PDRIVER_OBJECT DriverObject);
+
+VOID
+SpxTdiCancel(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT, DriverEntry)
+#pragma alloc_text(PAGE, SpxUnload)
+#pragma alloc_text(PAGE, SpxDispatchOpenClose)
+#pragma alloc_text(PAGE, SpxDispatch)
+#pragma alloc_text(PAGE, SpxDeviceControl)
+#pragma alloc_text(PAGE, SpxUnload)
+#endif
+
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs initialization of the SPX ISN module.
+ It creates the device objects for the transport
+ provider and performs other driver initialization.
+
+Arguments:
+
+ DriverObject - Pointer to driver object created by the system.
+
+ RegistryPath - The name of ST's node in the registry.
+
+Return Value:
+
+ The function value is the final status from the initialization operation.
+
+--*/
+
+{
+ UNICODE_STRING deviceName;
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOLEAN BoundToIpx = FALSE;
+
+ // DBGBRK(FATAL);
+
+ // Initialize the Common Transport Environment.
+ if (CTEInitialize() == 0) {
+ return (STATUS_UNSUCCESSFUL);
+ }
+
+ // We have this #define'd. Ugh, but CONTAINING_RECORD has problem owise.
+ CTEAssert(NDIS_PACKET_SIZE == FIELD_OFFSET(NDIS_PACKET, ProtocolReserved[0]));
+
+ // Create the device object. (IoCreateDevice zeroes the memory
+ // occupied by the object.)
+ RtlInitUnicodeString(&deviceName, SPX_DEVICE_NAME);
+ status = SpxInitCreateDevice(
+ DriverObject,
+ &deviceName,
+ &SpxDevice);
+
+ if (!NT_SUCCESS(status))
+ {
+ return(status);
+ }
+
+ do
+ {
+ CTEInitLock (&SpxGlobalInterlock);
+ CTEInitLock (&SpxGlobalQInterlock);
+
+ // Initialize the unload event
+ KeInitializeEvent(
+ &SpxUnloadEvent,
+ NotificationEvent,
+ FALSE);
+
+ // !!!The device is created at this point!!!
+ // Get information from the registry.
+ status = SpxInitGetConfiguration(
+ RegistryPath,
+ &SpxDevice->dev_ConfigInfo);
+
+ if (!NT_SUCCESS(status))
+ {
+ break;
+ }
+
+#if defined(_PNP_POWER)
+ //
+ // Make Tdi ready for pnp notifications before binding
+ // to IPX
+ //
+ TdiInitialize();
+
+ // Initialize the timer system. This should be done before
+ // binding to ipx because we should have timers intialized
+ // before ipx calls our pnp indications.
+ if (!NT_SUCCESS(status = SpxTimerInit()))
+ {
+ break;
+ }
+#endif _PNP_POWER
+
+ // Bind to the IPX transport.
+ if (!NT_SUCCESS(status = SpxInitBindToIpx()))
+ {
+ // BUGBUG: Have ipx name here as second string
+ LOG_ERROR(
+ EVENT_TRANSPORT_BINDING_FAILED,
+ status,
+ NULL,
+ NULL,
+ 0);
+
+ break;
+ }
+
+ BoundToIpx = TRUE;
+
+#if !defined(_PNP_POWER)
+ // Initialize the timer system
+ if (!NT_SUCCESS(status = SpxTimerInit()))
+ {
+ break;
+ }
+#endif !_PNP_POWER
+
+ // Initialize the block manager
+ if (!NT_SUCCESS(status = SpxInitMemorySystem(SpxDevice)))
+ {
+
+ // Stop the timer subsystem
+ SpxTimerFlushAndStop();
+ break;
+ }
+
+ // Initialize the driver object with this driver's entry points.
+ DriverObject->MajorFunction [IRP_MJ_CREATE] = SpxDispatchOpenClose;
+ DriverObject->MajorFunction [IRP_MJ_CLOSE] = SpxDispatchOpenClose;
+ DriverObject->MajorFunction [IRP_MJ_CLEANUP] = SpxDispatchOpenClose;
+ DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL]
+ = SpxDispatch;
+ DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]
+ = SpxDispatchInternal;
+ DriverObject->DriverUnload = SpxUnload;
+
+ // Initialize the provider info
+ SpxQueryInitProviderInfo(&SpxDevice->dev_ProviderInfo);
+ SpxDevice->dev_CurrentSocket = (USHORT)PARAM(CONFIG_SOCKET_RANGE_START);
+
+#if !defined(_PNP_POWER)
+ // We are open now.
+ SpxDevice->dev_State = DEVICE_STATE_OPEN;
+#endif !_PNP_POWER
+
+ // Set the window size in statistics
+ SpxDevice->dev_Stat.MaximumSendWindow =
+ SpxDevice->dev_Stat.AverageSendWindow = PARAM(CONFIG_WINDOW_SIZE) *
+ IpxLineInfo.MaximumSendSize;
+
+#if defined(_PNP_POWER)
+ if ( DEVICE_STATE_CLOSED == SpxDevice->dev_State ) {
+ SpxDevice->dev_State = DEVICE_STATE_LOADED;
+ }
+#endif _PNP_POWER
+
+ } while (FALSE);
+
+ if (!NT_SUCCESS(status) )
+ {
+ // Delete the device and any associated resources created.
+ if( BoundToIpx ) {
+ SpxDerefDevice(SpxDevice);
+ }
+ SpxDestroyDevice(SpxDevice);
+ }
+
+ return (status);
+}
+
+
+
+
+VOID
+SpxUnload(
+ IN PDRIVER_OBJECT DriverObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unloads the sample transport driver. The I/O system will not
+ call us until nobody above has ST open.
+
+Arguments:
+
+ DriverObject - Pointer to driver object created by the system.
+
+Return Value:
+
+ None. When the function returns, the driver is unloaded.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER (DriverObject);
+
+ // Stop the timer subsystem
+ SpxTimerFlushAndStop();
+
+ // Remove creation reference count on the IPX device object.
+ SpxDerefDevice(SpxDevice);
+
+ // Wait on the unload event.
+ KeWaitForSingleObject(
+ &SpxUnloadEvent,
+ Executive,
+ KernelMode,
+ TRUE,
+ (PLARGE_INTEGER)NULL);
+
+ // Release the block memory stuff
+ SpxDeInitMemorySystem(SpxDevice);
+ SpxDestroyDevice(SpxDevice);
+ return;
+}
+
+
+
+NTSTATUS
+SpxDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the main dispatch routine for the ST device 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;
+ PDEVICE Device = (PDEVICE)DeviceObject;
+ PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+ if (Device->dev_State != DEVICE_STATE_OPEN) {
+ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+ // Make sure status information is consistent every time.
+ IoMarkIrpPending (Irp);
+ Irp->IoStatus.Status = STATUS_PENDING;
+ Irp->IoStatus.Information = 0;
+
+ // 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) {
+
+ case IRP_MJ_DEVICE_CONTROL:
+
+ Status = SpxDeviceControl (DeviceObject, Irp);
+ break;
+
+ default:
+
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+
+ //
+ // Complete the Irp here instead of below.
+ //
+ IrpSp->Control &= ~SL_PENDING_RETURNED;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+
+ } // major function switch
+
+ /* Commented out and re-located to the default case above.
+
+ if (Status != STATUS_PENDING) {
+ IrpSp->Control &= ~SL_PENDING_RETURNED;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ }
+ */
+
+ // Return the immediate status code to the caller.
+ return Status;
+
+} // SpxDispatch
+
+VOID
+SpxAssignControlChannelId(
+ IN PDEVICE Device,
+ IN PIRP Request
+ )
+/*++
+
+Routine Description:
+
+ This routine is required to ensure that the Device lock (to protect the ControlChannelId in the Device)
+ is not taken in a pageable routine (SpxDispatchOpenClose).
+
+ NOTE: SPX returns the ControlChannelId in the Request, but never uses it later when it comes down in a
+ close/cleanup. The CCID is a ULONG; in future, if we start using this field (as in IPX which uses these Ids
+ to determine lineup Irps to complete), then we may run out of numbers (since we monotonically increase the CCID);
+ though there is a low chance of that since we will probably run out of memory before that! Anyhow, if that
+ happens, one solution (used in IPX) is to make the CCID into a Large Integer and pack the values into the
+ REQUEST_OPEN_TYPE(Irp) too.
+
+
+Arguments:
+
+ Device - Pointer to the device object for this driver.
+
+ Request - Pointer to the request packet representing the I/O request.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ CTELockHandle LockHandle;
+
+ CTEGetLock (&Device->dev_Lock, &LockHandle);
+
+ REQUEST_OPEN_CONTEXT(Request) = (PVOID)(Device->dev_CcId);
+ ++Device->dev_CcId;
+ if (Device->dev_CcId == 0) {
+ Device->dev_CcId = 1;
+ }
+
+ CTEFreeLock (&Device->dev_Lock, LockHandle);
+}
+
+NTSTATUS
+SpxDispatchOpenClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is the main dispatch routine for the ST device 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.
+
+--*/
+
+{
+ PDEVICE Device = (PDEVICE)DeviceObject;
+ NTSTATUS Status;
+ BOOLEAN found;
+ PREQUEST Request;
+ UINT i;
+ PFILE_FULL_EA_INFORMATION openType;
+ CONNECTION_CONTEXT connCtx;
+
+
+#if !defined(_PNP_POWER)
+ if (Device->dev_State != DEVICE_STATE_OPEN) {
+ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+#endif !_PNP_POWER
+
+ // Allocate a request to track this IRP.
+ Request = SpxAllocateRequest (Device, Irp);
+ IF_NOT_ALLOCATED(Request) {
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+
+ // Make sure status information is consistent every time.
+ MARK_REQUEST_PENDING(Request);
+ REQUEST_STATUS(Request) = STATUS_PENDING;
+ REQUEST_INFORMATION(Request) = 0;
+
+ // 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 (REQUEST_MAJOR_FUNCTION(Request)) {
+
+ // The Create function opens a transport object (either address or
+ // connection). Access checking is performed on the specified
+ // address to ensure security of transport-layer addresses.
+ case IRP_MJ_CREATE:
+
+#if defined(_PNP_POWER)
+ if (Device->dev_State != DEVICE_STATE_OPEN) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ break;
+ }
+#endif _PNP_POWER
+
+ openType = OPEN_REQUEST_EA_INFORMATION(Request);
+
+ if (openType != NULL) {
+
+ found = TRUE;
+
+ for (i=0;i<openType->EaNameLength;i++) {
+ if (openType->EaName[i] == TdiTransportAddress[i]) {
+ continue;
+ } else {
+ found = FALSE;
+ break;
+ }
+ }
+
+ if (found) {
+ Status = SpxAddrOpen (Device, Request);
+ break;
+ }
+
+ // Connection?
+ found = TRUE;
+
+ for (i=0;i<openType->EaNameLength;i++) {
+ if (openType->EaName[i] == TdiConnectionContext[i]) {
+ continue;
+ } else {
+ found = FALSE;
+ break;
+ }
+ }
+
+ if (found) {
+ if (openType->EaValueLength < sizeof(CONNECTION_CONTEXT))
+ {
+
+ DBGPRINT(CREATE, ERR,
+ ("Create: Context size %d\n", openType->EaValueLength));
+
+ Status = STATUS_EA_LIST_INCONSISTENT;
+ break;
+ }
+
+ connCtx =
+ *((CONNECTION_CONTEXT UNALIGNED *)
+ &openType->EaName[openType->EaNameLength+1]);
+
+ Status = SpxConnOpen(
+ Device,
+ connCtx,
+ Request);
+
+ break;
+ }
+
+ } else {
+
+ //
+ // Takes a lock in a Pageable routine - call another (non-paged) function to do that.
+ //
+ SpxAssignControlChannelId(Device, Request);
+
+ REQUEST_OPEN_TYPE(Request) = (PVOID)SPX_FILE_TYPE_CONTROL;
+ Status = STATUS_SUCCESS;
+ }
+
+ break;
+
+ case IRP_MJ_CLOSE:
+
+#if defined(_PNP_POWER)
+ if ((Device->dev_State != DEVICE_STATE_OPEN) && ( Device->dev_State != DEVICE_STATE_LOADED )) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ break;
+ }
+#endif _PNP_POWER
+
+ // The Close function closes a transport endpoint, terminates
+ // all outstanding transport activity on the endpoint, and unbinds
+ // the endpoint from its transport address, if any. If this
+ // is the last transport endpoint bound to the address, then
+ // the address is removed from the provider.
+ switch ((ULONG)REQUEST_OPEN_TYPE(Request)) {
+ case TDI_TRANSPORT_ADDRESS_FILE:
+
+ Status = SpxAddrFileClose(Device, Request);
+ break;
+
+ case TDI_CONNECTION_FILE:
+ Status = SpxConnClose(Device, Request);
+ break;
+
+ case SPX_FILE_TYPE_CONTROL:
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+ Status = STATUS_INVALID_HANDLE;
+ }
+
+ break;
+
+ case IRP_MJ_CLEANUP:
+
+#if defined(_PNP_POWER)
+ if ((Device->dev_State != DEVICE_STATE_OPEN) && ( Device->dev_State != DEVICE_STATE_LOADED )) {
+ Status = STATUS_INVALID_DEVICE_STATE;
+ break;
+ }
+#endif _PNP_POWER
+
+ // Handle the two stage IRP for a file close operation. When the first
+ // stage hits, run down all activity on the object of interest. This
+ // do everything to it but remove the creation hold. Then, when the
+ // CLOSE irp hits, actually close the object.
+ switch ((ULONG)REQUEST_OPEN_TYPE(Request)) {
+ case TDI_TRANSPORT_ADDRESS_FILE:
+
+ Status = SpxAddrFileCleanup(Device, Request);
+ break;
+
+ case TDI_CONNECTION_FILE:
+
+ Status = SpxConnCleanup(Device, Request);
+ break;
+
+ case SPX_FILE_TYPE_CONTROL:
+
+ Status = STATUS_SUCCESS;
+ break;
+
+ default:
+ Status = STATUS_INVALID_HANDLE;
+ }
+
+ break;
+
+ default:
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+
+ } // major function switch
+
+ if (Status != STATUS_PENDING) {
+ UNMARK_REQUEST_PENDING(Request);
+ REQUEST_STATUS(Request) = Status;
+ SpxCompleteRequest (Request);
+ SpxFreeRequest (Device, Request);
+ }
+
+ // Return the immediate status code to the caller.
+ return Status;
+
+} // SpxDispatchOpenClose
+
+
+
+
+NTSTATUS
+SpxDeviceControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches TDI request types to different handlers based
+ on the minor IOCTL function code in the IRP's current stack location.
+ In addition to cracking the minor function code, this routine also
+ reaches into the IRP and passes the packetized parameters stored there
+ as parameters to the various TDI request handlers so that they are
+ not IRP-dependent.
+
+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 = IoGetCurrentIrpStackLocation (Irp);
+
+ // Convert the user call to the proper internal device call.
+ Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp);
+ if (Status == STATUS_SUCCESS) {
+
+ // If TdiMapUserRequest returns SUCCESS then the IRP
+ // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL
+ // IRP, so we dispatch it as usual. The IRP will
+ // be completed by this call.
+ Status = SpxDispatchInternal (DeviceObject, Irp);
+
+ //
+ // Return the proper error code here. If SpxDispatchInternal returns an error,
+ // then we used to map it to pending below; this is wrong since the client above
+ // us could wait for ever since the IO subsystem does not set the event if an
+ // error is returned and the Irp is not marked pending.
+ //
+
+ // Status = STATUS_PENDING;
+ } else {
+
+ DBGPRINT(TDI, DBG,
+ ("Unknown Tdi code in Irp: %lx\n", Irp));
+
+ //
+ // Complete the Irp....
+ //
+ IrpSp->Control &= ~SL_PENDING_RETURNED;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ }
+
+ return Status;
+
+} // SpxDeviceControl
+
+
+
+
+NTSTATUS
+SpxDispatchInternal (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+/*++
+
+Routine Description:
+
+ This routine dispatches TDI request types to different handlers based
+ on the minor IOCTL function code in the IRP's current stack location.
+ In addition to cracking the minor function code, this routine also
+ reaches into the IRP and passes the packetized parameters stored there
+ as parameters to the various TDI request handlers so that they are
+ not IRP-dependent.
+
+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.
+
+--*/
+
+{
+ PREQUEST Request;
+ KIRQL oldIrql;
+ NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
+ PDEVICE Device = (PDEVICE)DeviceObject;
+
+
+ if (Device->dev_State != DEVICE_STATE_OPEN)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+
+ // Allocate a request to track this IRP.
+ Request = SpxAllocateRequest (Device, Irp);
+ IF_NOT_ALLOCATED(Request)
+ {
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
+ return STATUS_INVALID_DEVICE_STATE;
+ }
+
+
+ // Make sure status information is consistent every time.
+ MARK_REQUEST_PENDING(Request);
+ REQUEST_STATUS(Request) = STATUS_PENDING;
+ REQUEST_INFORMATION(Request) = 0;
+
+ // Cancel irp
+ IoAcquireCancelSpinLock(&oldIrql);
+ if (!Irp->Cancel)
+ {
+ IoSetCancelRoutine(Irp, (PDRIVER_CANCEL)SpxTdiCancel);
+ }
+ IoReleaseCancelSpinLock(oldIrql);
+
+ if (Irp->Cancel)
+ return STATUS_CANCELLED;
+
+ // Branch to the appropriate request handler. Preliminary checking of
+ // the size of the request block is performed here so that it is known
+ // in the handlers that the minimum input parameters are readable. It
+ // is *not* determined here whether variable length input fields are
+ // passed correctly; this is a check which must be made within each routine.
+ switch (REQUEST_MINOR_FUNCTION(Request))
+ {
+ case TDI_ACCEPT:
+
+ Status = SpxConnAccept(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_SET_EVENT_HANDLER:
+
+ Status = SpxAddrSetEventHandler(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_RECEIVE:
+
+ Status = SpxConnRecv(
+ Device,
+ Request);
+ break;
+
+
+ case TDI_SEND:
+
+ Status = SpxConnSend(
+ Device,
+ Request);
+ break;
+
+ case TDI_ACTION:
+
+ Status = SpxConnAction(
+ Device,
+ Request);
+ break;
+
+ case TDI_ASSOCIATE_ADDRESS:
+
+ Status = SpxConnAssociate(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_DISASSOCIATE_ADDRESS:
+
+ Status = SpxConnDisAssociate(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_CONNECT:
+
+ Status = SpxConnConnect(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_DISCONNECT:
+
+ Status = SpxConnDisconnect(
+ Device,
+ Request);
+ break;
+
+ case TDI_LISTEN:
+
+ Status = SpxConnListen(
+ Device,
+ Request);
+ break;
+
+ case TDI_QUERY_INFORMATION:
+
+ Status = SpxTdiQueryInformation(
+ Device,
+ Request);
+
+ break;
+
+ case TDI_SET_INFORMATION:
+
+ Status = SpxTdiSetInformation(
+ Device,
+ Request);
+
+ break;
+
+ // Something we don't know about was submitted.
+ default:
+
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ if (Status != STATUS_PENDING)
+ {
+ UNMARK_REQUEST_PENDING(Request);
+ REQUEST_STATUS(Request) = Status;
+ IoAcquireCancelSpinLock(&oldIrql);
+ IoSetCancelRoutine(Irp, (PDRIVER_CANCEL)NULL);
+ IoReleaseCancelSpinLock(oldIrql);
+ SpxCompleteRequest (Request);
+ SpxFreeRequest (Device, Request);
+ }
+
+ // Return the immediate status code to the caller.
+ return Status;
+
+} // SpxDispatchInternal
+
+
+
+
+VOID
+SpxTdiCancel(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+/*++
+
+Routine Description:
+
+ This routine handles cancellation of IO requests
+
+Arguments:
+
+
+Return Value:
+--*/
+{
+ PREQUEST Request;
+ PSPX_ADDR_FILE pSpxAddrFile;
+ PSPX_ADDR pSpxAddr;
+ PDEVICE Device = (PDEVICE)DeviceObject;
+ CTELockHandle connectIrql;
+ CTELockHandle TempIrql;
+ PSPX_CONN_FILE pSpxConnFile;
+
+ Request = SpxAllocateRequest (Device, Irp);
+ IF_NOT_ALLOCATED(Request)
+ {
+ return;
+ }
+
+ DBGPRINT(TDI, ERR,
+ ("SpxTdiCancel: Cancel irp called %lx.%lx\n",
+ Irp, REQUEST_OPEN_CONTEXT(Request)));
+
+ switch ((ULONG)REQUEST_OPEN_TYPE(Request))
+ {
+ case TDI_CONNECTION_FILE:
+ pSpxConnFile = (PSPX_CONN_FILE)REQUEST_OPEN_CONTEXT(Request);
+ CTEGetLock(&pSpxConnFile->scf_Lock, &connectIrql);
+
+ //
+ // Swap the irql
+ //
+ TempIrql = connectIrql;
+ connectIrql = Irp->CancelIrql;
+ Irp->CancelIrql = TempIrql;
+
+ IoReleaseCancelSpinLock (Irp->CancelIrql);
+ if (!SPX_CONN_FLAG(pSpxConnFile, SPX_CONNFILE_STOPPING))
+ {
+ if (!SPX_CONN_IDLE(pSpxConnFile))
+ {
+ //
+ // This releases the lock
+ //
+ spxConnAbortiveDisc(
+ pSpxConnFile,
+ STATUS_LOCAL_DISCONNECT,
+ SPX_CALL_TDILEVEL,
+ connectIrql,
+ FALSE); // [SA] bug #15249
+ }
+ }
+
+// SpxConnStop((PSPX_CONN_FILE)REQUEST_OPEN_CONTEXT(Request));
+ break;
+
+ case TDI_TRANSPORT_ADDRESS_FILE:
+
+ IoReleaseCancelSpinLock (Irp->CancelIrql);
+ pSpxAddrFile = (PSPX_ADDR_FILE)REQUEST_OPEN_CONTEXT(Request);
+ pSpxAddr = pSpxAddrFile->saf_Addr;
+ SpxAddrFileStop(pSpxAddrFile, pSpxAddr);
+ break;
+
+ default:
+
+ IoReleaseCancelSpinLock (Irp->CancelIrql);
+ break;
+
+ }
+
+}