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.
 
 
 
 
 
 

1346 lines
29 KiB

/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
Ndiswan.c
Abstract:
This is the initialization file for the NdisWan driver. This driver
is a shim between the protocols, where it conforms to the NDIS 3.1
Miniport interface spec, and the WAN Miniport drivers, where it exports
the WAN Extensions for Miniports (it looks like a protocol to the WAN
Miniport drivers).
Author:
Tony Bell (TonyBe) June 06, 1995
Environment:
Kernel Mode
Revision History:
TonyBe 06/06/95 Created
--*/
//
// We want to initialize all of the global variables now!
//
#include "wan.h"
EXPORT
VOID
NdisTapiRegisterProvider(
IN NDIS_HANDLE DriverHandle,
IN PVOID RequestProc
);
//
// Globals
//
NDISWANCB NdisWanCB; // Global control block for NdisWan
WAN_GLOBAL_LIST ThresholdEventQueue; // Global thresholdevent queue
WAN_GLOBAL_LIST RecvPacketQueue; // Global receive packet queue
WAN_GLOBAL_LIST FreeBundleCBList; // List of free BundleCB's
WAN_GLOBAL_LIST AdapterCBList; // List of NdisWan AdapterCB's
WAN_GLOBAL_LIST WanAdapterCBList; // List of WAN Miniport structures
WAN_GLOBAL_LIST GlobalRecvDescPool; // Global pool of free recvdesc's
PCONNECTION_TABLE ConnectionTable = NULL; // Pointer to connection table
PPPP_PROTOCOL_TABLE PPP_ProtocolTable = NULL; // Pointer to the PPP/Protocol lookup table
NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
#ifdef NT
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Name:
DriverEntry
Routine Description:
This is the NT OS specific driver entry point. It kicks off initialization
for the driver. We return from this routine only after NdisWan has installed
itself as: a Miniport driver, a "transport" to the WAN Miniport drivers, and
has been bound to the WAN Miniport drivers.
Arguments:
DriverObject - NT OS specific Object
RegistryPath - NT OS specific pointer to registry location for NdisWan
Return Values:
STATUS_SUCCESS
STATUS_FAILURE
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan");
NDIS_STRING Name = NDIS_STRING_CONST("\\Device\\NdisWan");
ULONG i;
NdisZeroMemory(&NdisWanCB, sizeof(NdisWanCB));
NdisWanCB.ulTraceLevel = DBG_CRITICAL_ERROR;
NdisWanCB.ulTraceMask = DBG_ALL;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Enter"));
//
// Initialize as a Miniport MAC driver first
//
NdisMInitializeWrapper(&(NdisWanCB.hNdisWrapperHandle),
DriverObject,
RegistryPath,
NULL);
//
// Initialize globals
//
NdisAllocateSpinLock(&NdisWanCB.Lock);
NdisWanCB.pDriverObject = DriverObject;
NdisZeroMemory(&AdapterCBList, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&(AdapterCBList.List));
NdisAllocateSpinLock(&AdapterCBList.Lock);
NdisZeroMemory(&WanAdapterCBList, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&(WanAdapterCBList.List));
NdisAllocateSpinLock(&WanAdapterCBList.Lock);
NdisZeroMemory(&ThresholdEventQueue, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&(ThresholdEventQueue.List));
NdisAllocateSpinLock(&ThresholdEventQueue.Lock);
NdisZeroMemory(&RecvPacketQueue, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&(RecvPacketQueue.List));
NdisAllocateSpinLock(&RecvPacketQueue.Lock);
NdisZeroMemory(&FreeBundleCBList, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&(FreeBundleCBList.List));
NdisAllocateSpinLock(&FreeBundleCBList.Lock);
NdisZeroMemory(&GlobalRecvDescPool, sizeof(WAN_GLOBAL_LIST));
InitializeListHead(&GlobalRecvDescPool.List);
NdisAllocateSpinLock(&GlobalRecvDescPool.Lock);
Status = NdisWanCreatePPPProtocolTable();
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("NdisWanInitProtocolLookupTable Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
goto DriverEntryError;
}
//
// Initialize as a Miniport driver to the transports
//
Status = DoMiniportInit();
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("DoMiniportInit Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
goto DriverEntryError;
}
//
// Now initialzie as a "Protocol" to the WAN Miniport drivers
//
Status = DoProtocolInit(RegistryPath);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("DoProtocolInit Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
goto DriverEntryError;
}
NdisWanReadRegistry(RegistryPath);
//
// Bind NdisWan to the WAN Miniport drivers
//
Status = DoWanMiniportInit();
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("DoWanMiniportInit Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
goto DriverEntryError;
}
//
// Code commented out for PNP. We may go through DriverEntry and not have
// any miniports bound to us yet. We will get called to bind to a WanMiniport
// at a later time by the ProtocolBindHandler call (?).
//
/*
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
if (WanAdapterCBList.ulCount == 0) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("No WanAdapters installed!"));
NdisReleaseSpinLock(&WanAdapterCBList.Lock);
goto DriverEntryError;
}
NdisReleaseSpinLock(&WanAdapterCBList.Lock);
*/
//
// Allocate and initialize the ConnectionTable
//
Status = NdisWanCreateConnectionTable(NdisWanCB.ulNumberOfLinks + 10);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("NdisWanInitConnectionTable Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
goto DriverEntryError;
}
//
// Initialize the Ioctl interface
//
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
NdisWanCB.MajorFunction[i] = (PVOID)DriverObject->MajorFunction[i];
DriverObject->MajorFunction[i] = NdisWanIrpStub;
}
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisWanIoctl;
IoCreateDevice(DriverObject,
sizeof(LIST_ENTRY),
&Name,
FILE_DEVICE_NDISWAN,
0,
FALSE,
(PDEVICE_OBJECT*)&NdisWanCB.pDeviceObject);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("IoCreateSymbolicLink: %ls -> %ls",
SymbolicName.Buffer, Name.Buffer));
((PDEVICE_OBJECT)NdisWanCB.pDeviceObject)->Flags |= DO_BUFFERED_IO;
IoCreateSymbolicLink(&SymbolicName,
&Name);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit"));
return (STATUS_SUCCESS);
//
// An error occured so we need to cleanup things
//
DriverEntryError:
NdisWanGlobalCleanup();
// NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
// NdisWanCB.pDriverObject);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit Error!"));
return (STATUS_UNSUCCESSFUL);
}
VOID
NdisWanReadRegistry(
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Name:
NdisWanReadRegistry
Routine Description:
This routine will read the registry values for NdisWan. These values only
need to be read once for all adapters as their information is global.
Arguments:
WrapperConfigurationContext - Handle to registry key where NdisWan information
is stored.
Return Values:
None
--*/
{
NDIS_STATUS Status;
PWSTR ParameterKey = L"NdisWan\\Parameters";
PWSTR BindKeyWord = L"Bind";
PWSTR ProtocolKeyWord = L"ProtocolType";
PWSTR PPPKeyWord = L"PPPProtocolType";
PWSTR FragmentSizeKeyWord = L"MinimumFragmentSize";
PWSTR DebugLevelKeyWord = L"DebugLevel";
PWSTR DebugIDKeyWord = L"DebugIdentifier";
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
ULONG GenericULong;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Enter"));
//
// Read the Bind Parameter MULTI_SZ
//
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = BindQueryRoutine;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = BindKeyWord;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'Bind' Status: 0x%x",
Status));
//
// Read the ProtocolType parameter MULTI_SZ
//
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = ProtocolKeyWord;
QueryTable[0].EntryContext = (PVOID)PROTOCOL_TYPE;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'ProtocolType' Status: 0x%x",
Status));
//
// Read the PPPProtocolType parameter MULTI_SZ
//
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = PPPKeyWord;
QueryTable[0].EntryContext = (PVOID)PPP_TYPE;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'PPPProtocolType' Status: 0x%x",
Status));
//
// Read the MinFragmentSize parameter DWORD
//
NdisWanCB.ulMinFragmentSize = 100;
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = FragmentSizeKeyWord;
QueryTable[0].EntryContext = (PVOID)&GenericULong;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'MinimumFragmentSize' Status: 0x%x",
Status));
if (Status == NDIS_STATUS_SUCCESS) {
NdisWanCB.ulMinFragmentSize = GenericULong;
}
//
// Read the DebugLevel parameter DWORD
//
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = DebugLevelKeyWord;
QueryTable[0].EntryContext = (PVOID)&GenericULong;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'DebugLevel' Status: 0x%x",
Status));
if (Status == NDIS_STATUS_SUCCESS) {
NdisWanCB.ulTraceLevel = GenericULong;
}
//
// Read the DebugIdentifier parameter DWORD
//
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = NULL;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = DebugIDKeyWord;
QueryTable[0].EntryContext = (PVOID)&GenericULong;
QueryTable[0].DefaultType = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
ParameterKey,
&QueryTable[0],
NULL,
NULL);
NdisWanDbgOut(DBG_INFO, DBG_INIT,
("RtlQueryRegistry - 'DebugID' Status: 0x%x",
Status));
if (Status == NDIS_STATUS_SUCCESS) {
NdisWanCB.ulTraceMask = GenericULong;
}
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Exit"));
}
NTSTATUS
BindQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("MiniportName %ls", ValueData));
//
// Create the WanAdapterCB
//
Status = NdisWanCreateWanAdapterCB(ValueData);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
("NdisWanCreateWanAdapterCB Failed! Status: 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
}
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Exit Status: 0x%x", Status));
return (Status);
}
NTSTATUS
ProtocolTypeQueryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
NDIS_STRING String;
ULONG Value;
NTSTATUS Status = STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Enter"));
//
// Convert to an NDIS_STRING
//
NdisWanStringToNdisString(&String, ValueData);
//
// Convert to an integer
//
NdisWanNdisStringToInteger(&String, &Value);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolID 0x%x", Value));
NdisWanFreeNdisString(&String);
//
// Place in table
//
InsertPPP_ProtocolID(Value, (ULONG)EntryContext);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Exit"));
return (Status);
}
#endif // NT specific code
NDIS_STATUS
DoMiniportInit(
VOID
)
/*++
Routine Name:
DoMiniportInit
Routine Description:
This routines registers NdisWan as a Miniport driver with the NDIS wrapper.
The wrapper will now call NdisWanInitialize once for each adapter instance
of NdisWan that is in the registry.
Arguments:
None
Return Values:
NDIS_STATUS_SUCCESS
NDIS_STATUS_BAD_VERSION
NDIS_STATUS_FAILURE
--*/
{
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_MINIPORT_CHARACTERISTICS MiniportChars;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Enter"));
NdisZeroMemory(&MiniportChars, sizeof(MiniportChars));
MiniportChars.MajorNdisVersion = 3;
MiniportChars.MinorNdisVersion = 0;
MiniportChars.HaltHandler = NdisWanHalt;
MiniportChars.InitializeHandler = NdisWanInitialize;
MiniportChars.QueryInformationHandler = NdisWanQueryInformation;
MiniportChars.ReconfigureHandler = NdisWanReconfigure;
MiniportChars.ResetHandler = NdisWanReset;
MiniportChars.SendHandler = NdisWanSend;
MiniportChars.SetInformationHandler = NdisWanSetInformation;
MiniportChars.TransferDataHandler = NdisWanTransferData;
//
// Since we don't have any hardware to worry about we will
// not handle any of the interrupt stuff!
//
MiniportChars.DisableInterruptHandler = NULL;
MiniportChars.EnableInterruptHandler = NULL;
MiniportChars.HandleInterruptHandler = NULL;
MiniportChars.ISRHandler = NULL;
//
// We will disable the check for hang timeout so we do not
// need a check for hang handler!
//
// MiniportChars.CheckForHangHandler = NdisWanCheckForHang;
MiniportChars.CheckForHangHandler = NULL;
Status = NdisMRegisterMiniport(NdisWanCB.hNdisWrapperHandle,
&MiniportChars,
sizeof(MiniportChars));
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Exit"));
return (Status);
}
NDIS_STATUS
DoProtocolInit(
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Name:
DoProtocolInit
Routine Description:
This function registers NdisWan as a protocol with the NDIS wrapper.
Arguments:
None
Return Values:
NDIS_STATUS_BAD_CHARACTERISTICS
NDIS_STATUS_BAD_VERSION
NDIS_STATUS_RESOURCES
NDIS_STATUS_SUCCESS
--*/
{
//
// The name of the "transport" side of NdisWan
//
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars;
NDIS_STATUS Status;
NDIS_STRING NdisWanName = NDIS_STRING_CONST("\\Device\\NdisWan");
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Enter"));
NdisZeroMemory(&ProtocolChars, sizeof(ProtocolChars));
ProtocolChars.Name.Length = NdisWanName.Length;
ProtocolChars.Name.Buffer = (PVOID)NdisWanName.Buffer;
ProtocolChars.MajorNdisVersion = 3;
ProtocolChars.MinorNdisVersion = 0;
ProtocolChars.CloseAdapterCompleteHandler = NdisWanCloseAdapterComplete;
ProtocolChars.StatusHandler = NdisWanIndicateStatus;
ProtocolChars.StatusCompleteHandler = NdisWanIndicateStatusComplete;
ProtocolChars.OpenAdapterCompleteHandler = NdisWanOpenAdapterComplete;
ProtocolChars.RequestCompleteHandler = NdisWanRequestComplete;
ProtocolChars.ResetCompleteHandler = NdisWanResetComplete;
ProtocolChars.WanSendCompleteHandler = NdisWanSendCompleteHandler;
ProtocolChars.TransferDataCompleteHandler = NdisWanTransferDataComplete;
ProtocolChars.WanReceiveHandler = NdisWanReceiveIndication;
ProtocolChars.ReceiveCompleteHandler = NdisWanReceiveComplete;
NdisRegisterProtocol(&Status,
&NdisWanCB.hProtocolHandle,
(PNDIS_PROTOCOL_CHARACTERISTICS)&ProtocolChars,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Exit"));
return (Status);
}
NDIS_STATUS
DoWanMiniportInit(
VOID
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
PWAN_ADAPTERCB pWanAdapterCB;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NDIS_MEDIUM WanMediumSubType;
NDIS_WAN_INFO WanInfo;
NDIS_REQUEST NdisRequest;
//
// For each WAN Miniport that we have a WANAdapterCB for we will
// open the WAN Miniport thus binding to it. We will also query
// each WAN Miniport adapter to get information about it.
//
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Enter"));
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
for (pWanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCBList.List.Flink;
(PVOID)pWanAdapterCB != (PVOID)&(WanAdapterCBList.List);
pWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Flink) {
NdisReleaseSpinLock(&WanAdapterCBList.Lock);
Status = NdisWanOpenWanAdapter(pWanAdapterCB);
if (Status != NDIS_STATUS_SUCCESS) {
PWAN_ADAPTERCB pPrevWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Blink;
RemoveEntryList(&pWanAdapterCB->Linkage);
WanAdapterCBList.ulCount--;
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("Failed to bind to %ls! Error 0x%x - %s",
pWanAdapterCB->MiniportName.Buffer, Status, NdisWanGetNdisStatus(Status)));
NdisWanDestroyWanAdapterCB(pWanAdapterCB);
pWanAdapterCB = pPrevWanAdapterCB;
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
continue;
}
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("Successful Binding to %ls!",
pWanAdapterCB->MiniportName.Buffer));
//
// Get the medium subtype. We don't use this info right now but
// maybe someday...
//
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_MEDIUM_SUBTYPE;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMediumSubType;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanMediumSubType);
Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_MEDIUM_SUBTYPE! Error 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
continue;
}
pWanAdapterCB->MediumSubType = WanMediumSubType;
//
// Get more information about the WAN Miniport that we are bound to!
//
NdisZeroMemory(&WanInfo, sizeof(WanInfo));
NdisRequest.RequestType = NdisRequestQueryInformation;
NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_INFO;
NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanInfo;
NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanInfo);
Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
&NdisRequest,
SYNC,
NDISWAN);
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_GET_INFO! Error 0x%x - %s",
Status, NdisWanGetNdisStatus(Status)));
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
continue;
}
NdisMoveMemory(&pWanAdapterCB->WanInfo, &WanInfo, sizeof(NDIS_WAN_INFO));
NdisWanCB.ulNumberOfLinks += pWanAdapterCB->WanInfo.Endpoints;
NdisAcquireSpinLock(&FreeBundleCBList.Lock);
FreeBundleCBList.ulMaxCount = NdisWanCB.ulNumberOfLinks;
NdisReleaseSpinLock(&FreeBundleCBList.Lock);
if (pWanAdapterCB->WanInfo.FramingBits & TAPI_PROVIDER) {
//
// Tell tapi about this device
//
NdisTapiRegisterProvider(pWanAdapterCB, NdisWanTapiRequestProc);
}
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
}
//
// The following lines are commented out to take into account pnp.
// We may not have any miniports to bind to initially but get called
// to bind to them later!
//
// if (WanAdapterCBList.ulCount == 0)
// Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
// else
Status = NDIS_STATUS_SUCCESS;
NdisReleaseSpinLock(&WanAdapterCBList.Lock);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Exit"));
return (Status);
}
VOID
InsertPPP_ProtocolID(
IN ULONG Value,
IN ULONG ValueType
)
/*++
Routine Name:
InsertPPP_ProtocolID
Routine Description:
This routine takes a protocol value or a PPP protocol value and inserts it
into the appropriate lookup table.
Arguments:
Value - Either a ProtocolID or PPP ProtocolID
ValueType - Either PROTOCOL_TYPE or PPP_TYPE
Return Values:
--*/
{
ULONG i;
ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
PUSHORT ValueArray;
//
// Figure out which array we should be looking at for
// this value type
//
if (ValueType == PROTOCOL_TYPE) {
ValueArray = PPP_ProtocolTable->ProtocolID;
} else {
ValueArray = PPP_ProtocolTable->PPPProtocolID;
}
NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
//
// First check to see if this value is already in the array
//
for (i = 0; i < ArraySize; i++) {
if (ValueArray[i] == (USHORT)Value) {
//
// If it is then we just update the value
//
ValueArray[i] = (USHORT)Value;
break;
}
}
//
// We did not find the value in the array so
// we will add it at the 1st available spot
//
if (i >= ArraySize) {
for (i = 0; i < ArraySize; i++) {
//
// We are looking for an empty slot to add
// the new value to
//
if (ValueArray[i] == 0) {
ValueArray[i] = (USHORT)Value;
if (ValueType == PROTOCOL_TYPE) {
NdisWanCB.ulNumberOfProtocols++;
}
break;
}
}
}
NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
}
USHORT
GetPPP_ProtocolID(
IN USHORT Value,
IN ULONG ValueType
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG i;
ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
PUSHORT ValueArray, ReturnValueArray;
USHORT ReturnValue = INVALID_PROTOCOL;
//
// Figure out which array we should be looking at for
// this value type
//
if (ValueType == PROTOCOL_TYPE) {
ValueArray = PPP_ProtocolTable->ProtocolID;
ReturnValueArray = PPP_ProtocolTable->PPPProtocolID;
} else {
ValueArray = PPP_ProtocolTable->PPPProtocolID;
ReturnValueArray = PPP_ProtocolTable->ProtocolID;
}
NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
for (i = 0; i < ArraySize; i++) {
if (ValueArray[i] == Value) {
ReturnValue = ReturnValueArray[i];
break;
}
}
NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
return (ReturnValue);
}
NDIS_HANDLE
InsertLinkInConnectionTable(
IN PLINKCB LinkCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG Index;
PLINKCB *LinkArray = ConnectionTable->LinkArray;
NdisAcquireSpinLock(&ConnectionTable->Lock);
//
// We are doing a linear search for an empty spot in
// the link array
//
for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
if (LinkArray[Index] == NULL) {
LinkArray[Index] = LinkCB;
ConnectionTable->ulNumActiveLinks++;
LinkCB->hLinkHandle = (NDIS_HANDLE)Index;
break;
}
}
ASSERT(Index < ConnectionTable->ulArraySize);
NdisReleaseSpinLock(&ConnectionTable->Lock);
return ((NDIS_HANDLE)Index);
}
VOID
RemoveLinkFromConnectionTable(
IN PLINKCB LinkCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG Index = (ULONG)LinkCB->hLinkHandle;
PLINKCB *LinkArray = ConnectionTable->LinkArray;
NdisAcquireSpinLock(&ConnectionTable->Lock);
if (LinkArray[Index] != NULL) {
ASSERT(LinkCB == LinkArray[Index]);
LinkArray[Index] = NULL;
ConnectionTable->ulNumActiveLinks--;
} else {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("LinkCB not in connection table! LinkCB: 0x%8.8x", LinkCB));
ASSERT(0);
}
NdisReleaseSpinLock(&ConnectionTable->Lock);
}
NDIS_HANDLE
InsertBundleInConnectionTable(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG Index;
PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
NdisAcquireSpinLock(&ConnectionTable->Lock);
//
// We are doing a linear search for an empty spot in
// the link array
//
for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
if (BundleArray[Index] == NULL) {
BundleArray[Index] = BundleCB;
ConnectionTable->ulNumActiveBundles++;
BundleCB->hBundleHandle = (NDIS_HANDLE)Index;
break;
}
}
InsertTailList(&ConnectionTable->BundleList, &BundleCB->Linkage);
ASSERT(Index != ConnectionTable->ulArraySize);
NdisReleaseSpinLock(&ConnectionTable->Lock);
return ((NDIS_HANDLE)Index);
}
VOID
RemoveBundleFromConnectionTable(
IN PBUNDLECB BundleCB
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
ULONG Index = (ULONG)BundleCB->hBundleHandle;
PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
NdisAcquireSpinLock(&ConnectionTable->Lock);
if (BundleArray[Index] != NULL) {
ASSERT(BundleCB == BundleArray[Index]);
RemoveEntryList(&BundleCB->Linkage);
BundleArray[Index] = NULL;
ConnectionTable->ulNumActiveBundles--;
} else {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("BundleCB not in connection table! BundleCB: 0x%8.8x", BundleCB));
ASSERT(0);
}
NdisReleaseSpinLock(&ConnectionTable->Lock);
}
VOID
NdisWanGlobalCleanup(
VOID
)
/*++
Routine Name:
NdisWanGlobalCleanup
Routine Description:
This routine is responsible for cleaning up all allocated resources.
Arguments:
None
Return Values:
None
--*/
{
//
// Stop all timers
//
//
// Complete all outstanding requests
//
//
// Free all of the AdapterCB's
//
NdisAcquireSpinLock(&AdapterCBList.Lock);
while (!IsListEmpty(&AdapterCBList.List)) {
PADAPTERCB AdapterCB;
AdapterCB = (PADAPTERCB)RemoveHeadList(&AdapterCBList.List);
NdisWanFreeMemory(AdapterCB);
}
NdisReleaseSpinLock(&AdapterCBList.Lock);
//
// Free all of the WanAdapterCB's
//
NdisAcquireSpinLock(&WanAdapterCBList.Lock);
while (!IsListEmpty(&WanAdapterCBList.List)) {
PWAN_ADAPTERCB WanAdapterCB;
WanAdapterCB = (PWAN_ADAPTERCB)RemoveHeadList(&WanAdapterCBList.List);
NdisWanFreeMemory(WanAdapterCB);
}
NdisReleaseSpinLock(&WanAdapterCBList.Lock);
//
// Free all of the BundleCB's
//
//
// Free all of the LinkCB's
//
//
// Free globals
//
if (ConnectionTable != NULL) {
NdisWanFreeMemory(ConnectionTable);
}
if (PPP_ProtocolTable != NULL) {
NdisWanFreeMemory(PPP_ProtocolTable);
}
//
// Terminate the wrapper
//
NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
NdisWanCB.pDriverObject);
}
BOOLEAN
IsHandleValid(
USHORT usHandleType,
NDIS_HANDLE hHandle
)
/*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/
{
BOOLEAN RetValue = FALSE;
PVOID Cb;
if (usHandleType == LINKHANDLE) {
LINKCB_FROM_LINKH((PLINKCB)Cb, hHandle);
} else if (usHandleType == BUNDLEHANDLE) {
BUNDLECB_FROM_BUNDLEH((PBUNDLECB)Cb, hHandle);
}
if (Cb != NULL) {
RetValue = TRUE;
}
return (RetValue);
}
#if DBG // Debug
PUCHAR
NdisWanGetNdisStatus(
NDIS_STATUS GeneralStatus
)
/*++
Routine Name:
NdisWanGetNdisStatus
Routine Description:
This routine returns a pointer to the string describing the NDIS error
denoted by GeneralStatus
Arguments:
GeneralStatus - The NDIS status you wish to make readable
Return Values:
Returns a pointer to a string describing GeneralStatus
--*/
{
static NDIS_STATUS Status[] = {
NDIS_STATUS_SUCCESS,
NDIS_STATUS_PENDING,
NDIS_STATUS_ADAPTER_NOT_FOUND,
NDIS_STATUS_ADAPTER_NOT_OPEN,
NDIS_STATUS_ADAPTER_NOT_READY,
NDIS_STATUS_ADAPTER_REMOVED,
NDIS_STATUS_BAD_CHARACTERISTICS,
NDIS_STATUS_BAD_VERSION,
NDIS_STATUS_CLOSING,
NDIS_STATUS_DEVICE_FAILED,
NDIS_STATUS_FAILURE,
NDIS_STATUS_INVALID_DATA,
NDIS_STATUS_INVALID_LENGTH,
NDIS_STATUS_INVALID_OID,
NDIS_STATUS_INVALID_PACKET,
NDIS_STATUS_MULTICAST_FULL,
NDIS_STATUS_NOT_INDICATING,
NDIS_STATUS_NOT_RECOGNIZED,
NDIS_STATUS_NOT_RESETTABLE,
NDIS_STATUS_NOT_SUPPORTED,
NDIS_STATUS_OPEN_FAILED,
NDIS_STATUS_OPEN_LIST_FULL,
NDIS_STATUS_REQUEST_ABORTED,
NDIS_STATUS_RESET_IN_PROGRESS,
NDIS_STATUS_RESOURCES,
NDIS_STATUS_UNSUPPORTED_MEDIA
};
static PUCHAR String[] = {
"SUCCESS",
"PENDING",
"ADAPTER_NOT_FOUND",
"ADAPTER_NOT_OPEN",
"ADAPTER_NOT_READY",
"ADAPTER_REMOVED",
"BAD_CHARACTERISTICS",
"BAD_VERSION",
"CLOSING",
"DEVICE_FAILED",
"FAILURE",
"INVALID_DATA",
"INVALID_LENGTH",
"INVALID_OID",
"INVALID_PACKET",
"MULTICAST_FULL",
"NOT_INDICATING",
"NOT_RECOGNIZED",
"NOT_RESETTABLE",
"NOT_SUPPORTED",
"OPEN_FAILED",
"OPEN_LIST_FULL",
"REQUEST_ABORTED",
"RESET_IN_PROGRESS",
"RESOURCES",
"UNSUPPORTED_MEDIA"
};
static UCHAR BadStatus[] = "UNDEFINED";
#define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS))
INT i;
for (i=0; i<StatusCount; i++)
if (GeneralStatus == Status[i])
return String[i];
return BadStatus;
#undef StatusCount
}
#endif // End Debug