Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1465 lines
34 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
stubmp.c
Abstract:
Author:
Dan Knudson (DanKn) 11-Apr-1995
Environment:
kernel mode only
Revision History:
Notes:
--*/
#include "ntddk.h"
//#include "ntos.h"
#include "ndismain.h"
#include "stdarg.h"
#include "stdio.h"
#include "ndistapi.h"
#include "stubmp.h"
#include "intrface.h"
PDEVICE_EXTENSION DeviceExtension;
#ifdef DBG
//ULONG StubmpDebugLevel = 3;
ULONG StubmpDebugLevel = 0;
#define DBGOUT(arg) DbgPrt arg
VOID
DbgPrt(
IN ULONG DbgLevel,
IN PUCHAR DbgMessage,
IN ...
);
#else
#define DBGOUT(arg)
#endif
NTSTATUS
StubmpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NDIS_STATUS
StubmpRequest(
NDIS_HANDLE NdisBindingHandle,
PNDIS_REQUEST NdisRequest
);
VOID
StubmpUnload(
IN PDRIVER_OBJECT DriverObject
);
VOID
StubmpCancel(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
WriteRingBuffer(
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
);
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path
to driver-specific key in the registry
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
ULONG i, ulNumLines = 4,
ulNumAddrsPerLine = 4,
ulNumCallsPerLine = 4;
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus;
WCHAR deviceNameBuffer[] = L"\\Device\\Stubmp";
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Stubmp";
UNICODE_STRING deviceLinkUnicodeString;
DBGOUT ((2, "DriverEntry: enter"));
//
// Create an EXCLUSIVE device, i.e. only 1 thread at a time can send
// i/o requests.
//
RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
ntStatus = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION) + (ulNumLines - 1) * sizeof(PDRVLINE),
&deviceNameUnicodeString,
FILE_DEVICE_STUBMP,
0,
FALSE, // not exclusive
&deviceObject
);
if (NT_SUCCESS(ntStatus))
{
ULONG numBytesPerLine = sizeof(DRVLINE) +
(ulNumCallsPerLine - 1) * sizeof(DRVCALL);
DeviceExtension = (PDEVICE_EXTENSION)
deviceObject->DeviceExtension;
RtlZeroMemory (DeviceExtension, sizeof (DEVICE_EXTENSION));
DeviceExtension->CompleteAsync = TRUE;
DeviceExtension->ulNumLines = ulNumLines;
DeviceExtension->ulNumAddrsPerLine = ulNumAddrsPerLine;
DeviceExtension->ulNumCallsPerLine = ulNumCallsPerLine;
KeInitializeSpinLock (&DeviceExtension->EventSpinLock);
DeviceExtension->EventDataQueueLength = 1024;
DeviceExtension->EventDataQueue =
DeviceExtension->DataIn =
DeviceExtension->DataOut = ExAllocatePoolWithTag(
NonPagedPool,
DeviceExtension->EventDataQueueLength,
'TAPI'
);
//
//
//
for (i = 0; i < ulNumLines; i++)
{
DeviceExtension->apLines[i] = ExAllocatePoolWithTag(
NonPagedPool,
numBytesPerLine,
'TAPI'
);
RtlZeroMemory (DeviceExtension->apLines[i], numBytesPerLine);
}
//
// Create a symbolic link that Win32 apps can specify to gain access
// to this driver/device
//
RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer);
ntStatus = IoCreateSymbolicLink(
&deviceLinkUnicodeString,
&deviceNameUnicodeString
);
if (!NT_SUCCESS(ntStatus))
{
DBGOUT ((0, "DriverEntry: IoCreateSymbolicLink failed"));
}
//
// Init dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StubmpDispatch;
DriverObject->DriverUnload = StubmpUnload;
}
done_DriverEntry:
if (!NT_SUCCESS(ntStatus))
{
//
// Something went wrong, so clean up (free resources, etc.)
//
if (deviceObject)
{
IoDeleteDevice (deviceObject);
}
}
return ntStatus;
}
NTSTATUS
StubmpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Process the IRPs sent to this device.
Arguments:
DeviceObject - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
--*/
{
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
NDIS_TAPI_EVENT event;
PIO_STACK_LOCATION irpStack;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
//
// 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 it's length
//
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength =
irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
DBGOUT ((2, "IRP_MJ_CREATE"));
break;
case IRP_MJ_CLOSE:
DBGOUT ((2, "IRP_MJ_CLOSE"));
break;
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_STUBMP_APPREQUEST:
{
PREQUESTBLOCK pRequestBlock = (PREQUESTBLOCK) ioBuffer;
DBGOUT ((2, "IOCTL_STUBMP_APPREQUEST"));
switch (pRequestBlock->ulRequestType)
{
case RT_REGISTER:
NdisTapiRegisterProvider(
(NDIS_HANDLE) 0x55,
(REQUEST_PROC) StubmpRequest
);
break;
case RT_DEREGISTER:
NdisTapiDeregisterProvider ((NDIS_HANDLE) 0x55);
break;
case RT_COMPLETEREQUEST:
{
ULONG *args = (ULONG *) (pRequestBlock->Data);
DBGOUT ((2, "completing req x%x", *args));
NdisTapiCompleteRequest(
(NDIS_HANDLE) 0x55,
(PNDIS_REQUEST) *args,
(NDIS_STATUS) *(args + 1)
);
break;
}
case RT_SYNCCOMPLETIONS:
DeviceExtension->CompleteAsync = FALSE;
break;
case RT_ASYNCCOMPLETIONS:
DeviceExtension->CompleteAsync = TRUE;
break;
case RT_INCOMINGCALL:
//BUGBUG
break;
case RT_EVENT:
//BUGBUG
break;
default:
break;
}
break;
}
case IOCTL_STUBMP_GETEVENTS:
{
KIRQL oldIrql;
KIRQL cancelIrql;
BOOLEAN satisfiedRequest = FALSE;
//
// Sync event buf access by acquiring EventSpinLock
//
KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
//
// Inspect DeviceExtension to see if there's any data available
//
DBGOUT((
2,
"IOCTL_STUBMP_GETEVENTS, Irp=x%x, bytesInQ=x%x",
Irp,
DeviceExtension->BytesInQueue
));
if (DeviceExtension->BytesInQueue != 0)
{
ULONG bytesInQueue;
ULONG bytesToMove;
ULONG moveSize;
PCHAR EventBuffer = (PCHAR) ((ULONG *) ioBuffer + 1);
bytesInQueue = DeviceExtension->BytesInQueue;
bytesToMove = *((ULONG *) ioBuffer);
bytesToMove = (bytesInQueue < bytesToMove) ? bytesInQueue : bytesToMove;
//
// moveSize <- MIN(Number of bytes to be moved from the event data queue,
// Number of bytes to end of event data queue).
//
bytesInQueue =
((PCHAR) DeviceExtension->EventDataQueue +
DeviceExtension->EventDataQueueLength) -
(PCHAR) DeviceExtension->DataOut;
moveSize = (bytesToMove < bytesInQueue) ? bytesToMove : bytesInQueue;
//
// Move bytes from the class input data queue to SystemBuffer, until
// the request is satisfied or we wrap the class input data buffer.
//
RtlMoveMemory(
EventBuffer,
(PCHAR) DeviceExtension->DataOut,
moveSize
);
EventBuffer += moveSize;
//
// If the data wraps in the event data buffer, copy the rest
// of the data from the start of the input data queue
// buffer through the end of the queued data.
//
if ((bytesToMove - moveSize) > 0)
{
//
// moveSize <- Remaining number bytes to move.
//
moveSize = bytesToMove - moveSize;
//
// Move the bytes from the
//
RtlMoveMemory(
EventBuffer,
(PCHAR) DeviceExtension->EventDataQueue,
moveSize
);
//
// Update the class input data queue removal pointer.
//
DeviceExtension->DataOut =
((PCHAR) DeviceExtension->EventDataQueue) + moveSize;
}
else
{
//
// Update the input data queue removal pointer.
//
DeviceExtension->DataOut =
((PCHAR) DeviceExtension->DataOut) + moveSize;
}
//
// Update the event data queue EventCount.
//
DeviceExtension->BytesInQueue -= bytesToMove;
//
//
//
*((ULONG *) ioBuffer) = bytesToMove;
//
//
//
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(ULONG) + bytesToMove;
satisfiedRequest = TRUE;
}
else
{
//
// Hold the request pending. It remains in the cancelable
// state. When new line event input is received
// (NdisTapiIndicateStatus) or generated (i.e.
// LINEDEVSTATE_REINIT) the data will get copied & the
// request completed.
//
DeviceExtension->EventsRequestIrp = Irp;
Irp->IoStatus.Status = STATUS_PENDING;
IoAcquireCancelSpinLock (&cancelIrql);
IoSetCancelRoutine (Irp, StubmpCancel);
IoReleaseCancelSpinLock (cancelIrql);
}
KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
//
// If request not satisfied just return pending
//
if (!satisfiedRequest)
{
return STATUS_PENDING;
}
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
DBGOUT ((2, "unknown IRP_MJ_DEVICE_CONTROL"));
break;
}
break;
}
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
//
// We never have pending operation so always return the status code.
//
return ntStatus;
}
PDRVLINE
GetpLine(
HDRV_LINE hdLine
)
{
return (DeviceExtension->apLines
[(ULONG) hdLine - DeviceExtension->DeviceIDBase]);
}
NDIS_STATUS
StubmpRequest(
NDIS_HANDLE NdisBindingHandle,
PNDIS_REQUEST NdisRequest
)
{
BOOLEAN completeAsync = DeviceExtension->CompleteAsync;
ULONG i, j, ulRequestSpecific = 0;
NDIS_STATUS status = NDIS_STATUS_SUCCESS;
NDIS_TAPI_EVENT event;
//
// Handle the request
//
if (NdisRequest->RequestType == NdisRequestQueryInformation)
{
switch (NdisRequest->DATA.QUERY_INFORMATION.Oid)
{
case OID_TAPI_CONFIG_DIALOG:
{
PNDIS_TAPI_CONFIG_DIALOG pConfigDialog =
(PNDIS_TAPI_CONFIG_DIALOG)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_DEV_SPECIFIC:
{
PNDIS_TAPI_DEV_SPECIFIC pDevSpecific =
(PNDIS_TAPI_DEV_SPECIFIC)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_ADDRESS_CAPS:
{
PNDIS_TAPI_GET_ADDRESS_CAPS pGetAddressCaps =
(PNDIS_TAPI_GET_ADDRESS_CAPS)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_ADDRESS_ID:
{
PNDIS_TAPI_GET_ADDRESS_ID pGetAddressID =
(PNDIS_TAPI_GET_ADDRESS_ID)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_ADDRESS_STATUS:
{
PNDIS_TAPI_GET_ADDRESS_STATUS pGetAddressStatus =
(PNDIS_TAPI_GET_ADDRESS_STATUS)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_CALL_ADDRESS_ID:
{
PNDIS_TAPI_GET_CALL_ADDRESS_ID pGetCallAddressID =
(PNDIS_TAPI_GET_CALL_ADDRESS_ID)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_CALL_INFO:
{
PNDIS_TAPI_GET_CALL_INFO pGetCallInfo =
(PNDIS_TAPI_GET_CALL_INFO)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_CALL_STATUS:
{
PNDIS_TAPI_GET_CALL_STATUS pGetCallStatus =
(PNDIS_TAPI_GET_CALL_STATUS)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_DEV_CAPS:
{
PNDIS_TAPI_GET_DEV_CAPS pGetDevCaps = (PNDIS_TAPI_GET_DEV_CAPS)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_DEV_CONFIG:
{
PNDIS_TAPI_GET_DEV_CONFIG pGetDevConfig =
(PNDIS_TAPI_GET_DEV_CONFIG)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_EXTENSION_ID:
{
PNDIS_TAPI_GET_EXTENSION_ID pGetExtensionID =
(PNDIS_TAPI_GET_EXTENSION_ID)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_ID:
{
PNDIS_TAPI_GET_ID pGetID = (PNDIS_TAPI_GET_ID)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_GET_LINE_DEV_STATUS:
{
PNDIS_TAPI_GET_LINE_DEV_STATUS pGetLineDevStatus =
(PNDIS_TAPI_GET_LINE_DEV_STATUS)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_MAKE_CALL:
{
PNDIS_TAPI_MAKE_CALL pMakeCall = (PNDIS_TAPI_MAKE_CALL)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
PDRVLINE pLine = GetpLine (pMakeCall->hdLine);
for (i = 0; i < DeviceExtension->ulNumCallsPerLine; i++)
{
if (!pLine->aCalls[i].htCall)
{
pLine->aCalls[i].htCall = pMakeCall->htCall;
pLine->aCalls[i].pLine = pLine;
pMakeCall->hdCall = (HDRV_CALL) (pLine->aCalls + i);
break;
}
}
if (i == DeviceExtension->ulNumCallsPerLine)
{
status = NDIS_STATUS_TAPI_CALLUNAVAIL;
}
ulRequestSpecific = (ULONG) (pLine->aCalls + i);
break;
}
case OID_TAPI_NEGOTIATE_EXT_VERSION:
{
PNDIS_TAPI_NEGOTIATE_EXT_VERSION pNegotiateExtVersion =
(PNDIS_TAPI_NEGOTIATE_EXT_VERSION)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_OPEN:
{
PNDIS_TAPI_OPEN pOpen = (PNDIS_TAPI_OPEN)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
PDRVLINE pLine = DeviceExtension->apLines
[pOpen->ulDeviceID - DeviceExtension->DeviceIDBase];
ulRequestSpecific =
pLine->htLine = pOpen->htLine;
pOpen->hdLine = (HDRV_LINE) pOpen->ulDeviceID;
break;
}
case OID_TAPI_PROVIDER_INITIALIZE:
{
PNDIS_TAPI_PROVIDER_INITIALIZE pInitialize =
(PNDIS_TAPI_PROVIDER_INITIALIZE)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
DeviceExtension->DeviceIDBase = pInitialize->ulDeviceIDBase;
for (i = 0; i < DeviceExtension->ulNumLines; i++)
{
DeviceExtension->apLines[i]->ulDeviceID =
pInitialize->ulDeviceIDBase + i;
for (j = 0; j < DeviceExtension->ulNumCallsPerLine; j++)
{
DeviceExtension->apLines[i]->aCalls[j].htCall =
(HTAPI_CALL) NULL;
}
}
ulRequestSpecific =
pInitialize->ulNumLineDevs = DeviceExtension->ulNumLines;
break;
}
default:
break;
} // switch
//
// Send info about this request to the app
//
{
ULONG *args = (ULONG *)
NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
ULONG requestData[8] =
{
ET_REQUEST,
(ULONG) completeAsync,
(ULONG) NdisRequest,
(ULONG) status,
(ULONG) NdisRequest->DATA.QUERY_INFORMATION.Oid,
*args,
*(args+1),
ulRequestSpecific
};
WriteRingBuffer (requestData, 8 * sizeof(ULONG));
}
}
else if (NdisRequest->RequestType == NdisRequestSetInformation)
{
switch (NdisRequest->DATA.SET_INFORMATION.Oid)
{
case OID_TAPI_ACCEPT:
{
PNDIS_TAPI_ACCEPT pAccept = (PNDIS_TAPI_ACCEPT)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_ANSWER:
{
PNDIS_TAPI_ANSWER pAnswer = (PNDIS_TAPI_ANSWER)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_CLOSE:
{
PNDIS_TAPI_CLOSE pClose = (PNDIS_TAPI_CLOSE)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
PDRVLINE pLine = GetpLine (pClose->hdLine);
pLine->htLine = 0;
break;
}
case OID_TAPI_CLOSE_CALL:
{
PNDIS_TAPI_CLOSE_CALL pCloseCall = (PNDIS_TAPI_CLOSE_CALL)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
PDRVCALL pCall = (PDRVCALL) pCloseCall->hdCall;
pCall->htCall = (HTAPI_CALL) NULL;
break;
}
case OID_TAPI_CONDITIONAL_MEDIA_DETECTION:
{
PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION pConditionalMediaDetection =
(PNDIS_TAPI_CONDITIONAL_MEDIA_DETECTION)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_DIAL:
{
PNDIS_TAPI_DIAL pDial = (PNDIS_TAPI_DIAL)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_DROP:
{
PNDIS_TAPI_DROP pDrop = (PNDIS_TAPI_DROP)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_PROVIDER_SHUTDOWN:
{
PNDIS_TAPI_PROVIDER_SHUTDOWN pShutdown =
(PNDIS_TAPI_PROVIDER_SHUTDOWN)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SECURE_CALL:
{
PNDIS_TAPI_SECURE_CALL pSecureCall = (PNDIS_TAPI_SECURE_CALL)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SELECT_EXT_VERSION:
{
PNDIS_TAPI_SELECT_EXT_VERSION pSelectExtVersion =
(PNDIS_TAPI_SELECT_EXT_VERSION)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SEND_USER_USER_INFO:
{
PNDIS_TAPI_SEND_USER_USER_INFO pSendUserUserInfo =
(PNDIS_TAPI_SEND_USER_USER_INFO)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_APP_SPECIFIC:
{
PNDIS_TAPI_SET_APP_SPECIFIC pSetApSpecific =
(PNDIS_TAPI_SET_APP_SPECIFIC)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_CALL_PARAMS:
{
PNDIS_TAPI_SET_CALL_PARAMS pSetCallParams =
(PNDIS_TAPI_SET_CALL_PARAMS)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_DEFAULT_MEDIA_DETECTION:
{
PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION pSetDefaultMediaDetection =
(PNDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_DEV_CONFIG:
{
PNDIS_TAPI_SET_DEV_CONFIG pSetDevConfig =
(PNDIS_TAPI_SET_DEV_CONFIG)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_MEDIA_MODE:
{
PNDIS_TAPI_SET_MEDIA_MODE pSetMediaMode =
(PNDIS_TAPI_SET_MEDIA_MODE)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
case OID_TAPI_SET_STATUS_MESSAGES:
{
PNDIS_TAPI_SET_STATUS_MESSAGES pSetStatusMessages =
(PNDIS_TAPI_SET_STATUS_MESSAGES)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
break;
}
default:
break;
} // switch
//
// Send info about this request to the app
//
{
ULONG *args = (ULONG *)
NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
REQUEST_PARAMS requestParams =
{
ET_REQUEST,
(ULONG) completeAsync,
(ULONG) NdisRequest,
(ULONG) status,
(ULONG) NdisRequest->DATA.SET_INFORMATION.Oid,
*args,
*(args+1),
ulRequestSpecific
};
WriteRingBuffer (&requestParams, sizeof(REQUEST_PARAMS));
}
}
else
{
DBGOUT((1, "StubmpRequest: unknown NdisRequest->RequestType"));
}
if (completeAsync)
{
status = NDIS_STATUS_PENDING;
DBGOUT((2, "StubmpRequest: Req x%x pending", NdisRequest));
}
else
{
DBGOUT((2, "StubmpRequest: Req x%x completing sync", NdisRequest));
}
return status;
}
VOID
StubmpUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object
Return Value:
--*/
{
ULONG i;
WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Stubmp";
UNICODE_STRING deviceLinkUnicodeString;
DBGOUT ((2, "StubmpUnload: enter"));
//
// Delete the symbolic link
//
RtlInitUnicodeString (&deviceLinkUnicodeString,
deviceLinkBuffer
);
IoDeleteSymbolicLink (&deviceLinkUnicodeString);
//
// Free all the resources
//
for (i = 0; i < DeviceExtension->ulNumLines; i++)
{
ExFreePool (DeviceExtension->apLines[i]);
}
//
// Delete the device object
//
IoDeleteDevice (DriverObject->DeviceObject);
}
VOID
StubmpCancel(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KIRQL oldIrql;
DBGOUT((2,"StubmpCancel: enter"));
//
// Release the cancel spinlock
//
IoReleaseCancelSpinLock (Irp->CancelIrql);
//
// Acquire the EventSpinLock & check to see if we're canceling a
// pending get-events Irp
//
KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
if (Irp == DeviceExtension->EventsRequestIrp)
{
DeviceExtension->EventsRequestIrp = NULL;
}
KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
StubmpCancel_done:
//
// Complete the request with STATUS_CANCELLED.
//
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
DBGOUT((2,"StubmpCancel: exit (completing irp=x%x)", Irp));
return;
}
#ifdef DBG
VOID
DbgPrt(
IN ULONG DbgLevel,
IN PUCHAR DbgMessage,
IN ...
)
/*++
Routine Description:
Formats the incoming debug message & calls DbgPrint
Arguments:
DbgLevel - level of message verboseness
DbgMessage - printf-style format string, followed by appropriate
list of arguments
Return Value:
--*/
{
if (DbgLevel <= StubmpDebugLevel)
{
char buf[256] = "STUBMP.SYS: ";
va_list ap;
va_start (ap, DbgMessage);
vsprintf (&buf[12], DbgMessage, ap);
strcat (buf, "\n");
DbgPrint (buf);
va_end(ap);
}
return;
}
#endif
VOID
WriteRingBuffer(
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
/*++
Routine Description:
This func gets called by Ndis when a miniport driver calls
NdisIndicateStatus to notify us of an async event
(i.e. new call, call state chg, dev state chg, etc.)
Arguments:
Return Value:
--*/
{
PIRP irp;
KIRQL oldIrql;
KIRQL cancelIrql;
ULONG bytesInQueue;
ULONG bytesToMove;
ULONG moveSize;
BOOLEAN satisfiedPendingEventsRequest = FALSE;
PCHAR ioBuffer;
DBGOUT((2,"WriteRingBuffer: enter"));
bytesInQueue = StatusBufferSize;
moveSize = 0;
//
// Sync event buf access by acquiring EventSpinLock
//
KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql);
//
// Check of there is an outstanding request to satisfy
//
if (DeviceExtension->EventsRequestIrp)
{
//
// Acquire the cancel spinlock, remove the request from the
// cancellable state, and free the cancel spinlock.
//
IoAcquireCancelSpinLock (&cancelIrql);
irp = DeviceExtension->EventsRequestIrp;
IoSetCancelRoutine (irp, NULL);
DeviceExtension->EventsRequestIrp = NULL;
IoReleaseCancelSpinLock (cancelIrql);
//
// Copy as much of the input data possible from the input data
// queue to the SystemBuffer to satisfy the read.
//
ioBuffer = irp->AssociatedIrp.SystemBuffer;
bytesToMove = *((ULONG *) ioBuffer);
moveSize = (bytesInQueue < bytesToMove) ? bytesInQueue : bytesToMove;
RtlMoveMemory (
ioBuffer + sizeof(ULONG),
(PCHAR) StatusBuffer,
moveSize
);
//
// Set the flag so that we start the next packet and complete
// this read request (with STATUS_SUCCESS) prior to return.
//
*((ULONG *) ioBuffer) = moveSize;
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = sizeof(ULONG) + moveSize;
satisfiedPendingEventsRequest = TRUE;
}
//
// If there is still data in the input data queue, move it
// to the event data queue
//
StatusBuffer = ((PCHAR) StatusBuffer) + moveSize;
moveSize = bytesInQueue - moveSize;
if (moveSize > 0)
{
//
// Move the remaining data from the status data queue to the
// event data queue. The move will happen in two parts in
// the case where the event data buffer wraps.
//
bytesInQueue = DeviceExtension->EventDataQueueLength -
DeviceExtension->BytesInQueue;
bytesToMove = moveSize;
if (bytesInQueue == 0)
{
//
// Refuse to move any bytes that would cause an event data
// queue overflow. Just drop the bytes on the floor, and
// log an overrun error.
//
DBGOUT((1,"WriteRingBuffer: event queue overflow"));
}
else
{
//
// There is room in the event data queue, so move the
// remaining status data to it.
//
// bytesToMove <- MIN(Number of unused bytes in event data queue,
// Number of bytes remaining in status buffer)
//
// This is the total number of bytes that actually will move from
// the status data buffer to the event data queue.
//
bytesToMove = (bytesInQueue < bytesToMove) ?
bytesInQueue : bytesToMove;
//
// bytesInQueue <- Number of unused bytes from insertion pointer
// to the end of the event data queue (i.e., until the buffer
// wraps)
//
bytesInQueue =
((PCHAR) DeviceExtension->EventDataQueue +
DeviceExtension->EventDataQueueLength) -
(PCHAR) DeviceExtension->DataIn;
//
// moveSize <- Number of bytes to handle in the first move.
//
moveSize = (bytesToMove < bytesInQueue) ?
bytesToMove : bytesInQueue;
//
// Do the move from the status data buffer to the event data queue
//
RtlMoveMemory(
(PCHAR) DeviceExtension->DataIn,
(PCHAR) StatusBuffer,
moveSize
);
//
// Increment the event data queue pointer and the status data
// buffer insertion pointer. Wrap the insertion pointer,
// if necessary.
//
StatusBuffer = ((PCHAR) StatusBuffer) + moveSize;
DeviceExtension->DataIn =
((PCHAR) DeviceExtension->DataIn) + moveSize;
if ((PCHAR) DeviceExtension->DataIn >=
((PCHAR) DeviceExtension->EventDataQueue +
DeviceExtension->EventDataQueueLength))
{
DeviceExtension->DataIn =
DeviceExtension->EventDataQueue;
}
if ((bytesToMove - moveSize) > 0)
{
//
// Special case. The data must wrap in the event data
// buffer. Copy the rest of the status data into the
// beginning of the event data queue.
//
//
// moveSize <- Number of bytes to handle in the second move.
//
moveSize = bytesToMove - moveSize;
//
// Do the move from the status data buffer to the event data
// queue
//
RtlMoveMemory(
(PCHAR) DeviceExtension->DataIn,
(PCHAR) StatusBuffer,
moveSize
);
//
// Update the event data queue insertion pointer
//
DeviceExtension->DataIn =
((PCHAR) DeviceExtension->DataIn) + moveSize;
}
//
// Update the event data queue counter
//
DeviceExtension->BytesInQueue += bytesToMove;
}
}
//
// Release the spinlock
//
KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql);
//
// If we satisfied an outstanding get events request then complete it
//
if (satisfiedPendingEventsRequest)
{
IoCompleteRequest (irp, IO_NO_INCREMENT);
DBGOUT((2, "WriteRingBuffer: completing req x%x", irp));
}
DBGOUT((2,"WriteRingBuffer: exit"));
return;
}