You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1214 lines
35 KiB
1214 lines
35 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
pxntinit.c
|
|
|
|
Abstract:
|
|
|
|
The module contains the NT-specific init code forthe NDIS Proxy.
|
|
|
|
Author:
|
|
|
|
Richard Machin (RMachin)
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
|
|
RMachin 10-3-96 created
|
|
TonyBe 02-21-99 re-work/re-write
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include "ntddk.h"
|
|
//#include <cxport.h>
|
|
#include <precomp.h>
|
|
|
|
#define MODULE_NUMBER MODULE_NTINIT
|
|
#define _FILENUMBER 'NITN'
|
|
|
|
PPX_DEVICE_EXTENSION DeviceExtension;
|
|
NPAGED_LOOKASIDE_LIST ProviderEventLookaside;
|
|
NPAGED_LOOKASIDE_LIST VcLookaside;
|
|
TAPI_TSP_CB TspCB;
|
|
VC_TABLE VcTable;
|
|
TAPI_LINE_TABLE LineTable;
|
|
TSP_EVENT_LIST TspEventList;
|
|
|
|
//
|
|
// Local funcion prototypes
|
|
//
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
);
|
|
|
|
VOID
|
|
PxUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
PxIOCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
PxIOClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
PxIODispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
PxIOCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
VOID
|
|
PxCancelGetEvents(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
//
|
|
// All of the init code can be discarded.
|
|
//
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text(INIT, DriverEntry)
|
|
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
//
|
|
// Tapi OIDs that the Proxy supports
|
|
//
|
|
OID_DISPATCH TapiOids[] =
|
|
{
|
|
{OID_TAPI_ACCEPT,sizeof (NDIS_TAPI_ACCEPT), PxTapiAccept},
|
|
{OID_TAPI_ANSWER, sizeof (NDIS_TAPI_ANSWER), PxTapiAnswer},
|
|
{OID_TAPI_CLOSE, sizeof (NDIS_TAPI_CLOSE), PxTapiClose},
|
|
{OID_TAPI_CLOSE_CALL, sizeof (NDIS_TAPI_CLOSE_CALL), PxTapiCloseCall},
|
|
{OID_TAPI_CONDITIONAL_MEDIA_DETECTION, sizeof (NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION), PxTapiConditionalMediaDetection},
|
|
{OID_TAPI_CONFIG_DIALOG, sizeof (NDIS_TAPI_CONFIG_DIALOG), PxTapiConfigDialog},
|
|
{OID_TAPI_DEV_SPECIFIC, sizeof (NDIS_TAPI_DEV_SPECIFIC), PxTapiDevSpecific},
|
|
{OID_TAPI_DIAL, sizeof (NDIS_TAPI_DIAL), PxTapiDial},
|
|
{OID_TAPI_DROP, sizeof (NDIS_TAPI_DROP), PxTapiDrop},
|
|
{OID_TAPI_GET_ADDRESS_CAPS, sizeof (NDIS_TAPI_GET_ADDRESS_CAPS), PxTapiGetAddressCaps},
|
|
{OID_TAPI_GET_ADDRESS_ID, sizeof (NDIS_TAPI_GET_ADDRESS_ID), PxTapiGetAddressID},
|
|
{OID_TAPI_GET_ADDRESS_STATUS, sizeof (NDIS_TAPI_GET_ADDRESS_STATUS), PxTapiGetAddressStatus},
|
|
{OID_TAPI_GET_CALL_ADDRESS_ID, sizeof (NDIS_TAPI_GET_CALL_ADDRESS_ID), PxTapiGetCallAddressID},
|
|
{OID_TAPI_GET_CALL_INFO, sizeof (NDIS_TAPI_GET_CALL_INFO), PxTapiGetCallInfo},
|
|
{OID_TAPI_GET_CALL_STATUS, sizeof (NDIS_TAPI_GET_CALL_STATUS), PxTapiGetCallStatus},
|
|
{OID_TAPI_GET_DEV_CAPS, sizeof (NDIS_TAPI_GET_DEV_CAPS), PxTapiGetDevCaps},
|
|
{OID_TAPI_GET_DEV_CONFIG, sizeof (NDIS_TAPI_GET_DEV_CONFIG), PxTapiGetDevConfig},
|
|
{OID_TAPI_GET_EXTENSION_ID, sizeof (NDIS_TAPI_GET_EXTENSION_ID), PxTapiGetExtensionID},
|
|
{OID_TAPI_GET_ID, sizeof (NDIS_TAPI_GET_ID), PxTapiLineGetID},
|
|
{OID_TAPI_GET_LINE_DEV_STATUS, sizeof (NDIS_TAPI_GET_LINE_DEV_STATUS), PxTapiGetLineDevStatus},
|
|
{OID_TAPI_MAKE_CALL, sizeof (NDIS_TAPI_MAKE_CALL), PxTapiMakeCall},
|
|
{OID_TAPI_NEGOTIATE_EXT_VERSION, sizeof (NDIS_TAPI_NEGOTIATE_EXT_VERSION), PxTapiNegotiateExtVersion},
|
|
{OID_TAPI_OPEN, sizeof (NDIS_TAPI_OPEN) + sizeof(NDISTAPI_OPENDATA), PxTapiOpen},
|
|
{OID_TAPI_PROVIDER_INITIALIZE, sizeof (NDIS_TAPI_PROVIDER_INITIALIZE), PxTapiProviderInit},
|
|
{OID_TAPI_PROVIDER_SHUTDOWN, sizeof (NDIS_TAPI_PROVIDER_SHUTDOWN), PxTapiProviderShutdown},
|
|
{OID_TAPI_SECURE_CALL, sizeof (NDIS_TAPI_SECURE_CALL), PxTapiSecureCall},
|
|
{OID_TAPI_SELECT_EXT_VERSION, sizeof (NDIS_TAPI_SELECT_EXT_VERSION), PxTapiSelectExtVersion},
|
|
{OID_TAPI_SEND_USER_USER_INFO, sizeof (NDIS_TAPI_SEND_USER_USER_INFO), PxTapiSendUserUserInfo},
|
|
{OID_TAPI_SET_APP_SPECIFIC, sizeof (NDIS_TAPI_SET_APP_SPECIFIC), PxTapiSetAppSpecific},
|
|
{OID_TAPI_SET_CALL_PARAMS, sizeof (NDIS_TAPI_SET_CALL_PARAMS), PxTapiSetCallParams},
|
|
{OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, sizeof (NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION), PxTapiSetDefaultMediaDetection},
|
|
{OID_TAPI_SET_DEV_CONFIG, sizeof (NDIS_TAPI_SET_DEV_CONFIG), PxTapiSetDevConfig},
|
|
{OID_TAPI_SET_MEDIA_MODE, sizeof (NDIS_TAPI_SET_MEDIA_MODE), PxTapiSetMediaMode},
|
|
{OID_TAPI_SET_STATUS_MESSAGES, sizeof (NDIS_TAPI_SET_STATUS_MESSAGES), PxTapiSetStatusMessages},
|
|
{OID_TAPI_GATHER_DIGITS, sizeof (NDIS_TAPI_GATHER_DIGITS), PxTapiGatherDigits},
|
|
{OID_TAPI_MONITOR_DIGITS, sizeof (NDIS_TAPI_MONITOR_DIGITS), PxTapiMonitorDigits}
|
|
};
|
|
|
|
//
|
|
// TAPI OIDs that do not map to NDIS5, and are passed-through to CallManagers:
|
|
//
|
|
|
|
#define MAX_TAPI_SUPPORTED_OIDS (sizeof(TapiOids)/sizeof(OID_DISPATCH))
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialization routine for the NDIS Proxy.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to the driver object created by the system.
|
|
RegistryPath - Points to global registry path
|
|
|
|
Return Value:
|
|
|
|
The final status from the initialization operation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING deviceName;
|
|
USHORT i;
|
|
UINT initStatus;
|
|
PDEVICE_OBJECT DeviceObject;
|
|
ULONG SizeNeeded;
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_INIT, ("NDIS Proxy DriverEntry; built %s, %s\n", __DATE__, __TIME__));
|
|
|
|
ExInitializeNPagedLookasideList(&ProviderEventLookaside,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
sizeof(PROVIDER_EVENT),
|
|
PX_EVENT_TAG,
|
|
0);
|
|
|
|
ExInitializeNPagedLookasideList(&VcLookaside,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
sizeof(PX_VC),
|
|
PX_VC_TAG,
|
|
0);
|
|
|
|
NdisZeroMemory(&TspCB, sizeof(TspCB));
|
|
NdisZeroMemory(&TspEventList, sizeof(TspEventList));
|
|
NdisZeroMemory(&VcTable, sizeof(VcTable));
|
|
NdisZeroMemory(&LineTable, sizeof(LineTable));
|
|
|
|
//
|
|
// Create the device objects. IoCreateDevice zeroes the memory
|
|
// occupied by the object.
|
|
//
|
|
RtlInitUnicodeString(&deviceName, DD_PROXY_DEVICE_NAME);
|
|
|
|
Status = IoCreateDevice(DriverObject,
|
|
sizeof (PX_DEVICE_EXTENSION),
|
|
&deviceName,
|
|
FILE_DEVICE_NETWORK,
|
|
0,
|
|
FALSE,
|
|
&DeviceObject);
|
|
|
|
if(!NT_SUCCESS(Status)) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Initialize the driver object
|
|
//
|
|
DeviceExtension =
|
|
(PPX_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
NdisZeroMemory(DeviceExtension,
|
|
sizeof (PX_DEVICE_EXTENSION));
|
|
|
|
DeviceExtension->pDriverObject = DriverObject;
|
|
NdisAllocateSpinLock(&DeviceExtension->Lock);
|
|
InitializeListHead(&DeviceExtension->AdapterList);
|
|
|
|
GetRegistryParameters (RegistryPath);
|
|
|
|
NdisAllocateSpinLock(&TspCB.Lock);
|
|
TspCB.Status = NDISTAPI_STATUS_DISCONNECTED;
|
|
TspCB.NdisTapiNumDevices = 0;
|
|
TspCB.htCall = 1;
|
|
InitializeListHead(&TspCB.ProviderList);
|
|
|
|
NdisAllocateSpinLock(&TspEventList.Lock);
|
|
InitializeListHead(&TspEventList.List);
|
|
|
|
//
|
|
// Intialize the VcTable
|
|
//
|
|
NdisInitializeReadWriteLock(&VcTable.Lock);
|
|
VcTable.Size = VC_TABLE_SIZE;
|
|
InitializeListHead(&VcTable.List);
|
|
|
|
SizeNeeded = (VC_TABLE_SIZE * sizeof(PPX_VC));
|
|
|
|
PxAllocMem(VcTable.Table, SizeNeeded, PX_VCTABLE_TAG);
|
|
|
|
if (VcTable.Table == NULL) {
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("DriverEntry: ExAllocPool for VcTable\n"));
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
goto DriverEntry_err;
|
|
}
|
|
|
|
NdisZeroMemory(VcTable.Table, SizeNeeded);
|
|
|
|
//
|
|
// Initialize the LineTable
|
|
//
|
|
NdisInitializeReadWriteLock(&LineTable.Lock);
|
|
LineTable.Size = LINE_TABLE_SIZE;
|
|
SizeNeeded = (LINE_TABLE_SIZE * sizeof(PPX_TAPI_LINE));
|
|
|
|
PxAllocMem(LineTable.Table, SizeNeeded, PX_LINETABLE_TAG);
|
|
|
|
if (LineTable.Table == NULL) {
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("DriverEntry: ExAllocPool for VcTable\n"));
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
goto DriverEntry_err;
|
|
}
|
|
|
|
NdisZeroMemory(LineTable.Table, SizeNeeded);
|
|
|
|
DeviceExtension->pDeviceObject = DeviceObject;
|
|
|
|
DriverObject->DriverUnload = PxUnload;
|
|
DriverObject->FastIoDispatch = NULL;
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = PxIOCreate;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PxIOClose;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PxIODispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PxIOCleanup;
|
|
|
|
//
|
|
// Intialize the device objects.
|
|
//
|
|
DeviceObject->Flags |= DO_DIRECT_IO;
|
|
DeviceExtension->pDeviceObject = DeviceObject;
|
|
|
|
//
|
|
// Finally, initialize the stack.
|
|
//
|
|
initStatus = InitNDISProxy();
|
|
|
|
if (initStatus == TRUE) {
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
DriverEntry_err:
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
while (!(IsListEmpty(&TspEventList.List))) {
|
|
PPROVIDER_EVENT ProviderEvent;
|
|
|
|
ProviderEvent = (PPROVIDER_EVENT)
|
|
RemoveHeadList(&TspEventList.List);
|
|
|
|
ExFreeToNPagedLookasideList(&ProviderEventLookaside, ProviderEvent);
|
|
}
|
|
|
|
if (VcTable.Table != NULL) {
|
|
PxFreeMem(VcTable.Table);
|
|
VcTable.Table = NULL;
|
|
}
|
|
|
|
if (LineTable.Table != NULL) {
|
|
PxFreeMem(LineTable.Table);
|
|
LineTable.Table = NULL;
|
|
}
|
|
|
|
if(DeviceObject != NULL) {
|
|
IoDeleteDevice(DeviceObject);
|
|
DeviceExtension->pDeviceObject = NULL;
|
|
}
|
|
|
|
ExDeleteNPagedLookasideList(&ProviderEventLookaside);
|
|
ExDeleteNPagedLookasideList(&VcLookaside);
|
|
|
|
return(Status);
|
|
}
|
|
|
|
VOID
|
|
PxUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free all the allocated resources, etc.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to a driver object
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, ("PxUnload: enter\n"));
|
|
|
|
//
|
|
// Call our unload handler
|
|
//
|
|
PxCoUnloadProtocol();
|
|
|
|
NdisAcquireSpinLock(&TspEventList.Lock);
|
|
|
|
while (!(IsListEmpty(&TspEventList.List))) {
|
|
PPROVIDER_EVENT ProviderEvent;
|
|
|
|
ProviderEvent = (PPROVIDER_EVENT)
|
|
RemoveHeadList(&TspEventList.List);
|
|
|
|
ExFreeToNPagedLookasideList(&ProviderEventLookaside, ProviderEvent);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
|
|
ExDeleteNPagedLookasideList(&ProviderEventLookaside);
|
|
ExDeleteNPagedLookasideList(&VcLookaside);
|
|
|
|
if (DeviceExtension->pDeviceObject != NULL) {
|
|
IoDeleteDevice (DeviceExtension->pDeviceObject);
|
|
}
|
|
|
|
//
|
|
// Free Vc table memory
|
|
//
|
|
ASSERT(VcTable.Count == 0);
|
|
PxFreeMem(VcTable.Table);
|
|
|
|
//
|
|
// Free the allocated tapi resources
|
|
// (TapiProviders, TapiLines, TapiAddrs)
|
|
//
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
while (!IsListEmpty(&TspCB.ProviderList)) {
|
|
PPX_TAPI_PROVIDER tp;
|
|
|
|
tp = (PPX_TAPI_PROVIDER)
|
|
RemoveHeadList(&TspCB.ProviderList);
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
FreeTapiProvider(tp);
|
|
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
NdisFreeSpinLock(&TspCB.Lock);
|
|
|
|
//
|
|
// Free the line table
|
|
//
|
|
ASSERT(LineTable.Count == 0);
|
|
PxFreeMem(LineTable.Table);
|
|
|
|
|
|
NdisFreeSpinLock(&(DeviceExtension->Lock));
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_INIT, ("PxUnload: exit\n"));
|
|
}
|
|
|
|
NTSTATUS
|
|
PxIOCreate(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, ("IRP_MJ_CREATE, Irp=%p", Irp));
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
PxIOClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PPX_TAPI_PROVIDER Provider;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, ("IRP_MJ_CLOSE, Entry\n"));
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PxIODispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the generic dispatch routine for the Proxy. Irps come from the
|
|
usermode TSP component.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to device object for target device
|
|
Irp - Pointer to I/O request packet
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS -- Indicates whether the request was successfully queued.
|
|
|
|
--*/
|
|
|
|
{
|
|
PVOID ioBuffer;
|
|
ULONG inputBufferLength;
|
|
ULONG outputBufferLength;
|
|
ULONG ioControlCode;
|
|
ULONG InfoSize = 0;
|
|
NTSTATUS ntStatus = STATUS_PENDING;
|
|
PIO_STACK_LOCATION IrpStack;
|
|
ULONG RequestId;
|
|
|
|
//
|
|
// Get a pointer to the current location in the Irp. This is where
|
|
// the function codes and parameters are located.
|
|
//
|
|
IrpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
//
|
|
// Get the pointer to the input/output buffer and its length
|
|
//
|
|
ioBuffer =
|
|
Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
inputBufferLength =
|
|
IrpStack->Parameters.DeviceIoControl.InputBufferLength;
|
|
|
|
outputBufferLength =
|
|
IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
if ((IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
|
|
(DeviceObject != DeviceExtension->pDeviceObject)) {
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return (STATUS_NOT_SUPPORTED);
|
|
}
|
|
|
|
ioControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
// PxAssert((ioControlCode & (METHOD_BUFFERED | METHOD_IN_DIRECT | METHOD_OUT_DIRECT | METHOD_NEITHER)) == METHOD_BUFFERED);
|
|
|
|
switch(ioControlCode)
|
|
{
|
|
case IOCTL_NDISTAPI_CONNECT:
|
|
{
|
|
PPX_TAPI_PROVIDER Provider;
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_INIT, ("IOCTL_NDISTAPI_CONNECT, Irp=%p\n", Irp));
|
|
|
|
//
|
|
// Someone's connecting. Make sure they passed us a valid
|
|
// info buffer.
|
|
//
|
|
if ((inputBufferLength < 2*sizeof(ULONG)) ||
|
|
(outputBufferLength < sizeof(ULONG))) {
|
|
PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_CONNECT: buffer too small\n"));
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
//
|
|
// Return the number of line devs
|
|
//
|
|
PxAssert(outputBufferLength >= sizeof(ULONG));
|
|
|
|
*((ULONG *) ioBuffer)= TspCB.NdisTapiNumDevices;
|
|
|
|
TspCB.Status = NDISTAPI_STATUS_CONNECTED;
|
|
|
|
Provider = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
|
|
|
|
while ((PVOID)Provider != (PVOID)&TspCB.ProviderList) {
|
|
|
|
NdisAcquireSpinLock(&Provider->Lock);
|
|
|
|
if (Provider->Status == PROVIDER_STATUS_ONLINE) {
|
|
|
|
MarkProviderConnected(Provider);
|
|
}
|
|
NdisReleaseSpinLock(&Provider->Lock);
|
|
|
|
Provider = (PPX_TAPI_PROVIDER)Provider->Linkage.Flink;
|
|
}
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
InfoSize = sizeof (ULONG);
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_NDISTAPI_DISCONNECT:
|
|
{
|
|
PPX_TAPI_PROVIDER Provider;
|
|
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
//
|
|
// If no one is talking then set state to
|
|
// disconnected.
|
|
//
|
|
TspCB.Status = NDISTAPI_STATUS_DISCONNECTING;
|
|
|
|
Provider = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
|
|
|
|
while ((PVOID)Provider != (PVOID)&TspCB.ProviderList) {
|
|
|
|
NdisAcquireSpinLock(&Provider->Lock);
|
|
|
|
if (Provider->Status == PROVIDER_STATUS_ONLINE) {
|
|
MarkProviderDisconnected(Provider);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&Provider->Lock);
|
|
|
|
Provider =
|
|
(PPX_TAPI_PROVIDER)Provider->Linkage.Flink;
|
|
}
|
|
|
|
NdisReleaseSpinLock (&TspCB.Lock);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
InfoSize = 0;
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_NDISTAPI_QUERY_INFO:
|
|
case IOCTL_NDISTAPI_SET_INFO:
|
|
{
|
|
ULONG targetDeviceID;
|
|
NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
|
|
NDIS_HANDLE providerHandle = NULL;
|
|
PNDISTAPI_REQUEST ndisTapiRequest;
|
|
KIRQL oldIrql;
|
|
KIRQL cancelIrql;
|
|
PPX_TAPI_LINE TapiLine = NULL;
|
|
INT n=0;
|
|
PKDEVICE_QUEUE_ENTRY packet;
|
|
|
|
//
|
|
// All the following OIDs come in here as query/set IOCTls:
|
|
//Init
|
|
//Accept
|
|
//Answer
|
|
//Close
|
|
//CloseCall
|
|
//ConditionalMediaDetection
|
|
//ConfigDialog
|
|
//DevSpecific
|
|
//Dial
|
|
//Drop
|
|
//GetAddressCaps
|
|
//GetAddressID
|
|
//GetAddressStatus
|
|
//GetCallAddressID
|
|
//GetCallInfo
|
|
//GetCallStatus
|
|
//GetDevCaps
|
|
//GetDevConfig
|
|
//GetExtensionID
|
|
//GetID
|
|
//GetLineDevStatus
|
|
//MakeCall
|
|
//NegotiateExtVersion
|
|
//Open
|
|
//ProviderInitialize
|
|
//ProviderShutdown
|
|
//SecureCall
|
|
//SelectExtVersion
|
|
//SendUserUserInfo
|
|
//SetAppSpecific
|
|
//SetCallParams
|
|
//SetDefaultMediaDetection
|
|
//SetDevConfig
|
|
//SetMediaMode
|
|
//SetStatusMessages
|
|
//
|
|
|
|
//
|
|
// Verify we're connected, then check the device ID of the
|
|
// incoming request against our list of online devices
|
|
//
|
|
|
|
//
|
|
// Something other then pending was returned so complete
|
|
// the irp
|
|
//
|
|
|
|
if (inputBufferLength < sizeof (NDISTAPI_REQUEST) ||
|
|
outputBufferLength < sizeof(NDISTAPI_REQUEST)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength! len %d needed %d\n",
|
|
inputBufferLength, sizeof(NDISTAPI_REQUEST)));
|
|
|
|
ntStatus = STATUS_INFO_LENGTH_MISMATCH;
|
|
break;
|
|
}
|
|
|
|
ndisTapiRequest = ioBuffer;
|
|
|
|
targetDeviceID = ndisTapiRequest->ulDeviceID;
|
|
|
|
InfoSize = sizeof(NDISTAPI_REQUEST);
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, (
|
|
"NdisTapiRequest: Irp: %p Oid: %x, devID: %d, reqID: %x\n",
|
|
Irp,
|
|
ndisTapiRequest->Oid,
|
|
ndisTapiRequest->ulDeviceID,
|
|
*((ULONG *)ndisTapiRequest->Data)));
|
|
|
|
n = ndisTapiRequest->Oid - OID_TAPI_ACCEPT;
|
|
|
|
if (n > MAX_TAPI_SUPPORTED_OIDS) {
|
|
PXDEBUGP(PXD_WARNING,PXM_INIT, ("IOCTL_SET/QUERY: Invalid OID %x index %d\n",
|
|
ndisTapiRequest->Oid, n));
|
|
|
|
ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_INVALPARAM;
|
|
ntStatus = STATUS_SUCCESS;
|
|
break; // out of switch
|
|
}
|
|
|
|
//
|
|
// defensive check that data buffer size is not bad
|
|
//
|
|
if (ndisTapiRequest->ulDataSize < TapiOids[n].SizeofStruct) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength2! len %d needed %d\n",
|
|
ndisTapiRequest->ulDataSize, TapiOids[n].SizeofStruct));
|
|
ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_STRUCTURETOOSMALL;
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure the IRP contained sufficient data.
|
|
//
|
|
if (ndisTapiRequest->ulDataSize >
|
|
inputBufferLength - FIELD_OFFSET(NDISTAPI_REQUEST, Data[0])) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength3! len %d needed %d\n",
|
|
ndisTapiRequest->ulDataSize, inputBufferLength - FIELD_OFFSET(NDISTAPI_REQUEST, Data[0])));
|
|
ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_STRUCTURETOOSMALL;
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock (&TspCB.Lock);
|
|
|
|
//
|
|
// Are we initialized with TAPI?
|
|
//
|
|
if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("TAPI not connected, returning err\n"));
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
ndisTapiRequest->ulReturnValue = NDISTAPIERR_UNINITIALIZED;
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get a unique ID for this request -- value between 1 and fffffffe.
|
|
// (Can't use the TAPI ID in case it's spoofed)
|
|
//
|
|
|
|
if (++TspCB.ulUniqueId > 0xfffffffe) {
|
|
TspCB.ulUniqueId = 0x80000001;
|
|
}
|
|
|
|
RequestId =
|
|
ndisTapiRequest->ulUniqueRequestId =
|
|
TspCB.ulUniqueId;
|
|
|
|
ndisTapiRequest->Irp = Irp;
|
|
|
|
NdisReleaseSpinLock (&TspCB.Lock);
|
|
|
|
//
|
|
// Mark the TAPI request pending
|
|
//
|
|
IoMarkIrpPending(Irp);
|
|
ntStatus = STATUS_PENDING;
|
|
|
|
//
|
|
// Dispatch the request
|
|
//
|
|
ndisStatus =
|
|
(*TapiOids[n].FuncPtr)(ndisTapiRequest);
|
|
|
|
if (ndisStatus == NDIS_STATUS_PENDING) {
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_INIT, ("IOCTL_TAPI_SET/QUERY_INFO: reqProc returning PENDING\n" ));
|
|
|
|
return (STATUS_PENDING);
|
|
}
|
|
|
|
//
|
|
// Something other then pending was returned so complete
|
|
// the irp
|
|
//
|
|
InfoSize = MIN (outputBufferLength,
|
|
sizeof(NDISTAPI_REQUEST)+ndisTapiRequest->ulDataSize);
|
|
//
|
|
// Set the TAPI return status
|
|
//
|
|
ndisTapiRequest->ulReturnValue = ndisStatus;
|
|
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_NDISTAPI_GET_LINE_EVENTS:
|
|
{
|
|
KIRQL oldIrql;
|
|
KIRQL cancelIrql;
|
|
PNDISTAPI_EVENT_DATA ndisTapiEventData = ioBuffer;
|
|
|
|
PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS\n"));
|
|
|
|
//
|
|
// Defensive check that the input buffer is at least
|
|
// the size of the request,
|
|
// and that we can move at least one event
|
|
//
|
|
if (inputBufferLength < sizeof (NDISTAPI_EVENT_DATA)) {
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
InfoSize = sizeof (ULONG);
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: buffer too small\n"));
|
|
break;
|
|
}
|
|
|
|
if (outputBufferLength - sizeof(NDISTAPI_EVENT_DATA) + 1 < ndisTapiEventData->ulTotalSize) {
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
InfoSize = sizeof (ULONG);
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: buffer too small\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Sync event buf access by acquiring EventSpinLock
|
|
//
|
|
NdisAcquireSpinLock(&TspEventList.Lock);
|
|
|
|
//
|
|
// Is there any data available?
|
|
//
|
|
if (TspEventList.Count != 0) {
|
|
//
|
|
// There's line event data queued in our ring buffer. Grab as
|
|
// much as we can & complete the request.
|
|
//
|
|
PXDEBUGP(PXD_VERY_LOUD, PXM_INIT,
|
|
("IOCTL_NDISTAPI_GET_LINE_EVENTS: event count = x%x, IoBuffer->TotalSize = %x\n",
|
|
TspEventList.Count, ndisTapiEventData->ulTotalSize));
|
|
|
|
ndisTapiEventData->ulUsedSize =
|
|
GetLineEvents(ndisTapiEventData->Data,
|
|
ndisTapiEventData->ulTotalSize);
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
InfoSize =
|
|
MIN (outputBufferLength, ((ndisTapiEventData->ulUsedSize) + sizeof(NDISTAPI_EVENT_DATA) - 1));
|
|
|
|
} else {
|
|
PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: no events in queue\n"));
|
|
|
|
//
|
|
// Hold the request pending. It remains in the cancelable
|
|
// state. When new line event input is received or generated (i.e.
|
|
// LINEDEVSTATE_REINIT) the data will get copied & the
|
|
// request completed.
|
|
//
|
|
|
|
if (NULL == TspEventList.RequestIrp) {
|
|
|
|
IoSetCancelRoutine (Irp, PxCancelGetEvents);
|
|
|
|
IoMarkIrpPending (Irp);
|
|
|
|
Irp->IoStatus.Status = STATUS_PENDING;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
TspEventList.RequestIrp = Irp;
|
|
|
|
ntStatus = STATUS_PENDING;
|
|
|
|
} else {
|
|
ntStatus = STATUS_UNSUCCESSFUL;
|
|
InfoSize = sizeof (ULONG);
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
|
|
break;
|
|
}
|
|
|
|
case IOCTL_NDISTAPI_SET_DEVICEID_BASE:
|
|
{
|
|
ULONG BaseId;
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE, Irp=x%x, inputBufLen = %x\n", Irp, inputBufferLength ));
|
|
|
|
//
|
|
// Someone's connecting. Make sure they passed us a valid
|
|
// info buffer
|
|
//
|
|
if ((inputBufferLength < sizeof(ULONG))) {
|
|
PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE: buffer too small\n"));
|
|
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
NdisAcquireSpinLock(&TspCB.Lock);
|
|
|
|
if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
|
|
PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE: Disconnected\n"));
|
|
ntStatus = STATUS_UNSUCCESSFUL;
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the base ID
|
|
//
|
|
BaseId = *((ULONG *) ioBuffer);
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, ("BaseID %d\n", BaseId));
|
|
|
|
NdisReleaseSpinLock(&TspCB.Lock);
|
|
|
|
{
|
|
LOCK_STATE LockState;
|
|
ULONG i;
|
|
|
|
//
|
|
// Update the deviceId's for each line on the provider
|
|
//
|
|
NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
|
|
|
|
for (i = 0; i < LineTable.Size; i++) {
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
TapiLine = LineTable.Table[i];
|
|
|
|
if ((TapiLine != NULL)) {
|
|
|
|
TapiLine->ulDeviceID = BaseId++;
|
|
}
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
|
|
}
|
|
|
|
InfoSize = 0;
|
|
ntStatus = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
case IOCTL_NDISTAPI_CREATE:
|
|
{
|
|
PPX_TAPI_PROVIDER Provider;
|
|
PNDISTAPI_CREATE_INFO CreateInfo;
|
|
PPX_TAPI_LINE TapiLine;
|
|
|
|
InfoSize = 0;
|
|
|
|
if (inputBufferLength < sizeof(CreateInfo)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_CREATE: buffer too small\n"));
|
|
|
|
ntStatus = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
CreateInfo = (PNDISTAPI_CREATE_INFO)ioBuffer;
|
|
|
|
if (!IsTapiLineValid(CreateInfo->TempID, &TapiLine)) {
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT,
|
|
("IOCTL_NDISTAPI_CREATE: Failed to find Id %d\n",
|
|
CreateInfo->TempID));
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT,
|
|
("IOCTL_NDISTAPI_CREATE: Created new Line %p Id %d\n",
|
|
TapiLine, CreateInfo->DeviceID));
|
|
|
|
TapiLine->ulDeviceID = CreateInfo->DeviceID;
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
|
|
ntStatus = STATUS_INVALID_PARAMETER;
|
|
|
|
PXDEBUGP(PXD_WARNING, PXM_INIT, ("unknown IRP_MJ_DEVICE_CONTROL\n"));
|
|
|
|
break;
|
|
|
|
} // switch
|
|
|
|
//
|
|
// Complete this IRP synchronously if we are done.
|
|
//
|
|
if (ntStatus != STATUS_PENDING) {
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
Irp->IoStatus.Status = ntStatus;
|
|
Irp->IoStatus.Information = InfoSize;
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
IrpSp->Control &= ~SL_PENDING_RETURNED;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("PxDispatch: Completing Irp %p (Status %x) synchronously\n", Irp, ntStatus));
|
|
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
NTSTATUS
|
|
PxIOCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the dispatch routine for cleanup requests.
|
|
All requests queued are completed with STATUS_CANCELLED.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to device object.
|
|
|
|
Irp - Pointer to the request packet.
|
|
|
|
Return Value:
|
|
|
|
Status is returned.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIRP MyIrp;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT, ("PxIOCleanup: enter\n"));
|
|
|
|
NdisAcquireSpinLock (&TspEventList.Lock);
|
|
|
|
//
|
|
// Cancel the EventRequest Irp
|
|
//
|
|
MyIrp = TspEventList.RequestIrp;
|
|
|
|
if ((MyIrp != NULL) &&
|
|
(MyIrp->Tail.Overlay.OriginalFileObject ==
|
|
Irp->Tail.Overlay.OriginalFileObject)) {
|
|
|
|
if (IoSetCancelRoutine(MyIrp, NULL) != NULL) {
|
|
TspEventList.RequestIrp = NULL;
|
|
MyIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
MyIrp->IoStatus.Information = 0;
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
IoCompleteRequest(MyIrp, IO_NO_INCREMENT);
|
|
NdisAcquireSpinLock(&TspEventList.Lock);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cancel any Set/Query Irp's
|
|
//
|
|
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
|
|
//
|
|
// Complete the cleanup request with STATUS_SUCCESS.
|
|
//
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
|
|
|
PXDEBUGP (PXD_LOUD, PXM_INIT, ("PxIOCleanup: exit\n"));
|
|
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
PxCancelGetEvents(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
PIRP MyIrp;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT,
|
|
("PxCancelGetEvents: enter. Irp = %x\n", Irp));
|
|
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
|
|
//
|
|
// Acquire the EventSpinLock & check to see if we're canceling a
|
|
// pending get-events Irp
|
|
//
|
|
NdisAcquireSpinLock (&TspEventList.Lock);
|
|
|
|
MyIrp = TspEventList.RequestIrp;
|
|
TspEventList.RequestIrp = NULL;
|
|
|
|
NdisReleaseSpinLock(&TspEventList.Lock);
|
|
|
|
if (MyIrp != NULL) {
|
|
|
|
ASSERT(MyIrp == Irp);
|
|
|
|
//
|
|
// Don't let it get cancelled again
|
|
//
|
|
IoSetCancelRoutine (MyIrp, NULL);
|
|
|
|
MyIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
MyIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (MyIrp, IO_NO_INCREMENT);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PxCancelSetQuery(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
BOOLEAN Found = FALSE;
|
|
LOCK_STATE LockState;
|
|
PPX_VC pVc;
|
|
PIRP MyIrp;
|
|
|
|
PXDEBUGP(PXD_LOUD, PXM_INIT,
|
|
("PxCancelSetQuery: enter. Irp = %x\n", Irp));
|
|
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
|
|
//
|
|
// We must search through the Vc's in the Vc table
|
|
// and find the pending ndisrequest!
|
|
//
|
|
NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
|
|
|
|
pVc = (PPX_VC)VcTable.List.Flink;
|
|
|
|
while ((PVOID)pVc != (PVOID)&VcTable.List) {
|
|
PLIST_ENTRY Entry;
|
|
PNDISTAPI_REQUEST Request;
|
|
|
|
NdisAcquireSpinLock(&pVc->Lock);
|
|
|
|
Entry = pVc->PendingDropReqs.Flink;
|
|
|
|
while (Entry != &pVc->PendingDropReqs) {
|
|
|
|
Request =
|
|
CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
|
|
|
|
MyIrp = Request->Irp;
|
|
|
|
if (MyIrp->Cancel) {
|
|
Found = TRUE;
|
|
RemoveEntryList(&Request->Linkage);
|
|
break;
|
|
}
|
|
|
|
Entry = Entry->Flink;
|
|
}
|
|
|
|
if (!Found) {
|
|
if (pVc->PendingGatherDigits != NULL) {
|
|
MyIrp = pVc->PendingGatherDigits->Irp;
|
|
|
|
if (MyIrp->Cancel) {
|
|
Found = TRUE;
|
|
pVc->PendingGatherDigits = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&pVc->Lock);
|
|
|
|
if (Found) {
|
|
break;
|
|
}
|
|
|
|
pVc = (PPX_VC)pVc->Linkage.Flink;
|
|
}
|
|
|
|
NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
|
|
|
|
if (Found) {
|
|
|
|
//
|
|
// Don't let it get cancelled again
|
|
//
|
|
IoSetCancelRoutine (MyIrp, NULL);
|
|
MyIrp->IoStatus.Status = STATUS_CANCELLED;
|
|
MyIrp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest (MyIrp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
PXDEBUGP(PXD_INFO, PXM_INIT, ("PxIOCancel: completing Irp=%p\n", Irp));
|
|
}
|
|
|
|
|