diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/ndistapi | |
download | NT4.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 '')
-rw-r--r-- | private/ntos/ndis/ndistapi/intrface.h | 138 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/makefile | 7 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/ndistapi.c | 2873 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/ndistapi.rc | 38 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/ndistapi.src | 7 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/private.h | 251 | ||||
-rw-r--r-- | private/ntos/ndis/ndistapi/sources | 40 |
7 files changed, 3354 insertions, 0 deletions
diff --git a/private/ntos/ndis/ndistapi/intrface.h b/private/ntos/ndis/ndistapi/intrface.h new file mode 100644 index 000000000..6babe2fb5 --- /dev/null +++ b/private/ntos/ndis/ndistapi/intrface.h @@ -0,0 +1,138 @@ +/*++ BUILD Version: 0000 // Increment this if a change has global effects + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + intrface.h + +Abstract: + + Definition for user-mode/kernel-mode tapi/connection wrapper interface. + +Author: + + Dan Knudson (DanKn) 20-Feb-1994 + +Revision History: + +--*/ + + + +#define NDISTAPIERR_UNINITIALIZED 0x00001001 +#define NDISTAPIERR_BADDEVICEID 0x00001002 +#define NDISTAPIERR_DEVICEOFFLINE 0x00001003 + + + +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// + +#define FILE_DEVICE_NDISTAPI 0x00008fff + + + +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// + +#define NDISTAPI_IOCTL_INDEX 0x8f0 + + + +// +// The NDISTAPI device driver IOCTLs +// + +#define IOCTL_NDISTAPI_CONNECT CTL_CODE(FILE_DEVICE_NDISTAPI, \ + NDISTAPI_IOCTL_INDEX, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_NDISTAPI_DISCONNECT CTL_CODE(FILE_DEVICE_NDISTAPI, \ + NDISTAPI_IOCTL_INDEX + 1, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_NDISTAPI_QUERY_INFO CTL_CODE(FILE_DEVICE_NDISTAPI, \ + NDISTAPI_IOCTL_INDEX + 2, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_NDISTAPI_SET_INFO CTL_CODE(FILE_DEVICE_NDISTAPI, \ + NDISTAPI_IOCTL_INDEX + 3, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_NDISTAPI_GET_LINE_EVENTS CTL_CODE(FILE_DEVICE_NDISTAPI, \ + NDISTAPI_IOCTL_INDEX + 4, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + + +// +// Type definitions +// + +typedef struct _NDISTAPI_REQUEST +{ + // + // Return value + // + + OUT ULONG ulReturnValue; + + // + // Operation idenfifier + // + + IN ULONG Oid; + + // + // Target line device ID + // + + IN ULONG ulDeviceID; + + // + // Total size of request data in buffer + // + + IN ULONG ulDataSize; + + // + // Buffer for request data + // + + IN OUT UCHAR Data[1]; + +} NDISTAPI_REQUEST, *PNDISTAPI_REQUEST; + + +typedef struct _NDISTAPI_EVENT_DATA +{ + // + // Total size of the event data buffer + // + + IN ULONG ulTotalSize; + + // + // Size of the returned event data + // + + OUT ULONG ulUsedSize; + + // + // Event data buffer + // + + OUT UCHAR Data[1]; + +} NDISTAPI_EVENT_DATA, *PNDISTAPI_EVENT_DATA; diff --git a/private/ntos/ndis/ndistapi/makefile b/private/ntos/ndis/ndistapi/makefile new file mode 100644 index 000000000..58189757d --- /dev/null +++ b/private/ntos/ndis/ndistapi/makefile @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/ndis/ndistapi/ndistapi.c b/private/ntos/ndis/ndistapi/ndistapi.c new file mode 100644 index 000000000..ea37cd6b3 --- /dev/null +++ b/private/ntos/ndis/ndistapi/ndistapi.c @@ -0,0 +1,2873 @@ +/*++ BUILD Version: 0000 // Increment this if a change has global effects + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + ndistapi.c + +Abstract: + + This module contains the NdisTapi.sys implementation + +Author: + + Dan Knudson (DanKn) 20-Feb-1994 + +Notes: + + (Future/outstanding issues) + + - stuff marked with "PnP" needs to be rev'd for plug 'n play support + +Revision History: + +--*/ + + + +#include "ntos.h" +#include "ndis.h" +#include "stdarg.h" +#include "stdio.h" +#include "ntddndis.h" +#include "ndistapi.h" +#include "private.h" +#include "intrface.h" + + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ); + +VOID +NdisTapiCancel( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +NdisTapiCleanup( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +NdisTapiDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +VOID +NdisTapiUnload( + IN PDRIVER_OBJECT DriverObject + ); + + +#if DBG +VOID +DbgPrt( + IN ULONG DbgLevel, + IN PUCHAR DbgMessage, + IN ... + ); +#endif + +VOID +DoProviderInitComplete( + PPROVIDER_REQUEST ProviderRequest + ); + +ULONG +GetLineEvents( + PVOID EventBuffer, + ULONG BufferSize + ); + +VOID +GetRegistryParameters( + IN PUNICODE_STRING RegistryPath +); + +BOOLEAN +SyncInitAllProviders( + void + ); + +NDIS_STATUS +SendProviderInitRequest( + PPROVIDER_INFO Provider + ); + +NDIS_STATUS +SendProviderShutdown( + PPROVIDER_INFO Provider + ); + + +// +// Use the alloc_text pragma to specify the driver initialization routines +// (they can be paged out). +// + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,DriverEntry) +#pragma alloc_text(INIT,GetRegistryParameters) +#endif + + +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 + +--*/ + +{ + + PDEVICE_OBJECT deviceObject = NULL; + NTSTATUS ntStatus; + WCHAR deviceNameBuffer[] = L"\\Device\\NdisTapi"; + UNICODE_STRING deviceNameUnicodeString; + UNICODE_STRING registryPath; + + + DBGOUT ((2, "DriverEntry: enter")); + + + // + // Create a NON-EXCLUSIVE device, i.e. multiple threads at a time + // can send i/o requests. + // + + RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer); + + ntStatus = IoCreateDevice( + DriverObject, + sizeof (DEVICE_EXTENSION), + &deviceNameUnicodeString, + FILE_DEVICE_NDISTAPI, + 0, + FALSE, + &deviceObject + ); + + + if (NT_SUCCESS(ntStatus)) + { + // + // Init the global & sero the extension + // + + DeviceExtension = + (PDEVICE_EXTENSION) deviceObject->DeviceExtension; + + RtlZeroMemory( + DeviceExtension, + sizeof (DEVICE_EXTENSION) + ); + + + // + // Create a NULL-terminated registry path & retrieve the registry + // params (EventDataQueueLength) + // + + registryPath.Buffer = ExAllocatePoolWithTag( + PagedPool, + RegistryPath->Length + sizeof(UNICODE_NULL), + 'TAPI' + ); + + if (!registryPath.Buffer) + { + DBGOUT((1, "DriverEntry: ExAllocPool for szRegistryPath failed")); + + ntStatus = STATUS_UNSUCCESSFUL; + + goto DriverEntry_err; + } + else + { + registryPath.Length = RegistryPath->Length; + registryPath.MaximumLength = + registryPath.Length + sizeof(UNICODE_NULL); + + RtlZeroMemory( + registryPath.Buffer, + registryPath.MaximumLength + ); + + RtlMoveMemory( + registryPath.Buffer, + RegistryPath->Buffer, + RegistryPath->Length + ); + } + + GetRegistryParameters (®istryPath); + + ExFreePool (registryPath.Buffer); + + + // + // Init event data buf, state vars, spin lock, device queue, & event + // + + DeviceExtension->EventData = + DeviceExtension->DataIn = + DeviceExtension->DataOut = ExAllocatePoolWithTag( + NonPagedPool, + DeviceExtension->EventDataQueueLength, + 'TAPI' + ); + + if (!DeviceExtension->DataOut) + { + DBGOUT((1, "DriverEntry: ExAllocPool for event data buf failed")); + + ntStatus = STATUS_UNSUCCESSFUL; + + goto DriverEntry_err; + } + + DeviceExtension->DeviceObject = deviceObject; + DeviceExtension->Status = NDISTAPI_STATUS_DISCONNECTED; + DeviceExtension->NdisTapiNumDevices = 0; + DeviceExtension->htCall = 0x80000000; + + KeInitializeSpinLock (&DeviceExtension->SpinLock); + KeInitializeSpinLock (&DeviceExtension->EventSpinLock); + + KeInitializeDeviceQueue (&DeviceExtension->DeviceQueue); + + KeInitializeEvent( + &DeviceExtension->SyncEvent, + SynchronizationEvent, + FALSE + ); + + + // + // Create dispatch points for device control, create, close. + // + + DriverObject->MajorFunction[IRP_MJ_CREATE] = + DriverObject->MajorFunction[IRP_MJ_CLOSE] = + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisTapiDispatch; + DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisTapiCleanup; + DriverObject->DriverUnload = NdisTapiUnload; + } + + + if (!NT_SUCCESS(ntStatus)) + { + +DriverEntry_err: + + // + // Something went wrong, so clean up + // + + DBGOUT((0, "init failed")); + + if (deviceObject) + { + if (DeviceExtension->EventData) + { + ExFreePool (DeviceExtension->EventData); + } + + IoDeleteDevice (deviceObject); + } + } + + + DBGOUT ((2, "DriverEntry: exit")); + + return ntStatus; +} + + + +VOID +NdisTapiCancel( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +{ + KIRQL oldIrql; +// KIRQL cancelIrql; + + + DBGOUT((2,"NdisTapiCancel: 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); + + goto NdisTapiCancel_done; + } + + KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql); + + + // + // Acquire the SpinLock & try to remove request from our special + // user-mode requests dev queue + // + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + if (TRUE != KeRemoveEntryDeviceQueue( + &DeviceExtension->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry + )) + { + // + // If we couldn't find the Irp in the device queue then it's + // "unknown", i.e. perhaps it was completed before we got here, + // so set it to NULL + // + + Irp = NULL; + + DBGOUT((1,"NdisTapiCancel: Irp 0x%x not in device queue?!?\n", Irp)); + } + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + +NdisTapiCancel_done: + + if (Irp) + { + // + // Complete the request with STATUS_CANCELLED. + // + + Irp->IoStatus.Status = STATUS_CANCELLED; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + DBGOUT((2,"NdisTapiCancel: completing irp=x%x", Irp)); + } + else + { + DBGOUT((2,"NdisTapiCancel: irp=x%x not found, not completing!", Irp)); + } + + DBGOUT((2,"NdisTapiCancel: exit")); + + return; +} + + + +NTSTATUS +NdisTapiCleanup( + 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 irp; + KIRQL oldIrql; + KIRQL cancelIrql; + BOOLEAN completeRequest; + PNDISTAPI_REQUEST ndisTapiRequest; + PKDEVICE_QUEUE_ENTRY packet; + + + DBGOUT((2,"NdisTapiCleanup: enter")); + + + // + // If this cleanup originated from the NCPA then don't bother + // completing stuff (we don't want to possibly hose tapisrv & by + // canceling it's requests) + // + + if (DeviceExtension->NCPAFileObject && + (Irp->Tail.Overlay.OriginalFileObject == + DeviceExtension->NCPAFileObject)) + { + goto NdisTapiCleanup_CompleteRequest; + } + + + // + // Sync access to EventsRequestIrp by acquiring EventSpinLock + // + + KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql); + + + // + // Check to see if there's a get-events request pending that needs + // completing + // + + completeRequest = FALSE; + + 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); + + irp->IoStatus.Status = STATUS_CANCELLED; + irp->IoStatus.Information = 0; + + completeRequest = TRUE; + } + + KeReleaseSpinLock (&DeviceExtension->EventSpinLock, oldIrql); + + if (completeRequest) + { + IoCompleteRequest (irp, IO_NO_INCREMENT); + + DBGOUT((2,"NdisTapiCleanup: completing GET_EVENTS request x%x", irp)); + } + + + // + // Sync access to our request device queue by acquiring SpinLock + // + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + + // + // Cancel all outstanding QUERY/SET_INFO requests + // + + if (DeviceExtension->DeviceQueue.Busy == TRUE) + { + IoAcquireCancelSpinLock (&cancelIrql); + + while ((packet = KeRemoveDeviceQueue (&DeviceExtension->DeviceQueue)) + != NULL) + { + irp = CONTAINING_RECORD( + packet, + IRP, + Tail.Overlay.DeviceQueueEntry + ); + + // + // Remove the IRP from the cancelable state + // + + IoSetCancelRoutine (irp, NULL); + IoReleaseCancelSpinLock (cancelIrql); + + + // + // Release the SpinLock since IoCompleteRequest() must be + // called at <= DISPATCH_LEVEL + // + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + + // + // Set the status & info size values appropriately, & complete + // the request + // + + ndisTapiRequest = irp->AssociatedIrp.SystemBuffer; + ndisTapiRequest->ulReturnValue = (ULONG) NDIS_STATUS_FAILURE; + + irp->IoStatus.Status = STATUS_CANCELLED; + irp->IoStatus.Information = 0; + + IoCompleteRequest (irp, IO_NO_INCREMENT); + + DBGOUT((2,"NdisTapiCleanup: completing QRY/SET request x%x", irp)); + + + // + // Reacquire the SpinLock protecting the device queue + // & the cancel spinlock + // + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + IoAcquireCancelSpinLock (&cancelIrql); + } + + IoReleaseCancelSpinLock (cancelIrql); + } + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + + + // + // Complete the cleanup request with STATUS_SUCCESS. + // + +NdisTapiCleanup_CompleteRequest: + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + + DBGOUT((2,"NdisTapiCleanup: exit\n")); + + return(STATUS_SUCCESS); +} + + + + +NTSTATUS +NdisTapiDispatch( + 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: + + +--*/ + +{ + KIRQL oldIrql; + PVOID ioBuffer; + ULONG inputBufferLength; + ULONG outputBufferLength; + ULONG ioControlCode; + NTSTATUS ntStatus; + 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, Irp=x%x", Irp)); + + break; + + case IRP_MJ_CLOSE: + + DBGOUT ((2, "IRP_MJ_CLOSE, Irp=x%x", Irp)); + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + if (DeviceExtension->NCPAFileObject && + DeviceExtension->TapiSrvFileObject) + { + // + // Both TapiSrv & NCPA are currently running, so we + // don't want to shutdown the providers/chg state because + // one is closing + // + } + else if ((Irp->Tail.Overlay.OriginalFileObject == + DeviceExtension->NCPAFileObject) || + + (Irp->Tail.Overlay.OriginalFileObject == + DeviceExtension->TapiSrvFileObject)) + { + // + // Either the NCPA or TapiSrv (but no both) was running, + // but is now shutting down, so send shutdown msg to providers + // & chg state + // + + if (DeviceExtension->Status == NDISTAPI_STATUS_CONNECTED) + { + PPROVIDER_INFO provider; + + + // + // State change + // + + DeviceExtension->Status = + NDISTAPI_STATUS_DISCONNECTING; + + + // + // Send the providers a shutdown request + // + + provider = DeviceExtension->Providers; + + while (provider != NULL) + { + switch (provider->Status) + { + case PROVIDER_STATUS_ONLINE: + case PROVIDER_STATUS_PENDING_INIT: + + // + // Reset provider status + // + + provider->Status = PROVIDER_STATUS_PENDING_INIT; + + SendProviderShutdown (provider); + + break; + + case PROVIDER_STATUS_OFFLINE: + + // + // If provider is currently offline just remove it + // since it's not wanting to talk to us right now + // + + // PnP provider = DoRemoveProvider (provider); + + break; + + } + + provider = provider->Next; + } + + + // + // State change + // + + DeviceExtension->Status = NDISTAPI_STATUS_DISCONNECTED; + } + } + + + // + // Zero the DeviceExtension->XxxFileObject as appropriate + // (Note that we actually get two close requests from each + // client, since the each open both a sync & an async driver + // handle) + // + + if (Irp->Tail.Overlay.OriginalFileObject == + DeviceExtension->NCPAFileObject) + { + DeviceExtension->NCPAFileObject = NULL; + } + else if (Irp->Tail.Overlay.OriginalFileObject == + DeviceExtension->TapiSrvFileObject) + { + DeviceExtension->TapiSrvFileObject = NULL; + } + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + break; + + case IRP_MJ_DEVICE_CONTROL: + + ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; + + switch (ioControlCode) + { + case IOCTL_NDISTAPI_CONNECT: + { + DBGOUT ((2, "IOCTL_NDISTAPI_CONNECT, Irp=x%x", Irp)); + + + // + // Someone's connecting. Make sure they passed us a valid + // info buffer + // + + if ((inputBufferLength < 2*sizeof(ULONG)) || + (outputBufferLength < sizeof(ULONG)) + ) + { + DBGOUT ((3, "IOCTL_NDISTAPI_CONNECT: buffer too small")); + + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + + break; + } + + + if (DeviceExtension->Status == NDISTAPI_STATUS_DISCONNECTED) + { + DeviceExtension->Status = NDISTAPI_STATUS_CONNECTING; + + + // + // Reset the async event buf count & pointers + // + + DeviceExtension->EventCount = 0; + DeviceExtension->DataIn = + DeviceExtension->DataOut = DeviceExtension->EventData; + + + // + // Synchronously init all providers + // + + SyncInitAllProviders(); + } + + + // + // Check to see if this is the NCPA + // + + if (*(((ULONG *) ioBuffer) + 1) == 0) + { + DeviceExtension->NCPAFileObject = + Irp->Tail.Overlay.OriginalFileObject; + } + else + { + DeviceExtension->TapiSrvFileObject = + Irp->Tail.Overlay.OriginalFileObject; + } + + + // + // Return the number of line devs + // + + *((ULONG *) ioBuffer)= + DeviceExtension->NdisTapiNumDevices; + + DeviceExtension->Status = NDISTAPI_STATUS_CONNECTED; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(ULONG); + + break; + } + + case IOCTL_NDISTAPI_QUERY_INFO: + case IOCTL_NDISTAPI_SET_INFO: + { + ULONG targetDeviceID; + NDIS_STATUS ndisStatus; + NDIS_HANDLE providerHandle = NULL; + REQUEST_PROC requestProc; + PPROVIDER_INFO provider; + PNDISTAPI_REQUEST ndisTapiRequest; + PPROVIDER_REQUEST providerRequest; + KIRQL oldIrql; + KIRQL cancelIrql; + + + DBGOUT ((2, "IOCTL_NDISTAPI_QUERY/SET_INFO, Irp=x%x", Irp)); + + + // + // Verify we're connected, then check the device ID of the + // incoming request against our list of online devices + // + + ndisTapiRequest = ioBuffer; + + targetDeviceID = ndisTapiRequest->ulDeviceID; + + DBGOUT(( + 3, + "\tOid=0x%x, retVal=0x%x, devID=%d, dataSize=%d, reqID=%d, parm1=0x%x", + ndisTapiRequest->Oid, + ndisTapiRequest->ulReturnValue, + ndisTapiRequest->ulDeviceID, + ndisTapiRequest->ulDataSize, + *((ULONG *)ndisTapiRequest->Data), + *(((ULONG *)ndisTapiRequest->Data) + 1) + )); + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + if (DeviceExtension->Status != NDISTAPI_STATUS_CONNECTED) + { + DBGOUT((3, "\tunconnected, returning err")); + + ndisTapiRequest->ulReturnValue = NDISTAPIERR_UNINITIALIZED; + } + + else if ((targetDeviceID < + DeviceExtension->NdisTapiDeviceIDBase) || + (targetDeviceID >= + DeviceExtension->NdisTapiDeviceIDBase + + DeviceExtension->NdisTapiNumDevices)) + { + DBGOUT((3, "\tdev ID out of range, returning err")); + + ndisTapiRequest->ulReturnValue = NDISTAPIERR_BADDEVICEID; + } + + else + { + provider = DeviceExtension->Providers; + + while (provider != NULL) + { + if ((provider->Status == PROVIDER_STATUS_ONLINE) && + (targetDeviceID >= provider->DeviceIDBase) && + (targetDeviceID < + provider->DeviceIDBase + provider->NumDevices) + ) + { + providerHandle = provider->ProviderHandle; + requestProc = provider->RequestProc; + + break; + } + + provider = provider->Next; + } + + if (provider == NULL) + { + DBGOUT((3, "dev offline, returning err")); + + ndisTapiRequest->ulReturnValue = NDISTAPIERR_DEVICEOFFLINE; + } + } + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + if (providerHandle == NULL) + { + // + // Set Irp->IoStatus.Information large enough that err code + // gets copied back to user buffer + // + + Irp->IoStatus.Information = sizeof(ULONG); + + break; + } + + + // + // Create the providerRequest & submit it + // + + providerRequest = ExAllocatePoolWithTag( + NonPagedPoolCacheAligned, + sizeof(PROVIDER_REQUEST) + ndisTapiRequest->ulDataSize - + sizeof(ULONG), // to acct for ULONG in PROVIDER_REQUEST + 'TAPI' + ); + + if (!providerRequest) + { + DBGOUT((1, "NdisTapiDispatch: unable to alloc request buf")); + + Irp->IoStatus.Information = sizeof (ULONG); + + ndisTapiRequest->ulReturnValue = (ULONG) NDIS_STATUS_RESOURCES; + + break; + } + + providerRequest->NdisRequest.RequestType = + (ioControlCode == IOCTL_NDISTAPI_QUERY_INFO ? + NdisRequestQueryInformation : NdisRequestSetInformation); + + providerRequest->NdisRequest.DATA.SET_INFORMATION.Oid = + ndisTapiRequest->Oid; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBuffer = + providerRequest->Data; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = + ndisTapiRequest->ulDataSize; + + providerRequest->Provider = provider; + + RtlMoveMemory( + providerRequest->Data, + ndisTapiRequest->Data, + ndisTapiRequest->ulDataSize + ); + + + // + // Queue up this TAPI request in our special device queue + // prior to submitting the provider request. + // + + KeRaiseIrql (DISPATCH_LEVEL, &oldIrql); + + if (!KeInsertByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry, + *((ULONG *) ndisTapiRequest->Data) // sort key = req ID + )) + { + // + // If here the queue was not busy, but KeInsertXxx marked + // it busy, so try again. We want to toss this in the + // queue regardless- it's just going to sit there until + // the corresponding provider request is completed, or the + // TAPI request is canceled. + // + + KeInsertByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + &Irp->Tail.Overlay.DeviceQueueEntry, + *((ULONG *) ndisTapiRequest->Data) // sort key = req ID + ); + } + + KeLowerIrql (oldIrql); + + + // + // Mark the TAPI request pending + // + + Irp->IoStatus.Status = STATUS_PENDING; + + + // + // Set the cancel routine for the TAPI request + // + + IoAcquireCancelSpinLock (&cancelIrql); + IoSetCancelRoutine (Irp, NdisTapiCancel); + IoReleaseCancelSpinLock (cancelIrql); + + + // + // Call the provider's request proc + // + + ndisStatus = (*requestProc)( + providerHandle, + (PNDIS_REQUEST) providerRequest + ); + + + // + // If PENDING was returned then just exit & let the completion + // routine handle the request completion + // + // NOTE: If pending was returned then the request may have + // already been completed, so DO NOT touch anything + // in the Irp (don't reference the pointer, etc.) + // + + if (ndisStatus == NDIS_STATUS_PENDING) + { + return STATUS_PENDING; + } + else + { + DBGOUT(( + 1, + "IOCTL_TAPI_SET/QUERY_INFO: reqProc return !pending" + )); + + // + // The provider request completed synchronously, so remove + // the TAPI request from the device queue. We need to + // synchronize access to this queue with the + // SpinLock since the NdisTapiCompleteRequest + // func might have removed this request temporarily. + // + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + KeRemoveByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + *((ULONG *) ndisTapiRequest->Data) // sort key = req ID + ); + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + + // + // Mark request as successfully completed + // + + Irp->IoStatus.Status = STATUS_SUCCESS; + + + // + // If this was a succesful QUERY_INFO request copy all the + // data back to the tapi request buf & set + // Irp->IoStatus.Information appropriately. Otherwise, we + // just need to pass back the return value. + // + + if ((ioControlCode == IOCTL_NDISTAPI_QUERY_INFO) && + (ndisStatus == NDIS_STATUS_SUCCESS)) + { + RtlMoveMemory( + ndisTapiRequest->Data, + providerRequest->Data, + ndisTapiRequest->ulDataSize + ); + + Irp->IoStatus.Information = + irpStack->Parameters.DeviceIoControl.OutputBufferLength; + } + else + { + Irp->IoStatus.Information = sizeof (ULONG); + } + + ndisTapiRequest->ulReturnValue = ndisStatus; + + + // + // Free the providerRequest + // + + ExFreePool (providerRequest); + } + + break; + } + + case IOCTL_NDISTAPI_GET_LINE_EVENTS: + { + KIRQL oldIrql; + KIRQL cancelIrql; + BOOLEAN satisfiedRequest = FALSE; + + + DBGOUT ((2, "IOCTL_NDISTAPI_GET_LINE_EVENTS, Irp=x%x", Irp)); + + + // + // Sync event buf access by acquiring EventSpinLock + // + + KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql); + + + // + // Inspect DeviceExtension to see if there's any data available + // + + if (DeviceExtension->EventCount != 0) + { + // + // There's line event data queued in our ring buffer. Grab as + // much as we can & complete the request. + // + + PNDISTAPI_EVENT_DATA ndisTapiEventData = ioBuffer; + + + ndisTapiEventData->ulUsedSize = GetLineEvents( + ndisTapiEventData->Data, + ndisTapiEventData->ulTotalSize + ); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = ndisTapiEventData->ulUsedSize + + sizeof(NDISTAPI_EVENT_DATA) - 1; + + 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, NdisTapiCancel); + 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; + + } // switch + + break; + } + + + // + // DON'T try to use the status field of the irp in the return + // status. That IRP IS GONE as soon as you call IoCompleteRequest. + // + + if ((ntStatus = Irp->IoStatus.Status) != STATUS_PENDING) + { + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + DBGOUT((3, "NdisTapiDispatch: completed Irp=x%x", Irp)); + } + else + { + DBGOUT((3, "NdisTapiDispatch: pending Irp=x%x", Irp)); + } + + return ntStatus; +} + + + + +VOID +NdisTapiUnload( + IN PDRIVER_OBJECT DriverObject + ) + +/*++ + +Routine Description: + + Free all the allocated resources, etc. + +Arguments: + + DriverObject - pointer to a driver object + +Return Value: + + +--*/ + +{ + PPROVIDER_INFO provider, nextProvider; + + + DBGOUT ((2, "NdisTapiUnload: enter")); + + + // + // Delete the device object & sundry resources + // + + ExFreePool (DeviceExtension->EventData); + + provider = DeviceExtension->Providers, nextProvider; + + while (provider != NULL) + { + nextProvider = provider->Next; + + ExFreePool (provider); + + provider = nextProvider; + } + + IoDeleteDevice (DriverObject->DeviceObject); + + DBGOUT ((2, "NdisTapiUnload: exit")); + + return; +} + + + +VOID +NdisTapiRegisterProvider( + IN NDIS_HANDLE ProviderHandle, + IN REQUEST_PROC RequestProc + ) + +/*++ + +Routine Description: + + This func gets called by Ndis as a result of a Mac driver + registering for Connection Wrapper services. + +Arguments: + + + +Return Value: + + +--*/ + +{ +// KIRQL oldIrql; + BOOLEAN sendRequest = FALSE; + NDIS_STATUS ndisStatus; + PPROVIDER_INFO provider, newProvider; + + + DBGOUT ((2, "NdisTapiRegisterProvider: enter")); + + + // + // Create a new provider instance + // + + newProvider = ExAllocatePoolWithTag( + NonPagedPoolCacheAligned, + sizeof(PROVIDER_INFO), + 'TAPI' + ); + + newProvider->Status = PROVIDER_STATUS_PENDING_INIT; + newProvider->ProviderHandle = ProviderHandle; + newProvider->RequestProc = RequestProc; + newProvider->Next = NULL; + + + + // + // Grab the spin lock & add the new provider, and see whether to + // send the provider an init request + // + +// KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + if ((provider = DeviceExtension->Providers) == NULL) + { + DeviceExtension->Providers = newProvider; + } + else + { + while (provider->Next != NULL) + { + provider = provider->Next; + } + + provider->Next = newProvider; + } + + // + // The only case where we want to send off an init request to the + // provider directly is when we are currently connected to TAPI, + // and even then only when there are no other inits pending (since + // we must synchronize inits due to calculation of DeviceIDBase) + // + + if ((DeviceExtension->Status == NDISTAPI_STATUS_CONNECTED) && + (DeviceExtension->ProviderInitPending == FALSE) + ) + { + ndisStatus = SendProviderInitRequest (newProvider); + + if (ndisStatus == NDIS_STATUS_PENDING) + { + DeviceExtension->ProviderInitPending == TRUE; + } + } + +// KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + // Pnp: we should keep track of the current # of providers + // registered, so that we can bump up NdisTapiNumDevices + // appropriately + + return; +} + + + +VOID +NdisTapiDeregisterProvider( + IN NDIS_HANDLE ProviderHandle + ) + +/*++ + +Routine Description: + + This func... + + Note that this func does not send the provider a shutdown message, + as an implicit shutdown is assumed when the provider deegisters. + +Arguments: + + + +Return Value: + + +--*/ + +{ +// KIRQL oldIrql; + BOOLEAN sendShutdownMsg = FALSE; + PPROVIDER_INFO provider, previousProvider; + + + DBGOUT ((2, "NdisTapiDeregisterProvider: enter")); + + + // + // Grab the spin lock protecting the device extension + // + +// KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + + + // + // Find the provider instance corresponding to ProviderHandle + // + + provider = DeviceExtension->Providers; + + if (provider == NULL) + { + goto NdisTapiDeregisterProvider_err; + } + + while (provider->ProviderHandle != ProviderHandle) + { + previousProvider = provider; + + provider = provider->Next; + + if (provider == NULL) + { + goto NdisTapiDeregisterProvider_err; + } + } + + + // + // Do the right thing according to the current NdisTapi state + // + + switch (DeviceExtension->Status) + { + case NDISTAPI_STATUS_CONNECTED: + + // + // Mark provider as offline + // + + provider->Status = PROVIDER_STATUS_OFFLINE; + + + // PnP: what if providerInfo->State == PROVIDER_INIT_PENDING + // PnP: what if providerInfo->State == PROVIDER_OFFLINE + + break; + + case NDISTAPI_STATUS_DISCONNECTING: + case NDISTAPI_STATUS_DISCONNECTED: + + // + // Fix up pointers, remove provider from list + // + + if (provider == DeviceExtension->Providers) + { + DeviceExtension->Providers = provider->Next; + } + else + { + previousProvider->Next = provider->Next; + } + + ExFreePool (provider); + + break; + + case NDISTAPI_STATUS_CONNECTING: + + // PnP: implement + + break; + + } // switch + + goto NdisTapiDeregisterProvider_ReleaseSpinLock; + + +NdisTapiDeregisterProvider_err: + + DBGOUT((0, "NdisTapiDeregisterProvider: bad provider handle")); + + +NdisTapiDeregisterProvider_ReleaseSpinLock: + +// KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + DBGOUT((2, "NdisTapiDeregisterProvider: exit")); + + return; +} + + + +VOID +NdisTapiIndicateStatus( + IN ULONG DriverHandle, + 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; + PNDIS_TAPI_EVENT ndisTapiEvent; + PNDISTAPI_EVENT_DATA ndisTapiEventData; + + + DBGOUT((2,"NdisTapiIndicateStatus: enter")); + + + bytesInQueue = StatusBufferSize; + + moveSize = 0; + + + // + // Sync event buf access by acquiring EventSpinLock + // + + KeAcquireSpinLock (&DeviceExtension->EventSpinLock, &oldIrql); + + + // + // The very first thing to do is check if this is a LINE_NEWCALL + // indication. If so, we need to generate a unique tapi call + // handle, which will be both returned to the calling miniport + // (for use in subsequent status indications) and passed up to + // the tapi server. Note that valid htCall values as generated by + // this driver range between 0x80000000 and 0xfffffffe (the + // user-mode tapi server reserves the range 0x1-0x7fffffff). + // + + ndisTapiEvent = StatusBuffer; + + if (ndisTapiEvent->ulMsg == LINE_NEWCALL) + { + ndisTapiEvent->ulParam2 = DeviceExtension->htCall; + + DeviceExtension->htCall++; + + if (DeviceExtension->htCall > 0xfffffffe) + { + DeviceExtension->htCall = 0x80000000; + } + } + + + // + // 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. + // + + ndisTapiEventData = irp->AssociatedIrp.SystemBuffer; + + bytesToMove = ndisTapiEventData->ulTotalSize; + + moveSize = (bytesInQueue < bytesToMove) ? bytesInQueue : bytesToMove; + + RtlMoveMemory ( + ndisTapiEventData->Data, + (PCHAR) StatusBuffer, + moveSize + ); + + + // + // Set the flag so that we start the next packet and complete + // this read request (with STATUS_SUCCESS) prior to return. + // + + ndisTapiEventData->ulUsedSize = moveSize; + + irp->IoStatus.Status = STATUS_SUCCESS; + + irp->IoStatus.Information = sizeof(NDISTAPI_EVENT_DATA) + moveSize - 1; + + 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->EventCount * sizeof(NDIS_TAPI_EVENT)); + + 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,"NdisTapiIndicateStatus: 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->EventData + + 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->EventData + + DeviceExtension->EventDataQueueLength)) + { + DeviceExtension->DataIn = DeviceExtension->EventData; + } + + 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->EventCount += + (bytesToMove / sizeof(NDIS_TAPI_EVENT)); + } + } + + + // + // 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, "NdisTapiIndicateStatus: completion req 0x%x", irp)); + } + + + DBGOUT((2,"NdisTapiIndicateStatus: exit")); + + return; +} + + + +VOID +NdisTapiCompleteRequest( + IN NDIS_HANDLE NdisHandle, + IN PNDIS_REQUEST NdisRequest, + IN NDIS_STATUS NdisStatus + ) + +/*++ + +Routine Description: + + This func gets called by Ndis as a result of a Mac driver + calling NdisCompleteRequest of one of our requests. + +Arguments: + + + +Return Value: + + +--*/ + +{ + PIRP irp; + KIRQL oldIrql; + KIRQL cancelIrql; + ULONG requestID; +// PPROVIDER_INFO provider; + PNDISTAPI_REQUEST ndisTapiRequest; + PPROVIDER_REQUEST providerRequest = (PPROVIDER_REQUEST) NdisRequest; + PIO_STACK_LOCATION irpStack; + PKDEVICE_QUEUE_ENTRY packet; + + + DBGOUT ((2, "NdisTapiCompleteRequest: enter")); + + + requestID = providerRequest->Data[0]; + + + // + // Determine the type of request + // + + if (requestID == 0) + { + // + // This request originated from NdisTapi.sys + // + + switch (providerRequest->NdisRequest.DATA.SET_INFORMATION.Oid) + { + case OID_TAPI_PROVIDER_INITIALIZE: + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + switch (DeviceExtension->Status) + { + case NDISTAPI_STATUS_CONNECTED: + + // PnP: what if NdisStatus != NDIS_STATUS_SUCCESS? + + DoProviderInitComplete (providerRequest); + + if (SyncInitAllProviders() == TRUE) + { + DeviceExtension->ProviderInitPending = FALSE; + } + + break; + + case NDISTAPI_STATUS_DISCONNECTED: + + break; + + case NDISTAPI_STATUS_CONNECTING: + + // PnP: what if NdisStatus != NDIS_STATUS_SUCCESS? + + // + // Mark provider as online, etc. + // + + DoProviderInitComplete (providerRequest); + + + // + // Set the event which sync's miniport inits + // + + KeSetEvent( + &DeviceExtension->SyncEvent, + 0, + FALSE + ); + + break; + + case NDISTAPI_STATUS_DISCONNECTING: + + break; + + } // switch + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + break; + + case OID_TAPI_PROVIDER_SHUTDOWN: + + break; + + default: + + DBGOUT((1, "NdisTapiCompleteRequest: unrecognized Oid")); + + break; + } + } + else + { + // + // This is a request originating from TAPI + // + + // + // Acquire the SpinLock since we're going to be removing a + // TAPI request from the queue, and it might not be the request + // we're looking for. The primary concern is that we could (if + // the request we're really looking for has been removed) remove + // a synchrously-completed request that is about to be removed & + // completed in NdisTapiDispatch, in which case we want to stick + // the request back in the queue before NdisTapiDispatch tries + // to remove it. + // + + KeAcquireSpinLock (&DeviceExtension->SpinLock, &oldIrql); + + + + // + // Grab the cancel spin lock & get the IRP out of our queue. + // + + IoAcquireCancelSpinLock (&cancelIrql); + + packet = KeRemoveByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + requestID + ); + + if (packet != NULL) + { + // + // Get the ptrs + // + + irp = CONTAINING_RECORD( + packet, + IRP, + Tail.Overlay.DeviceQueueEntry + ); + + ndisTapiRequest = irp->AssociatedIrp.SystemBuffer; + + + // + // Verify the IRP we got back was the one we wanted to remove + // + + if (requestID == *((ULONG *)ndisTapiRequest->Data)) + { + // + // Remove the IRP from the cancelable state + // + + IoSetCancelRoutine (irp, NULL); + IoReleaseCancelSpinLock (cancelIrql); + + + // + // Release the SpinLock + // + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + + + // + // Copy the relevant info back to the IRP + // + + irpStack = IoGetCurrentIrpStackLocation (irp); + + + // + // If this was a succesful QUERY_INFO request copy all the + // data back to the tapi request buf & set + // Irp->IoStatus.Information appropriately. Otherwise, we + // just need to pass back the return value. Also mark irp + // as successfully completed (regardless of actual op result) + // + + if ((NdisRequest->RequestType == NdisRequestQueryInformation)&& + (NdisStatus == 0)) + { + RtlMoveMemory( + ndisTapiRequest->Data, + NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer, + ndisTapiRequest->ulDataSize + ); + + irp->IoStatus.Information = + irpStack->Parameters.DeviceIoControl.OutputBufferLength; + } + else + { + irp->IoStatus.Information = sizeof (ULONG); + } + + irp->IoStatus.Status = STATUS_SUCCESS; + + ndisTapiRequest->ulReturnValue = NdisStatus; + + + // + // Finally, complete the TAPI request + // + + DBGOUT ((3, "completing request 0x%lx", requestID)); + + IoCompleteRequest (irp, IO_NO_INCREMENT); + } + else + { + DBGOUT ((1, "Wrong IRP removed from queue- requeueing")); + + + // + // We got the wrong IRP out, the one we wanted probably + // has been canceled. Stick this IRP back in the queue. + // + + if (!KeInsertByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + &irp->Tail.Overlay.DeviceQueueEntry, + *((ULONG *) ndisTapiRequest->Data) // sortkey=reqID + )) + { + // + // If here the queue was not busy, but KeInsertXxx marked + // it busy, so try again. We want to toss this in the + // queue regardless- it's just going to sit there until + // the corresponding provider request is completed, or the + // TAPI request is canceled. + // + + KeInsertByKeyDeviceQueue( + &DeviceExtension->DeviceQueue, + &irp->Tail.Overlay.DeviceQueueEntry, + *((ULONG *) ndisTapiRequest->Data) // sortkey=reqID + ); + } + + + // + // Release the cancel spin lock + // + + IoReleaseCancelSpinLock (cancelIrql); + + + // + // Release the SpinLock. + // + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + } + } + else + { + // + // No packets in the queue, release the cancel spin lock + // + + IoReleaseCancelSpinLock (cancelIrql); + + + // + // Release the SpinLock. + // + + KeReleaseSpinLock (&DeviceExtension->SpinLock, oldIrql); + } + } + + ExFreePool (NdisRequest); + + DBGOUT ((2, "NdisTapiCompleteRequest: exit")); + + return; +} + + +#if 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 <= NdisTapiDebugLevel) + { + char buf[256] = "NDISTAPI.SYS: "; + va_list ap; + + va_start (ap, DbgMessage); + + vsprintf (&buf[14], DbgMessage, ap); + + strcat (buf, "\n"); + + DbgPrint (buf); + + va_end(ap); + } + + return; +} +#endif // DBG + + +VOID +DoProviderInitComplete( + PPROVIDER_REQUEST ProviderRequest + ) + +/*++ + +Routine Description: + + + +Arguments: + + ProviderInitRequest - pointer successfully completed init request + +Return Value: + + + +Note: + + Assumes DeviceExtension->SpinLock held by caller. + +--*/ + +{ + PPROVIDER_INFO provider = ProviderRequest->Provider; + PNDIS_TAPI_PROVIDER_INITIALIZE providerInitData = + (PNDIS_TAPI_PROVIDER_INITIALIZE) ProviderRequest->Data; + + + DBGOUT ((2, "DoProviderInitComplete: enter")); + + + // + // Wrap this in an exception handler in case the provider was + // removed during an async completion + // + + try + { + provider->Status = PROVIDER_STATUS_ONLINE; + provider->ProviderID = providerInitData->ulProviderID; + provider->NumDevices = providerInitData->ulNumLineDevs; + + DBGOUT(( + 3, + "providerID = 0x%lx, numDevices = 0x%lx", + provider->ProviderID, + provider->NumDevices + )); + } + except (EXCEPTION_EXECUTE_HANDLER) + { + DBGOUT((1, "DoProviderInitComplete: provider invalid")); + } + + // + // PnP: Check to see if this is a provider that registered & + // deregistered earlier (look at ProviderID's). + // + + DBGOUT ((2, "DoProviderInitComplete: exit")); +} + + +ULONG +GetLineEvents( + PCHAR EventBuffer, + ULONG BufferSize + ) + +/*++ + +Routine Description: + + + +Arguments: + + + +Return Value: + + + +Note: + + Assumes DeviceExtension->EventSpinLock held by caller. + +--*/ + +{ + ULONG bytesInQueue; + ULONG bytesToMove; + ULONG moveSize; + + + bytesInQueue = DeviceExtension->EventCount * sizeof(NDIS_TAPI_EVENT); + + bytesToMove = BufferSize; + + 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->EventData + + 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->EventData, + moveSize + ); + + // + // Update the class input data queue removal pointer. + // + + DeviceExtension->DataOut = + ((PCHAR) DeviceExtension->EventData) + moveSize; + } + else + { + // + // Update the input data queue removal pointer. + // + + DeviceExtension->DataOut = + ((PCHAR) DeviceExtension->DataOut) + moveSize; + } + + + // + // Update the event data queue EventCount. + // + + DeviceExtension->EventCount -= + (bytesToMove / sizeof(NDIS_TAPI_EVENT)); + + return bytesToMove; +} + + +VOID +GetRegistryParameters( + IN PUNICODE_STRING RegistryPath +) + +/*++ + +Routine Description: + + This routine stores the configuration information for this device. + +Arguments: + + RegistryPath - Pointer to the null-terminated Unicode name of the + registry path for this driver. + +Return Value: + + None. As a side-effect, sets DeviceExtension->EventDataQueuLength field + +--*/ + +{ + ULONG defaultDataQueueSize = 32 * sizeof(NDIS_TAPI_EVENT); + PWSTR path = NULL; + USHORT queriesPlusOne = 2; + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING parametersPath; + PRTL_QUERY_REGISTRY_TABLE parameters = NULL; + + + parametersPath.Buffer = NULL; + + + // + // Registry path is already null-terminated, so just use it. + // + + path = RegistryPath->Buffer; + + if (NT_SUCCESS(status)) + { + // + // Allocate the Rtl query table. + // + + parameters = ExAllocatePool( + PagedPool, + sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne + ); + + if (!parameters) + { + DBGOUT((1, "NdisTapiConfiguration: ExAllocPool failed")); + + status = STATUS_UNSUCCESSFUL; + } + else + { + RtlZeroMemory( + parameters, + sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne + ); + + // + // Form a path to this driver's Parameters subkey. + // + + RtlInitUnicodeString( + ¶metersPath, + NULL + ); + + parametersPath.MaximumLength = RegistryPath->Length + + sizeof(L"\\Parameters"); + + parametersPath.Buffer = ExAllocatePool( + PagedPool, + parametersPath.MaximumLength + ); + + if (!parametersPath.Buffer) + { + DBGOUT((1, "NdisTapiConfiguration: ExAllocPool failed")); + + status = STATUS_UNSUCCESSFUL; + } + } + } + + if (NT_SUCCESS(status)) + { + // + // Form the parameters path. + // + + RtlZeroMemory( + parametersPath.Buffer, + parametersPath.MaximumLength + ); + + RtlAppendUnicodeToString( + ¶metersPath, + path + ); + + RtlAppendUnicodeToString( + ¶metersPath, + L"\\Parameters" + ); + + DBGOUT(( + 1, + "NdisTapiConfiguration: parameters path is %ws\n", + parametersPath.Buffer + )); + + + // + // Gather all of the "user specified" information from + // the registry. + // + + parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + parameters[0].Name = L"AsyncEventQueueSize"; + parameters[0].EntryContext = + &DeviceExtension->EventDataQueueLength; + parameters[0].DefaultType = REG_DWORD; + parameters[0].DefaultData = &defaultDataQueueSize; + parameters[0].DefaultLength = sizeof(ULONG); + + status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + parametersPath.Buffer, + parameters, + NULL, + NULL + ); + + if (!NT_SUCCESS(status)) + { + DBGOUT(( + 1, + "NdisTapiConfiguration: RtlQueryRegistryVals failed, err=x%x", + status + )); + } + } + + if (!NT_SUCCESS(status)) + { + // + // Go ahead and assign driver defaults. + // + + DeviceExtension->EventDataQueueLength = defaultDataQueueSize; + } + + + // + // Data queue ought be a least the size of the default + // + + if (DeviceExtension->EventDataQueueLength < defaultDataQueueSize) + { + DeviceExtension->EventDataQueueLength = defaultDataQueueSize; + } + + + // + // Make sure the queue length is an integral # of (sizeof) events + // + + DeviceExtension->EventDataQueueLength -= + DeviceExtension->EventDataQueueLength % sizeof(NDIS_TAPI_EVENT); + + + // + // Dump value + // + + DBGOUT (( + 1, + "NdisTapiConfiguration: EventDataQueueLength = x%x", + DeviceExtension->EventDataQueueLength + )); + + + // + // Free the allocated memory before returning. + // + + if (parametersPath.Buffer) + { + ExFreePool(parametersPath.Buffer); + } + + if (parameters) + { + ExFreePool(parameters); + } +} + + +NDIS_STATUS +SendProviderInitRequest( + PPROVIDER_INFO Provider + ) + +/*++ + +Routine Description: + + + +Arguments: + + Provider - pointer to a PROVIDER_INFO representing provider to initialize + +Return Value: + + + +Note: + + Assumes DeviceExtension->SpinLock held by caller + +--*/ + +{ + NDIS_STATUS ndisStatus; + PPROVIDER_INFO tmpProvider; + PPROVIDER_REQUEST providerRequest; + PNDIS_TAPI_PROVIDER_INITIALIZE providerInitData; + + + DBGOUT ((2, "SendProviderInitRequest: enter")); + + + // + // Determine the DeviceIDBase to be used for this provider + // + + Provider->DeviceIDBase = DeviceExtension->NdisTapiDeviceIDBase; + + tmpProvider = DeviceExtension->Providers; + + while (tmpProvider != NULL) + { + if (tmpProvider->Status != PROVIDER_STATUS_PENDING_INIT) + { + Provider->DeviceIDBase += tmpProvider->NumDevices; + } + tmpProvider = tmpProvider->Next; + } + + + + // + // Create a provider init request + // + + providerRequest = ExAllocatePoolWithTag( + NonPagedPoolCacheAligned, + sizeof(PROVIDER_REQUEST) + sizeof(NDIS_TAPI_PROVIDER_INITIALIZE) - + sizeof(ULONG), + 'TAPI' + ); + + + providerRequest->NdisRequest.RequestType = NdisRequestQueryInformation; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.Oid = + OID_TAPI_PROVIDER_INITIALIZE; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBuffer = + providerRequest->Data; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = + sizeof(NDIS_TAPI_PROVIDER_INITIALIZE); + + + providerRequest->Provider = Provider; + + + providerInitData = + (PNDIS_TAPI_PROVIDER_INITIALIZE) providerRequest->Data; + + providerInitData->ulRequestID = 0; + providerInitData->ulDeviceIDBase = Provider->DeviceIDBase; + + + // + // Send the request + // + + ndisStatus= + (*Provider->RequestProc)( + Provider->ProviderHandle, + (PNDIS_REQUEST) providerRequest + ); + + if (ndisStatus == NDIS_STATUS_SUCCESS) + { + DoProviderInitComplete (providerRequest); + + ExFreePool (providerRequest); + } + else if (ndisStatus == NDIS_STATUS_PENDING) + { + // + // Do nothing + // + } + else + { + // PnP: an error occured, clean up & act like this never happened + } + + DBGOUT ((2, "SendProviderInitRequest: exit")); + + return ndisStatus; +} + + +NDIS_STATUS +SendProviderShutdown( + PPROVIDER_INFO Provider + ) + +/*++ + +Routine Description: + + + +Arguments: + + + +Return Value: + + A pointer to the next provider in the global providers list + +Note: + + Assumes DeviceExtension->SpinLock held by caller. + +--*/ + +{ + NDIS_STATUS ndisStatus; + PPROVIDER_REQUEST providerRequest; + + + DBGOUT ((2, "SendProviderShutdown: enter")); + + + + // + // Create a provider init request + // + + providerRequest = ExAllocatePoolWithTag( + NonPagedPoolCacheAligned, + sizeof(PROVIDER_REQUEST) + sizeof(NDIS_TAPI_PROVIDER_SHUTDOWN) - + sizeof(ULONG), + 'TAPI' + ); + + + providerRequest->NdisRequest.RequestType = NdisRequestSetInformation; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.Oid = + OID_TAPI_PROVIDER_SHUTDOWN; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBuffer = + providerRequest->Data; + + providerRequest->NdisRequest.DATA.SET_INFORMATION.InformationBufferLength = + sizeof(NDIS_TAPI_PROVIDER_SHUTDOWN); + + + providerRequest->Provider = Provider; + + providerRequest->Data[0] = 0; // request ID, 0 = driver-initiated req + + + // + // Send the request + // + + ndisStatus = (*Provider->RequestProc)( + Provider->ProviderHandle, + (PNDIS_REQUEST) providerRequest + ); + + + // + // If request was completed synchronously then free the request + // (otherwise it will get freed when the completion proc is called) + // + + if (ndisStatus != NDIS_STATUS_PENDING) + { + ExFreePool (providerRequest); + } + + + DBGOUT ((2, "SendProviderShutdown: exit")); + + return ndisStatus; +} + + +BOOLEAN +SyncInitAllProviders( + void + ) + +/*++ + +Routine Description: + + This functions walks the list of registered providers and sends + init requests to the providers in the PENDING_INIT state + +Arguments: + + (none) + +Return Value: + + TRUE if all registered providers initialized, or + FALSE if there are more providers to initialze + +Note: + + Assumes DeviceExtension->SpinLock held by caller + +--*/ + +{ + ULONG numDevices = 0; + NDIS_STATUS ndisStatus; + PPROVIDER_INFO provider = DeviceExtension->Providers; + + + DBGOUT((2, "SyncInitAllProviders: enter")); + + + while (provider != NULL) + { + if (provider->Status == PROVIDER_STATUS_PENDING_INIT) + { + ndisStatus = SendProviderInitRequest (provider); + + if (ndisStatus == NDIS_STATUS_PENDING) + { + // + // Wait for completion routine to get called + // + + KeWaitForSingleObject (&DeviceExtension->SyncEvent, + Executive, + KernelMode, + FALSE, + (PTIME) NULL + ); + } + else if (ndisStatus == NDIS_STATUS_SUCCESS) + { + provider->Status == PROVIDER_STATUS_ONLINE; + } + else + { + provider->Status == PROVIDER_STATUS_OFFLINE; + } + } + + provider = provider->Next; + } + + + // + // If here all providers (>= 1) initialized, so determine the total + // # of line devices currently in the list + // + + provider = DeviceExtension->Providers; + + while (provider != NULL) + { + numDevices += provider->NumDevices; + + provider = provider->Next; + } + + if (DeviceExtension->Status == NDISTAPI_STATUS_CONNECTING) + { + DeviceExtension->NdisTapiNumDevices = numDevices; + } + else if ((DeviceExtension->Status == NDISTAPI_STATUS_CONNECTED) && + (numDevices > DeviceExtension->NdisTapiNumDevices)) + { + // PnP: need to send TAPI a reinit msg (or LINE_CREATE?) + + DBGOUT((1, "SyncInitAllProviders: exceeded numDevs, must reinit")); + } + + + DBGOUT((2, "SyncInitAllProviders: exit")); + + return TRUE; +} diff --git a/private/ntos/ndis/ndistapi/ndistapi.rc b/private/ntos/ndis/ndistapi/ndistapi.rc new file mode 100644 index 000000000..a0f75325a --- /dev/null +++ b/private/ntos/ndis/ndistapi/ndistapi.rc @@ -0,0 +1,38 @@ +#include <windows.h> +#include <ntverp.h> + +/*-----------------------------------------------*/ +/* the following lines are specific to this file */ +/*-----------------------------------------------*/ + +/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR + * and VER_INTERNALNAME_STR must be defined before including COMMON.VER + * The strings don't need a '\0', since common.ver has them. + */ +#define VER_FILETYPE VFT_DRV +/* possible values: VFT_UNKNOWN + VFT_APP + VFT_DLL + VFT_DRV + VFT_FONT + VFT_VXD + VFT_STATIC_LIB +*/ +#define VER_FILESUBTYPE VFT2_DRV_NETWORK +/* possible values VFT2_UNKNOWN + VFT2_DRV_PRINTER + VFT2_DRV_KEYBOARD + VFT2_DRV_LANGUAGE + VFT2_DRV_DISPLAY + VFT2_DRV_MOUSE + VFT2_DRV_NETWORK + VFT2_DRV_SYSTEM + VFT2_DRV_INSTALLABLE + VFT2_DRV_SOUND + VFT2_DRV_COMM +*/ +#define VER_FILEDESCRIPTION_STR "NDIS 3.0 connection wrapper driver" +#define VER_INTERNALNAME_STR "NDISTAPI.SYS" +#define VER_ORIGINALFILENAME_STR "NDISTAPI.SYS" + +#include "common.ver" diff --git a/private/ntos/ndis/ndistapi/ndistapi.src b/private/ntos/ndis/ndistapi/ndistapi.src new file mode 100644 index 000000000..3a071870e --- /dev/null +++ b/private/ntos/ndis/ndistapi/ndistapi.src @@ -0,0 +1,7 @@ +NAME NDISTAPI.SYS +DESCRIPTION 'NDISTAPI.SYS' +EXPORTS + NdisTapiRegisterProvider + NdisTapiCompleteRequest + NdisTapiIndicateStatus + NdisTapiDeregisterProvider diff --git a/private/ntos/ndis/ndistapi/private.h b/private/ntos/ndis/ndistapi/private.h new file mode 100644 index 000000000..5129f0ac5 --- /dev/null +++ b/private/ntos/ndis/ndistapi/private.h @@ -0,0 +1,251 @@ +/*++ BUILD Version: 0000 // Increment this if a change has global effects + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + private.h + +Abstract: + + Private definitions for NdisTapi.sys + +Author: + + Dan Knudson (DanKn) 20-Feb-1994 + +Revision History: + +--*/ + + +// +// Various definitions +// + +typedef enum _PROVIDER_STATUS +{ + PROVIDER_STATUS_ONLINE, + PROVIDER_STATUS_OFFLINE, + PROVIDER_STATUS_PENDING_INIT + +} PROVIDER_STATUS, *PPROVIDER_STATUS; + + +typedef NDIS_STATUS (*REQUEST_PROC)(NDIS_HANDLE, PNDIS_REQUEST); + + +typedef struct _PROVIDER_INFO +{ + PROVIDER_STATUS Status; + + NDIS_HANDLE ProviderHandle; + + REQUEST_PROC RequestProc; + + ULONG ProviderID; + + ULONG NumDevices; + + ULONG DeviceIDBase; + + struct _PROVIDER_INFO *Next; + +} PROVIDER_INFO, *PPROVIDER_INFO; + + +typedef enum _NDISTAPI_STATUS +{ + NDISTAPI_STATUS_CONNECTED, + NDISTAPI_STATUS_DISCONNECTED, + NDISTAPI_STATUS_CONNECTING, + NDISTAPI_STATUS_DISCONNECTING + +} NDISTAPI_STATUS, *PNDISTAPI_STATUS; + + +typedef struct _DEVICE_EXTENSION +{ + // + // The following are set only in DriverEntry and are not + // modified elsewhere + // + + // + // Pointer to the NdisTapi device object + // + + PDEVICE_OBJECT DeviceObject; + + // + // Length in bytes of the event data buf + // + + ULONG EventDataQueueLength; + + // + // Pointer to a circular event data buf + // + + PCHAR EventData; + + + + // + // Synchronizes access to the device extension following fields + // + + KSPIN_LOCK SpinLock; + + // + // Whether TAPI has the the connection wrapper open + // + + NDISTAPI_STATUS Status; + + // + // Event we use for synchronizing provider inits + // + + KEVENT SyncEvent; + + // + // The connection wrapper's device ID base as passed down by TAPI + // when it connected. + // + + ULONG NdisTapiDeviceIDBase; + + // + // The number of line devices we told told TAPI we supported when + // it opened us (some of which may not actually be online at any + // given time) + // + + ULONG NdisTapiNumDevices; + + // + // Whether we have an outstanding provider init request + // + + BOOLEAN ProviderInitPending; + + // + // Pointer to a list of registered providers. (Some may actually + // not be currently registered, but they were at one point so we've + // saved a placeholder for them should they come back online at some + // point.) + // + + PPROVIDER_INFO Providers; + + // + // + // + + BOOLEAN CleanupWasInitiated; + + // + // A special queue for QUERY/SET_INFO requests + // + + KDEVICE_QUEUE DeviceQueue; + + + + // + // Synchronizes access to the events buffer & related fields + // + + KSPIN_LOCK EventSpinLock; + + // + // Value return to provider for next NEWCALL msg + // + + ULONG htCall; + + // + // Outstanding get-events request + // + + PIRP EventsRequestIrp; + + // + // Pointer to next place to PUT event data (from provider) + // + + PCHAR DataIn; + + // + // Pointer to next place to GET event data (for user-mode request) + // + + PCHAR DataOut; + + // + // Number of valid events in queue + // + + ULONG EventCount; + + + // + // + // + + PFILE_OBJECT TapiSrvFileObject; + + // + // + // + + PFILE_OBJECT NCPAFileObject; + +} DEVICE_EXTENSION, *PDEVICE_EXTENSION; + + +typedef struct _PROVIDER_REQUEST +{ + NDIS_REQUEST NdisRequest; + + PPROVIDER_INFO Provider; + + // + // This field is a placeholder for an NDIS_TAPI_XXX structure, the + // first ULONG of which is always a request ID. + // + + ULONG Data[1]; + +} PROVIDER_REQUEST, *PPROVIDER_REQUEST; + + +// +// Our global device extension +// + +PDEVICE_EXTENSION DeviceExtension; + + + +#if DBG + +// +// A var which determines the verboseness of the msgs printed by DBGOUT() +// +// + +ULONG NdisTapiDebugLevel = 0; + +// +// DbgPrint wrapper +// + +#define DBGOUT(arg) DbgPrt arg + +#else + +#define DBGOUT(arg) + +#endif diff --git a/private/ntos/ndis/ndistapi/sources b/private/ntos/ndis/ndistapi/sources new file mode 100644 index 000000000..7d876fe2c --- /dev/null +++ b/private/ntos/ndis/ndistapi/sources @@ -0,0 +1,40 @@ +!IF 0 + +Copyright (c) 1989-1993 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + John Rogers (JohnRo) 25-Oct-1991 + +NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=ndis + +TARGETNAME=ndistapi +TARGETPATH=\nt\public\sdk\lib +TARGETTYPE=EXPORT_DRIVER + +INCLUDES=..\..\inc +C_DEFINES= $(C_DEFINES) + +SOURCES=ndistapi.c \ + ndistapi.rc + +DLLDEF=obj\*\ndistapi.def + +MSC_WARNING_LEVEL=/W3 /WX |