mirror of https://github.com/tongzx/nt5src
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.
1711 lines
46 KiB
1711 lines
46 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1989-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
config.c
|
|
|
|
Abstract:
|
|
|
|
This contains all routines necessary for the support of the dynamic
|
|
configuration of the ISN IPX module.
|
|
|
|
Revision History:
|
|
|
|
Sanjay Anand (SanjayAn) 19-Sept-1995
|
|
Changes to support Plug and Play
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Local functions used to access the registry.
|
|
//
|
|
|
|
NTSTATUS
|
|
IpxGetConfigValue(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
IpxGetBindingValue(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
IpxGetFrameType(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
IpxAddBind(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
IpxAddExport(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
NTSTATUS
|
|
IpxReadLinkageInformation(
|
|
IN PCONFIG Config
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,IpxGetConfiguration)
|
|
#pragma alloc_text(INIT,IpxFreeConfiguration)
|
|
|
|
#pragma alloc_text(INIT,IpxAddBind)
|
|
#pragma alloc_text(INIT,IpxAddExport)
|
|
#pragma alloc_text(INIT,IpxReadLinkageInformation)
|
|
#endif
|
|
#define MAX_PATH 260
|
|
|
|
|
|
NTSTATUS
|
|
IpxGetConfiguration (
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
OUT PCONFIG * ConfigPtr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by IPX 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 ipxcnfg.h file. A list of adapters to bind to is chained
|
|
on to the config information.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Used for logging errors.
|
|
|
|
RegistryPath - The name of IPX's node in the registry.
|
|
|
|
ConfigPtr - Returns the configuration information.
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
|
|
otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSTR RegistryPathBuffer;
|
|
PCONFIG Config;
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[CONFIG_PARAMETERS+2];
|
|
NTSTATUS Status;
|
|
ULONG Zero = 0;
|
|
ULONG One = 1;
|
|
ULONG Five = 5;
|
|
ULONG Eight = 8;
|
|
ULONG Ten = 10;
|
|
ULONG Fifteen = 15;
|
|
ULONG Fifty = 50;
|
|
ULONG DefaultSocketStart = 0x4000;
|
|
ULONG DefaultSocketEnd = 0x8000;
|
|
ULONG RipSegments = RIP_SEGMENTS;
|
|
PWSTR Parameters = L"Parameters";
|
|
struct {
|
|
PWSTR KeyName;
|
|
PULONG DefaultValue;
|
|
} ParameterValues[CONFIG_PARAMETERS] = {
|
|
{ L"DedicatedRouter", &Zero } ,
|
|
{ L"InitDatagrams", &Ten } ,
|
|
{ L"MaxDatagrams", &Fifty } ,
|
|
{ L"RipAgeTime", &Five } , // minutes
|
|
{ L"RipCount", &Five } ,
|
|
{ L"RipTimeout", &One } , // half-second
|
|
{ L"RipUsageTime", &Fifteen } , // minutes
|
|
{ L"SourceRouteUsageTime", &Ten } , // minutes
|
|
{ L"SocketUniqueness", &Eight } ,
|
|
{ L"SocketStart", &DefaultSocketStart } ,
|
|
{ L"SocketEnd", &DefaultSocketEnd } ,
|
|
{ L"VirtualNetworkNumber", &Zero } ,
|
|
{ L"MaxMemoryUsage", &Zero } ,
|
|
{ L"RipTableSize", &RipSegments } ,
|
|
{ L"VirtualNetworkOptional", &One } ,
|
|
{ L"EthernetPadToEven", &One } ,
|
|
{ L"EthernetExtraPadding", &Zero } ,
|
|
{ L"SingleNetworkActive", &Zero } ,
|
|
{ L"DisableDialoutSap", &Zero } ,
|
|
{ L"DisableDialinNetbios", &One } ,
|
|
{ L"VerifySourceAddress", &One } };
|
|
|
|
UINT i;
|
|
|
|
|
|
//
|
|
// Allocate memory for the main config structure.
|
|
//
|
|
|
|
Config = IpxAllocateMemory (sizeof(CONFIG), MEMORY_CONFIG, "Config");
|
|
if (Config == NULL) {
|
|
IpxWriteResourceErrorLog(
|
|
(PVOID)DriverObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
sizeof(CONFIG),
|
|
MEMORY_CONFIG);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Config->DeviceName.Buffer = NULL;
|
|
InitializeListHead (&Config->BindingList);
|
|
Config->DriverObject = DriverObject;
|
|
|
|
//
|
|
// Read in the NDIS binding information.
|
|
//
|
|
// IpxReadLinkageInformation expects a null-terminated path,
|
|
// so we have to create one from the UNICODE_STRING.
|
|
//
|
|
|
|
RegistryPathBuffer = (PWSTR)IpxAllocateMemory(RegistryPath->Length + sizeof(WCHAR),
|
|
MEMORY_CONFIG, "RegistryPathBuffer");
|
|
if (RegistryPathBuffer == NULL) {
|
|
IpxFreeConfiguration(Config);
|
|
IpxWriteResourceErrorLog(
|
|
(PVOID)DriverObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
RegistryPath->Length + sizeof(WCHAR),
|
|
MEMORY_CONFIG);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
|
|
*(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
|
|
|
|
Config->RegistryPathBuffer = RegistryPathBuffer;
|
|
|
|
//
|
|
// Determine what name to export and who to bind to.
|
|
//
|
|
|
|
Status = IpxReadLinkageInformation (Config);
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
//
|
|
// It logged an error if it failed.
|
|
//
|
|
IpxFreeMemory (Config->RegistryPathBuffer,
|
|
RegistryPath->Length + sizeof(WCHAR),
|
|
MEMORY_CONFIG,
|
|
"RegistryPathBuffer");
|
|
IpxFreeConfiguration(Config);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Read the per-transport (as opposed to per-binding)
|
|
// parameters.
|
|
//
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the Parameters key below IPX
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Parameters;
|
|
|
|
//
|
|
// 2-14) Call IpxGetConfigValue for each of the keys we
|
|
// care about.
|
|
//
|
|
|
|
for (i = 0; i < CONFIG_PARAMETERS; i++) {
|
|
|
|
QueryTable[i+1].QueryRoutine = IpxGetConfigValue;
|
|
QueryTable[i+1].Flags = 0;
|
|
QueryTable[i+1].Name = ParameterValues[i].KeyName;
|
|
QueryTable[i+1].EntryContext = UlongToPtr(i);
|
|
QueryTable[i+1].DefaultType = REG_DWORD;
|
|
QueryTable[i+1].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
|
|
QueryTable[i+1].DefaultLength = sizeof(ULONG);
|
|
|
|
}
|
|
|
|
//
|
|
// 15) Stop
|
|
//
|
|
|
|
QueryTable[CONFIG_PARAMETERS+1].QueryRoutine = NULL;
|
|
QueryTable[CONFIG_PARAMETERS+1].Flags = 0;
|
|
QueryTable[CONFIG_PARAMETERS+1].Name = NULL;
|
|
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
Config->RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)Config,
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
IpxFreeMemory (Config->RegistryPathBuffer,
|
|
RegistryPath->Length + sizeof(WCHAR),
|
|
MEMORY_CONFIG,
|
|
"RegistryPathBuffer");
|
|
IpxFreeConfiguration(Config);
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
905,
|
|
Status,
|
|
Parameters,
|
|
0,
|
|
NULL);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
//
|
|
// For PnP, we need to keep this path around
|
|
//
|
|
|
|
*ConfigPtr = Config;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxGetConfiguration */
|
|
|
|
|
|
VOID
|
|
IpxFreeConfiguration (
|
|
IN PCONFIG Config
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by IPX to get free any storage that was allocated
|
|
by IpxGetConfiguration in producing the specified CONFIG structure.
|
|
|
|
Arguments:
|
|
|
|
Config - A pointer to the configuration information structure.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY p;
|
|
PBINDING_CONFIG Binding;
|
|
|
|
while (!IsListEmpty (&Config->BindingList)) {
|
|
p = RemoveHeadList (&Config->BindingList);
|
|
Binding = CONTAINING_RECORD (p, BINDING_CONFIG, Linkage);
|
|
IpxFreeMemory (Binding->AdapterName.Buffer, Binding->AdapterName.MaximumLength, MEMORY_CONFIG, "NameBuffer");
|
|
IpxFreeMemory (Binding, sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
|
|
}
|
|
|
|
if (Config->DeviceName.Buffer) {
|
|
IpxFreeMemory (Config->DeviceName.Buffer, Config->DeviceName.MaximumLength, MEMORY_CONFIG, "DeviceName");
|
|
}
|
|
|
|
IpxFreeMemory (Config, sizeof(CONFIG), MEMORY_CONFIG, "Config");
|
|
|
|
} /* IpxFreeConfiguration */
|
|
|
|
|
|
NTSTATUS
|
|
IpxGetConfigValue(
|
|
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 entry in the Parameters
|
|
node to set the config values. The table is set up
|
|
so that this function will be called with correct default
|
|
values for keys that are not present.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value (ignored).
|
|
|
|
ValueType - The type of the value (REG_DWORD -- ignored).
|
|
|
|
ValueData - The data for the value.
|
|
|
|
ValueLength - The length of ValueData (ignored).
|
|
|
|
Context - A pointer to the CONFIG structure.
|
|
|
|
EntryContext - The index in Config->Parameters to save the value.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONFIG Config = (PCONFIG)Context;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
if ((ValueType != REG_DWORD) || (ValueLength != sizeof(ULONG))) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
904,
|
|
STATUS_INVALID_PARAMETER,
|
|
ValueName,
|
|
0,
|
|
NULL);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
#ifdef SUNDOWN
|
|
IPX_DEBUG (CONFIG, ("Config parameter %d, value %lx\n",
|
|
(ULONG_PTR)EntryContext, *(UNALIGNED ULONG *)ValueData));
|
|
Config->Parameters[(ULONG_PTR)EntryContext] = *(UNALIGNED ULONG *)ValueData;
|
|
#else
|
|
IPX_DEBUG (CONFIG, ("Config parameter %d, value %lx\n",
|
|
(ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData));
|
|
Config->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxGetConfigValue */
|
|
|
|
|
|
NTSTATUS
|
|
IpxGetBindingValue(
|
|
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 entry in the NetConfig\DriverNN
|
|
node to set the per-binding values. The table is set up
|
|
so that this function will be called with correct default
|
|
values for keys that are not present.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value (ignored).
|
|
|
|
ValueType - The type of the value (REG_DWORD -- ignored).
|
|
|
|
ValueData - The data for the value.
|
|
|
|
ValueLength - The length of ValueData (ignored).
|
|
|
|
Context - A pointer to the BINDING_CONFIG structure.
|
|
|
|
EntryContext - The index in Binding->Parameters to save the value.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PBINDING_CONFIG Binding = (PBINDING_CONFIG)Context;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
UNREFERENCED_PARAMETER(ValueLength);
|
|
|
|
if ((ValueType != REG_DWORD) || (ValueLength != sizeof(ULONG))) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Binding->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
903,
|
|
STATUS_INVALID_PARAMETER,
|
|
ValueName,
|
|
0,
|
|
NULL);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
#ifdef SUNDOWN
|
|
IPX_DEBUG (CONFIG, ("Binding parameter %d, value %lx\n",
|
|
(ULONG_PTR)EntryContext, *(UNALIGNED ULONG *)ValueData));
|
|
Binding->Parameters[(ULONG_PTR)EntryContext] = *(UNALIGNED ULONG *)ValueData;
|
|
#else
|
|
IPX_DEBUG (CONFIG, ("Binding parameter %d, value %lx\n",
|
|
(ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData));
|
|
Binding->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxGetBindingValue */
|
|
|
|
|
|
NTSTATUS
|
|
IpxGetFrameType(
|
|
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 of the entry in the "PktType" and
|
|
"NetworkNumber" multi-strings for a given binding.
|
|
|
|
Arguments:
|
|
|
|
ValueName - The name of the value ("PktType" or "NetworkNumber" -- 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 - A pointer to the BINDING_CONFIG structure.
|
|
|
|
EntryContext - A pointer to a count of multi-string entries.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PBINDING_CONFIG Binding = (PBINDING_CONFIG)Context;
|
|
ULONG IntegerValue;
|
|
PWCHAR Cur;
|
|
PULONG Count = (PULONG)EntryContext;
|
|
|
|
ASSERT(Binding->DriverObject != NULL);
|
|
|
|
if ((ValueType != REG_SZ) ||
|
|
(*Count >= 4)) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Binding->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
903,
|
|
STATUS_INVALID_PARAMETER,
|
|
ValueName,
|
|
0,
|
|
NULL);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
IntegerValue = 0;
|
|
for (Cur = (PWCHAR)(ValueData); ; Cur++) {
|
|
if (*Cur >= L'0' && *Cur <= L'9') {
|
|
IntegerValue = (IntegerValue * 16) + (*Cur - L'0');
|
|
} else if (*Cur >= L'A' && *Cur <= L'F') {
|
|
IntegerValue = (IntegerValue * 16) + (*Cur - L'A' + 10);
|
|
} else if (*Cur >= L'a' && *Cur <= L'f') {
|
|
IntegerValue = (IntegerValue * 16) + (*Cur - L'a' + 10);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (((PWCHAR)ValueName)[0] == L'P') {
|
|
|
|
//
|
|
// PktType. We map arcnet to 802_3 so the code around
|
|
// here can assume there are only four packets type --
|
|
// the frame type is ignored later for arcnet.
|
|
//
|
|
|
|
if ((IntegerValue > ISN_FRAME_TYPE_ARCNET) &&
|
|
(IntegerValue != ISN_FRAME_TYPE_AUTO)) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Binding->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
903,
|
|
STATUS_INVALID_PARAMETER,
|
|
ValueName,
|
|
0,
|
|
NULL);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
IPX_DEBUG (CONFIG, ("PktType(%d) is %lx\n", *Count, IntegerValue));
|
|
if (IntegerValue == ISN_FRAME_TYPE_ARCNET) {
|
|
Binding->FrameType[*Count] = ISN_FRAME_TYPE_802_3;
|
|
} else {
|
|
Binding->FrameType[*Count] = IntegerValue;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// NetworkNumber
|
|
//
|
|
|
|
IPX_DEBUG (CONFIG, ("NetworkNumber(%d) is %d\n", *Count, IntegerValue));
|
|
Binding->NetworkNumber[*Count] = IntegerValue;
|
|
|
|
}
|
|
|
|
++(*Count);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxGetFrameType */
|
|
|
|
|
|
NTSTATUS
|
|
IpxAddBind(
|
|
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 Config structure. It
|
|
also queries the per-binding information and stores it.
|
|
|
|
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.
|
|
|
|
Context - A pointer to the Config structure.
|
|
|
|
EntryContext - A pointer to a count of binds that is incremented.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONFIG Config = (PCONFIG)Context;
|
|
PBINDING_CONFIG Binding;
|
|
PULONG CurBindNum = ((PULONG)EntryContext);
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[BINDING_PARAMETERS+4];
|
|
ULONG FrameTypeCount, NetworkNumberCount;
|
|
ULONG StringLoc;
|
|
BOOLEAN AutoDetect;
|
|
ULONG AutoDetectLoc;
|
|
ULONG SlideCount;
|
|
PWCHAR NameBuffer;
|
|
NTSTATUS Status;
|
|
BOOLEAN FrameTypeUsed[ISN_FRAME_TYPE_MAX];
|
|
ULONG Zero = 0;
|
|
ULONG One = 1;
|
|
ULONG DefaultBindSap = 0x8137;
|
|
ULONG DefaultAutoDetectType = ISN_FRAME_TYPE_802_2;
|
|
WCHAR Subkey[MAX_PATH];// = L"Parameters\\Adapters\\12345678901234567890";
|
|
PWSTR ValueDataWstr = (PWSTR)ValueData;
|
|
struct {
|
|
PWSTR KeyName;
|
|
PULONG DefaultValue;
|
|
} ParameterValues[BINDING_PARAMETERS] = {
|
|
{ L"MaxPktSize", &Zero } ,
|
|
{ L"BindSap", &DefaultBindSap } ,
|
|
{ L"DefaultAutoDetectType", &DefaultAutoDetectType } ,
|
|
{ L"SourceRouting", &One } ,
|
|
{ L"SourceRouteDef", &Zero } ,
|
|
{ L"SourceRouteBcast", &Zero } ,
|
|
{ L"SourceRouteMcast", &Zero } ,
|
|
{ L"EnableFuncaddr", &One } ,
|
|
{ L"EnableWanRouter", &One } };
|
|
ULONG BindingPreference[ISN_FRAME_TYPE_MAX] = {
|
|
ISN_FRAME_TYPE_802_2,
|
|
ISN_FRAME_TYPE_802_3,
|
|
ISN_FRAME_TYPE_ETHERNET_II,
|
|
ISN_FRAME_TYPE_SNAP };
|
|
|
|
UINT i, j, k;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
|
|
|
|
Binding = (PBINDING_CONFIG)IpxAllocateMemory (sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
|
|
if (Binding == NULL) {
|
|
IpxWriteResourceErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
sizeof(BINDING_CONFIG),
|
|
MEMORY_CONFIG);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
NameBuffer = (PWCHAR)IpxAllocateMemory (ValueLength, MEMORY_CONFIG, "NameBuffer");
|
|
if (NameBuffer == NULL) {
|
|
IpxFreeMemory (Binding, sizeof(BINDING_CONFIG), MEMORY_CONFIG, "Binding");
|
|
IpxWriteResourceErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
ValueLength,
|
|
MEMORY_CONFIG);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory (NameBuffer, ValueData, ValueLength);
|
|
Binding->AdapterName.Buffer = NameBuffer;
|
|
Binding->AdapterName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
|
|
Binding->AdapterName.MaximumLength = (USHORT)ValueLength;
|
|
|
|
Binding->DriverObject = Config->DriverObject;
|
|
|
|
FrameTypeCount = 0;
|
|
NetworkNumberCount = 0;
|
|
|
|
//
|
|
// The structure is allocated OK, insert it into the list.
|
|
//
|
|
|
|
InsertTailList (&Config->BindingList, &Binding->Linkage);
|
|
++(*CurBindNum);
|
|
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the NetConfig\XXXX key below IPX
|
|
// (we construct the right name in Subkey,
|
|
// first scan back to find the \, then copy
|
|
// the rest over, including the final '\0').
|
|
//
|
|
|
|
StringLoc = (ValueLength / sizeof(WCHAR)) - 2;
|
|
while (ValueDataWstr[StringLoc] != L'\\') {
|
|
--StringLoc;
|
|
}
|
|
|
|
RtlCopyMemory(&Subkey, L"Parameters\\Adapters\\12345678901234567890", 40);
|
|
RtlCopyMemory(&Subkey[20], &ValueDataWstr[StringLoc+1], ValueLength - ((StringLoc+1) * sizeof(WCHAR)));
|
|
KdPrint(("Subkey:%ws\n", Subkey));
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 2) Call IpxGetFrameType for each part of the
|
|
// "PktType" multi-string.
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = IpxGetFrameType;
|
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[1].Name = L"PktType";
|
|
QueryTable[1].EntryContext = &FrameTypeCount;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 3) Call IpxGetFrameType for each part of the
|
|
// "NetworkNumber" multi-string.
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = IpxGetFrameType;
|
|
QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[2].Name = L"NetworkNumber";
|
|
QueryTable[2].EntryContext = &NetworkNumberCount;
|
|
QueryTable[2].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 4-11) Call IpxGetBindingValue for each of the keys we
|
|
// care about.
|
|
//
|
|
|
|
for (i = 0; i < BINDING_PARAMETERS; i++) {
|
|
|
|
QueryTable[i+3].QueryRoutine = IpxGetBindingValue;
|
|
QueryTable[i+3].Flags = 0;
|
|
QueryTable[i+3].Name = ParameterValues[i].KeyName;
|
|
QueryTable[i+3].EntryContext = UlongToPtr(i);
|
|
QueryTable[i+3].DefaultType = REG_DWORD;
|
|
QueryTable[i+3].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
|
|
QueryTable[i+3].DefaultLength = sizeof(ULONG);
|
|
|
|
}
|
|
|
|
//
|
|
// 12) Stop
|
|
//
|
|
|
|
QueryTable[BINDING_PARAMETERS+3].QueryRoutine = NULL;
|
|
QueryTable[BINDING_PARAMETERS+3].Flags = 0;
|
|
QueryTable[BINDING_PARAMETERS+3].Name = NULL;
|
|
|
|
|
|
IPX_DEBUG (CONFIG, ("Read bind key for %ws (%ws)\n", ValueData, Subkey));
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
Config->RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)Binding,
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
//
|
|
// The binding will get freed during cleanup.
|
|
//
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
906,
|
|
Status,
|
|
Subkey,
|
|
0,
|
|
NULL);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
if (FrameTypeCount == 0) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_NO_FRAME_TYPES,
|
|
907,
|
|
Status,
|
|
Subkey + 10,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
if (FrameTypeCount > NetworkNumberCount) {
|
|
for (i = NetworkNumberCount; i <FrameTypeCount; i++) {
|
|
Binding->NetworkNumber[i] = 0;
|
|
}
|
|
}
|
|
Binding->FrameTypeCount = FrameTypeCount;
|
|
|
|
//
|
|
// Go through and eliminate duplicates from the frame
|
|
// type array.
|
|
//
|
|
|
|
for (i = 0; i < Binding->FrameTypeCount; i++) {
|
|
|
|
for (j = i+1; j < Binding->FrameTypeCount; j++) {
|
|
|
|
if (Binding->FrameType[j] == Binding->FrameType[i]) {
|
|
|
|
IPX_DEBUG (CONFIG, ("Frame types %d and %d identical\n", i, j));
|
|
|
|
//
|
|
// A duplicate, slide everything else down.
|
|
//
|
|
|
|
for (k = j+1; k < Binding->FrameTypeCount; k++) {
|
|
Binding->FrameType[k-1] = Binding->FrameType[k];
|
|
Binding->NetworkNumber[k-1] = Binding->NetworkNumber[k];
|
|
}
|
|
--Binding->FrameTypeCount;
|
|
|
|
--j; // so we check whoever just moved into this spot.
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Mark all the explicitly configured frame types, and
|
|
// see if we have to auto-detect.
|
|
//
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
FrameTypeUsed[i] = FALSE;
|
|
}
|
|
|
|
AutoDetect = FALSE;
|
|
for (i = 0; i < Binding->FrameTypeCount; i++) {
|
|
if (Binding->FrameType[i] == ISN_FRAME_TYPE_AUTO) {
|
|
AutoDetectLoc = i;
|
|
AutoDetect = TRUE;
|
|
} else {
|
|
Binding->AutoDetect[i] = FALSE;
|
|
Binding->DefaultAutoDetect[i] = FALSE;
|
|
FrameTypeUsed[Binding->FrameType[i]] = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!AutoDetect) {
|
|
IPX_DEBUG (AUTO_DETECT, ("No bindings auto-detected\n"));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Slide everything that is past the auto-detect point up
|
|
// to the end.
|
|
//
|
|
|
|
SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
|
|
for (j = 3; j > 3 - SlideCount; j--) {
|
|
Binding->FrameType[j] = Binding->FrameType[j-(3-Binding->FrameTypeCount)];
|
|
Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(3-Binding->FrameTypeCount)];
|
|
Binding->AutoDetect[j] = Binding->AutoDetect[j-(3-Binding->FrameTypeCount)];
|
|
Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(3-Binding->FrameTypeCount)];
|
|
}
|
|
|
|
//
|
|
// Now fill in any frame types that are not hard-coded,
|
|
// this will start at AutoDetectLoc and exactly fill up
|
|
// the gap created when we slid things up above. We
|
|
// first put the default auto-detect at the first spot.
|
|
//
|
|
|
|
if (!FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]]) {
|
|
Binding->FrameType[AutoDetectLoc] = Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT];
|
|
Binding->NetworkNumber[AutoDetectLoc] = 0;
|
|
Binding->AutoDetect[AutoDetectLoc] = TRUE;
|
|
Binding->DefaultAutoDetect[AutoDetectLoc] = TRUE;
|
|
++AutoDetectLoc;
|
|
FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]] = TRUE;
|
|
}
|
|
|
|
//
|
|
// Now fill in the array, using the preference order in
|
|
// the BindingPreference array (this comes into effect
|
|
// because the first frame type in our list that we
|
|
// find is used).
|
|
//
|
|
|
|
for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
|
|
|
|
if (!FrameTypeUsed[BindingPreference[i]]) {
|
|
Binding->FrameType[AutoDetectLoc] = BindingPreference[i];
|
|
Binding->NetworkNumber[AutoDetectLoc] = 0;
|
|
Binding->AutoDetect[AutoDetectLoc] = TRUE;
|
|
Binding->DefaultAutoDetect[AutoDetectLoc] = FALSE;
|
|
++AutoDetectLoc;
|
|
}
|
|
}
|
|
|
|
Binding->FrameTypeCount = ISN_FRAME_TYPE_MAX;
|
|
|
|
#if DBG
|
|
for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
|
|
IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, defaultautodetect %d\n",
|
|
i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
|
|
}
|
|
#endif
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxAddBind */
|
|
|
|
|
|
NTSTATUS
|
|
IpxAddExport(
|
|
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. It
|
|
saves the first callback string in the Config 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.
|
|
|
|
Context - A pointer to the Config structure.
|
|
|
|
EntryContext - A pointer to a ULONG that goes to 1 after the
|
|
first call to this routine (so we know to ignore other ones).
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
|
|
{
|
|
PCONFIG Config = (PCONFIG)Context;
|
|
PULONG ValueReadOk = ((PULONG)EntryContext);
|
|
PWCHAR NameBuffer;
|
|
|
|
UNREFERENCED_PARAMETER(ValueName);
|
|
UNREFERENCED_PARAMETER(ValueType);
|
|
|
|
if (*ValueReadOk == 0) {
|
|
|
|
IPX_DEBUG (CONFIG, ("Read export value %ws\n", ValueData));
|
|
|
|
NameBuffer = (PWCHAR)IpxAllocateMemory (ValueLength, MEMORY_CONFIG, "DeviceName");
|
|
if (NameBuffer == NULL) {
|
|
IpxWriteResourceErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
ValueLength,
|
|
MEMORY_CONFIG);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlCopyMemory (NameBuffer, ValueData, ValueLength);
|
|
Config->DeviceName.Buffer = NameBuffer;
|
|
Config->DeviceName.Length = (USHORT)(ValueLength - sizeof(WCHAR));
|
|
Config->DeviceName.MaximumLength = (USHORT)ValueLength;
|
|
|
|
//
|
|
// Set this to ignore any other callbacks and let the
|
|
// caller know we read something.
|
|
//
|
|
|
|
*ValueReadOk = 1;
|
|
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxAddExport */
|
|
|
|
|
|
NTSTATUS
|
|
IpxReadLinkageInformation(
|
|
IN PCONFIG Config
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by IPX to read its linkage information
|
|
from the registry.
|
|
|
|
Arguments:
|
|
|
|
Config - The config structure which will have per-binding information
|
|
linked on to it.
|
|
|
|
Return Value:
|
|
|
|
The status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
|
|
PWSTR Subkey = L"Linkage";
|
|
PWSTR Bind = L"Bind";
|
|
PWSTR Export = L"Export";
|
|
ULONG ValueReadOk;
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the Linkage key below IPX
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 1) Call IpxAddExport for each string in "Export"
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = IpxAddExport;
|
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[1].Name = Export;
|
|
QueryTable[1].EntryContext = (PVOID)&ValueReadOk;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 2) Stop
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = NULL;
|
|
QueryTable[2].Flags = 0;
|
|
QueryTable[2].Name = NULL;
|
|
|
|
|
|
ValueReadOk = 0;
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
Config->RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)Config,
|
|
NULL);
|
|
|
|
if ((Status != STATUS_SUCCESS) || (ValueReadOk == 0)) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
901,
|
|
Status,
|
|
Export,
|
|
0,
|
|
NULL);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxReadLinkageInformation */
|
|
|
|
|
|
VOID
|
|
IpxWriteDefaultAutoDetectType(
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN struct _ADAPTER * Adapter,
|
|
IN ULONG FrameType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when we were unable to detect the default
|
|
auto-detect type and instead found a different one. We update
|
|
the "DefaultAutoDetectType" in the registry.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - The name of IPX's node in the registry.
|
|
|
|
Adapter - The adapter which we auto-detected on.
|
|
|
|
FrameType - The new auto-detected value.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PWSTR FullRegistryPath;
|
|
PUCHAR CurRegistryPath;
|
|
ULONG FullRegistryPathLength;
|
|
ULONG AdapterNameLength;
|
|
WCHAR Adapters[] = L"\\Parameter\\Adapters\\";
|
|
static PWCHAR FrameTypeNames[4] = { L"Ethernet II", L"802.3", L"802.2", L"SNAP" };
|
|
PWCHAR CurAdapterName;
|
|
NTSTATUS Status;
|
|
|
|
|
|
//
|
|
// We need to allocate a buffer which contains the registry path,
|
|
// followed by "\Parameters\Adapters\", followed by the adapter name, and
|
|
// then NULL-terminated.
|
|
//
|
|
|
|
CurAdapterName = &Adapter->AdapterName[(Adapter->AdapterNameLength/sizeof(WCHAR))-2];
|
|
while (*CurAdapterName != L'\\') {
|
|
--CurAdapterName;
|
|
}
|
|
|
|
// AdapterNameLength is unlikely to exceed 32-bit, RtlCopyMemory takes 32-bit only, so we cast it to ULONG
|
|
AdapterNameLength = (ULONG) (Adapter->AdapterNameLength - ((CurAdapterName - Adapter->AdapterName) * sizeof(WCHAR)) - sizeof(WCHAR));
|
|
|
|
FullRegistryPathLength = RegistryPath->Length + sizeof(Adapters) + AdapterNameLength;
|
|
|
|
FullRegistryPath = (PWSTR)IpxAllocateMemory (FullRegistryPathLength, MEMORY_CONFIG, "FullRegistryPath");
|
|
if (FullRegistryPath == NULL) {
|
|
IpxWriteResourceErrorLog(
|
|
IpxDevice->DeviceObject,
|
|
EVENT_TRANSPORT_RESOURCE_POOL,
|
|
FullRegistryPathLength,
|
|
MEMORY_CONFIG);
|
|
return;
|
|
}
|
|
|
|
CurRegistryPath = (PUCHAR)FullRegistryPath;
|
|
RtlCopyMemory (CurRegistryPath, RegistryPath->Buffer, RegistryPath->Length);
|
|
CurRegistryPath += RegistryPath->Length;
|
|
RtlCopyMemory (CurRegistryPath, Adapters, sizeof(Adapters) - sizeof(WCHAR));
|
|
CurRegistryPath += (sizeof(Adapters) - sizeof(WCHAR));
|
|
RtlCopyMemory (CurRegistryPath, CurAdapterName, AdapterNameLength);
|
|
CurRegistryPath += AdapterNameLength;
|
|
*(PWCHAR)CurRegistryPath = L'\0';
|
|
|
|
Status = RtlWriteRegistryValue(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
FullRegistryPath,
|
|
L"DefaultAutoDetectType",
|
|
REG_DWORD,
|
|
&FrameType,
|
|
sizeof(ULONG));
|
|
|
|
IpxFreeMemory (FullRegistryPath, FullRegistryPathLength, MEMORY_CONFIG, "FullRegistryPath");
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
IpxDevice->DeviceObject,
|
|
EVENT_IPX_NEW_DEFAULT_TYPE,
|
|
888,
|
|
STATUS_SUCCESS,
|
|
FrameTypeNames[FrameType],
|
|
0,
|
|
NULL);
|
|
|
|
} /* IpxWriteDefaultAutoDetectType */
|
|
|
|
|
|
//
|
|
// Vnet# and VnetOptional
|
|
//
|
|
#define VIRTUAL_NETWORK_PARAMETERS 2
|
|
|
|
NTSTATUS
|
|
IpxPnPGetVirtualNetworkNumber (
|
|
IN PCONFIG Config
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by IPX to read the virtual network number
|
|
from the registry. This is called on appearance/disappearance of an
|
|
adapter from the system. We read the registry, starting at RegistryPath,
|
|
to get the value of the VirtualNetworkNumber parameter. If it doesn't
|
|
exist, we use the default set in ipxcnfg.h file.
|
|
Adapted from IpxGetConfiguration().
|
|
|
|
Arguments:
|
|
|
|
Config - Contians the configuration information.
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS if everything OK, STATUS_DEVICE_CONFIGURATION_ERROR
|
|
otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[VIRTUAL_NETWORK_PARAMETERS+2];
|
|
NTSTATUS Status;
|
|
ULONG Zero = 0;
|
|
ULONG One = 1;
|
|
PWSTR Parameters = L"Parameters";
|
|
struct {
|
|
PWSTR KeyName;
|
|
PULONG DefaultValue;
|
|
} ParameterValues[VIRTUAL_NETWORK_PARAMETERS] = {
|
|
{ L"VirtualNetworkNumber", &Zero } ,
|
|
{ L"VirtualNetworkOptional", &One } };
|
|
UINT i;
|
|
|
|
//
|
|
// Read the virtual net number from the parameters.
|
|
//
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the Parameters key below IPX
|
|
//
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Parameters;
|
|
|
|
//
|
|
// 2) Call IpxGetConfigValue for the virtual net number key
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = IpxGetConfigValue;
|
|
QueryTable[1].Flags = 0;
|
|
QueryTable[1].Name = ParameterValues[0].KeyName;
|
|
QueryTable[1].EntryContext = (PVOID)CONFIG_VIRTUAL_NETWORK;
|
|
QueryTable[1].DefaultType = REG_DWORD;
|
|
QueryTable[1].DefaultData = (PVOID)(ParameterValues[0].DefaultValue);
|
|
QueryTable[1].DefaultLength = sizeof(ULONG);
|
|
|
|
//
|
|
// 2) Call IpxGetConfigValue for the virtual net optional key
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = IpxGetConfigValue;
|
|
QueryTable[2].Flags = 0;
|
|
QueryTable[2].Name = ParameterValues[1].KeyName;
|
|
QueryTable[2].EntryContext = (PVOID)CONFIG_VIRTUAL_OPTIONAL;
|
|
QueryTable[2].DefaultType = REG_DWORD;
|
|
QueryTable[2].DefaultData = (PVOID)(ParameterValues[1].DefaultValue);
|
|
QueryTable[2].DefaultLength = sizeof(ULONG);
|
|
|
|
//
|
|
// 15) Stop
|
|
//
|
|
|
|
QueryTable[3].QueryRoutine = NULL;
|
|
QueryTable[3].Flags = 0;
|
|
QueryTable[3].Name = NULL;
|
|
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
Config->RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)Config,
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
905,
|
|
Status,
|
|
Parameters,
|
|
0,
|
|
NULL);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
} /* IpxPnPGetNetworkNumber */
|
|
|
|
#define IPX_REG_KEY_CONFIG_NAME L"Parameters\\Adapters\\12345678901234567890"
|
|
#define IPX_REG_KEY_CONFIG_DUMMY_LENGTH 40
|
|
#define IPX_REG_KEY_CONFIG_LENGTH 20
|
|
|
|
|
|
NTSTATUS
|
|
IpxPnPGetAdapterParameters(
|
|
IN PCONFIG Config,
|
|
IN PNDIS_STRING DeviceName,
|
|
IN OUT PBINDING_CONFIG Binding
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by IPX to read the adapter-specific parameters
|
|
from the registry on PnP appearance of an adapter in the system.
|
|
We read the registry, starting at RegistryPath\NetConfig\DeviceName.
|
|
|
|
Adapted from IpxAddBind().
|
|
|
|
Arguments:
|
|
|
|
Config - Config structure - supplies the DeviceObject and RegistryPathBuffer.
|
|
|
|
DeviceName - name of the adapter that was added.
|
|
|
|
Binding - Returns the configuration information per adapter.
|
|
|
|
Return Value:
|
|
|
|
Status - STATUS_SUCCESS if everything OK, STATUS_DEVICE_CONFIGURATION_ERROR
|
|
otherwise.
|
|
|
|
--*/
|
|
{
|
|
RTL_QUERY_REGISTRY_TABLE QueryTable[BINDING_PARAMETERS+4];
|
|
ULONG FrameTypeCount, NetworkNumberCount;
|
|
ULONG StringLoc;
|
|
BOOLEAN AutoDetect;
|
|
ULONG AutoDetectLoc;
|
|
ULONG SlideCount;
|
|
PWCHAR NameBuffer;
|
|
NTSTATUS Status;
|
|
BOOLEAN FrameTypeUsed[ISN_FRAME_TYPE_MAX];
|
|
ULONG Zero = 0;
|
|
ULONG One = 1;
|
|
ULONG DefaultBindSap = 0x8137;
|
|
ULONG DefaultAutoDetectType = ISN_FRAME_TYPE_802_2;
|
|
WCHAR Subkey[MAX_PATH];// = L"NetConfig\\12345678901234567890";
|
|
struct {
|
|
PWSTR KeyName;
|
|
PULONG DefaultValue;
|
|
} ParameterValues[BINDING_PARAMETERS] = {
|
|
{ L"MaxPktSize", &Zero } ,
|
|
{ L"BindSap", &DefaultBindSap } ,
|
|
{ L"DefaultAutoDetectType", &DefaultAutoDetectType } ,
|
|
{ L"SourceRouting", &One } ,
|
|
{ L"SourceRouteDef", &Zero } ,
|
|
{ L"SourceRouteBcast", &Zero } ,
|
|
{ L"SourceRouteMcast", &Zero } ,
|
|
{ L"EnableFuncaddr", &One } ,
|
|
{ L"EnableWanRouter", &One } };
|
|
ULONG BindingPreference[ISN_FRAME_TYPE_MAX] = {
|
|
ISN_FRAME_TYPE_802_2,
|
|
ISN_FRAME_TYPE_802_3,
|
|
ISN_FRAME_TYPE_ETHERNET_II,
|
|
ISN_FRAME_TYPE_SNAP };
|
|
|
|
UINT i, j, k;
|
|
|
|
ASSERT(Binding->DriverObject != NULL);
|
|
|
|
FrameTypeCount = 0;
|
|
NetworkNumberCount = 0;
|
|
|
|
//
|
|
// The structure is allocated OK, insert it into the list.
|
|
//
|
|
|
|
// InsertTailList (&Config->BindingList, &Binding->Linkage);
|
|
// ++(*CurBindNum);
|
|
|
|
|
|
//
|
|
// Set up QueryTable to do the following:
|
|
//
|
|
|
|
//
|
|
// 1) Switch to the NetConfig\XXXX key below IPX
|
|
// (we construct the right name in Subkey,
|
|
// first scan back to find the \, then copy
|
|
// the rest over, including the final '\0').
|
|
//
|
|
StringLoc = (DeviceName->Length / sizeof(WCHAR)) - 2;
|
|
while (DeviceName->Buffer[StringLoc] != L'\\') {
|
|
--StringLoc;
|
|
}
|
|
|
|
RtlCopyMemory(&Subkey, IPX_REG_KEY_CONFIG_NAME, IPX_REG_KEY_CONFIG_DUMMY_LENGTH);
|
|
RtlCopyMemory(&Subkey[IPX_REG_KEY_CONFIG_LENGTH], &DeviceName->Buffer[StringLoc+1], DeviceName->Length - ((StringLoc+1) * sizeof(WCHAR)));
|
|
|
|
Subkey[IPX_REG_KEY_CONFIG_LENGTH + (DeviceName->Length / sizeof (WCHAR)) - (StringLoc+1) ] = L'\0';
|
|
|
|
IPX_DEBUG(CONFIG, ("Subkey:%ws\n", Subkey));
|
|
//RtlCopyMemory(&Subkey[10], &DeviceName->Buffer[StringLoc+1], DeviceName->MaximumLength - ((StringLoc+1) * sizeof(WCHAR)));
|
|
|
|
QueryTable[0].QueryRoutine = NULL;
|
|
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
|
QueryTable[0].Name = Subkey;
|
|
|
|
//
|
|
// 2) Call IpxGetFrameType for each part of the
|
|
// "PktType" multi-string.
|
|
//
|
|
|
|
QueryTable[1].QueryRoutine = IpxGetFrameType;
|
|
QueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[1].Name = L"PktType";
|
|
QueryTable[1].EntryContext = &FrameTypeCount;
|
|
QueryTable[1].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 3) Call IpxGetFrameType for each part of the
|
|
// "NetworkNumber" multi-string.
|
|
//
|
|
|
|
QueryTable[2].QueryRoutine = IpxGetFrameType;
|
|
QueryTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED;
|
|
QueryTable[2].Name = L"NetworkNumber";
|
|
QueryTable[2].EntryContext = &NetworkNumberCount;
|
|
QueryTable[2].DefaultType = REG_NONE;
|
|
|
|
//
|
|
// 4-11) Call IpxGetBindingValue for each of the keys we
|
|
// care about.
|
|
//
|
|
|
|
for (i = 0; i < BINDING_PARAMETERS; i++) {
|
|
|
|
QueryTable[i+3].QueryRoutine = IpxGetBindingValue;
|
|
QueryTable[i+3].Flags = 0;
|
|
QueryTable[i+3].Name = ParameterValues[i].KeyName;
|
|
QueryTable[i+3].EntryContext = UlongToPtr(i);
|
|
QueryTable[i+3].DefaultType = REG_DWORD;
|
|
QueryTable[i+3].DefaultData = (PVOID)(ParameterValues[i].DefaultValue);
|
|
QueryTable[i+3].DefaultLength = sizeof(ULONG);
|
|
|
|
}
|
|
|
|
//
|
|
// 12) Stop
|
|
//
|
|
|
|
QueryTable[BINDING_PARAMETERS+3].QueryRoutine = NULL;
|
|
QueryTable[BINDING_PARAMETERS+3].Flags = 0;
|
|
QueryTable[BINDING_PARAMETERS+3].Name = NULL;
|
|
|
|
|
|
IPX_DEBUG (CONFIG, ("Read bind key for %ws (%ws)\n", DeviceName->Buffer, Subkey));
|
|
|
|
Status = RtlQueryRegistryValues(
|
|
RTL_REGISTRY_ABSOLUTE,
|
|
Config->RegistryPathBuffer,
|
|
QueryTable,
|
|
(PVOID)Binding,
|
|
NULL);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
//
|
|
// The binding will get freed during cleanup.
|
|
//
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_ILLEGAL_CONFIG,
|
|
906,
|
|
Status,
|
|
Subkey,
|
|
0,
|
|
NULL);
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
if (FrameTypeCount == 0) {
|
|
|
|
IpxWriteGeneralErrorLog(
|
|
(PVOID)Config->DriverObject,
|
|
EVENT_IPX_NO_FRAME_TYPES,
|
|
907,
|
|
Status,
|
|
Subkey + 10,
|
|
0,
|
|
NULL);
|
|
}
|
|
|
|
if (FrameTypeCount > NetworkNumberCount) {
|
|
for (i = NetworkNumberCount; i <FrameTypeCount; i++) {
|
|
Binding->NetworkNumber[i] = 0;
|
|
}
|
|
}
|
|
Binding->FrameTypeCount = FrameTypeCount;
|
|
|
|
//
|
|
// Go through and eliminate duplicates from the frame
|
|
// type array.
|
|
//
|
|
|
|
for (i = 0; i < Binding->FrameTypeCount; i++) {
|
|
|
|
for (j = i+1; j < Binding->FrameTypeCount; j++) {
|
|
|
|
if (Binding->FrameType[j] == Binding->FrameType[i]) {
|
|
|
|
IPX_DEBUG (CONFIG, ("Frame types %d and %d identical\n", i, j));
|
|
|
|
//
|
|
// A duplicate, slide everything else down.
|
|
//
|
|
|
|
for (k = j+1; k < Binding->FrameTypeCount; k++) {
|
|
Binding->FrameType[k-1] = Binding->FrameType[k];
|
|
Binding->NetworkNumber[k-1] = Binding->NetworkNumber[k];
|
|
}
|
|
--Binding->FrameTypeCount;
|
|
|
|
--j; // so we check whoever just moved into this spot.
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Mark all the explicitly configured frame types, and
|
|
// see if we have to auto-detect.
|
|
//
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
FrameTypeUsed[i] = FALSE;
|
|
}
|
|
|
|
AutoDetect = FALSE;
|
|
for (i = 0; i < Binding->FrameTypeCount; i++) {
|
|
if ((Binding->FrameType[i] == ISN_FRAME_TYPE_AUTO)) {
|
|
AutoDetectLoc = i;
|
|
AutoDetect = TRUE;
|
|
} else {
|
|
Binding->AutoDetect[i] = FALSE;
|
|
Binding->DefaultAutoDetect[i] = FALSE;
|
|
FrameTypeUsed[Binding->FrameType[i]] = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!AutoDetect) {
|
|
IPX_DEBUG (AUTO_DETECT, ("No bindings auto-detected\n"));
|
|
#if DBG
|
|
for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
|
|
IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, default auto detect %d\n",
|
|
i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
|
|
}
|
|
#endif
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Slide everything that is past the auto-detect point up
|
|
// to the end.
|
|
//
|
|
|
|
//
|
|
// Fixed this loop which can spill over if the FrameTypeCount is 4 and the SlideCount > 0.
|
|
// Here, the FrameTypeCount is 1-based, whereas the indices are 0-based, we need to make
|
|
// the index 1-based for this to work. So, instead of (3-Binding->FrameTypeCount), we use
|
|
// (4-Binding->FrameTypeCount). This loop copies all the non-auto-detect frametypes down to
|
|
// the bottom of the array to make space after the last auto-detect frame-type for filling
|
|
// in the frametypes in the preference order.
|
|
//
|
|
#if 0
|
|
SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
|
|
for (j = 3; j > 3 - SlideCount; j--) {
|
|
Binding->FrameType[j] = Binding->FrameType[j-(3-Binding->FrameTypeCount)];
|
|
Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(3-Binding->FrameTypeCount)];
|
|
Binding->AutoDetect[j] = Binding->AutoDetect[j-(3-Binding->FrameTypeCount)];
|
|
Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(3-Binding->FrameTypeCount)];
|
|
}
|
|
#else
|
|
SlideCount = Binding->FrameTypeCount - AutoDetectLoc - 1;
|
|
for (j = 3; j > 3 - SlideCount; j--) {
|
|
Binding->FrameType[j] = Binding->FrameType[j-(4-Binding->FrameTypeCount)];
|
|
Binding->NetworkNumber[j] = Binding->NetworkNumber[j-(4-Binding->FrameTypeCount)];
|
|
Binding->AutoDetect[j] = Binding->AutoDetect[j-(4-Binding->FrameTypeCount)];
|
|
Binding->DefaultAutoDetect[j] = Binding->DefaultAutoDetect[j-(4-Binding->FrameTypeCount)];
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Now fill in any frame types that are not hard-coded,
|
|
// this will start at AutoDetectLoc and exactly fill up
|
|
// the gap created when we slid things up above. We
|
|
// first put the default auto-detect at the first spot.
|
|
//
|
|
|
|
if (!FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]]) {
|
|
Binding->FrameType[AutoDetectLoc] = Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT];
|
|
Binding->NetworkNumber[AutoDetectLoc] = 0;
|
|
Binding->AutoDetect[AutoDetectLoc] = TRUE;
|
|
Binding->DefaultAutoDetect[AutoDetectLoc] = TRUE;
|
|
++AutoDetectLoc;
|
|
FrameTypeUsed[Binding->Parameters[BINDING_DEFAULT_AUTO_DETECT]] = TRUE;
|
|
}
|
|
|
|
//
|
|
// Now fill in the array, using the preference order in
|
|
// the BindingPreference array (this comes into effect
|
|
// because the first frame type in our list that we
|
|
// find is used).
|
|
//
|
|
|
|
for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
|
|
|
|
if (!FrameTypeUsed[BindingPreference[i]]) {
|
|
Binding->FrameType[AutoDetectLoc] = BindingPreference[i];
|
|
Binding->NetworkNumber[AutoDetectLoc] = 0;
|
|
Binding->AutoDetect[AutoDetectLoc] = TRUE;
|
|
Binding->DefaultAutoDetect[AutoDetectLoc] = FALSE;
|
|
++AutoDetectLoc;
|
|
}
|
|
}
|
|
|
|
Binding->FrameTypeCount = ISN_FRAME_TYPE_MAX;
|
|
|
|
#if DBG
|
|
for (i = 0; i < ISN_FRAME_TYPE_MAX; i++) {
|
|
IPX_DEBUG (AUTO_DETECT, ("%d: type %d, net %d, auto %d, default auto detect %d\n",
|
|
i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i], Binding->DefaultAutoDetect[i]));
|
|
}
|
|
#endif
|
|
|
|
return STATUS_SUCCESS;
|
|
} /* IpxPnPGetAdapterParameters */
|
|
|
|
|