|
|
/*++
Copyright (c) 1990-1997 Microsoft Corporation
Module Name:
Init.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/NDIS 5.0 Miniport interface specs, and the miniport drivers, where it exports the NDIS 3.1 WAN Extensions for Miniports and NDIS 5.0 Call Manager/Miniport interfaces (it looks like a NDIS 3.1 protocol to NDIS 3.1 WAN Miniport drivers and a NDIS 5.0 client to NDIS 5.0 miniports).
Author:
Tony Bell (TonyBe) January 9, 1997
Environment:
Kernel Mode
Revision History:
TonyBe 01/09/97 Created
--*/
#include "wan.h"
#define __FILE_SIG__ INIT_FILESIG
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(INIT, NdisWanReadRegistry)
#pragma alloc_text(INIT, DoProtocolInit)
#pragma alloc_text(INIT, DoMiniportInit)
#endif
EXPORT VOID NdisTapiRegisterProvider( IN NDIS_HANDLE, IN PNDISTAPI_CHARACTERISTICS );
//
// We want to initialize all of the global variables now!
//
//
// Globals
//
NDISWANCB NdisWanCB; // Global control block for NdisWan
WAN_GLOBAL_LIST MiniportCBList; // List of NdisWan MiniportCB's
WAN_GLOBAL_LIST OpenCBList; // List of WAN Miniport structures
WAN_GLOBAL_LIST ThresholdEventQueue; // Global thresholdevent queue
IO_RECV_LIST IoRecvList;
WAN_GLOBAL_LIST_EX BonDWorkList;
WAN_GLOBAL_LIST_EX DeferredWorkList;
POOLDESC_LIST PacketPoolList; // List of free packet descs/ndispackets
NPAGED_LOOKASIDE_LIST BundleCBList; // List of free BundleCBs
NPAGED_LOOKASIDE_LIST LinkProtoCBList; // List of free LinkCBs
NPAGED_LOOKASIDE_LIST SmallDataDescList; // List of free small data descs
NPAGED_LOOKASIDE_LIST LargeDataDescList; // List of free small data descs
NPAGED_LOOKASIDE_LIST WanRequestList; // List of free WanRequest descs
NPAGED_LOOKASIDE_LIST AfSapVcCBList; // List of free afsapcb's
#if DBG
NPAGED_LOOKASIDE_LIST DbgPacketDescList; UCHAR reA[1024] = {0}; UCHAR LastIrpAction; ULONG reI = 0; LIST_ENTRY WanTrcList; ULONG WanTrcCount; #endif
ULONG glDebugLevel; // Trace Level values 0 - 10 (10 verbose)
ULONG glDebugMask; // Trace bit mask
ULONG glSendQueueDepth; // # of seconds of send queue buffering
ULONG glMaxMTU = DEFAULT_MTU; // Maximum MTU of all protocols
ULONG glMRU; // Maximum recv for a link
ULONG glMRRU; // Maximum reconstructed recv for a bundle
ULONG glSmallDataBufferSize; // Size of databuffer
ULONG glLargeDataBufferSize; // Size of databuffer
ULONG glTunnelMTU; // MTU to be used over a VPN
ULONG glMinFragSize; ULONG glMaxFragSize; ULONG glMinLinkBandwidth; BOOLEAN gbSniffLink = FALSE; BOOLEAN gbDumpRecv = FALSE; BOOLEAN gbHistoryless = TRUE; BOOLEAN gbIGMPIdle = TRUE; BOOLEAN gbAtmUseLLCOnSVC = FALSE; BOOLEAN gbAtmUseLLCOnPVC = FALSE; ULONG glSendCount = 0; ULONG glSendCompleteCount = 0; ULONG glPacketPoolCount; ULONG glPacketPoolOverflow; ULONG glProtocolMaxSendPackets; ULONG glLinkCount; ULONG glConnectCount; ULONG glCachedKeyCount = 16; ULONG glMaxOutOfOrderDepth = 128; ULONG glNdisTapiKey = 0; PVOID hSystemState = NULL; NDIS_RW_LOCK ConnTableLock;
PCONNECTION_TABLE ConnectionTable = NULL; // Pointer to connection table
PPROTOCOL_INFO_TABLE ProtocolInfoTable = NULL; // Pointer to the PPP/Protocol lookup table
NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
#ifdef NT
VOID NdisWanUnload( PDRIVER_OBJECT DriverObject );
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 NdisTapiName = NDIS_STRING_CONST("NdisTapi");
NdisZeroMemory(&NdisWanCB, sizeof(NdisWanCB));
glDebugLevel = DBG_CRITICAL_ERROR; glDebugMask = DBG_ALL;
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Enter"));
NdisMInitializeWrapper(&(NdisWanCB.NdisWrapperHandle), DriverObject, RegistryPath, NULL);
Status = NdisWanCreateProtocolInfoTable();
if (Status != NDIS_STATUS_SUCCESS) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("NdisWanCreatePPPProtocolTable Failed! Status: 0x%x - %s", Status, NdisWanGetNdisStatus(Status)));
return (STATUS_UNSUCCESSFUL); }
NdisWanReadRegistry(RegistryPath);
//
// Initialize globals
//
NdisAllocateSpinLock(&NdisWanCB.Lock);
NdisWanCB.pDriverObject = DriverObject;
NdisZeroMemory(&MiniportCBList, sizeof(WAN_GLOBAL_LIST)); InitializeListHead(&(MiniportCBList.List)); NdisAllocateSpinLock(&MiniportCBList.Lock);
NdisZeroMemory(&OpenCBList, sizeof(WAN_GLOBAL_LIST)); InitializeListHead(&(OpenCBList.List)); NdisAllocateSpinLock(&OpenCBList.Lock);
NdisZeroMemory(&ThresholdEventQueue, sizeof(WAN_GLOBAL_LIST)); InitializeListHead(&(ThresholdEventQueue.List)); NdisAllocateSpinLock(&ThresholdEventQueue.Lock);
NdisZeroMemory(&PacketPoolList, sizeof(POOLDESC_LIST)); InitializeListHead(&PacketPoolList.List); NdisAllocateSpinLock(&PacketPoolList.Lock);
NdisZeroMemory(&IoRecvList, sizeof(IO_RECV_LIST)); InitializeListHead(&IoRecvList.IrpList); InitializeListHead(&IoRecvList.DescList); NdisAllocateSpinLock(&IoRecvList.Lock);
KeInitializeTimerEx(&IoRecvList.Timer, NotificationTimer); KeInitializeDpc(&IoRecvList.Dpc, IoRecvIrpWorker, NULL);
NdisZeroMemory(&BonDWorkList, sizeof(WAN_GLOBAL_LIST_EX)); InitializeListHead(&BonDWorkList.List); NdisAllocateSpinLock(&BonDWorkList.Lock); KeInitializeTimerEx(&BonDWorkList.Timer, NotificationTimer); KeInitializeDpc(&BonDWorkList.Dpc, BonDWorker, NULL);
NdisZeroMemory(&DeferredWorkList, sizeof(WAN_GLOBAL_LIST_EX)); InitializeListHead(&DeferredWorkList.List); NdisAllocateSpinLock(&DeferredWorkList.Lock); KeInitializeTimerEx(&DeferredWorkList.Timer, NotificationTimer); KeInitializeDpc(&DeferredWorkList.Dpc, DeferredWorker, NULL);
//
// Is depth used by the OS?
//
NdisInitializeNPagedLookasideList(&BundleCBList, NULL, NULL, 0, BUNDLECB_SIZE, BUNDLECB_TAG, 0);
NdisInitializeNPagedLookasideList(&LinkProtoCBList, NULL, NULL, 0, LINKPROTOCB_SIZE, LINKPROTOCB_TAG, 0);
//
// Calculated from the following:
// MAX_FRAME_SIZE + PROTOCOL_HEADER_LENGTH + sizeof(PVOID) + (MAX_FRAME_SIZE + 7)/8
//
{ ULONG Size = (glMaxMTU > glMRRU) ? glMaxMTU : glMRRU;
glLargeDataBufferSize = Size + PROTOCOL_HEADER_LENGTH + sizeof(PVOID) + ((Size + 7)/8); glLargeDataBufferSize &= ~((ULONG_PTR)sizeof(PVOID) - 1);
glSmallDataBufferSize = glLargeDataBufferSize/2 + sizeof(PVOID); glSmallDataBufferSize &= ~((ULONG_PTR)sizeof(PVOID) - 1);
NdisInitializeNPagedLookasideList(&SmallDataDescList, AllocateDataDesc, FreeDataDesc, 0, DATADESC_SIZE + glSmallDataBufferSize, SMALLDATADESC_TAG, 0);
NdisInitializeNPagedLookasideList(&LargeDataDescList, AllocateDataDesc, FreeDataDesc, 0, DATADESC_SIZE + glLargeDataBufferSize, LARGEDATADESC_TAG, 0); }
NdisInitializeNPagedLookasideList(&WanRequestList, NULL, NULL, 0, sizeof(WAN_REQUEST), WANREQUEST_TAG, 0);
NdisInitializeNPagedLookasideList(&AfSapVcCBList, NULL, NULL, 0, AFSAPVCCB_SIZE, AFSAPVCCB_TAG, 0);
NdisInitializeReadWriteLock(&ConnTableLock);
#if DBG
NdisInitializeNPagedLookasideList(&DbgPacketDescList, NULL, NULL, 0, sizeof(DBG_PACKET), DBGPACKET_TAG, 0); InitializeListHead(&WanTrcList); WanTrcCount = 0; #endif
WanInitECP(); WanInitVJ();
//
// 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; }
//
// 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; }
//
// Open the miniports
//
#if 0
NdisWanBindMiniports(RegistryPath); #endif
//
// Allocate and initialize the ConnectionTable
//
Status = NdisWanCreateConnectionTable(NdisWanCB.NumberOfLinks);
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
//
#ifdef MY_DEVICE_OBJECT
{ NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan"); NDIS_STRING Name = NDIS_STRING_CONST("\\Device\\NdisWan"); ULONG i;
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { NdisWanCB.MajorFunction[i] = (PVOID)DriverObject->MajorFunction[i]; DriverObject->MajorFunction[i] = NdisWanIrpStub; } DriverObject->MajorFunction[IRP_MJ_CREATE] = NdisWanCreate; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisWanIoctl; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisWanCleanup; // DriverObject->MajorFunction[IRP_MJ_PNP_POWER] = NdisWanPnPPower;
NdisWanCB.NdisUnloadHandler = DriverObject->DriverUnload; DriverObject->DriverUnload = (PVOID)NdisWanUnload; 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); } #endif
NdisMRegisterUnloadHandler(NdisWanCB.NdisWrapperHandle, NdisWanUnload);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit"));
return (STATUS_SUCCESS);
//
// An error occured so we need to cleanup things
//
DriverEntryError:
NdisWanGlobalCleanup();
//
// Terminate the wrapper
//
NdisTerminateWrapper(NdisWanCB.NdisWrapperHandle, NdisWanCB.pDriverObject);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit Error!"));
return (STATUS_UNSUCCESSFUL); }
VOID NdisWanUnload( PDRIVER_OBJECT DriverObject ) { NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanUnload: Entry!"));
NdisWanGlobalCleanup();
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanUnload: Exit!")); }
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 MinFragmentSizeKeyWord = L"MinimumFragmentSize"; PWSTR MaxFragmentSizeKeyWord = L"MaximumFragmentSize"; PWSTR LinkBandwidthKeyWord = L"MinimumLinkBandwidth"; PWSTR CachedKeyCountKeyWord = L"CachedKeyCount"; PWSTR MaxOutOfOrderDepthKeyWord = L"MaxOutOfOrderDepth"; PWSTR DebugLevelKeyWord = L"DebugLevel"; PWSTR DebugMaskKeyWord = L"DebugMask"; PWSTR NumberOfPortsKeyWord = L"NumberOfPorts"; PWSTR PacketPoolCountKeyWord = L"NdisPacketPoolCount"; PWSTR PacketPoolOverflowKeyWord = L"NdisPacketPoolOverflow"; PWSTR ProtocolMaxSendPacketsKeyWord = L"ProtocolMaxSendPackets"; PWSTR SniffLinkKeyWord = L"SniffLink"; PWSTR SendQueueDepthKeyWord = L"SendQueueDepth"; PWSTR MRUKeyWord = L"MRU"; PWSTR MRRUKeyWord = L"MRRU"; PWSTR TunnelMTUKeyWord = L"TunnelMTU"; PWSTR HistorylessKeyWord = L"Historyless"; PWSTR AtmUseLLCOnSVCKeyWord = L"AtmUseLLCOnSVC"; PWSTR AtmUseLLCOnPVCKeyWord = L"AtmUseLLCOnPVC"; PWSTR IGMPIdleKeyWord = L"IGMPIdle"; ULONG GenericULong; RTL_QUERY_REGISTRY_TABLE QueryTable[6];
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Enter"));
//
// First setup the protocol id table
//
{ PWSTR ProtocolsKey = L"NdisWan\\Parameters\\Protocols\\"; PWSTR ProtocolKeyWord = L"ProtocolType"; PWSTR PPPKeyWord = L"PPPProtocolType"; PWSTR ProtocolMTUKeyWord = L"ProtocolMTU"; PWSTR TunnelMTUKeyword = L"TunnelMTU"; PWSTR QueueDepthKeyword = L"PacketQueueDepth"; ULONG i, Generic1, Generic2; PROTOCOL_INFO ProtocolInfo; UNICODE_STRING uni1;
NdisInitUnicodeString(&uni1, ProtocolsKey);
NdisZeroMemory(QueryTable, sizeof(QueryTable));
//
// Read the ProtocolType parameter MULTI_SZ
//
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = ProtocolKeyWord; QueryTable[0].EntryContext = &Generic1; QueryTable[0].DefaultType = 0;
//
// Read the PPPProtocolType parameter MULTI_SZ
//
QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[1].Name = PPPKeyWord; QueryTable[1].EntryContext = &Generic2; QueryTable[1].DefaultType = 0;
//
// Read the ProtocolMTU parameter DWORD
//
QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[2].Name = ProtocolMTUKeyWord; QueryTable[2].EntryContext = &ProtocolInfo.MTU; QueryTable[2].DefaultType = 0;
//
// Read the ProtocolMTU parameter DWORD
//
QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[3].Name = TunnelMTUKeyWord; QueryTable[3].EntryContext = &ProtocolInfo.TunnelMTU; QueryTable[3].DefaultType = 0;
//
// Read the PacketQueueDepth parameter DWORD
//
QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[4].Name = QueueDepthKeyword; QueryTable[4].EntryContext = &ProtocolInfo.PacketQueueDepth; QueryTable[4].DefaultType = 0;
for (i = 0; i < 32; i++) { WCHAR Buffer[512] = {0}; WCHAR Buffer2[256] = {0}; UNICODE_STRING uni2; UNICODE_STRING IndexString;
uni2.Buffer = Buffer; uni2.MaximumLength = sizeof(Buffer); uni2.Length = uni1.Length; RtlCopyUnicodeString(&uni2, &uni1); IndexString.Buffer = Buffer2; IndexString.MaximumLength = sizeof(Buffer2); RtlIntegerToUnicodeString(i, 10, &IndexString); RtlAppendUnicodeStringToString(&uni2, &IndexString);
NdisZeroMemory(&ProtocolInfo, sizeof(ProtocolInfo));
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, uni2.Buffer, QueryTable, NULL, NULL); if (Status == STATUS_SUCCESS) { ProtocolInfo.ProtocolType = (USHORT)Generic1; ProtocolInfo.PPPId = (USHORT)Generic2; ProtocolInfo.Flags = PROTOCOL_UNBOUND; SetProtocolInfo(&ProtocolInfo); } } }
//
// Read the MinFragmentSize parameter DWORD
//
glMinFragSize = DEFAULT_MIN_FRAG_SIZE; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = MinFragmentSizeKeyWord; 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 && GenericULong > 0) { glMinFragSize = GenericULong; }
//
// Read the MaxFragmentSize parameter DWORD
//
glMaxFragSize = glMaxMTU; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = MaxFragmentSizeKeyWord; 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 - 'MaximumFragmentSize' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong > 0 && GenericULong < glMaxMTU) { glMaxFragSize = GenericULong; }
if (glMaxFragSize < glMinFragSize) { glMinFragSize = glMaxFragSize; }
//
// Read the MinimumLinkBandwidth parameter DWORD
//
glMinLinkBandwidth = 25; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = LinkBandwidthKeyWord; 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 - 'MinimumLinkBandwidth' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong <= 100) { glMinLinkBandwidth = GenericULong; }
//
// Read the NumberOfPorts parameter DWORD
//
NdisWanCB.NumberOfLinks = 250; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = NumberOfPortsKeyWord; 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 - 'NumberOfPorts' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong > 0) { NdisWanCB.NumberOfLinks = GenericULong; }
//
// Read the NdisPacketPoolCount parameter DWORD
//
glPacketPoolCount = 100; // glPacketPoolCount = 1;
NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = PacketPoolCountKeyWord; 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 - 'NdisPacketPoolCount' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong > 0) { glPacketPoolCount = GenericULong; }
//
// Read the NdisPacketPoolOverflow parameter DWORD
//
// glPacketPoolOverflow = PAGE_SIZE / (sizeof(NDIS_PACKET) + sizeof(NDISWAN_PROTOCOL_RESERVED));
glPacketPoolOverflow = 0; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = PacketPoolOverflowKeyWord; 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 - 'NdisPacketPoolOverflow' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong > 0) { glPacketPoolOverflow = GenericULong; }
//
// Read the ProtocolMaxSendPackets parameter DWORD
//
glProtocolMaxSendPackets = 5; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = ProtocolMaxSendPacketsKeyWord; 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 - 'ProtocolMaxSendPackets' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS && GenericULong > 0) { glProtocolMaxSendPackets = GenericULong; }
//
// Read the CachedKeyCount parameter DWORD
//
NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = CachedKeyCountKeyWord; 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 - 'CachedKeyCount' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glCachedKeyCount = GenericULong; }
//
// Read the MaxOutOfOrderDepth parameter DWORD
//
NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = MaxOutOfOrderDepthKeyWord; 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 - 'MaxOutOfOrderDepth' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glMaxOutOfOrderDepth = 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) { glDebugLevel = 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 = DebugMaskKeyWord; 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 - 'DebugMask' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glDebugMask = GenericULong; }
//
// Read the SniffLink parameter DWORD
//
gbSniffLink = FALSE; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = SniffLinkKeyWord; 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 - 'SniffLink' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { gbSniffLink = (GenericULong == 0) ? FALSE : TRUE; }
//
// Read the SendQueueDepth parameter DWORD
//
glSendQueueDepth = 2; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = SendQueueDepthKeyWord; 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 - 'SendQueueDepth' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glSendQueueDepth = (GenericULong == 0) ? 2 : GenericULong; }
//
// Read the MRU parameter DWORD
//
glMRU = DEFAULT_MRU; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = MRUKeyWord; 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 - 'MRU' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glMRU = (GenericULong == 0) ? DEFAULT_MRU : GenericULong; }
//
// Read the MRRU parameter DWORD
//
glMRRU = DEFAULT_MRRU; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = MRRUKeyWord; 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 - 'MRRU' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glMRRU = (GenericULong == 0) ? DEFAULT_MRRU : GenericULong; }
//
// Read the TunnelMTU parameter DWORD
//
glTunnelMTU = DEFAULT_TUNNEL_MTU; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = TunnelMTUKeyWord; 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 - 'TunnelMTU' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { glTunnelMTU = (GenericULong == 0) ? DEFAULT_TUNNEL_MTU : GenericULong; }
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Exit"));
NdisZeroMemory(QueryTable, sizeof(QueryTable)); gbHistoryless = TRUE; QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = HistorylessKeyWord; 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 - 'Historyless' Status: 0x%x", Status)); if (Status == NDIS_STATUS_SUCCESS) { gbHistoryless = (GenericULong) ? TRUE : FALSE; }
NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = AtmUseLLCOnSVCKeyWord; 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 - 'AtmUseLLCOnSVC' Status: 0x%x", Status)); if (Status == NDIS_STATUS_SUCCESS) { gbAtmUseLLCOnSVC = (GenericULong) ? TRUE : FALSE; }
NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = AtmUseLLCOnPVCKeyWord; 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 - 'AtmUseLLCOnPVC' Status: 0x%x", Status)); if (Status == NDIS_STATUS_SUCCESS) { gbAtmUseLLCOnPVC = (GenericULong) ? TRUE : FALSE; }
//
// Read the IGMPIdle parameter DWORD
//
gbIGMPIdle = TRUE; NdisZeroMemory(QueryTable, sizeof(QueryTable)); QueryTable[0].QueryRoutine = NULL; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = IGMPIdleKeyWord; 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 - 'IGMPIdle' Status: 0x%x", Status));
if (Status == NDIS_STATUS_SUCCESS) { gbIGMPIdle = (GenericULong == 0) ? FALSE : TRUE; } }
#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 = 5; MiniportChars.MinorNdisVersion = 0;
//
// NDIS 3.0 handlers
//
MiniportChars.HaltHandler = MPHalt; MiniportChars.InitializeHandler = MPInitialize; // MiniportChars.QueryInformationHandler = MPQueryInformation;
MiniportChars.ReconfigureHandler = MPReconfigure; MiniportChars.ResetHandler = MPReset; // MiniportChars.SetInformationHandler = MPSetInformation;
//
// We are providing a sendpackets handlers so
// we don't need the regular send handler
//
MiniportChars.SendHandler = NULL;
//
// We are going to indicate packets so we
// don't need a transfer data handler
//
MiniportChars.TransferDataHandler = NULL;
//
// 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 = NULL;
//
// NDIS 4.0 handlers
//
MiniportChars.ReturnPacketHandler = MPReturnPacket; MiniportChars.SendPacketsHandler = MPSendPackets;
//
// unused
//
MiniportChars.AllocateCompleteHandler = NULL;
//
// NDIS 5.0 handlers
//
MiniportChars.CoCreateVcHandler = MPCoCreateVc; MiniportChars.CoDeleteVcHandler = MPCoDeleteVc; MiniportChars.CoActivateVcHandler = MPCoActivateVc; MiniportChars.CoDeactivateVcHandler = MPCoDeactivateVc; MiniportChars.CoSendPacketsHandler = MPCoSendPackets; MiniportChars.CoRequestHandler = MPCoRequest;
Status = NdisMRegisterMiniport(NdisWanCB.NdisWrapperHandle, &MiniportChars, sizeof(MiniportChars));
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Exit %x", Status));
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
--*/ { NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars; NDIS_STATUS Status; // NDIS_STRING NdisWanName = NDIS_STRING_CONST("NdisWanProto");
NDIS_STRING NdisWanName = NDIS_STRING_CONST("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 = 5; ProtocolChars.MinorNdisVersion = 0;
//
// NDIS 3.0 handlers
//
ProtocolChars.OpenAdapterCompleteHandler = ProtoOpenAdapterComplete; ProtocolChars.CloseAdapterCompleteHandler = ProtoCloseAdapterComplete; ProtocolChars.WanSendCompleteHandler = ProtoWanSendComplete; ProtocolChars.TransferDataCompleteHandler = NULL; ProtocolChars.ResetCompleteHandler = ProtoResetComplete; ProtocolChars.RequestCompleteHandler = ProtoRequestComplete; ProtocolChars.WanReceiveHandler = ProtoWanReceiveIndication; ProtocolChars.ReceiveCompleteHandler = ProtoReceiveComplete; ProtocolChars.StatusHandler = ProtoIndicateStatus; ProtocolChars.StatusCompleteHandler = ProtoIndicateStatusComplete;
//
// NDIS 4.0 handlers
//
ProtocolChars.ReceivePacketHandler = NULL;
//
// PnP handlers
//
ProtocolChars.BindAdapterHandler = ProtoBindAdapter; ProtocolChars.UnbindAdapterHandler = ProtoUnbindAdapter; ProtocolChars.PnPEventHandler = ProtoPnPEvent; ProtocolChars.UnloadHandler = ProtoUnload;
//
// NDIS 5.0 handlers
//
ProtocolChars.CoSendCompleteHandler = ProtoCoSendComplete; ProtocolChars.CoStatusHandler = ProtoCoIndicateStatus; ProtocolChars.CoReceivePacketHandler = ProtoCoReceivePacket; ProtocolChars.CoAfRegisterNotifyHandler = ProtoCoAfRegisterNotify;
NdisRegisterProtocol(&Status, &NdisWanCB.ProtocolHandle, (PNDIS_PROTOCOL_CHARACTERISTICS)&ProtocolChars, sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Exit"));
return (Status); }
VOID SetProtocolInfo( IN PPROTOCOL_INFO ProtocolInfo ) /*++
Routine Name:
InsertProtocolInfo
Routine Description:
This routine takes a information about a protocol and inserts it into the appropriate lookup table.
Arguments:
Return Values:
--*/ { ULONG i; ULONG ArraySize; PPROTOCOL_INFO InfoArray;
if (ProtocolInfo->ProtocolType == 0) { return; }
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
ArraySize = ProtocolInfoTable->ulArraySize;
//
// First check to see if this value is already in the array
//
for (i = 0, InfoArray = ProtocolInfoTable->ProtocolInfo; i < ArraySize; i++, InfoArray++) { if (InfoArray->ProtocolType == ProtocolInfo->ProtocolType) { //
// This protocol is already in the table
// update values if they are valid (0 is invalid)
//
if (ProtocolInfo->PPPId != 0) { InfoArray->PPPId = ProtocolInfo->PPPId; } if (ProtocolInfo->TunnelMTU != 0) { InfoArray->TunnelMTU = ProtocolInfo->TunnelMTU; } if (ProtocolInfo->MTU != 0) { InfoArray->MTU = ProtocolInfo->MTU; if (InfoArray->MTU < InfoArray->TunnelMTU) { InfoArray->TunnelMTU = InfoArray->MTU; } } if (ProtocolInfo->MTU > glMaxMTU) { glMaxMTU = ProtocolInfo->MTU; } if (ProtocolInfo->PacketQueueDepth != 0) { InfoArray->PacketQueueDepth = ProtocolInfo->PacketQueueDepth; } if (ProtocolInfo->Flags != 0) { //
// Is this a bind notification?
//
if (ProtocolInfo->Flags & PROTOCOL_BOUND) { if (InfoArray->Flags & PROTOCOL_UNBOUND) { InfoArray->Flags &= ~PROTOCOL_UNBOUND; InfoArray->Flags |= (PROTOCOL_BOUND | PROTOCOL_EVENT_OCCURRED); ProtocolInfoTable->Flags |= PROTOCOL_EVENT_OCCURRED; } else if ((InfoArray->Flags & PROTOCOL_BOUND) && (ProtocolInfo->ProtocolType == PROTOCOL_IP)) { //
// This means we were unbound and then
// bound again without our miniport being
// halted (layered driver insertion i.e psched).
// Currently this only interferes with rasman
// if the protocol is IP.
// We need to tell ras about two events,
// the unbind and the bind.
//
InfoArray->Flags |= (PROTOCOL_BOUND | PROTOCOL_REBOUND | PROTOCOL_EVENT_OCCURRED); ProtocolInfoTable->Flags |= PROTOCOL_EVENT_OCCURRED;
} }
//
// is this an unbind notification?
//
if (ProtocolInfo->Flags & PROTOCOL_UNBOUND) { if (InfoArray->Flags & PROTOCOL_BOUND) { InfoArray->Flags &= ~(PROTOCOL_BOUND | PROTOCOL_REBOUND); InfoArray->Flags |= (PROTOCOL_UNBOUND | PROTOCOL_EVENT_OCCURRED); ProtocolInfoTable->Flags |= PROTOCOL_EVENT_OCCURRED; } } }
if (ProtocolInfoTable->Flags & PROTOCOL_EVENT_OCCURRED && !(ProtocolInfoTable->Flags & PROTOCOL_EVENT_SIGNALLED)) {
if (ProtocolInfoTable->EventIrp != NULL) { PIRP Irp;
Irp = ProtocolInfoTable->EventIrp;
if (IoSetCancelRoutine(Irp, NULL)) {
ProtocolInfoTable->EventIrp = NULL; ProtocolInfoTable->Flags |= PROTOCOL_EVENT_SIGNALLED;
NdisReleaseSpinLock(&ProtocolInfoTable->Lock);
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
NdisAcquireSpinLock(&ProtocolInfoTable->Lock); } } }
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, InfoArray = ProtocolInfoTable->ProtocolInfo; i < ArraySize; i++, InfoArray++) { //
// We are looking for an empty slot to add
// the new values to the table
//
if (InfoArray->ProtocolType == 0) { *InfoArray = *ProtocolInfo; if (ProtocolInfo->MTU > glMaxMTU) { glMaxMTU = ProtocolInfo->MTU; } break; } } }
NdisReleaseSpinLock(&ProtocolInfoTable->Lock); }
BOOLEAN GetProtocolInfo( IN OUT PPROTOCOL_INFO ProtocolInfo ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG i; ULONG ArraySize; PPROTOCOL_INFO InfoArray; BOOLEAN ReturnValue = FALSE;
NdisAcquireSpinLock(&ProtocolInfoTable->Lock);
ArraySize = ProtocolInfoTable->ulArraySize;
for (i = 0, InfoArray = ProtocolInfoTable->ProtocolInfo; i < ArraySize; i++, InfoArray++) {
if (InfoArray->ProtocolType == ProtocolInfo->ProtocolType) { *ProtocolInfo = *InfoArray; ReturnValue = TRUE; break; } }
NdisReleaseSpinLock(&ProtocolInfoTable->Lock); return (ReturnValue); }
NDIS_HANDLE InsertLinkInConnectionTable( IN PLINKCB LinkCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG Index, i; PLINKCB *LinkArray; NDIS_STATUS Status; LOCK_STATE LockState;
NdisAcquireReadWriteLock(&ConnTableLock, TRUE, &LockState);
if (ConnectionTable->ulNumActiveLinks > (ConnectionTable->ulArraySize - 1)/2) { //
// We need to grow the table!
//
Status = NdisWanCreateConnectionTable(ConnectionTable->ulArraySize + (ConnectionTable->ulArraySize * 2));
if (Status != NDIS_STATUS_SUCCESS) { NdisReleaseReadWriteLock(&ConnTableLock, &LockState); return (NULL); } }
//
// We are doing a linear search for an empty spot in
// the link array
//
LinkArray = ConnectionTable->LinkArray; i = ConnectionTable->ulArraySize; Index = (ConnectionTable->ulNextLink == 0) ? 1 : ConnectionTable->ulNextLink; do {
if (LinkArray[Index] == NULL) { LinkArray[Index] = LinkCB; LinkCB->hLinkHandle = (NDIS_HANDLE)ULongToPtr(Index); ConnectionTable->ulNextLink = (Index+1) % ConnectionTable->ulArraySize; InterlockedIncrement(&glLinkCount); if (ConnectionTable->ulNumActiveLinks == 0) { hSystemState = PoRegisterSystemState(NULL, ES_SYSTEM_REQUIRED | ES_CONTINUOUS); } ConnectionTable->ulNumActiveLinks++; InsertTailList(&ConnectionTable->LinkList, &LinkCB->ConnTableLinkage); break; } Index = (Index+1) % ConnectionTable->ulArraySize; Index = (Index == 0) ? 1 : Index; i--; } while ( i );
if (i == 0) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("InsertLinkCB: ConnectionTable is full!")); Index = 0; }
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
return ((NDIS_HANDLE)ULongToPtr(Index)); }
VOID RemoveLinkFromConnectionTable( IN PLINKCB LinkCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG Index = PtrToUlong(LinkCB->hLinkHandle); PLINKCB *LinkArray; LOCK_STATE LockState;
NdisAcquireReadWriteLock(&ConnTableLock, TRUE, &LockState);
LinkArray = ConnectionTable->LinkArray; do {
if (Index == 0 || Index > ConnectionTable->ulArraySize) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("RemoveLinkCB: Invalid LinkHandle! Handle: %d\n", Index)); ASSERT(0); break; }
if (LinkArray[Index] == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("RemoveLinkCB: LinkCB not in connection table! LinkCB: %p\n", LinkCB)); ASSERT(0); break; }
ASSERT(LinkCB == LinkArray[Index]);
LinkArray[Index] = NULL; RemoveEntryList(&LinkCB->ConnTableLinkage);
ConnectionTable->ulNumActiveLinks--;
if (ConnectionTable->ulNumActiveLinks == 0) { PoUnregisterSystemState(hSystemState); hSystemState = NULL; }
} while ( 0 );
NdisReleaseReadWriteLock(&ConnTableLock, &LockState); }
NDIS_HANDLE InsertBundleInConnectionTable( IN PBUNDLECB BundleCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG Index,i; PBUNDLECB *BundleArray; NDIS_STATUS Status; LOCK_STATE LockState;
NdisAcquireReadWriteLock(&ConnTableLock, TRUE, &LockState);
if (ConnectionTable->ulNumActiveBundles > (ConnectionTable->ulArraySize - 1)/2) { //
// We need to grow the table!
//
Status = NdisWanCreateConnectionTable(ConnectionTable->ulArraySize + (ConnectionTable->ulArraySize * 2));
if (Status != NDIS_STATUS_SUCCESS) { NdisReleaseReadWriteLock(&ConnTableLock, &LockState); return (NULL); } }
//
// We are doing a linear search for an empty spot in
// the link array
//
BundleArray = ConnectionTable->BundleArray; i = ConnectionTable->ulArraySize; Index = (ConnectionTable->ulNextBundle == 0) ? 1 : ConnectionTable->ulNextBundle; do {
if (BundleArray[Index] == NULL) { BundleArray[Index] = BundleCB; ConnectionTable->ulNumActiveBundles++; BundleCB->hBundleHandle = (NDIS_HANDLE)ULongToPtr(Index); InsertTailList(&ConnectionTable->BundleList, &BundleCB->Linkage); ConnectionTable->ulNextBundle = (Index+1) % ConnectionTable->ulArraySize; break; } Index = (Index+1) % ConnectionTable->ulArraySize; Index = (Index == 0) ? 1 : Index; i--; } while ( i );
if (i == 0) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("InsertBundleCB: ConnectionTable is full!")); Index = 0; }
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
return ((NDIS_HANDLE)ULongToPtr(Index)); }
VOID RemoveBundleFromConnectionTable( IN PBUNDLECB BundleCB ) /*++
Routine Name:
Routine Description:
Arguments:
Return Values:
--*/ { ULONG Index = PtrToUlong(BundleCB->hBundleHandle); PBUNDLECB *BundleArray; LOCK_STATE LockState;
NdisAcquireReadWriteLock(&ConnTableLock, TRUE, &LockState);
BundleArray = ConnectionTable->BundleArray;
do {
if (Index == 0 || Index > ConnectionTable->ulArraySize) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("RemoveBundleCB: Invalid BundleHandle! Handle: %d\n", Index)); ASSERT(0); break; }
if (BundleArray[Index] == NULL) { NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("RemoveBundleCB: BundleCB not in connection table! BundleCB: %p\n", BundleCB)); ASSERT(0); break; }
ASSERT(BundleCB == BundleArray[Index]);
RemoveEntryList(&BundleCB->Linkage);
BundleArray[Index] = NULL; ConnectionTable->ulNumActiveBundles--;
} while ( 0 );
NdisReleaseReadWriteLock(&ConnTableLock, &LockState); }
VOID NdisWanGlobalCleanup( VOID ) /*++
Routine Name:
NdisWanGlobalCleanup
Routine Description: This routine is responsible for cleaning up all allocated resources.
Arguments:
None
Return Values:
None
--*/ { NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("GlobalCleanup - Enter"));
//
// Stop all timers
//
//
// Complete all outstanding requests
//
if (NdisWanCB.ProtocolHandle != NULL) { NDIS_STATUS Status;
ASSERT(OpenCBList.ulCount == 0);
NdisDeregisterProtocol(&Status, NdisWanCB.ProtocolHandle); NdisWanCB.ProtocolHandle = NULL; }
WanDeleteECP(); WanDeleteVJ();
//
// Free all of the BundleCB's
//
//
// Free all of the LinkCB's
//
ASSERT(IsListEmpty(&MiniportCBList.List)); ASSERT(IsListEmpty(&OpenCBList.List));
NdisFreeSpinLock(&MiniportCBList.Lock); NdisFreeSpinLock(&OpenCBList.Lock); NdisFreeSpinLock(&ThresholdEventQueue.Lock); NdisFreeSpinLock(&PacketPoolList.Lock); NdisFreeSpinLock(&IoRecvList.Lock); NdisDeleteNPagedLookasideList(&BundleCBList); NdisDeleteNPagedLookasideList(&LinkProtoCBList); NdisDeleteNPagedLookasideList(&LargeDataDescList); NdisDeleteNPagedLookasideList(&SmallDataDescList); NdisDeleteNPagedLookasideList(&WanRequestList); NdisDeleteNPagedLookasideList(&AfSapVcCBList);
#if DBG
NdisDeleteNPagedLookasideList(&DbgPacketDescList); #endif
//
// Free globals
//
if (ConnectionTable != NULL) { NdisWanFreeMemory(ConnectionTable); ConnectionTable = NULL; }
if (ProtocolInfoTable != NULL) { NdisWanFreeMemory(ProtocolInfoTable); ProtocolInfoTable = NULL; }
//
// Free packet pool
//
NdisAcquireSpinLock(&PacketPoolList.Lock);
while (!IsListEmpty(&PacketPoolList.List)) { PPOOL_DESC PoolDesc;
PoolDesc = (PPOOL_DESC)RemoveHeadList(&PacketPoolList.List); ASSERT(PoolDesc->AllocatedCount == 0); NdisFreePacketPool(PoolDesc->PoolHandle);
NdisWanFreeMemory(PoolDesc); }
NdisReleaseSpinLock(&PacketPoolList.Lock);
NdisFreeSpinLock(&PacketPoolList.Lock);
#ifdef MY_DEVICE_OBJECT
if (NdisWanCB.pDeviceObject != NULL) { NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan");
IoDeleteSymbolicLink(&SymbolicName); IoDeleteDevice(NdisWanCB.pDeviceObject); NdisWanCB.pDeviceObject = NULL; } #else
if (NdisWanCB.pDeviceObject != NULL) { NdisMDeregisterDevice(NdisWanCB.DeviceHandle); NdisWanCB.pDeviceObject = NULL; } #endif
NdisFreeSpinLock(&NdisWanCB.Lock);
NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("GlobalCleanup - Exit")); }
#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
|