diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isn/ipx/config.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/tdi/isn/ipx/config.c')
-rw-r--r-- | private/ntos/tdi/isn/ipx/config.c | 1715 |
1 files changed, 1715 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/ipx/config.c b/private/ntos/tdi/isn/ipx/config.c new file mode 100644 index 000000000..f5d8aefbf --- /dev/null +++ b/private/ntos/tdi/isn/ipx/config.c @@ -0,0 +1,1715 @@ +/*++ + + +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 (in _PNP_POWER) + +--*/ + +#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) + +#ifndef _PNP_POWER +#pragma alloc_text(INIT,IpxGetConfigValue) +#pragma alloc_text(INIT,IpxGetBindingValue) +#pragma alloc_text(INIT,IpxGetFrameType) +#pragma alloc_text(INIT,IpxWriteDefaultAutoDetectType) +#endif + +#pragma alloc_text(INIT,IpxAddBind) +#pragma alloc_text(INIT,IpxAddExport) +#pragma alloc_text(INIT,IpxReadLinkageInformation) +#endif + + + +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. + // + + 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 = (PVOID)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) { + + 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 + // +#ifndef _PNP_POWER + IpxFreeMemory (RegistryPathBuffer, RegistryPath->Length + sizeof(WCHAR), MEMORY_CONFIG, "RegistryPathBuffer"); +#endif _PNP_POWER + + *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; + } + + IPX_DEBUG (CONFIG, ("Config parameter %d, value %lx\n", + (ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData)); + Config->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData; + + 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; + } + + IPX_DEBUG (CONFIG, ("Binding parameter %d, value %lx\n", + (ULONG)EntryContext, *(UNALIGNED ULONG *)ValueData)); + Binding->Parameters[(ULONG)EntryContext] = *(UNALIGNED ULONG *)ValueData; + + 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; + + 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; + PWSTR Subkey = L"NetConfig\\12345678901234567890"; // BUGBUG: hack + 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[10], &ValueDataWstr[StringLoc+1], ValueLength - ((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 = (PVOID)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\n", + i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[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; + } + +#ifndef _PNP_POWER +// +// This will be done as and when adapters appear. +// + // + // 1) Change to call IpxAddBind for each string in "Bind" + // + + QueryTable[1].QueryRoutine = IpxAddBind; + QueryTable[1].Flags = 0; // not required + QueryTable[1].Name = Bind; + QueryTable[1].EntryContext = (PVOID)&Config->BindCount; + QueryTable[1].DefaultType = REG_NONE; + + Config->BindCount = 0; + + Status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE, + Config->RegistryPathBuffer, + QueryTable, + (PVOID)Config, + NULL); + + // + // For the moment fail if we find no bindings -- eventually when + // we support dynamic binding we should stick around in this case. + // + + if ((Status != STATUS_SUCCESS) || (Config->BindCount == 0)) { + + IpxWriteGeneralErrorLog( + (PVOID)Config->DriverObject, + EVENT_IPX_ILLEGAL_CONFIG, + 902, + Status, + Bind, + 0, + NULL); + return STATUS_DEVICE_CONFIGURATION_ERROR; + } +#endif + 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 NetConfigName[] = L"\\NetConfig"; + 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 "NetConfig", followed by the adapter name, and + // then NULL-terminated. + // + + CurAdapterName = &Adapter->AdapterName[(Adapter->AdapterNameLength/sizeof(WCHAR))-2]; + while (*CurAdapterName != L'\\') { + --CurAdapterName; + } + CurAdapterName; + AdapterNameLength = Adapter->AdapterNameLength - ((CurAdapterName - Adapter->AdapterName) * sizeof(WCHAR)) - sizeof(WCHAR); + + FullRegistryPathLength = RegistryPath->Length + sizeof(NetConfigName) + 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, NetConfigName, sizeof(NetConfigName) - sizeof(WCHAR)); + CurRegistryPath += (sizeof(NetConfigName) - 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 */ + + +#ifdef _PNP_POWER +// +// 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 */ + + +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; + PWSTR Subkey = L"NetConfig\\12345678901234567890"; // BUGBUG: hack + 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; + + 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->MaximumLength / sizeof(WCHAR)) - 2; + while (DeviceName->Buffer[StringLoc] != L'\\') { + --StringLoc; + } + 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 = (PVOID)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")); + 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\n", + i, Binding->FrameType[i], Binding->NetworkNumber[i], Binding->AutoDetect[i])); + } +#endif + + return STATUS_SUCCESS; +} /* IpxPnPGetAdapterParameters */ + +#endif _PNP_POWER + |