1556 lines
47 KiB
C
1556 lines
47 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990-1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
init.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
NDIS wrapper functions initializing drivers.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Adam Barr (adamba) 11-Jul-1990
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
Kernel mode, FSD
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
26-Feb-1991 JohnsonA Added Debugging Code
|
||
|
10-Jul-1991 JohnsonA Implement revised Ndis Specs
|
||
|
01-Jun-1995 JameelH Re-organized
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <precomp.h>
|
||
|
#include <atm.h>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
//
|
||
|
// Define the module number for debug code.
|
||
|
//
|
||
|
#define MODULE_NUMBER MODULE_INIT
|
||
|
|
||
|
//
|
||
|
// Configuration Requests
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
NdisOpenConfiguration(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
OUT PNDIS_HANDLE ConfigurationHandle,
|
||
|
IN NDIS_HANDLE WrapperConfigurationContext
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to open the parameter subkey of the
|
||
|
adapter registry tree.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
ConfigurationHandle - Returns a handle which is used in calls to
|
||
|
NdisReadConfiguration and NdisCloseConfiguration.
|
||
|
|
||
|
WrapperConfigurationContext - a handle pointing to an RTL_QUERY_REGISTRY_TABLE
|
||
|
that is set up for this driver's parameters.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Handle to be returned
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_HANDLE HandleToReturn;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisOpenConfiguration: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
|
||
|
|
||
|
//
|
||
|
// Allocate the configuration handle
|
||
|
//
|
||
|
HandleToReturn = ALLOC_FROM_POOL(sizeof(NDIS_CONFIGURATION_HANDLE), NDIS_TAG_CONFIG_HANLDE);
|
||
|
|
||
|
*Status = (HandleToReturn != NULL) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
|
||
|
|
||
|
if (*Status == NDIS_STATUS_SUCCESS)
|
||
|
{
|
||
|
HandleToReturn->KeyQueryTable = ((PNDIS_WRAPPER_CONFIGURATION_HANDLE)WrapperConfigurationContext)->ParametersQueryTable;
|
||
|
HandleToReturn->ParameterList = NULL;
|
||
|
*ConfigurationHandle = (NDIS_HANDLE)HandleToReturn;
|
||
|
}
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisOpenConfiguration: WrapperConfigurationContext %p\n", WrapperConfigurationContext));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisOpenConfigurationKeyByName(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN NDIS_HANDLE ConfigurationHandle,
|
||
|
IN PNDIS_STRING KeyName,
|
||
|
OUT PNDIS_HANDLE KeyHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to open a subkey relative to the configuration handle.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
ConfigurationHandle - Handle to an already open section of the registry
|
||
|
|
||
|
KeyName - Name of the subkey to open
|
||
|
|
||
|
KeyHandle - Placeholder for the handle to the sub-key.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Handle to be returned
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_HANDLE SKHandle, ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
|
||
|
PNDIS_WRAPPER_CONFIGURATION_HANDLE WConfigHandle;
|
||
|
UNICODE_STRING Parent, Child, Sep;
|
||
|
#define PQueryTable WConfigHandle->ParametersQueryTable
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisOpenConfigurationKeyByName: ConfigurationHandle\n", ConfigurationHandle));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
|
||
|
if (*ConfigHandle->KeyQueryTable[3].Name)
|
||
|
{
|
||
|
RtlInitUnicodeString(&Parent, ConfigHandle->KeyQueryTable[3].Name);
|
||
|
RtlInitUnicodeString(&Sep, L"\\");
|
||
|
Child.MaximumLength = KeyName->Length + Parent.Length + Sep.Length + sizeof(WCHAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Child.MaximumLength = KeyName->Length + sizeof(WCHAR);
|
||
|
}
|
||
|
|
||
|
Child.Length = 0;
|
||
|
|
||
|
//
|
||
|
// Allocate the configuration handle
|
||
|
//
|
||
|
|
||
|
SKHandle = ALLOC_FROM_POOL(sizeof(NDIS_CONFIGURATION_HANDLE) +
|
||
|
sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE) +
|
||
|
Child.MaximumLength,
|
||
|
NDIS_TAG_CONFIG_HANLDE);
|
||
|
|
||
|
*Status = (SKHandle != NULL) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
|
||
|
|
||
|
if (*Status != NDIS_STATUS_SUCCESS)
|
||
|
{
|
||
|
*KeyHandle = (NDIS_HANDLE)NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
WConfigHandle = (PNDIS_WRAPPER_CONFIGURATION_HANDLE)((PUCHAR)SKHandle + sizeof(NDIS_CONFIGURATION_HANDLE));
|
||
|
Child.Buffer = (PWSTR)((PUCHAR)WConfigHandle + sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE));
|
||
|
|
||
|
//
|
||
|
// if there is no parent path, avoid starting the child path with "\\"
|
||
|
//
|
||
|
if (*ConfigHandle->KeyQueryTable[3].Name)
|
||
|
{
|
||
|
RtlCopyUnicodeString(&Child, &Parent);
|
||
|
RtlAppendUnicodeStringToString(&Child, &Sep);
|
||
|
}
|
||
|
|
||
|
RtlAppendUnicodeStringToString(&Child, KeyName);
|
||
|
|
||
|
SKHandle->KeyQueryTable = WConfigHandle->ParametersQueryTable;
|
||
|
|
||
|
|
||
|
PQueryTable[0].QueryRoutine = NULL;
|
||
|
PQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
||
|
PQueryTable[0].Name = L"";
|
||
|
|
||
|
//
|
||
|
// 1.
|
||
|
// Call ndisSaveParameter for a parameter, which will allocate storage for it.
|
||
|
//
|
||
|
PQueryTable[1].QueryRoutine = ndisSaveParameters;
|
||
|
PQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
|
||
|
PQueryTable[1].DefaultType = REG_NONE;
|
||
|
|
||
|
//
|
||
|
// PQueryTable[0].Name and PQueryTable[0].EntryContext
|
||
|
// are filled in inside ReadConfiguration, in preparation
|
||
|
// for the callback.
|
||
|
//
|
||
|
// PQueryTable[0].Name = KeywordBuffer;
|
||
|
// PQueryTable[0].EntryContext = ParameterValue;
|
||
|
|
||
|
//
|
||
|
// 2.
|
||
|
// Stop
|
||
|
//
|
||
|
PQueryTable[2].QueryRoutine = NULL;
|
||
|
PQueryTable[2].Flags = 0;
|
||
|
PQueryTable[2].Name = NULL;
|
||
|
|
||
|
//
|
||
|
// NOTE: Some fields in ParametersQueryTable[3] are used to store information for later retrieval.
|
||
|
//
|
||
|
PQueryTable[3].QueryRoutine = ConfigHandle->KeyQueryTable[3].QueryRoutine;
|
||
|
PQueryTable[3].Name = Child.Buffer;
|
||
|
PQueryTable[3].EntryContext = NULL;
|
||
|
PQueryTable[3].DefaultData = NULL;
|
||
|
|
||
|
SKHandle->ParameterList = NULL;
|
||
|
*KeyHandle = (NDIS_HANDLE)SKHandle;
|
||
|
} while (FALSE);
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisOpenConfigurationKeyByName: ConfigurationHandle\n", ConfigurationHandle));
|
||
|
|
||
|
#undef PQueryTable
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisOpenConfigurationKeyByIndex(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN NDIS_HANDLE ConfigurationHandle,
|
||
|
IN ULONG Index,
|
||
|
OUT PNDIS_STRING KeyName,
|
||
|
OUT PNDIS_HANDLE KeyHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to open a subkey relative to the configuration handle.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
ConfigurationHandle - Handle to an already open section of the registry
|
||
|
|
||
|
Index - Index of the sub-key to open
|
||
|
|
||
|
KeyName - Placeholder for the name of subkey being opened
|
||
|
|
||
|
KeyHandle - Placeholder for the handle to the sub-key.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PNDIS_CONFIGURATION_HANDLE ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
|
||
|
HANDLE Handle = NULL, RootHandle = NULL;
|
||
|
OBJECT_ATTRIBUTES ObjAttr;
|
||
|
UNICODE_STRING KeyPath = {0}, Services = {0}, AbsolutePath={0};
|
||
|
PKEY_BASIC_INFORMATION InfoBuf = NULL;
|
||
|
ULONG Len;
|
||
|
PDEVICE_OBJECT PhysicalDeviceObject;
|
||
|
PNDIS_MINIPORT_BLOCK Miniport;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisOpenConfigurationKeyByIndex: ConfigurationHandle\n", ConfigurationHandle));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
*KeyHandle = NULL;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (ConfigHandle->KeyQueryTable[3].Name != NULL)
|
||
|
{
|
||
|
RtlInitUnicodeString(&KeyPath, ConfigHandle->KeyQueryTable[3].Name);
|
||
|
}
|
||
|
|
||
|
if ((Miniport = (PNDIS_MINIPORT_BLOCK)ConfigHandle->KeyQueryTable[3].QueryRoutine) == NULL)
|
||
|
{
|
||
|
//
|
||
|
// protocols
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Open the current key and lookup the Nth subkey. But first conver the service relative
|
||
|
// path to absolute since this is what ZwOpenKey expects.
|
||
|
//
|
||
|
RtlInitUnicodeString(&Services, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Adapters
|
||
|
//
|
||
|
// for adapters, first we have to open the key for PDO
|
||
|
//
|
||
|
|
||
|
PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
|
||
|
|
||
|
#if NDIS_TEST_REG_FAILURE
|
||
|
*Status = STATUS_UNSUCCESSFUL;
|
||
|
#else
|
||
|
|
||
|
*Status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
|
||
|
PLUGPLAY_REGKEY_DRIVER,
|
||
|
GENERIC_READ | MAXIMUM_ALLOWED,
|
||
|
&RootHandle);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (!NT_SUCCESS(*Status))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (KeyPath.Length || Services.Length)
|
||
|
{
|
||
|
AbsolutePath.MaximumLength = KeyPath.Length + Services.Length + sizeof(WCHAR);
|
||
|
AbsolutePath.Buffer = (PWSTR)ALLOC_FROM_POOL(AbsolutePath.MaximumLength, NDIS_TAG_DEFAULT);
|
||
|
if (AbsolutePath.Buffer == NULL)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_RESOURCES;
|
||
|
break;
|
||
|
}
|
||
|
NdisMoveMemory(AbsolutePath.Buffer, Services.Buffer, Services.Length);
|
||
|
AbsolutePath.Length = Services.Length;
|
||
|
RtlAppendUnicodeStringToString(&AbsolutePath, &KeyPath);
|
||
|
}
|
||
|
|
||
|
InitializeObjectAttributes(&ObjAttr,
|
||
|
&AbsolutePath,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
RootHandle,
|
||
|
NULL);
|
||
|
|
||
|
*Status = ZwOpenKey(&Handle,
|
||
|
GENERIC_READ | MAXIMUM_ALLOWED,
|
||
|
&ObjAttr);
|
||
|
|
||
|
if (!NT_SUCCESS(*Status))
|
||
|
{
|
||
|
Handle = NULL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate memory for the call to ZwEnumerateKey
|
||
|
//
|
||
|
Len = sizeof(KEY_BASIC_INFORMATION) + 256;
|
||
|
InfoBuf = (PKEY_BASIC_INFORMATION)ALLOC_FROM_POOL(Len, NDIS_TAG_DEFAULT);
|
||
|
if (InfoBuf == NULL)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_RESOURCES;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the Index(th) key, if it exists
|
||
|
//
|
||
|
*Status = ZwEnumerateKey(Handle,
|
||
|
Index,
|
||
|
KeyValueBasicInformation,
|
||
|
InfoBuf,
|
||
|
Len,
|
||
|
&Len);
|
||
|
|
||
|
if (NT_SUCCESS(*Status))
|
||
|
{
|
||
|
//
|
||
|
// This worked. Now simply pick up the name and do a NdisOpenConfigurationKeyByName on it.
|
||
|
//
|
||
|
KeyPath.Length = KeyPath.MaximumLength = (USHORT)InfoBuf->NameLength;
|
||
|
KeyPath.Buffer = InfoBuf->Name;
|
||
|
NdisOpenConfigurationKeyByName(Status,
|
||
|
ConfigurationHandle,
|
||
|
&KeyPath,
|
||
|
KeyHandle);
|
||
|
|
||
|
if (*Status == NDIS_STATUS_SUCCESS)
|
||
|
{
|
||
|
PNDIS_CONFIGURATION_HANDLE NewHandle = *(PNDIS_CONFIGURATION_HANDLE *)KeyHandle;
|
||
|
|
||
|
//
|
||
|
// The path in the new handle has the name of the key. Extract it and return to caller
|
||
|
//
|
||
|
RtlInitUnicodeString(KeyName, NewHandle->KeyQueryTable[3].Name);
|
||
|
KeyName->Buffer = (PWSTR)((PUCHAR)KeyName->Buffer + KeyName->Length - KeyPath.Length);
|
||
|
KeyName->Length = KeyPath.Length;
|
||
|
KeyName->MaximumLength = KeyPath.MaximumLength;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (AbsolutePath.Buffer != NULL)
|
||
|
{
|
||
|
FREE_POOL(AbsolutePath.Buffer);
|
||
|
}
|
||
|
|
||
|
if (InfoBuf != NULL)
|
||
|
{
|
||
|
FREE_POOL(InfoBuf);
|
||
|
}
|
||
|
|
||
|
if (RootHandle)
|
||
|
ZwClose (RootHandle);
|
||
|
|
||
|
if (Handle)
|
||
|
ZwClose (Handle);
|
||
|
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisOpenConfigurationKeyByIndex: ConfigurationHandle\n", ConfigurationHandle));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisReadConfiguration(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
OUT PNDIS_CONFIGURATION_PARAMETER * ParameterValue,
|
||
|
IN NDIS_HANDLE ConfigurationHandle,
|
||
|
IN PNDIS_STRING Keyword,
|
||
|
IN NDIS_PARAMETER_TYPE ParameterType
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to read the parameter for a configuration
|
||
|
keyword from the configuration database.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
ParameterValue - Returns the value for this keyword.
|
||
|
|
||
|
ConfigurationHandle - Handle returned by NdisOpenConfiguration. Points
|
||
|
to the parameter subkey.
|
||
|
|
||
|
Keyword - The keyword to search for.
|
||
|
|
||
|
ParameterType - Ignored on NT, specifies the type of the value.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS RegistryStatus;
|
||
|
PWSTR KeywordBuffer;
|
||
|
UINT i;
|
||
|
PNDIS_CONFIGURATION_HANDLE ConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
|
||
|
PDEVICE_OBJECT PhysicalDeviceObject;
|
||
|
HANDLE Handle = NULL;
|
||
|
PNDIS_MINIPORT_BLOCK Miniport = NULL;
|
||
|
PDEVICE_OBJECT DeviceObject;
|
||
|
PCM_PARTIAL_RESOURCE_LIST pResourceList;
|
||
|
UINT j;
|
||
|
ULONG ValueData;
|
||
|
|
||
|
#define PQueryTable ConfigHandle->KeyQueryTable
|
||
|
|
||
|
//
|
||
|
// There are some built-in parameters which can always be
|
||
|
// read, even if not present in the registry. This is the
|
||
|
// number of them.
|
||
|
//
|
||
|
#define BUILT_IN_COUNT 3
|
||
|
|
||
|
static NDIS_STRING BuiltInStrings[BUILT_IN_COUNT] =
|
||
|
{
|
||
|
NDIS_STRING_CONST ("Environment"),
|
||
|
NDIS_STRING_CONST ("ProcessorType"),
|
||
|
NDIS_STRING_CONST ("NdisVersion")
|
||
|
};
|
||
|
|
||
|
static NDIS_STRING MiniportNameStr = NDIS_STRING_CONST ("MiniportName");
|
||
|
|
||
|
#define STANDARD_RESOURCE_COUNT 9
|
||
|
//
|
||
|
// The names of the standard resource types.
|
||
|
//
|
||
|
static NDIS_STRING StandardResourceStrings[STANDARD_RESOURCE_COUNT] =
|
||
|
{
|
||
|
NDIS_STRING_CONST ("IoBaseAddress"),
|
||
|
NDIS_STRING_CONST ("InterruptNumber"),
|
||
|
NDIS_STRING_CONST ("MemoryMappedBaseAddress"),
|
||
|
NDIS_STRING_CONST ("DmaChannel"),
|
||
|
//
|
||
|
// a few drivers use non-standard keywords, so take care of them for now
|
||
|
//
|
||
|
NDIS_STRING_CONST ("IoAddress"),
|
||
|
NDIS_STRING_CONST ("Interrupt"),
|
||
|
NDIS_STRING_CONST ("IOBase"),
|
||
|
NDIS_STRING_CONST ("Irq"),
|
||
|
NDIS_STRING_CONST ("RamAddress")
|
||
|
};
|
||
|
|
||
|
UCHAR StandardResourceTypes[STANDARD_RESOURCE_COUNT]=
|
||
|
{
|
||
|
CmResourceTypePort,
|
||
|
CmResourceTypeInterrupt,
|
||
|
CmResourceTypeMemory,
|
||
|
CmResourceTypeDma,
|
||
|
CmResourceTypePort,
|
||
|
CmResourceTypeInterrupt,
|
||
|
CmResourceTypePort,
|
||
|
CmResourceTypeInterrupt,
|
||
|
CmResourceTypeMemory
|
||
|
};
|
||
|
|
||
|
static NDIS_CONFIGURATION_PARAMETER BuiltInParameters[BUILT_IN_COUNT] =
|
||
|
{ { NdisParameterInteger, NdisEnvironmentWindowsNt },
|
||
|
{ NdisParameterInteger,
|
||
|
#if defined(_M_IX86)
|
||
|
NdisProcessorX86
|
||
|
#elif defined(_M_MRX000)
|
||
|
NdisProcessorMips
|
||
|
#elif defined(_ALPHA_)
|
||
|
NdisProcessorAlpha
|
||
|
#else
|
||
|
NdisProcessorPpc
|
||
|
#endif
|
||
|
},
|
||
|
{ NdisParameterInteger, ((NDIS_MAJOR_VERSION << 16) | NDIS_MINOR_VERSION)}
|
||
|
};
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisReadConfiguration\n"));
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
(" Keyword: "));
|
||
|
DBGPRINT_UNICODE(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
Keyword);
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("\n"));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
|
||
|
do
|
||
|
{
|
||
|
KeywordBuffer = Keyword->Buffer;
|
||
|
|
||
|
//
|
||
|
// assume failure
|
||
|
//
|
||
|
RegistryStatus = STATUS_UNSUCCESSFUL;
|
||
|
|
||
|
//
|
||
|
// First check if this is one of the built-in parameters.
|
||
|
//
|
||
|
for (i = 0; i < BUILT_IN_COUNT; i++)
|
||
|
{
|
||
|
if (RtlEqualUnicodeString(Keyword, &BuiltInStrings[i], TRUE))
|
||
|
{
|
||
|
RegistryStatus = STATUS_SUCCESS;
|
||
|
*ParameterValue = &BuiltInParameters[i];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS(RegistryStatus))
|
||
|
break;
|
||
|
|
||
|
if ((Miniport = (PNDIS_MINIPORT_BLOCK)PQueryTable[3].QueryRoutine) != NULL)
|
||
|
{
|
||
|
//
|
||
|
// check to see if driver is asking for miniport name
|
||
|
//
|
||
|
if (RtlEqualUnicodeString(Keyword, &MiniportNameStr, TRUE))
|
||
|
{
|
||
|
|
||
|
RegistryStatus = ndisSaveParameters(MiniportNameStr.Buffer,
|
||
|
REG_SZ,
|
||
|
(PVOID)Miniport->MiniportName.Buffer,
|
||
|
Miniport->MiniportName.Length,
|
||
|
(PVOID)ConfigHandle,
|
||
|
(PVOID)ParameterValue);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check to see if this is a resource keyword
|
||
|
//
|
||
|
for (i = 0; i < STANDARD_RESOURCE_COUNT; i++)
|
||
|
{
|
||
|
if (RtlEqualUnicodeString(Keyword, &StandardResourceStrings[i], TRUE))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i < STANDARD_RESOURCE_COUNT)
|
||
|
{
|
||
|
|
||
|
NDIS_WARN(TRUE, Miniport, NDIS_GFLAG_WARN_LEVEL_2,
|
||
|
("NdisReadConfiguration: Miniport %p should use NdisMQueryAdapterResources to get the standard resources.\n", Miniport));
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (Miniport->AllocatedResources == NULL)
|
||
|
break;
|
||
|
|
||
|
pResourceList = &(Miniport->AllocatedResources->List[0].PartialResourceList);
|
||
|
|
||
|
//
|
||
|
// walk through resource list and find the first one that matches
|
||
|
//
|
||
|
for (j = 0; j < pResourceList->Count; j++)
|
||
|
{
|
||
|
if (pResourceList->PartialDescriptors[j].Type == StandardResourceTypes[i])
|
||
|
{
|
||
|
//
|
||
|
// could have used pResourceList->PartialDescriptors[j].Generic.Start.LowPart for all
|
||
|
// cases, but in the future, memory value can be 64 bit
|
||
|
//
|
||
|
|
||
|
switch (StandardResourceTypes[i])
|
||
|
{
|
||
|
|
||
|
case CmResourceTypePort:
|
||
|
ValueData = pResourceList->PartialDescriptors[j].u.Port.Start.LowPart;
|
||
|
break;
|
||
|
|
||
|
case CmResourceTypeInterrupt:
|
||
|
ValueData = pResourceList->PartialDescriptors[j].u.Interrupt.Level;
|
||
|
break;
|
||
|
|
||
|
case CmResourceTypeMemory:
|
||
|
ValueData = pResourceList->PartialDescriptors[j].u.Memory.Start.LowPart;
|
||
|
break;
|
||
|
|
||
|
case CmResourceTypeDma:
|
||
|
ValueData = pResourceList->PartialDescriptors[j].u.Dma.Channel;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// call SaveParameter ourselves
|
||
|
//
|
||
|
RegistryStatus = ndisSaveParameters(StandardResourceStrings[i].Buffer,
|
||
|
REG_DWORD,
|
||
|
(PVOID)&ValueData,
|
||
|
sizeof(ULONG),
|
||
|
(PVOID)ConfigHandle,
|
||
|
(PVOID)ParameterValue);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j >= pResourceList->Count)
|
||
|
{
|
||
|
RegistryStatus = STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
//
|
||
|
// if keyword was a standard resource keyword, we should break here
|
||
|
// no matter what the outcome of finding the resource in resource list
|
||
|
//
|
||
|
break;
|
||
|
} // end of if it was a resource keyword
|
||
|
|
||
|
} // end of if NdisReadConfiguration called for a miniport
|
||
|
|
||
|
//
|
||
|
// the keyword was not a standard resource or built-in keyword
|
||
|
// get back to our regular programming...
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Allocate room for a null-terminated version of the keyword
|
||
|
//
|
||
|
if (Keyword->MaximumLength < (Keyword->Length + sizeof(WCHAR)))
|
||
|
{
|
||
|
KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
|
||
|
if (KeywordBuffer == NULL)
|
||
|
{
|
||
|
RegistryStatus = STATUS_UNSUCCESSFUL;;
|
||
|
break;
|
||
|
}
|
||
|
CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
|
||
|
}
|
||
|
|
||
|
if (*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) != (WCHAR)L'\0')
|
||
|
{
|
||
|
*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
|
||
|
}
|
||
|
|
||
|
|
||
|
PQueryTable[1].Name = KeywordBuffer;
|
||
|
PQueryTable[1].EntryContext = ParameterValue;
|
||
|
|
||
|
if (Miniport != NULL)
|
||
|
{
|
||
|
PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
|
||
|
|
||
|
//
|
||
|
// set the subkey
|
||
|
//
|
||
|
PQueryTable[0].Name = PQueryTable[3].Name;
|
||
|
|
||
|
#if NDIS_TEST_REG_FAILURE
|
||
|
RegistryStatus = STATUS_UNSUCCESSFUL;
|
||
|
#else
|
||
|
RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
|
||
|
PLUGPLAY_REGKEY_DRIVER,
|
||
|
GENERIC_READ | MAXIMUM_ALLOWED,
|
||
|
&Handle);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if(NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
|
||
|
Handle,
|
||
|
PQueryTable,
|
||
|
ConfigHandle, // context
|
||
|
NULL);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// protocols
|
||
|
//
|
||
|
RegistryStatus = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
|
||
|
PQueryTable[3].Name,
|
||
|
PQueryTable,
|
||
|
ConfigHandle, // context
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
//
|
||
|
// if a value is stored in registry as string but the driver is trying
|
||
|
// to read it as Integer or HexInteger, do the conversion here
|
||
|
//
|
||
|
|
||
|
if ((*ParameterValue)->ParameterType == NdisParameterString)
|
||
|
{
|
||
|
if (ParameterType == NdisParameterInteger)
|
||
|
{
|
||
|
RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
|
||
|
10, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
|
||
|
(*ParameterValue)->ParameterType = NdisParameterInteger;
|
||
|
}
|
||
|
else if (ParameterType == NdisParameterHexInteger)
|
||
|
{
|
||
|
RtlUnicodeStringToInteger(&(*ParameterValue)->ParameterData.StringData,
|
||
|
16, (PULONG)(&(*ParameterValue)->ParameterData.IntegerData));
|
||
|
(*ParameterValue)->ParameterType = NdisParameterHexInteger;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (KeywordBuffer != Keyword->Buffer)
|
||
|
{
|
||
|
FREE_POOL(KeywordBuffer); // no longer needed
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*Status = NDIS_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
if (Handle)
|
||
|
ZwClose(Handle);
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisReadConfiguration\n"));
|
||
|
|
||
|
#undef PQueryTable
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisWriteConfiguration(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN NDIS_HANDLE ConfigurationHandle,
|
||
|
IN PNDIS_STRING Keyword,
|
||
|
PNDIS_CONFIGURATION_PARAMETER ParameterValue
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to write a parameter to the configuration database.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
ConfigurationHandle - Handle passed to the driver
|
||
|
|
||
|
Keyword - The keyword to set.
|
||
|
|
||
|
ParameterValue - Specifies the new value for this keyword.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
|
||
|
NTSTATUS RegistryStatus;
|
||
|
PNDIS_MINIPORT_BLOCK Miniport;
|
||
|
PWSTR KeywordBuffer;
|
||
|
BOOLEAN FreeKwBuf = FALSE;
|
||
|
PVOID ValueData;
|
||
|
ULONG ValueLength;
|
||
|
ULONG ValueType;
|
||
|
PDEVICE_OBJECT PhysicalDeviceObject;
|
||
|
HANDLE Handle, RootHandle;
|
||
|
OBJECT_ATTRIBUTES ObjAttr;
|
||
|
UNICODE_STRING RelativePath;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
*Status = NDIS_STATUS_SUCCESS;
|
||
|
KeywordBuffer = Keyword->Buffer;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// Get the value data.
|
||
|
//
|
||
|
switch (ParameterValue->ParameterType)
|
||
|
{
|
||
|
case NdisParameterHexInteger:
|
||
|
case NdisParameterInteger:
|
||
|
ValueData = &ParameterValue->ParameterData.IntegerData;
|
||
|
ValueLength = sizeof(ParameterValue->ParameterData.IntegerData);
|
||
|
ValueType = REG_DWORD;
|
||
|
break;
|
||
|
|
||
|
case NdisParameterString:
|
||
|
ValueData = ParameterValue->ParameterData.StringData.Buffer;
|
||
|
ValueLength = ParameterValue->ParameterData.StringData.Length;
|
||
|
ValueType = REG_SZ;
|
||
|
break;
|
||
|
|
||
|
case NdisParameterMultiString:
|
||
|
ValueData = ParameterValue->ParameterData.StringData.Buffer;
|
||
|
ValueLength = ParameterValue->ParameterData.StringData.Length;
|
||
|
ValueType = REG_MULTI_SZ;
|
||
|
break;
|
||
|
|
||
|
case NdisParameterBinary:
|
||
|
ValueData = ParameterValue->ParameterData.BinaryData.Buffer;
|
||
|
ValueLength = ParameterValue->ParameterData.BinaryData.Length;
|
||
|
ValueType = REG_BINARY;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
*Status = NDIS_STATUS_NOT_SUPPORTED;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (*Status != NDIS_STATUS_SUCCESS)
|
||
|
break;
|
||
|
|
||
|
if (Keyword->MaximumLength <= (Keyword->Length + sizeof(WCHAR)))
|
||
|
{
|
||
|
KeywordBuffer = (PWSTR)ALLOC_FROM_POOL(Keyword->Length + sizeof(WCHAR), NDIS_TAG_DEFAULT);
|
||
|
if (KeywordBuffer == NULL)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_RESOURCES;
|
||
|
break;
|
||
|
}
|
||
|
CopyMemory(KeywordBuffer, Keyword->Buffer, Keyword->Length);
|
||
|
FreeKwBuf = TRUE;
|
||
|
}
|
||
|
|
||
|
if (*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) != (WCHAR)L'\0')
|
||
|
{
|
||
|
*(PWCHAR)(((PUCHAR)KeywordBuffer)+Keyword->Length) = (WCHAR)L'\0';
|
||
|
}
|
||
|
|
||
|
if ((Miniport = (PNDIS_MINIPORT_BLOCK)NdisConfigHandle->KeyQueryTable[3].QueryRoutine) != NULL)
|
||
|
{
|
||
|
//
|
||
|
// Adapters
|
||
|
//
|
||
|
PhysicalDeviceObject = Miniport->PhysicalDeviceObject;
|
||
|
|
||
|
#if NDIS_TEST_REG_FAILURE
|
||
|
RegistryStatus = STATUS_UNSUCCESSFUL;
|
||
|
RootHandle = NULL;
|
||
|
#else
|
||
|
RegistryStatus = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
|
||
|
PLUGPLAY_REGKEY_DRIVER,
|
||
|
GENERIC_WRITE | MAXIMUM_ALLOWED,
|
||
|
&RootHandle);
|
||
|
|
||
|
#endif
|
||
|
if (!NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
RtlInitUnicodeString(&RelativePath, NdisConfigHandle->KeyQueryTable[3].Name);
|
||
|
|
||
|
InitializeObjectAttributes(&ObjAttr,
|
||
|
&RelativePath,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
RootHandle,
|
||
|
NULL);
|
||
|
|
||
|
RegistryStatus = ZwOpenKey(&Handle,
|
||
|
GENERIC_READ | MAXIMUM_ALLOWED,
|
||
|
&ObjAttr);
|
||
|
|
||
|
if (NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
|
||
|
Handle,
|
||
|
KeywordBuffer,
|
||
|
ValueType,
|
||
|
ValueData,
|
||
|
ValueLength);
|
||
|
|
||
|
ZwClose (Handle);
|
||
|
}
|
||
|
|
||
|
ZwClose (RootHandle);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// protocols
|
||
|
//
|
||
|
RegistryStatus = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES,
|
||
|
NdisConfigHandle->KeyQueryTable[3].Name,
|
||
|
KeywordBuffer,
|
||
|
ValueType,
|
||
|
ValueData,
|
||
|
ValueLength);
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS(RegistryStatus))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
}
|
||
|
|
||
|
} while (FALSE);
|
||
|
|
||
|
if (FreeKwBuf)
|
||
|
{
|
||
|
FREE_POOL(KeywordBuffer); // no longer needed
|
||
|
}
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisWriteConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisCloseConfiguration(
|
||
|
IN NDIS_HANDLE ConfigurationHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to close a configuration database opened by
|
||
|
NdisOpenConfiguration.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ConfigurationHandle - Handle returned by NdisOpenConfiguration.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Obtain the actual configuration handle structure
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle;
|
||
|
PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
//
|
||
|
// deallocate the parameter nodes
|
||
|
//
|
||
|
ParameterNode = NdisConfigHandle->ParameterList;
|
||
|
|
||
|
while (ParameterNode != NULL)
|
||
|
{
|
||
|
NdisConfigHandle->ParameterList = ParameterNode->Next;
|
||
|
|
||
|
FREE_POOL(ParameterNode);
|
||
|
|
||
|
ParameterNode = NdisConfigHandle->ParameterList;
|
||
|
}
|
||
|
|
||
|
FREE_POOL(ConfigurationHandle);
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisCloseConfiguration: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisReadNetworkAddress(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
OUT PVOID * NetworkAddress,
|
||
|
OUT PUINT NetworkAddressLength,
|
||
|
IN NDIS_HANDLE ConfigurationHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is used to read the "NetworkAddress" parameter
|
||
|
from the configuration database. It reads the value as a
|
||
|
string separated by hyphens, then converts it to a binary
|
||
|
array and stores the result.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
NetworkAddress - Returns a pointer to the address.
|
||
|
|
||
|
NetworkAddressLength - Returns the length of the address.
|
||
|
|
||
|
ConfigurationHandle - Handle returned by NdisOpenConfiguration. Points
|
||
|
to the parameter subkey.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NDIS_STRING NetAddrStr = NDIS_STRING_CONST("NetworkAddress");
|
||
|
PNDIS_CONFIGURATION_PARAMETER ParameterValue;
|
||
|
NTSTATUS NtStatus;
|
||
|
UCHAR ConvertArray[3];
|
||
|
PWSTR CurrentReadLoc;
|
||
|
PWSTR AddressEnd;
|
||
|
PUCHAR CurrentWriteLoc;
|
||
|
UINT TotalBytesRead;
|
||
|
ULONG TempUlong;
|
||
|
ULONG AddressLength;
|
||
|
PNDIS_MINIPORT_BLOCK Miniport;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
|
||
|
ASSERT (KeGetCurrentIrql() < DISPATCH_LEVEL);
|
||
|
|
||
|
Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_CONFIGURATION_HANDLE)ConfigurationHandle)->KeyQueryTable[3].QueryRoutine;
|
||
|
|
||
|
ASSERT(Miniport != NULL);
|
||
|
ASSERT(Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE);
|
||
|
|
||
|
if (Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
|
||
|
{
|
||
|
Miniport->MacOptions |= NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE;
|
||
|
Miniport->InfoFlags |= NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE;
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
//
|
||
|
// First read the "NetworkAddress" from the registry
|
||
|
//
|
||
|
NdisReadConfiguration(Status, &ParameterValue, ConfigurationHandle, &NetAddrStr, NdisParameterString);
|
||
|
|
||
|
if ((*Status != NDIS_STATUS_SUCCESS) ||
|
||
|
(ParameterValue->ParameterType != NdisParameterString))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If there is not an address specified then exit now.
|
||
|
//
|
||
|
if (0 == ParameterValue->ParameterData.StringData.Length)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now convert the address to binary (we do this
|
||
|
// in-place, since this allows us to use the memory
|
||
|
// already allocated which is automatically freed
|
||
|
// by NdisCloseConfiguration).
|
||
|
//
|
||
|
|
||
|
ConvertArray[2] = '\0';
|
||
|
CurrentReadLoc = (PWSTR)ParameterValue->ParameterData.StringData.Buffer;
|
||
|
CurrentWriteLoc = (PUCHAR)CurrentReadLoc;
|
||
|
TotalBytesRead = ParameterValue->ParameterData.StringData.Length;
|
||
|
AddressEnd = CurrentReadLoc + (TotalBytesRead / sizeof(WCHAR));
|
||
|
AddressLength = 0;
|
||
|
|
||
|
while ((CurrentReadLoc+2) <= AddressEnd)
|
||
|
{
|
||
|
//
|
||
|
// Copy the current two-character value into ConvertArray
|
||
|
//
|
||
|
ConvertArray[0] = (UCHAR)(*(CurrentReadLoc++));
|
||
|
ConvertArray[1] = (UCHAR)(*(CurrentReadLoc++));
|
||
|
|
||
|
//
|
||
|
// Convert it to a Ulong and update
|
||
|
//
|
||
|
NtStatus = RtlCharToInteger(ConvertArray, 16, &TempUlong);
|
||
|
|
||
|
if (!NT_SUCCESS(NtStatus))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
*(CurrentWriteLoc++) = (UCHAR)TempUlong;
|
||
|
++AddressLength;
|
||
|
|
||
|
//
|
||
|
// If the next character is a hyphen, skip it.
|
||
|
//
|
||
|
if (CurrentReadLoc < AddressEnd)
|
||
|
{
|
||
|
if (*CurrentReadLoc == (WCHAR)L'-')
|
||
|
{
|
||
|
++CurrentReadLoc;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NtStatus != NDIS_STATUS_SUCCESS)
|
||
|
break;
|
||
|
|
||
|
*Status = NDIS_STATUS_SUCCESS;
|
||
|
*NetworkAddress = ParameterValue->ParameterData.StringData.Buffer;
|
||
|
*NetworkAddressLength = AddressLength;
|
||
|
if (AddressLength == 0)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
}
|
||
|
} while (FALSE);
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisReadNetworkAddress: ConfigurationHandle %p\n", ConfigurationHandle));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
NdisConvertStringToAtmAddress(
|
||
|
OUT PNDIS_STATUS Status,
|
||
|
IN PNDIS_STRING String,
|
||
|
OUT PATM_ADDRESS AtmAddress
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Status - Returns the status of the request.
|
||
|
|
||
|
String - String representation of the atm address.
|
||
|
|
||
|
* Format defined in Section 5.4,
|
||
|
* "Example Master File Format" in ATM95-1532R4 ATM Name System:
|
||
|
*
|
||
|
* AESA format: a string of hexadecimal digits, with '.' characters for punctuation, e.g.
|
||
|
*
|
||
|
* 39.246f.00.0e7c9c.0312.0001.0001.000012345678.00
|
||
|
*
|
||
|
* E164 format: A '+' character followed by a string of
|
||
|
* decimal digits, with '.' chars for punctuation, e.g.:
|
||
|
*
|
||
|
* +358.400.1234567
|
||
|
|
||
|
AtmAddress - The converted Atm address is returned here.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
USHORT i, j, NumDigits;
|
||
|
PWSTR p, q;
|
||
|
UNICODE_STRING Us;
|
||
|
ANSI_STRING As;
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("==>NdisConvertStringToAtmAddress\n"));
|
||
|
|
||
|
//
|
||
|
// Start off by stripping the punctuation characters from the string. We do this in place.
|
||
|
//
|
||
|
for (i = NumDigits = 0, j = String->Length/sizeof(WCHAR), p = q = String->Buffer;
|
||
|
(i < j) && (*p != 0);
|
||
|
i++, p++)
|
||
|
{
|
||
|
if ((*p == ATM_ADDR_BLANK_CHAR) ||
|
||
|
(*p == ATM_ADDR_PUNCTUATION_CHAR))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
*q++ = *p;
|
||
|
NumDigits ++;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Look at the first character to determine if the address is E.164 or NSAP.
|
||
|
// If the address isn't long enough, we assume that it is native E.164.
|
||
|
//
|
||
|
p = String->Buffer;
|
||
|
if ((*p == ATM_ADDR_E164_START_CHAR) || (NumDigits <= 15))
|
||
|
{
|
||
|
if (*p == ATM_ADDR_E164_START_CHAR)
|
||
|
{
|
||
|
p ++;
|
||
|
NumDigits --;
|
||
|
}
|
||
|
if ((NumDigits == 0) || (NumDigits > ATM_ADDRESS_LENGTH))
|
||
|
{
|
||
|
*Status = NDIS_STATUS_INVALID_LENGTH;
|
||
|
return;
|
||
|
}
|
||
|
AtmAddress->AddressType = ATM_E164;
|
||
|
AtmAddress->NumberOfDigits = NumDigits;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (NumDigits != 2*ATM_ADDRESS_LENGTH)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_INVALID_LENGTH;
|
||
|
return;
|
||
|
}
|
||
|
AtmAddress->AddressType = ATM_NSAP;
|
||
|
AtmAddress->NumberOfDigits = NumDigits/sizeof(WCHAR);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Convert the address to Ansi now
|
||
|
//
|
||
|
Us.Buffer = p;
|
||
|
Us.Length = Us.MaximumLength = NumDigits*sizeof(WCHAR);
|
||
|
As.Buffer = ALLOC_FROM_POOL(NumDigits + 1, NDIS_TAG_CO);
|
||
|
As.Length = 0;
|
||
|
As.MaximumLength = NumDigits + 1;
|
||
|
if (As.Buffer == NULL)
|
||
|
{
|
||
|
*Status = NDIS_STATUS_RESOURCES;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
*Status = NdisUnicodeStringToAnsiString(&As, &Us);
|
||
|
if (!NT_SUCCESS(*Status))
|
||
|
{
|
||
|
FREE_POOL(As.Buffer);
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now get the bytes into the destination ATM Address structure.
|
||
|
//
|
||
|
if (AtmAddress->AddressType == ATM_E164)
|
||
|
{
|
||
|
//
|
||
|
// We just need to copy in the digits in ANSI form.
|
||
|
//
|
||
|
NdisMoveMemory(AtmAddress->Address, As.Buffer, NumDigits);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// This is in NSAP form. We need to pack the hex digits.
|
||
|
//
|
||
|
UCHAR xxString[3];
|
||
|
ULONG val;
|
||
|
|
||
|
xxString[2] = 0;
|
||
|
for (i = 0; i < ATM_ADDRESS_LENGTH; i++)
|
||
|
{
|
||
|
xxString[0] = As.Buffer[i*2];
|
||
|
xxString[1] = As.Buffer[i*2+1];
|
||
|
*Status = CHAR_TO_INT(xxString, 16, &val);
|
||
|
if (!NT_SUCCESS(*Status))
|
||
|
{
|
||
|
FREE_POOL(As.Buffer);
|
||
|
*Status = NDIS_STATUS_FAILURE;
|
||
|
return;
|
||
|
}
|
||
|
AtmAddress->Address[i] = (UCHAR)val;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FREE_POOL(As.Buffer);
|
||
|
|
||
|
DBGPRINT_RAW(DBG_COMP_REG, DBG_LEVEL_INFO,
|
||
|
("<==NdisConvertStringToAtmAddress\n"));
|
||
|
|
||
|
*Status = NDIS_STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
ndisSaveParameters(
|
||
|
IN PWSTR ValueName,
|
||
|
IN ULONG ValueType,
|
||
|
IN PVOID ValueData,
|
||
|
IN ULONG ValueLength,
|
||
|
IN PVOID Context,
|
||
|
IN PVOID EntryContext
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback routine for RtlQueryRegistryValues
|
||
|
It is called with the value for a specified parameter. It allocates
|
||
|
memory to hold the data and copies it over.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ValueName - The name of the value (ignored).
|
||
|
|
||
|
ValueType - The type of the value.
|
||
|
|
||
|
ValueData - The null-terminated data for the value.
|
||
|
|
||
|
ValueLength - The length of ValueData.
|
||
|
|
||
|
Context - Points to the head of the parameter chain.
|
||
|
|
||
|
EntryContext - A pointer to
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NDIS_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// Obtain the actual configuration handle structure
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_HANDLE NdisConfigHandle = (PNDIS_CONFIGURATION_HANDLE)Context;
|
||
|
|
||
|
//
|
||
|
// Where the user wants a pointer returned to the data.
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_PARAMETER *ParameterValue = (PNDIS_CONFIGURATION_PARAMETER *)EntryContext;
|
||
|
|
||
|
//
|
||
|
// Use this to link parameters allocated to this open
|
||
|
//
|
||
|
PNDIS_CONFIGURATION_PARAMETER_QUEUE ParameterNode;
|
||
|
|
||
|
//
|
||
|
// Size of memory to allocate for parameter node
|
||
|
//
|
||
|
UINT Size;
|
||
|
|
||
|
//
|
||
|
// Allocate our parameter node
|
||
|
//
|
||
|
Size = sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE);
|
||
|
if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ) || (ValueType == REG_BINARY))
|
||
|
{
|
||
|
Size += ValueLength;
|
||
|
}
|
||
|
|
||
|
ParameterNode = ALLOC_FROM_POOL(Size, NDIS_TAG_PARAMETER_NODE);
|
||
|
|
||
|
Status = (ParameterNode != NULL) ? NDIS_STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
|
||
|
|
||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||
|
{
|
||
|
return (NTSTATUS)Status;
|
||
|
}
|
||
|
|
||
|
*ParameterValue = &ParameterNode->Parameter;
|
||
|
|
||
|
//
|
||
|
// Map registry datatypes to ndis data types
|
||
|
//
|
||
|
if (ValueType == REG_DWORD)
|
||
|
{
|
||
|
//
|
||
|
// The registry says that the data is in a dword boundary.
|
||
|
//
|
||
|
(*ParameterValue)->ParameterType = NdisParameterInteger;
|
||
|
(*ParameterValue)->ParameterData.IntegerData = *((PULONG) ValueData);
|
||
|
}
|
||
|
else if ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ))
|
||
|
{
|
||
|
(*ParameterValue)->ParameterType =
|
||
|
(ValueType == REG_SZ) ? NdisParameterString : NdisParameterMultiString;
|
||
|
|
||
|
(*ParameterValue)->ParameterData.StringData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
|
||
|
|
||
|
CopyMemory((*ParameterValue)->ParameterData.StringData.Buffer,
|
||
|
ValueData,
|
||
|
ValueLength);
|
||
|
(*ParameterValue)->ParameterData.StringData.Length = (USHORT)ValueLength;
|
||
|
(*ParameterValue)->ParameterData.StringData.MaximumLength = (USHORT)ValueLength;
|
||
|
|
||
|
//
|
||
|
// Special fix; if a string ends in a NULL and that is included
|
||
|
// in the length, remove it.
|
||
|
//
|
||
|
if (ValueType == REG_SZ)
|
||
|
{
|
||
|
if ((((PUCHAR)ValueData)[ValueLength-1] == 0) &&
|
||
|
(((PUCHAR)ValueData)[ValueLength-2] == 0))
|
||
|
{
|
||
|
(*ParameterValue)->ParameterData.StringData.Length -= 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (ValueType == REG_BINARY)
|
||
|
{
|
||
|
(*ParameterValue)->ParameterType = NdisParameterBinary;
|
||
|
(*ParameterValue)->ParameterData.BinaryData.Buffer = ValueData;
|
||
|
(*ParameterValue)->ParameterData.BinaryData.Length = (USHORT)ValueLength;
|
||
|
(*ParameterValue)->ParameterData.BinaryData.Buffer = (PWSTR)((PUCHAR)ParameterNode + sizeof(NDIS_CONFIGURATION_PARAMETER_QUEUE));
|
||
|
CopyMemory((*ParameterValue)->ParameterData.BinaryData.Buffer,
|
||
|
ValueData,
|
||
|
ValueLength);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FREE_POOL(ParameterNode);
|
||
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Queue this parameter node
|
||
|
//
|
||
|
ParameterNode->Next = NdisConfigHandle->ParameterList;
|
||
|
NdisConfigHandle->ParameterList = ParameterNode;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
ndisReadParameter(
|
||
|
IN PWSTR ValueName,
|
||
|
IN ULONG ValueType,
|
||
|
IN PVOID ValueData,
|
||
|
IN ULONG ValueLength,
|
||
|
IN PVOID Context,
|
||
|
IN PVOID EntryContext
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback routine for RtlQueryRegistryValues
|
||
|
It is called with the values for the "Bind" and "Export" multi-strings
|
||
|
for a given driver. It allocates memory to hold the data and copies
|
||
|
it over.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ValueName - The name of the value ("Bind" or "Export" -- ignored).
|
||
|
|
||
|
ValueType - The type of the value (REG_MULTI_SZ -- ignored).
|
||
|
|
||
|
ValueData - The null-terminated data for the value.
|
||
|
|
||
|
ValueLength - The length of ValueData.
|
||
|
|
||
|
Context - Unused.
|
||
|
|
||
|
EntryContext - A pointer to the pointer that holds the copied data.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_SUCCESS
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PUCHAR * Data = ((PUCHAR *)EntryContext);
|
||
|
|
||
|
UNREFERENCED_PARAMETER(ValueName);
|
||
|
|
||
|
//
|
||
|
// Allocate one DWORD more and zero is out
|
||
|
//
|
||
|
*Data = ALLOC_FROM_POOL(ValueLength + sizeof(ULONG), NDIS_TAG_REG_READ_DATA_BUFFER);
|
||
|
|
||
|
if (*Data == NULL)
|
||
|
{
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
ZeroMemory(*Data, ValueLength + sizeof(ULONG));
|
||
|
CopyMemory(*Data, ValueData, ValueLength);
|
||
|
|
||
|
if (Context)
|
||
|
{
|
||
|
*((PULONG)Context) = ValueType;
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|