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