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.
1487 lines
38 KiB
1487 lines
38 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
nbfconfig.c
|
|
|
|
Abstract:
|
|
|
|
This contains all routines necessary for the support of the dynamic
|
|
configuration of NBF. Note that the parts of this file that are
|
|
called at initialization time will be replaced by calls to the configuration manager over time.
|
|
|
|
Author:
|
|
|
|
David Beaver (dbeaver) 13-Feb-1991
|
|
|
|
Revision History:
|
|
|
|
David Beaver (dbeaver) 1-July-1991
|
|
modified to use new tdi interface
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Local functions used to access the registry.
|
|
//
|
|
|
|
VOID
|
|
NbfFreeConfigurationInfo (
|
|
IN PCONFIG_DATA ConfigurationInfo
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfOpenParametersKey(
|
|
IN HANDLE NbfConfigHandle,
|
|
OUT PHANDLE ParametersHandle
|
|
);
|
|
|
|
VOID
|
|
NbfCloseParametersKey(
|
|
IN HANDLE ParametersHandle
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfCountEntries(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfAddBind(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfAddExport(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
VOID
|
|
NbfReadLinkageInformation(
|
|
IN PWSTR RegistryPathBuffer,
|
|
IN PCONFIG_DATA * ConfigurationInfo
|
|
);
|
|
|
|
ULONG
|
|
NbfReadSingleParameter(
|
|
IN HANDLE ParametersHandle,
|
|
IN PWCHAR ValueName,
|
|
IN ULONG DefaultValue
|
|
);
|
|
|
|
VOID
|
|
NbfWriteSingleParameter(
|
|
IN HANDLE ParametersHandle,
|
|
IN PWCHAR ValueName,
|
|
IN ULONG ValueData
|
|
);
|
|
|
|
UINT
|
|
NbfWstrLength(
|
|
IN PWSTR Wstr
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfMatchBindName(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
NbfExportAtIndex(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,NbfWstrLength)
|
|
#pragma alloc_text(PAGE,NbfConfigureTransport)
|
|
#pragma alloc_text(PAGE,NbfFreeConfigurationInfo)
|
|
#pragma alloc_text(PAGE,NbfOpenParametersKey)
|
|
#pragma alloc_text(PAGE,NbfCloseParametersKey)
|
|
#pragma alloc_text(PAGE,NbfCountEntries)
|
|
#pragma alloc_text(PAGE,NbfAddBind)
|
|
#pragma alloc_text(PAGE,NbfAddExport)
|
|
#pragma alloc_text(PAGE,NbfReadLinkageInformation)
|
|
#pragma alloc_text(PAGE,NbfReadSingleParameter)
|
|
#pragma alloc_text(PAGE,NbfWriteSingleParameter)
|
|
#endif
|
|
|
|
UINT
|
|
NbfWstrLength(
|
|
IN PWSTR Wstr
|
|
)
|
|
{
|
|
UINT Length = 0;
|
|
while (*Wstr++) {
|
|
Length += sizeof(WCHAR);
|
|
}
|
|
return Length;
|
|
}
|
|
|
|
#define InsertAdapter(ConfigurationInfo, Subscript, Name) \
|
|
{ \
|
|
PWSTR _S; \
|
|
PWSTR _N = (Name); \
|
|
UINT _L = NbfWstrLength(_N)+sizeof(WCHAR); \
|
|
_S = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, _L, NBF_MEM_TAG_DEVICE_EXPORT); \
|
|
if (_S != NULL) { \
|
|
RtlCopyMemory(_S, _N, _L); \
|
|
RtlInitUnicodeString (&(ConfigurationInfo)->Names[Subscript], _S); \
|
|
} \
|
|
}
|
|
|
|
#define InsertDevice(ConfigurationInfo, Subscript, Name) \
|
|
{ \
|
|
PWSTR _S; \
|
|
PWSTR _N = (Name); \
|
|
UINT _L = NbfWstrLength(_N)+sizeof(WCHAR); \
|
|
_S = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, _L, NBF_MEM_TAG_DEVICE_EXPORT); \
|
|
if (_S != NULL) { \
|
|
RtlCopyMemory(_S, _N, _L); \
|
|
RtlInitUnicodeString (&(ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript], _S); \
|
|
} \
|
|
}
|
|
|
|
|
|
#define RemoveAdapter(ConfigurationInfo, Subscript) \
|
|
ExFreePool ((ConfigurationInfo)->Names[Subscript].Buffer)
|
|
|
|
#define RemoveDevice(ConfigurationInfo, Subscript) \
|
|
ExFreePool ((ConfigurationInfo)->Names[(ConfigurationInfo)->DevicesOffset+Subscript].Buffer)
|
|
|
|
|
|
|
|
//
|
|
// These strings are used in various places by the registry.
|
|
//
|
|
|
|
#define DECLARE_STRING(_str_) WCHAR Str ## _str_[] = L#_str_
|
|
|
|
|
|
#define READ_HIDDEN_CONFIG(_Field) \
|
|
{ \
|
|
ConfigurationInfo->_Field = \
|
|
NbfReadSingleParameter( \
|
|
ParametersHandle, \
|
|
Str ## _Field, \
|
|
ConfigurationInfo->_Field); \
|
|
}
|
|
|
|
#define WRITE_HIDDEN_CONFIG(_Field) \
|
|
{ \
|
|
NbfWriteSingleParameter( \
|
|
ParametersHandle, \
|
|
Str ## _Field, \
|
|
ConfigurationInfo->_Field); \
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
NbfConfigureTransport (
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PCONFIG_DATA * ConfigurationInfoPtr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to get information from the configuration
|
|
management routines. We read the registry, starting at RegistryPath,
|
|
to get the parameters. If they don't exist, we use the defaults
|
|
set in nbfcnfg.h file.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - The name of NBF's node in the registry.
|
|
|
|
ConfigurationInfoPtr - A pointer to the configuration information structure.
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
|
|
otherwise.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS OpenStatus;
|
|
HANDLE ParametersHandle;
|
|
HANDLE NbfConfigHandle;
|
|
NTSTATUS Status;
|
|
ULONG Disposition;
|
|
PWSTR RegistryPathBuffer;
|
|
OBJECT_ATTRIBUTES TmpObjectAttributes;
|
|
PCONFIG_DATA ConfigurationInfo;
|
|
|
|
DECLARE_STRING(InitRequests);
|
|
DECLARE_STRING(InitLinks);
|
|
DECLARE_STRING(InitConnections);
|
|
DECLARE_STRING(InitAddressFiles);
|
|
DECLARE_STRING(InitAddresses);
|
|
|
|
DECLARE_STRING(MaxRequests);
|
|
DECLARE_STRING(MaxLinks);
|
|
DECLARE_STRING(MaxConnections);
|
|
DECLARE_STRING(MaxAddressFiles);
|
|
DECLARE_STRING(MaxAddresses);
|
|
|
|
DECLARE_STRING(InitPackets);
|
|
DECLARE_STRING(InitReceivePackets);
|
|
DECLARE_STRING(InitReceiveBuffers);
|
|
DECLARE_STRING(InitUIFrames);
|
|
|
|
DECLARE_STRING(SendPacketPoolSize);
|
|
DECLARE_STRING(ReceivePacketPoolSize);
|
|
DECLARE_STRING(MaxMemoryUsage);
|
|
|
|
DECLARE_STRING(MinimumT1Timeout);
|
|
DECLARE_STRING(DefaultT1Timeout);
|
|
DECLARE_STRING(DefaultT2Timeout);
|
|
DECLARE_STRING(DefaultTiTimeout);
|
|
DECLARE_STRING(LlcRetries);
|
|
DECLARE_STRING(LlcMaxWindowSize);
|
|
DECLARE_STRING(MaximumIncomingFrames);
|
|
|
|
DECLARE_STRING(NameQueryRetries);
|
|
DECLARE_STRING(NameQueryTimeout);
|
|
DECLARE_STRING(AddNameQueryRetries);
|
|
DECLARE_STRING(AddNameQueryTimeout);
|
|
DECLARE_STRING(GeneralRetries);
|
|
DECLARE_STRING(GeneralTimeout);
|
|
DECLARE_STRING(WanNameQueryRetries);
|
|
|
|
DECLARE_STRING(UseDixOverEthernet);
|
|
DECLARE_STRING(QueryWithoutSourceRouting);
|
|
DECLARE_STRING(AllRoutesNameRecognized);
|
|
DECLARE_STRING(MinimumSendWindowLimit);
|
|
|
|
//
|
|
// Open the registry.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&TmpObjectAttributes,
|
|
RegistryPath, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
Status = ZwCreateKey(
|
|
&NbfConfigHandle,
|
|
KEY_WRITE,
|
|
&TmpObjectAttributes,
|
|
0, // title index
|
|
NULL, // class
|
|
0, // create options
|
|
&Disposition); // disposition
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
NbfPrint1("NBF: Could not open/create NBF key: %lx\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
IF_NBFDBG (NBF_DEBUG_REGISTRY) {
|
|
NbfPrint2("%s NBF key: %lx\n",
|
|
(Disposition == REG_CREATED_NEW_KEY) ? "created" : "opened",
|
|
NbfConfigHandle);
|
|
}
|
|
|
|
|
|
OpenStatus = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);
|
|
|
|
if (OpenStatus != STATUS_SUCCESS) {
|
|
return OpenStatus;
|
|
}
|
|
|
|
//
|
|
// Read in the NDIS binding information (if none is present
|
|
// the array will be filled with all known drivers).
|
|
//
|
|
// NbfReadLinkageInformation expects a null-terminated path,
|
|
// so we have to create one from the UNICODE_STRING.
|
|
//
|
|
|
|
RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
RegistryPath->Length + sizeof(WCHAR),
|
|
NBF_MEM_TAG_REGISTRY_PATH);
|
|
if (RegistryPathBuffer == NULL) {
|
|
NbfCloseParametersKey (ParametersHandle);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
|
|
*(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
|
|
|
|
NbfReadLinkageInformation (RegistryPathBuffer, ConfigurationInfoPtr);
|
|
|
|
if (*ConfigurationInfoPtr == NULL) {
|
|
ExFreePool (RegistryPathBuffer);
|
|
NbfCloseParametersKey (ParametersHandle);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
ConfigurationInfo = *ConfigurationInfoPtr;
|
|
|
|
|
|
//
|
|
// Configure the initial values for some NBF resources.
|
|
//
|
|
|
|
ConfigurationInfo->InitRequests = 1;
|
|
ConfigurationInfo->InitLinks = 2;
|
|
ConfigurationInfo->InitConnections = 2;
|
|
ConfigurationInfo->InitAddressFiles = 0;
|
|
ConfigurationInfo->InitAddresses = 0;
|
|
|
|
//
|
|
// These are the initial values; remember that the
|
|
// resources above also allocate some of these each
|
|
// time they are allocated (shown in the comment).
|
|
//
|
|
|
|
ConfigurationInfo->InitPackets = 30; // + link + 2*conn
|
|
ConfigurationInfo->InitReceivePackets = 10; // + link + addr
|
|
ConfigurationInfo->InitReceiveBuffers = 5; // + addr
|
|
ConfigurationInfo->InitUIFrames = 5; // + addr + conn
|
|
|
|
//
|
|
// Set the size of the packet pools and the total
|
|
// allocateable by NBF.
|
|
//
|
|
|
|
ConfigurationInfo->SendPacketPoolSize = 100;
|
|
ConfigurationInfo->ReceivePacketPoolSize = 30;
|
|
ConfigurationInfo->MaxMemoryUsage = 0; // no limit
|
|
|
|
|
|
//
|
|
// Now initialize the timeout etc. values.
|
|
//
|
|
|
|
ConfigurationInfo->MinimumT1Timeout = DLC_MINIMUM_T1;
|
|
ConfigurationInfo->DefaultT1Timeout = DLC_DEFAULT_T1;
|
|
ConfigurationInfo->DefaultT2Timeout = DLC_DEFAULT_T2;
|
|
ConfigurationInfo->DefaultTiTimeout = DLC_DEFAULT_TI;
|
|
ConfigurationInfo->LlcRetries = DLC_RETRIES;
|
|
ConfigurationInfo->LlcMaxWindowSize = DLC_WINDOW_LIMIT;
|
|
ConfigurationInfo->MaximumIncomingFrames = 4;
|
|
ConfigurationInfo->NameQueryRetries = NAME_QUERY_RETRIES;
|
|
ConfigurationInfo->NameQueryTimeout = NAME_QUERY_TIMEOUT;
|
|
ConfigurationInfo->AddNameQueryRetries = ADD_NAME_QUERY_RETRIES;
|
|
ConfigurationInfo->AddNameQueryTimeout = ADD_NAME_QUERY_TIMEOUT;
|
|
ConfigurationInfo->GeneralRetries = NAME_QUERY_RETRIES;
|
|
ConfigurationInfo->GeneralTimeout = NAME_QUERY_TIMEOUT;
|
|
ConfigurationInfo->WanNameQueryRetries = WAN_NAME_QUERY_RETRIES;
|
|
|
|
ConfigurationInfo->UseDixOverEthernet = 0;
|
|
ConfigurationInfo->QueryWithoutSourceRouting = 0;
|
|
ConfigurationInfo->AllRoutesNameRecognized = 0;
|
|
ConfigurationInfo->MinimumSendWindowLimit = 2;
|
|
|
|
|
|
//
|
|
// Now read the optional "hidden" parameters; if these do
|
|
// not exist then the current values are used. Note that
|
|
// the current values will be 0 unless they have been
|
|
// explicitly initialized above.
|
|
//
|
|
// NOTE: These macros expect "ConfigurationInfo" and
|
|
// "ParametersHandle" to exist when they are expanded.
|
|
//
|
|
|
|
READ_HIDDEN_CONFIG (InitRequests);
|
|
READ_HIDDEN_CONFIG (InitLinks);
|
|
READ_HIDDEN_CONFIG (InitConnections);
|
|
READ_HIDDEN_CONFIG (InitAddressFiles);
|
|
READ_HIDDEN_CONFIG (InitAddresses);
|
|
|
|
READ_HIDDEN_CONFIG (MaxRequests);
|
|
READ_HIDDEN_CONFIG (MaxLinks);
|
|
READ_HIDDEN_CONFIG (MaxConnections);
|
|
READ_HIDDEN_CONFIG (MaxAddressFiles);
|
|
READ_HIDDEN_CONFIG (MaxAddresses);
|
|
|
|
READ_HIDDEN_CONFIG (InitPackets);
|
|
READ_HIDDEN_CONFIG (InitReceivePackets);
|
|
READ_HIDDEN_CONFIG (InitReceiveBuffers);
|
|
READ_HIDDEN_CONFIG (InitUIFrames);
|
|
|
|
READ_HIDDEN_CONFIG (SendPacketPoolSize);
|
|
READ_HIDDEN_CONFIG (ReceivePacketPoolSize);
|
|
READ_HIDDEN_CONFIG (MaxMemoryUsage);
|
|
|
|
READ_HIDDEN_CONFIG (MinimumT1Timeout);
|
|
READ_HIDDEN_CONFIG (DefaultT1Timeout);
|
|
READ_HIDDEN_CONFIG (DefaultT2Timeout);
|
|
READ_HIDDEN_CONFIG (DefaultTiTimeout);
|
|
READ_HIDDEN_CONFIG (LlcRetries);
|
|
READ_HIDDEN_CONFIG (LlcMaxWindowSize);
|
|
READ_HIDDEN_CONFIG (MaximumIncomingFrames);
|
|
|
|
READ_HIDDEN_CONFIG (NameQueryRetries);
|
|
READ_HIDDEN_CONFIG (NameQueryTimeout);
|
|
READ_HIDDEN_CONFIG (AddNameQueryRetries);
|
|
READ_HIDDEN_CONFIG (AddNameQueryTimeout);
|
|
READ_HIDDEN_CONFIG (GeneralRetries);
|
|
READ_HIDDEN_CONFIG (GeneralTimeout);
|
|
READ_HIDDEN_CONFIG (WanNameQueryRetries);
|
|
|
|
READ_HIDDEN_CONFIG (UseDixOverEthernet);
|
|
READ_HIDDEN_CONFIG (QueryWithoutSourceRouting);
|
|
READ_HIDDEN_CONFIG (AllRoutesNameRecognized);
|
|
READ_HIDDEN_CONFIG (MinimumSendWindowLimit);
|
|
|
|
|
|
//
|
|
// Print out some config info, to make sure it is read right.
|
|
//
|
|
|
|
IF_NBFDBG (NBF_DEBUG_REGISTRY) {
|
|
NbfPrint2("Links: init %d, max %d\n",
|
|
ConfigurationInfo->InitLinks,
|
|
ConfigurationInfo->MaxLinks);
|
|
NbfPrint3("Timeouts (NBF ticks): T1 %d, T2 %d, Ti %d\n",
|
|
ConfigurationInfo->DefaultT1Timeout / SHORT_TIMER_DELTA,
|
|
ConfigurationInfo->DefaultT2Timeout / SHORT_TIMER_DELTA,
|
|
ConfigurationInfo->DefaultTiTimeout / LONG_TIMER_DELTA);
|
|
NbfPrint2("Pools: send %d, receive %d\n",
|
|
ConfigurationInfo->SendPacketPoolSize,
|
|
ConfigurationInfo->ReceivePacketPoolSize);
|
|
NbfPrint1("Max mem %d\n",
|
|
ConfigurationInfo->MaxMemoryUsage);
|
|
NbfPrint2("NQRetries %d, NQTimeout %d\n",
|
|
ConfigurationInfo->NameQueryRetries,
|
|
ConfigurationInfo->NameQueryTimeout / SHORT_TIMER_DELTA);
|
|
}
|
|
|
|
//
|
|
// Save the "hidden" parameters, these may not exist in
|
|
// the registry.
|
|
//
|
|
// NOTE: These macros expect "ConfigurationInfo" and
|
|
// "ParametersHandle" to exist when they are expanded.
|
|
//
|
|
|
|
//
|
|
// 5/22/92 - don't write the parameters that are set
|
|
// based on Size, since otherwise these will overwrite
|
|
// those values since hidden parameters are set up
|
|
// after the Size-based configuration is done.
|
|
//
|
|
|
|
WRITE_HIDDEN_CONFIG (MaxRequests);
|
|
WRITE_HIDDEN_CONFIG (MaxLinks);
|
|
WRITE_HIDDEN_CONFIG (MaxConnections);
|
|
WRITE_HIDDEN_CONFIG (MaxAddressFiles);
|
|
WRITE_HIDDEN_CONFIG (MaxAddresses);
|
|
|
|
WRITE_HIDDEN_CONFIG (MinimumT1Timeout);
|
|
WRITE_HIDDEN_CONFIG (DefaultT1Timeout);
|
|
WRITE_HIDDEN_CONFIG (DefaultT2Timeout);
|
|
WRITE_HIDDEN_CONFIG (DefaultTiTimeout);
|
|
WRITE_HIDDEN_CONFIG (LlcRetries);
|
|
WRITE_HIDDEN_CONFIG (LlcMaxWindowSize);
|
|
WRITE_HIDDEN_CONFIG (MaximumIncomingFrames);
|
|
|
|
WRITE_HIDDEN_CONFIG (NameQueryRetries);
|
|
WRITE_HIDDEN_CONFIG (NameQueryTimeout);
|
|
WRITE_HIDDEN_CONFIG (AddNameQueryRetries);
|
|
WRITE_HIDDEN_CONFIG (AddNameQueryTimeout);
|
|
WRITE_HIDDEN_CONFIG (GeneralRetries);
|
|
WRITE_HIDDEN_CONFIG (GeneralTimeout);
|
|
WRITE_HIDDEN_CONFIG (WanNameQueryRetries);
|
|
|
|
WRITE_HIDDEN_CONFIG (UseDixOverEthernet);
|
|
WRITE_HIDDEN_CONFIG (QueryWithoutSourceRouting);
|
|
WRITE_HIDDEN_CONFIG (AllRoutesNameRecognized);
|
|
|
|
// ZwFlushKey (ParametersHandle);
|
|
|
|
ExFreePool (RegistryPathBuffer);
|
|
NbfCloseParametersKey (ParametersHandle);
|
|
ZwClose (NbfConfigHandle);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfConfigureTransport */
|
|
|
|
|
|
VOID
|
|
NbfFreeConfigurationInfo (
|
|
IN PCONFIG_DATA ConfigurationInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to get free any storage that was allocated
|
|
by NbfConfigureTransport in producing the specified CONFIG_DATA structure.
|
|
|
|
Arguments:
|
|
|
|
ConfigurationInfo - A pointer to the configuration information structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
UINT i;
|
|
|
|
for (i=0; i<ConfigurationInfo->NumAdapters; i++) {
|
|
RemoveAdapter (ConfigurationInfo, i);
|
|
RemoveDevice (ConfigurationInfo, i);
|
|
}
|
|
ExFreePool (ConfigurationInfo);
|
|
|
|
} /* NbfFreeConfigurationInfo */
|
|
|
|
|
|
NTSTATUS
|
|
NbfOpenParametersKey(
|
|
IN HANDLE NbfConfigHandle,
|
|
OUT PHANDLE ParametersHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to open the NBF "Parameters" key.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle - Returns the handle used to read parameters.
|
|
|
|
Return Value:
|
|
|
|
The status of the request.
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
HANDLE ParamHandle;
|
|
PWSTR ParametersString = L"Parameters";
|
|
UNICODE_STRING ParametersKeyName;
|
|
OBJECT_ATTRIBUTES TmpObjectAttributes;
|
|
|
|
//
|
|
// Open the NBF parameters key.
|
|
//
|
|
|
|
RtlInitUnicodeString (&ParametersKeyName, ParametersString);
|
|
|
|
InitializeObjectAttributes(
|
|
&TmpObjectAttributes,
|
|
&ParametersKeyName, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NbfConfigHandle, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
|
|
Status = ZwOpenKey(
|
|
&ParamHandle,
|
|
KEY_READ,
|
|
&TmpObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
NbfPrint1("Could not open parameters key: %lx\n", Status);
|
|
return Status;
|
|
|
|
}
|
|
|
|
IF_NBFDBG (NBF_DEBUG_REGISTRY) {
|
|
NbfPrint1("Opened parameters key: %lx\n", ParamHandle);
|
|
}
|
|
|
|
|
|
*ParametersHandle = ParamHandle;
|
|
|
|
|
|
//
|
|
// All keys successfully opened or created.
|
|
//
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfOpenParametersKey */
|
|
|
|
VOID
|
|
NbfCloseParametersKey(
|
|
IN HANDLE ParametersHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to close the "Parameters" key.
|
|
It closes the handles passed in and does any other work needed.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle - The handle used to read other parameters.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ZwClose (ParametersHandle);
|
|
|
|
} /* NbfCloseParametersKey */
|
|
|
|
|
|
NTSTATUS
|
|
NbfCountEntries(
|
|
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 "Bind" and "Export" multi-strings.
|
|
It counts the number of name entries required in the
|
|
CONFIGURATION_DATA structure and then allocates it.
|
|
|
|
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 (ignored).
|
|
|
|
Context - A pointer to a pointer to the ConfigurationInfo structure.
|
|
When the "Export" callback is made this is filled in
|
|
with the allocate structure.
|
|
|
|
EntryContext - A pointer to a counter holding the total number
|
|
of name entries required.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG StringCount;
|
|
PWCHAR ValuePointer = (PWCHAR)ValueData;
|
|
PCONFIG_DATA * ConfigurationInfo = (PCONFIG_DATA *)Context;
|
|
PULONG TotalCount = ((PULONG)EntryContext);
|
|
ULONG OldTotalCount = *TotalCount;
|
|
|
|
#if DBG
|
|
ASSERT (ValueType == REG_MULTI_SZ);
|
|
#else
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
#endif
|
|
|
|
//
|
|
// Count the number of strings in the multi-string; first
|
|
// check that it is NULL-terminated to make the rest
|
|
// easier.
|
|
//
|
|
|
|
if ((ValueLength < 2) ||
|
|
(ValuePointer[(ValueLength/2)-1] != (WCHAR)'\0')) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
StringCount = 0;
|
|
while (*ValuePointer != (WCHAR)'\0') {
|
|
while (*ValuePointer != (WCHAR)'\0') {
|
|
++ValuePointer;
|
|
}
|
|
++StringCount;
|
|
++ValuePointer;
|
|
if ((ULONG)((PUCHAR)ValuePointer - (PUCHAR)ValueData) >= ValueLength) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
(*TotalCount) += StringCount;
|
|
|
|
if (*ValueName == (WCHAR)'E') {
|
|
|
|
//
|
|
// This is "Export", allocate the config data structure.
|
|
//
|
|
|
|
*ConfigurationInfo = ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
sizeof (CONFIG_DATA) +
|
|
((*TotalCount-1) * sizeof(NDIS_STRING)),
|
|
NBF_MEM_TAG_CONFIG_DATA);
|
|
|
|
if (*ConfigurationInfo == NULL) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(
|
|
*ConfigurationInfo,
|
|
sizeof(CONFIG_DATA) + ((*TotalCount-1) * sizeof(NDIS_STRING)));
|
|
|
|
(*ConfigurationInfo)->DevicesOffset = OldTotalCount;
|
|
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfCountEntries */
|
|
|
|
|
|
NTSTATUS
|
|
NbfAddBind(
|
|
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 for each piece of the "Bind" multi-string and
|
|
saves the information in a ConfigurationInfo structure.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value ("Bind" -- ignored).
|
|
|
|
ValueType - The type of the value (REG_SZ -- ignored).
|
|
|
|
ValueData - The null-terminated data for the value.
|
|
|
|
ValueLength - The length of ValueData (ignored).
|
|
|
|
Context - A pointer to the ConfigurationInfo structure.
|
|
|
|
EntryContext - A pointer to a count of binds that is incremented.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context;
|
|
PULONG CurBindNum = ((PULONG)EntryContext);
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
InsertAdapter(
|
|
ConfigurationInfo,
|
|
*CurBindNum,
|
|
(PWSTR)(ValueData));
|
|
|
|
++(*CurBindNum);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfAddBind */
|
|
|
|
|
|
NTSTATUS
|
|
NbfAddExport(
|
|
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 for each piece of the "Export" multi-string and
|
|
saves the information in a ConfigurationInfo structure.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value ("Export" -- ignored).
|
|
|
|
ValueType - The type of the value (REG_SZ -- ignored).
|
|
|
|
ValueData - The null-terminated data for the value.
|
|
|
|
ValueLength - The length of ValueData (ignored).
|
|
|
|
Context - A pointer to the ConfigurationInfo structure.
|
|
|
|
EntryContext - A pointer to a count of exports that is incremented.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONFIG_DATA ConfigurationInfo = *(PCONFIG_DATA *)Context;
|
|
PULONG CurExportNum = ((PULONG)EntryContext);
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
InsertDevice(
|
|
ConfigurationInfo,
|
|
*CurExportNum,
|
|
(PWSTR)(ValueData));
|
|
|
|
++(*CurExportNum);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfAddExport */
|
|
|
|
|
|
VOID
|
|
NbfReadLinkageInformation(
|
|
IN PWSTR RegistryPathBuffer,
|
|
IN PCONFIG_DATA * ConfigurationInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to read its linkage information
|
|
from the registry. If there is none present, then ConfigData
|
|
is filled with a list of all the adapters that are known
|
|
to NBF.
|
|
|
|
Arguments:
|
|
|
|
RegistryPathBuffer - The null-terminated root of the NBF registry tree.
|
|
|
|
ConfigurationInfo - Returns NBF's current configuration.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UINT ConfigBindings;
|
|
UINT NameCount = 0;
|
|
NTSTATUS Status;
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[6];
|
|
PWSTR Subkey = L"Linkage";
|
|
PWSTR Bind = L"Bind";
|
|
PWSTR Export = L"Export";
|
|
ULONG BindCount, ExportCount;
|
|
UINT i;
|
|
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the Linkage key below NBF
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 2) Call NbfCountEntries for the "Bind" multi-string
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = NbfCountEntries;
|
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
|
|
QueryTable[1].Name = Bind;
|
|
QueryTable[1].EntryContext = (PVOID)&NameCount;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 3) Call NbfCountEntries for the "Export" multi-string
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = NbfCountEntries;
|
|
QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
|
|
QueryTable[2].Name = Export;
|
|
QueryTable[2].EntryContext = (PVOID)&NameCount;
|
|
QueryTable[2].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 4) Call NbfAddBind for each string in "Bind"
|
|
//
|
|
|
|
QueryTable[3].QueryRoutine = NbfAddBind;
|
|
QueryTable[3].Flags = 0;
|
|
QueryTable[3].Name = Bind;
|
|
QueryTable[3].EntryContext = (PVOID)&BindCount;
|
|
QueryTable[3].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 5) Call NbfAddExport for each string in "Export"
|
|
//
|
|
|
|
QueryTable[4].QueryRoutine = NbfAddExport;
|
|
QueryTable[4].Flags = 0;
|
|
QueryTable[4].Name = Export;
|
|
QueryTable[4].EntryContext = (PVOID)&ExportCount;
|
|
QueryTable[4].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 6) Stop
|
|
//
|
|
|
|
QueryTable[5].QueryRoutine = NULL;
|
|
QueryTable[5].Flags = 0;
|
|
QueryTable[5].Name = NULL;
|
|
|
|
|
|
BindCount = 0;
|
|
ExportCount = 0;
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)ConfigurationInfo,
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Make sure that BindCount and ExportCount match, if not
|
|
// remove the extras.
|
|
//
|
|
|
|
if (BindCount < ExportCount) {
|
|
|
|
for (i=BindCount; i<ExportCount; i++) {
|
|
RemoveDevice (*ConfigurationInfo, i);
|
|
}
|
|
ConfigBindings = BindCount;
|
|
|
|
} else if (ExportCount < BindCount) {
|
|
|
|
for (i=ExportCount; i<BindCount; i++) {
|
|
RemoveAdapter (*ConfigurationInfo, i);
|
|
}
|
|
ConfigBindings = ExportCount;
|
|
|
|
} else {
|
|
|
|
ConfigBindings = BindCount; // which is equal to ExportCount
|
|
|
|
}
|
|
|
|
(*ConfigurationInfo)->NumAdapters = ConfigBindings;
|
|
|
|
} /* NbfReadLinkageInformation */
|
|
|
|
|
|
ULONG
|
|
NbfReadSingleParameter(
|
|
IN HANDLE ParametersHandle,
|
|
IN PWCHAR ValueName,
|
|
IN ULONG DefaultValue
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to read a single parameter
|
|
from the registry. If the parameter is found it is stored
|
|
in Data.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle - A pointer to the open registry.
|
|
|
|
ValueName - The name of the value to search for.
|
|
|
|
DefaultValue - The default value.
|
|
|
|
Return Value:
|
|
|
|
The value to use; will be the default if the value is not
|
|
found or is not in the correct range.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG InformationBuffer[32]; // declare ULONG to get it aligned
|
|
PKEY_VALUE_FULL_INFORMATION Information =
|
|
(PKEY_VALUE_FULL_INFORMATION)InformationBuffer;
|
|
UNICODE_STRING ValueKeyName;
|
|
ULONG InformationLength;
|
|
ULONG ReturnValue;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString (&ValueKeyName, ValueName);
|
|
|
|
Status = ZwQueryValueKey(
|
|
ParametersHandle,
|
|
&ValueKeyName,
|
|
KeyValueFullInformation,
|
|
(PVOID)Information,
|
|
sizeof (InformationBuffer),
|
|
&InformationLength);
|
|
|
|
if ((Status == STATUS_SUCCESS) &&
|
|
(Information->DataLength == sizeof(ULONG))) {
|
|
|
|
RtlCopyMemory(
|
|
(PVOID)&ReturnValue,
|
|
((PUCHAR)Information) + Information->DataOffset,
|
|
sizeof(ULONG));
|
|
|
|
if ((LONG)ReturnValue < 0) {
|
|
|
|
ReturnValue = DefaultValue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ReturnValue = DefaultValue;
|
|
|
|
}
|
|
|
|
return ReturnValue;
|
|
|
|
} /* NbfReadSingleParameter */
|
|
|
|
|
|
VOID
|
|
NbfWriteSingleParameter(
|
|
IN HANDLE ParametersHandle,
|
|
IN PWCHAR ValueName,
|
|
IN ULONG ValueData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by NBF to write a single parameter
|
|
from the registry.
|
|
|
|
Arguments:
|
|
|
|
ParametersHandle - A pointer to the open registry.
|
|
|
|
ValueName - The name of the value to store.
|
|
|
|
ValueData - The data to store at the value.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNICODE_STRING ValueKeyName;
|
|
NTSTATUS Status;
|
|
ULONG TmpValueData = ValueData;
|
|
|
|
RtlInitUnicodeString (&ValueKeyName, ValueName);
|
|
|
|
Status = ZwSetValueKey(
|
|
ParametersHandle,
|
|
&ValueKeyName,
|
|
0,
|
|
REG_DWORD,
|
|
(PVOID)&TmpValueData,
|
|
sizeof(ULONG));
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
NbfPrint1("NBF: Could not write dword key: %lx\n", Status);
|
|
}
|
|
|
|
} /* NbfWriteSingleParameter */
|
|
|
|
|
|
NTSTATUS
|
|
NbfGetExportNameFromRegistry(
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PUNICODE_STRING BindName,
|
|
OUT PUNICODE_STRING ExportName
|
|
)
|
|
{
|
|
NTSTATUS OpenStatus;
|
|
HANDLE ParametersHandle;
|
|
HANDLE NbfConfigHandle;
|
|
NTSTATUS Status;
|
|
PWSTR RegistryPathBuffer;
|
|
OBJECT_ATTRIBUTES TmpObjectAttributes;
|
|
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
|
PWSTR Subkey = L"Linkage";
|
|
PWSTR Bind = L"Bind";
|
|
PWSTR Export = L"Export";
|
|
LONG BindNumber;
|
|
|
|
//
|
|
// Open the registry.
|
|
//
|
|
|
|
InitializeObjectAttributes(
|
|
&TmpObjectAttributes,
|
|
RegistryPath, // name
|
|
OBJ_CASE_INSENSITIVE, // attributes
|
|
NULL, // root
|
|
NULL // security descriptor
|
|
);
|
|
|
|
OpenStatus = ZwOpenKey(
|
|
&NbfConfigHandle,
|
|
KEY_WRITE,
|
|
&TmpObjectAttributes
|
|
);
|
|
|
|
if (!NT_SUCCESS(OpenStatus)) {
|
|
NbfPrint1("NBF: Could not open NBF key: %lx\n", OpenStatus);
|
|
return OpenStatus;
|
|
}
|
|
|
|
Status = NbfOpenParametersKey (NbfConfigHandle, &ParametersHandle);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
ZwClose (NbfConfigHandle);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// NbfReadLinkageInformation expects a null-terminated path,
|
|
// so we have to create one from the UNICODE_STRING.
|
|
//
|
|
|
|
RegistryPathBuffer = (PWSTR)ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
RegistryPath->Length + sizeof(WCHAR),
|
|
NBF_MEM_TAG_REGISTRY_PATH);
|
|
|
|
if (RegistryPathBuffer == NULL) {
|
|
NbfCloseParametersKey (ParametersHandle);
|
|
ZwClose (NbfConfigHandle);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
|
|
*(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
|
|
|
|
//
|
|
// We have a new device whose binding was absent
|
|
// at boot - get export name given the bind name
|
|
//
|
|
|
|
// First we need to get index of the bind name
|
|
|
|
// Set up QueryTable to do the following:
|
|
|
|
//
|
|
// 1) Switch to the Linkage key below NBF
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 2) Call NbfMatchBindName for each string in "Bind"
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = NbfMatchBindName;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = Bind;
|
|
QueryTable[1].EntryContext = (PVOID)&BindNumber;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 3) Stop
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = NULL;
|
|
QueryTable[2].Flags = 0;
|
|
QueryTable[2].Name = NULL;
|
|
|
|
|
|
BindNumber = -1;
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)BindName,
|
|
NULL);
|
|
|
|
IF_NBFDBG (NBF_DEBUG_PNP) {
|
|
NbfPrint2 ("Status from NbfMatchBindName's = %08x, Bind Number = %d\n",
|
|
Status, BindNumber);
|
|
}
|
|
|
|
if (Status != STATUS_NO_MORE_MATCHES)
|
|
{
|
|
#if DBG
|
|
DbgBreakPoint();
|
|
#endif
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
// We did not find the device 'bind name'
|
|
Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
|
|
|
|
IF_NBFDBG (NBF_DEBUG_PNP) {
|
|
NbfPrint1 ("NBF - cannot find dynamic binding %S\n", BindName->Buffer);
|
|
}
|
|
}
|
|
|
|
goto Done;
|
|
}
|
|
|
|
ASSERT(BindNumber >= 0);
|
|
|
|
// First we need to get export name given index
|
|
|
|
// Set up QueryTable to do the following:
|
|
|
|
//
|
|
// 1) Switch to the Linkage key below NBF
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 2) Call NbfAddExport for each string in "Export"
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = NbfExportAtIndex;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = Export;
|
|
QueryTable[1].EntryContext = (PVOID)&BindNumber;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 3) Stop
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = NULL;
|
|
QueryTable[2].Flags = 0;
|
|
QueryTable[2].Name = NULL;
|
|
|
|
RtlInitUnicodeString(ExportName, NULL);
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)ExportName,
|
|
NULL);
|
|
|
|
IF_NBFDBG (NBF_DEBUG_PNP) {
|
|
NbfPrint2("Status from NbfExportAtIndex's = %08x, ExportLength = %d\n",
|
|
Status,
|
|
ExportName->Length);
|
|
|
|
if (ExportName->Length > 0)
|
|
{
|
|
NbfPrint1("ExportName = %S\n", ExportName->Buffer);
|
|
}
|
|
}
|
|
|
|
if (ExportName->Length != 0) {
|
|
|
|
ASSERT(Status == STATUS_NO_MORE_MATCHES);
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
|
|
// We found the bind, but no corr export
|
|
Status = NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER;
|
|
}
|
|
|
|
Done:
|
|
|
|
ExFreePool (RegistryPathBuffer);
|
|
|
|
NbfCloseParametersKey (ParametersHandle);
|
|
|
|
ZwClose (NbfConfigHandle);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NbfMatchBindName(
|
|
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 for each piece of the "Bind" multi-string and
|
|
tries to match a given bind name with each of these pieces.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value ("Bind" -- ignored).
|
|
|
|
ValueType - The type of the value (REG_SZ -- ignored).
|
|
|
|
ValueData - The null-terminated data for the value.
|
|
|
|
ValueLength - The length of ValueData (ignored).
|
|
|
|
Context - Bind name that we are trying to match.
|
|
|
|
EntryContext - A pointer where index of the match is stored.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PUNICODE_STRING BindName = (PUNICODE_STRING) Context;
|
|
PLONG CurBindNum = (PLONG) EntryContext;
|
|
UNICODE_STRING ValueString;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
RtlInitUnicodeString(&ValueString, ValueData);
|
|
|
|
// We are yet to find a match
|
|
|
|
(*CurBindNum)++ ;
|
|
|
|
if (NdisEqualString(BindName, &ValueString, TRUE)) {
|
|
return STATUS_NO_MORE_MATCHES;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfMatchBindName */
|
|
|
|
NTSTATUS
|
|
NbfExportAtIndex(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
)
|
|
{
|
|
PUNICODE_STRING ExportName = (PUNICODE_STRING) Context;
|
|
PLONG CurBindNum = (PLONG) EntryContext;
|
|
PWSTR ValueWideChars;
|
|
UINT ValueWideLength;
|
|
UNICODE_STRING ValueString;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
|
|
ASSERT(*CurBindNum >= 0);
|
|
|
|
if (*CurBindNum == 0)
|
|
{
|
|
ValueWideLength = NbfWstrLength(ValueData) + sizeof(WCHAR);
|
|
|
|
ValueWideChars = (PWSTR) ExAllocatePoolWithTag(NonPagedPool,
|
|
ValueWideLength,
|
|
NBF_MEM_TAG_DEVICE_EXPORT);
|
|
if (ValueWideChars == NULL)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory (ValueWideChars, ValueData, ValueWideLength);
|
|
|
|
RtlInitUnicodeString (ExportName, ValueWideChars);
|
|
|
|
return STATUS_NO_MORE_MATCHES;
|
|
}
|
|
|
|
(*CurBindNum)-- ;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* NbfExportAtIndex */
|
|
|