|
|
/*++
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; }
|