2123 lines
63 KiB
C
2123 lines
63 KiB
C
/*++
|
|
|
|
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 TransformDrvList;
|
|
|
|
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;
|
|
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);
|
|
|
|
NdisZeroMemory(&TransformDrvList, sizeof(WAN_GLOBAL_LIST));
|
|
InitializeListHead(&TransformDrvList.List);
|
|
NdisAllocateSpinLock(&TransformDrvList.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"));
|
|
|
|
//
|
|
// See if there are any data transform drivers in the system
|
|
//
|
|
{
|
|
PWSTR TransformDriversKey = L"TransformDriver\\Drivers";
|
|
PWSTR TransformDriverKeyWord = L"Drivers";
|
|
|
|
NdisZeroMemory(&QueryTable, sizeof(QueryTable));
|
|
QueryTable[0].QueryRoutine = OpenTransformDriver;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[0].Name = TransformDriverKeyWord;
|
|
QueryTable[0].EntryContext = NULL;
|
|
QueryTable[0].DefaultType = 0;
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
|
|
TransformDriversKey,
|
|
&QueryTable[0],
|
|
NULL,
|
|
NULL);
|
|
|
|
NdisWanDbgOut(DBG_INFO, DBG_INIT,
|
|
("RtlQueryRegistry - 'TransformDriver\\Drivers' Status: 0x%x",
|
|
Status));
|
|
}
|
|
|
|
|
|
//
|
|
// 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;
|
|
|
|
NdisWanInitUnicodeString(&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;
|
|
NdisWanCopyUnicodeString(&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;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
OpenTransformDriver(
|
|
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_STATUS Status = STATUS_SUCCESS;
|
|
PIRP Irp;
|
|
PTRANSDRVCB TransDrvCB;
|
|
KEVENT TransDrvEvent;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
NdisWanAllocateMemory(&TransDrvCB,
|
|
sizeof(PTRANSDRVCB),
|
|
TRANSDRV_TAG);
|
|
if (TransDrvCB == NULL) {
|
|
return (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
InterlockedExchange((PLONG)&TransDrvCB->State, TRANSDRV_OPENING);
|
|
|
|
//
|
|
// Open the transform driver
|
|
//
|
|
NdisWanStringToNdisString(&TransDrvCB->Name, ValueName);
|
|
|
|
Status =
|
|
IoGetDeviceObjectPointer(&TransDrvCB->Name,
|
|
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
|
|
&TransDrvCB->FObj,
|
|
&TransDrvCB->DObj);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
NdisWanFreeMemory(TransDrvCB);
|
|
NdisWanDbgOut(DBG_TRACE, DBG_INIT,
|
|
("NDISWAN: Failed to open the TransformDriver %ls! %x\n", TransDrvCB->Name.Buffer, Status));
|
|
return (Status);
|
|
}
|
|
|
|
ObReferenceObject(TransDrvCB->DObj);
|
|
ObDereferenceObject(TransDrvCB->FObj);
|
|
|
|
TransDrvCB->Open.ClientOpenContext = TransDrvCB;
|
|
TransDrvCB->Open.MajorVersion = 1;
|
|
TransDrvCB->Open.MinorVersion = 0;
|
|
TransDrvCB->Open.TransformRegisterHandler = TransformRegister;
|
|
TransDrvCB->Open.TransformTxCompleteHandler = TransformTxComplete;
|
|
TransDrvCB->Open.TransformRxCompleteHandler = TransformRxComplete;
|
|
TransDrvCB->Open.SendCtrlPacketHandler = TransformSendCtrlPacket;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_INIT,
|
|
("NDISWAN: Opened TransformDriver %ls successfully!\n", TransDrvCB->Name.Buffer));
|
|
|
|
//
|
|
// Build Irp
|
|
//
|
|
KeInitializeEvent(&TransDrvEvent, NotificationEvent, FALSE);
|
|
|
|
Irp =
|
|
IoBuildDeviceIoControlRequest(IOCTL_TRANSFORM_OPEN,
|
|
TransDrvCB->DObj,
|
|
&TransDrvCB->Open,
|
|
sizeof(TransDrvCB->Open),
|
|
&TransDrvCB->Open,
|
|
sizeof(TransDrvCB->Open),
|
|
FALSE,
|
|
&TransDrvEvent,
|
|
&IoStatus);
|
|
|
|
if (Irp == NULL) {
|
|
ObDereferenceObject(TransDrvCB->DObj);
|
|
NdisWanFreeMemory(TransDrvCB);
|
|
return (STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
//
|
|
// Send Irp
|
|
//
|
|
Status =
|
|
IoCallDriver(TransDrvCB->DObj, Irp);
|
|
|
|
if (Status == STATUS_PENDING) {
|
|
KeWaitForSingleObject(&TransDrvEvent,
|
|
UserRequest,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
ObDereferenceObject(TransDrvCB->DObj);
|
|
NdisWanFreeMemory(TransDrvCB);
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_INIT,
|
|
("NDISWAN: Failed registering with TransformDriver %ls. %x\n",
|
|
TransDrvCB->Name.Buffer, Status));
|
|
return(Status);
|
|
}
|
|
|
|
InterlockedExchange((PLONG)&TransDrvCB->State, TRANSDRV_OPENED);
|
|
|
|
//
|
|
// If successfull add driver to list
|
|
//
|
|
InsertTailGlobalList(TransformDrvList,
|
|
&TransDrvCB->Linkage);
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
#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
|
|
|