1278 lines
29 KiB
C
1278 lines
29 KiB
C
/*++
|
||
|
||
Copyright (c) 1989-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
stcnfg.c
|
||
|
||
Abstract:
|
||
|
||
This contains all routines necessary for the support of the dynamic
|
||
configuration of ST.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "st.h"
|
||
|
||
|
||
//
|
||
// Local functions used to access the registry.
|
||
//
|
||
|
||
NTSTATUS
|
||
StConfigureTransport (
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PCONFIG_DATA * ConfigurationInfoPtr
|
||
);
|
||
|
||
VOID
|
||
StFreeConfigurationInfo (
|
||
IN PCONFIG_DATA ConfigurationInfo
|
||
);
|
||
|
||
NTSTATUS
|
||
StOpenParametersKey(
|
||
IN HANDLE StConfigHandle,
|
||
OUT PHANDLE ParametersHandle
|
||
);
|
||
|
||
VOID
|
||
StCloseParametersKey(
|
||
IN HANDLE ParametersHandle
|
||
);
|
||
|
||
NTSTATUS
|
||
StCountEntries(
|
||
IN PWSTR ValueName,
|
||
IN ULONG ValueType,
|
||
IN PVOID ValueData,
|
||
IN ULONG ValueLength,
|
||
IN PVOID Context,
|
||
IN PVOID EntryContext
|
||
);
|
||
|
||
NTSTATUS
|
||
StAddBind(
|
||
IN PWSTR ValueName,
|
||
IN ULONG ValueType,
|
||
IN PVOID ValueData,
|
||
IN ULONG ValueLength,
|
||
IN PVOID Context,
|
||
IN PVOID EntryContext
|
||
);
|
||
|
||
NTSTATUS
|
||
StAddExport(
|
||
IN PWSTR ValueName,
|
||
IN ULONG ValueType,
|
||
IN PVOID ValueData,
|
||
IN ULONG ValueLength,
|
||
IN PVOID Context,
|
||
IN PVOID EntryContext
|
||
);
|
||
|
||
VOID
|
||
StReadLinkageInformation(
|
||
IN PWSTR RegistryPathBuffer,
|
||
IN PCONFIG_DATA * ConfigurationInfo
|
||
);
|
||
|
||
UINT
|
||
StReadSizeInformation(
|
||
IN HANDLE ParametersHandle
|
||
);
|
||
|
||
ULONG
|
||
StReadSingleParameter(
|
||
IN HANDLE ParametersHandle,
|
||
IN PWCHAR ValueName,
|
||
IN ULONG DefaultValue
|
||
);
|
||
|
||
VOID
|
||
StWriteSingleParameter(
|
||
IN HANDLE ParametersHandle,
|
||
IN PWCHAR ValueName,
|
||
IN ULONG ValueData
|
||
);
|
||
|
||
VOID
|
||
StSaveConfigInRegistry(
|
||
IN HANDLE ParametersHandle,
|
||
IN PCONFIG_DATA ConfigurationInfo
|
||
);
|
||
|
||
UINT
|
||
StWstrLength(
|
||
IN PWSTR Wstr
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,StWstrLength)
|
||
#pragma alloc_text(INIT,StConfigureTransport)
|
||
#pragma alloc_text(INIT,StFreeConfigurationInfo)
|
||
#pragma alloc_text(INIT,StOpenParametersKey)
|
||
#pragma alloc_text(INIT,StCloseParametersKey)
|
||
#pragma alloc_text(INIT,StCountEntries)
|
||
#pragma alloc_text(INIT,StAddBind)
|
||
#pragma alloc_text(INIT,StAddExport)
|
||
#pragma alloc_text(INIT,StReadLinkageInformation)
|
||
#pragma alloc_text(INIT,StReadSingleParameter)
|
||
#pragma alloc_text(INIT,StWriteSingleParameter)
|
||
#pragma alloc_text(INIT,StSaveConfigInRegistry)
|
||
#endif
|
||
|
||
|
||
UINT
|
||
StWstrLength(
|
||
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 = StWstrLength(_N)+sizeof(WCHAR); \
|
||
_S = (PWSTR)ExAllocatePool(NonPagedPool, _L); \
|
||
if (_S != NULL) { \
|
||
RtlCopyMemory(_S, _N, _L); \
|
||
RtlInitUnicodeString (&(ConfigurationInfo)->Names[Subscript], _S); \
|
||
} \
|
||
}
|
||
|
||
#define InsertDevice(ConfigurationInfo, Subscript, Name) \
|
||
{ \
|
||
PWSTR _S; \
|
||
PWSTR _N = (Name); \
|
||
UINT _L = StWstrLength(_N)+sizeof(WCHAR); \
|
||
_S = (PWSTR)ExAllocatePool(NonPagedPool, _L); \
|
||
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_) STATIC WCHAR Str ## _str_[] = L#_str_
|
||
|
||
DECLARE_STRING(Large);
|
||
DECLARE_STRING(Medium);
|
||
DECLARE_STRING(Small);
|
||
|
||
DECLARE_STRING(InitRequests);
|
||
DECLARE_STRING(InitConnections);
|
||
DECLARE_STRING(InitAddressFiles);
|
||
DECLARE_STRING(InitAddresses);
|
||
|
||
DECLARE_STRING(MaxRequests);
|
||
DECLARE_STRING(MaxConnections);
|
||
DECLARE_STRING(MaxAddressFiles);
|
||
DECLARE_STRING(MaxAddresses);
|
||
|
||
DECLARE_STRING(InitPackets);
|
||
DECLARE_STRING(InitReceivePackets);
|
||
DECLARE_STRING(InitReceiveBuffers);
|
||
|
||
DECLARE_STRING(SendPacketPoolSize);
|
||
DECLARE_STRING(ReceivePacketPoolSize);
|
||
DECLARE_STRING(MaxMemoryUsage);
|
||
|
||
|
||
#define READ_HIDDEN_CONFIG(_Field) \
|
||
{ \
|
||
ConfigurationInfo->_Field = \
|
||
StReadSingleParameter( \
|
||
ParametersHandle, \
|
||
Str ## _Field, \
|
||
ConfigurationInfo->_Field); \
|
||
}
|
||
|
||
#define WRITE_HIDDEN_CONFIG(_Field) \
|
||
{ \
|
||
StWriteSingleParameter( \
|
||
ParametersHandle, \
|
||
Str ## _Field, \
|
||
ConfigurationInfo->_Field); \
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
StConfigureTransport (
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PCONFIG_DATA * ConfigurationInfoPtr
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST 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 ST'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;
|
||
UINT StSize;
|
||
HANDLE StConfigHandle;
|
||
NTSTATUS Status;
|
||
ULONG Disposition;
|
||
PWSTR RegistryPathBuffer;
|
||
OBJECT_ATTRIBUTES TmpObjectAttributes;
|
||
PCONFIG_DATA ConfigurationInfo;
|
||
|
||
|
||
//
|
||
// Open the registry.
|
||
//
|
||
|
||
InitializeObjectAttributes(
|
||
&TmpObjectAttributes,
|
||
RegistryPath, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
NULL, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
Status = ZwCreateKey(
|
||
&StConfigHandle,
|
||
KEY_WRITE,
|
||
&TmpObjectAttributes,
|
||
0, // title index
|
||
NULL, // class
|
||
0, // create options
|
||
&Disposition); // disposition
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
StPrint1("ST: Could not open/create ST key: %lx\n", Status);
|
||
return Status;
|
||
}
|
||
|
||
|
||
OpenStatus = StOpenParametersKey (StConfigHandle, &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).
|
||
//
|
||
// StReadLinkageInformation expects a null-terminated path,
|
||
// so we have to create one from the UNICODE_STRING.
|
||
//
|
||
|
||
RegistryPathBuffer = (PWSTR)ExAllocatePool(
|
||
NonPagedPool,
|
||
RegistryPath->Length + sizeof(WCHAR));
|
||
if (RegistryPathBuffer == NULL) {
|
||
StCloseParametersKey (ParametersHandle);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
|
||
*(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
|
||
|
||
StReadLinkageInformation (RegistryPathBuffer, ConfigurationInfoPtr);
|
||
|
||
if (*ConfigurationInfoPtr == NULL) {
|
||
ExFreePool (RegistryPathBuffer);
|
||
StCloseParametersKey (ParametersHandle);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
ConfigurationInfo = *ConfigurationInfoPtr;
|
||
|
||
|
||
//
|
||
// Read the size parameter; this returns 0 if none is
|
||
// present, or 1 (Small), 2 (Medium) and 3 (Large).
|
||
//
|
||
|
||
StSize = StReadSizeInformation (ParametersHandle);
|
||
|
||
switch (StSize) {
|
||
|
||
case 0:
|
||
case 1:
|
||
|
||
//
|
||
// Default is Small.
|
||
//
|
||
|
||
//
|
||
// These are the initial value used; the comment after
|
||
// each one shows the expected maximum (if every resource
|
||
// is at the expected maximum, ST should be very close
|
||
// to being out of memory).
|
||
//
|
||
// For now the "Max" values default to 0 (no limit).
|
||
//
|
||
|
||
ConfigurationInfo->InitRequests = 5; // 30
|
||
ConfigurationInfo->InitConnections = 1; // 10
|
||
ConfigurationInfo->InitAddressFiles = 0; // 10
|
||
ConfigurationInfo->InitAddresses = 0; // 10
|
||
|
||
//
|
||
// 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 + conn (40)
|
||
ConfigurationInfo->InitReceivePackets = 10; // + link + addr (30)
|
||
ConfigurationInfo->InitReceiveBuffers = 5; // + addr (15)
|
||
|
||
//
|
||
// Set the size of the packet pools and the total
|
||
// allocateable by ST.
|
||
//
|
||
|
||
ConfigurationInfo->SendPacketPoolSize = 100;
|
||
ConfigurationInfo->ReceivePacketPoolSize = 30;
|
||
ConfigurationInfo->MaxMemoryUsage = 100000;
|
||
|
||
break;
|
||
|
||
case 2:
|
||
|
||
//
|
||
// Medium ST.
|
||
//
|
||
|
||
//
|
||
// These are the initial value used; the comment after
|
||
// each one shows the expected maximum (if every resource
|
||
// is at the expected maximum, ST should be very close
|
||
// to being out of memory).
|
||
//
|
||
// For now the "Max" values default to 0 (no limit).
|
||
//
|
||
|
||
ConfigurationInfo->InitRequests = 10; // 100
|
||
ConfigurationInfo->InitConnections = 2; // 64
|
||
ConfigurationInfo->InitAddressFiles = 1; // 20
|
||
ConfigurationInfo->InitAddresses = 1; // 20
|
||
|
||
//
|
||
// 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 = 50; // + link + conn (150)
|
||
ConfigurationInfo->InitReceivePackets = 15; // + link + addr (100)
|
||
ConfigurationInfo->InitReceiveBuffers = 10; // + addr (30)
|
||
|
||
//
|
||
// Set the size of the packet pools and the total
|
||
// allocateable by ST.
|
||
//
|
||
|
||
ConfigurationInfo->SendPacketPoolSize = 250;
|
||
ConfigurationInfo->ReceivePacketPoolSize = 100;
|
||
ConfigurationInfo->MaxMemoryUsage = 250000;
|
||
|
||
break;
|
||
|
||
case 3:
|
||
|
||
//
|
||
// Big ST.
|
||
//
|
||
|
||
//
|
||
// These are the initial value used.
|
||
//
|
||
// For now the "Max" values default to 0 (no limit).
|
||
//
|
||
|
||
ConfigurationInfo->InitRequests = 15;
|
||
ConfigurationInfo->InitConnections = 3;
|
||
ConfigurationInfo->InitAddressFiles = 2;
|
||
ConfigurationInfo->InitAddresses = 2;
|
||
|
||
//
|
||
// 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 = 75; // + link + conn
|
||
ConfigurationInfo->InitReceivePackets = 25; // + link + addr
|
||
ConfigurationInfo->InitReceiveBuffers = 20; // + addr
|
||
|
||
//
|
||
// Set the size of the packet pools and the total
|
||
// allocateable by ST.
|
||
//
|
||
|
||
ConfigurationInfo->SendPacketPoolSize = 500;
|
||
ConfigurationInfo->ReceivePacketPoolSize = 200;
|
||
ConfigurationInfo->MaxMemoryUsage = 0; // no limit
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
ASSERT(FALSE);
|
||
break;
|
||
|
||
}
|
||
|
||
|
||
//
|
||
// 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 (InitConnections);
|
||
READ_HIDDEN_CONFIG (InitAddressFiles);
|
||
READ_HIDDEN_CONFIG (InitAddresses);
|
||
|
||
READ_HIDDEN_CONFIG (MaxRequests);
|
||
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 (SendPacketPoolSize);
|
||
READ_HIDDEN_CONFIG (ReceivePacketPoolSize);
|
||
READ_HIDDEN_CONFIG (MaxMemoryUsage);
|
||
|
||
|
||
//
|
||
// Now that we are completely configured, save the information
|
||
// in the registry.
|
||
//
|
||
|
||
StSaveConfigInRegistry (ParametersHandle, ConfigurationInfo);
|
||
|
||
ExFreePool (RegistryPathBuffer);
|
||
StCloseParametersKey (ParametersHandle);
|
||
ZwClose (StConfigHandle);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* StConfigureTransport */
|
||
|
||
|
||
VOID
|
||
StFreeConfigurationInfo (
|
||
IN PCONFIG_DATA ConfigurationInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST to get free any storage that was allocated
|
||
by StConfigureTransport 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);
|
||
|
||
} /* StFreeConfigurationInfo */
|
||
|
||
|
||
NTSTATUS
|
||
StOpenParametersKey(
|
||
IN HANDLE StConfigHandle,
|
||
OUT PHANDLE ParametersHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST to open the ST "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 ST parameters key.
|
||
//
|
||
|
||
RtlInitUnicodeString (&ParametersKeyName, ParametersString);
|
||
|
||
InitializeObjectAttributes(
|
||
&TmpObjectAttributes,
|
||
&ParametersKeyName, // name
|
||
OBJ_CASE_INSENSITIVE, // attributes
|
||
StConfigHandle, // root
|
||
NULL // security descriptor
|
||
);
|
||
|
||
|
||
Status = ZwOpenKey(
|
||
&ParamHandle,
|
||
KEY_READ,
|
||
&TmpObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
StPrint1("Could not open parameters key: %lx\n", Status);
|
||
return Status;
|
||
|
||
}
|
||
|
||
*ParametersHandle = ParamHandle;
|
||
|
||
|
||
//
|
||
// All keys successfully opened or created.
|
||
//
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* StOpenParametersKey */
|
||
|
||
VOID
|
||
StCloseParametersKey(
|
||
IN HANDLE ParametersHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST 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);
|
||
|
||
} /* StCloseParametersKey */
|
||
|
||
|
||
NTSTATUS
|
||
StCountEntries(
|
||
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;
|
||
|
||
ASSERT (ValueType == REG_MULTI_SZ);
|
||
|
||
//
|
||
// 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 = ExAllocatePool(
|
||
NonPagedPool,
|
||
sizeof (CONFIG_DATA) +
|
||
((*TotalCount-1) * sizeof(NDIS_STRING)));
|
||
|
||
if (*ConfigurationInfo == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
RtlZeroMemory(
|
||
*ConfigurationInfo,
|
||
sizeof(CONFIG_DATA) + ((*TotalCount-1) * sizeof(NDIS_STRING)));
|
||
|
||
(*ConfigurationInfo)->DevicesOffset = OldTotalCount;
|
||
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} /* StCountEntries */
|
||
|
||
|
||
NTSTATUS
|
||
StAddBind(
|
||
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;
|
||
|
||
} /* StAddBind */
|
||
|
||
|
||
NTSTATUS
|
||
StAddExport(
|
||
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;
|
||
|
||
} /* StAddExport */
|
||
|
||
|
||
VOID
|
||
StReadLinkageInformation(
|
||
IN PWSTR RegistryPathBuffer,
|
||
IN PCONFIG_DATA * ConfigurationInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST 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 ST.
|
||
|
||
Arguments:
|
||
|
||
RegistryPathBuffer - The null-terminated root of the ST registry tree.
|
||
|
||
ConfigurationInfo - Returns ST'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 ST
|
||
//
|
||
|
||
QueryTable[0].QueryRoutine = NULL;
|
||
QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
|
||
QueryTable[0].Name = Subkey;
|
||
|
||
//
|
||
// 2) Call StCountEntries for the "Bind" multi-string
|
||
//
|
||
|
||
QueryTable[1].QueryRoutine = StCountEntries;
|
||
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 StCountEntries for the "Export" multi-string
|
||
//
|
||
|
||
QueryTable[2].QueryRoutine = StCountEntries;
|
||
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 StAddBind for each string in "Bind"
|
||
//
|
||
|
||
QueryTable[3].QueryRoutine = StAddBind;
|
||
QueryTable[3].Flags = 0;
|
||
QueryTable[3].Name = Bind;
|
||
QueryTable[3].EntryContext = (PVOID)&BindCount;
|
||
QueryTable[3].DefaultType = REG_NONE;
|
||
|
||
//
|
||
// 5) Call StAddExport for each string in "Export"
|
||
//
|
||
|
||
QueryTable[4].QueryRoutine = StAddExport;
|
||
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;
|
||
|
||
} /* StReadLinkageInformation */
|
||
|
||
|
||
UINT
|
||
StReadSizeInformation(
|
||
IN HANDLE ParametersHandle
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST to read the Size information
|
||
from the registry.
|
||
|
||
Arguments:
|
||
|
||
RegistryHandle - A pointer to the open registry.
|
||
|
||
Return Value:
|
||
|
||
0 - no Size specified
|
||
1 - Small
|
||
2 - Medium
|
||
3 - Big / Large
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
UINT SizeToReturn;
|
||
// STRING KeywordName;
|
||
// PCONFIG_KEYWORD Keyword;
|
||
|
||
ULONG InformationBuffer[16]; // declare ULONG to get it aligned
|
||
PKEY_VALUE_FULL_INFORMATION Information =
|
||
(PKEY_VALUE_FULL_INFORMATION)InformationBuffer;
|
||
ULONG InformationLength;
|
||
WCHAR SizeString[] = L"Size";
|
||
UNICODE_STRING SizeValueName;
|
||
NTSTATUS Status;
|
||
PUCHAR InformationData;
|
||
ULONG InformationLong;
|
||
|
||
|
||
//
|
||
// Read the size parameter out of the registry.
|
||
//
|
||
|
||
RtlInitUnicodeString (&SizeValueName, SizeString);
|
||
|
||
Status = ZwQueryValueKey(
|
||
ParametersHandle,
|
||
&SizeValueName,
|
||
KeyValueFullInformation,
|
||
(PVOID)Information,
|
||
sizeof (InformationBuffer),
|
||
&InformationLength);
|
||
|
||
//
|
||
// Compare to the expected values.
|
||
//
|
||
|
||
if (Status == STATUS_SUCCESS) {
|
||
|
||
InformationData = ((PUCHAR)Information) + Information->DataOffset;
|
||
InformationLong = *((PULONG)InformationData);
|
||
|
||
if ((Information->DataLength == sizeof(ULONG)) &&
|
||
(InformationLong >= 1 && InformationLong <= 3)) {
|
||
|
||
SizeToReturn = InformationLong;
|
||
|
||
} else {
|
||
|
||
if ((Information->DataLength >= 10) &&
|
||
(RtlEqualMemory (StrLarge, InformationData, 10))) {
|
||
|
||
SizeToReturn = 3;
|
||
|
||
} else if ((Information->DataLength >= 12) &&
|
||
(RtlEqualMemory (StrMedium, InformationData, 12))) {
|
||
|
||
SizeToReturn = 2;
|
||
|
||
} else if ((Information->DataLength >= 10) &&
|
||
(RtlEqualMemory (StrSmall, InformationData, 10))) {
|
||
|
||
SizeToReturn = 1;
|
||
|
||
} else {
|
||
|
||
SizeToReturn = 0;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
SizeToReturn = 0;
|
||
|
||
}
|
||
|
||
return SizeToReturn;
|
||
|
||
} /* StReadSizeInformation */
|
||
|
||
|
||
ULONG
|
||
StReadSingleParameter(
|
||
IN HANDLE ParametersHandle,
|
||
IN PWCHAR ValueName,
|
||
IN ULONG DefaultValue
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST 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[16]; // 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 (ReturnValue < 0) {
|
||
|
||
ReturnValue = DefaultValue;
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
ReturnValue = DefaultValue;
|
||
|
||
}
|
||
|
||
return ReturnValue;
|
||
|
||
} /* StReadSingleParameter */
|
||
|
||
|
||
VOID
|
||
StWriteSingleParameter(
|
||
IN HANDLE ParametersHandle,
|
||
IN PWCHAR ValueName,
|
||
IN ULONG ValueData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST 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)) {
|
||
StPrint1("ST: Could not write dword key: %lx\n", Status);
|
||
}
|
||
|
||
} /* StWriteSingleParameter */
|
||
|
||
|
||
VOID
|
||
StSaveConfigInRegistry(
|
||
IN HANDLE ParametersHandle,
|
||
IN PCONFIG_DATA ConfigurationInfo
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called by ST to save its configuraition
|
||
information in the registry. It saves the information if
|
||
the registry structure did not exist before this boot.
|
||
|
||
Arguments:
|
||
|
||
ParametersHandle - The handle used to read other parameters.
|
||
|
||
ConfigurationInfo - Describes ST's current configuration.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
//
|
||
// Save the "hidden" parameters, these may not exist in
|
||
// the registry.
|
||
//
|
||
// NOTE: These macros expect "ConfigurationInfo" and
|
||
// "ParametersHandle" to exist when they are expanded.
|
||
//
|
||
|
||
//
|
||
// 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 (MaxConnections);
|
||
WRITE_HIDDEN_CONFIG (MaxAddressFiles);
|
||
WRITE_HIDDEN_CONFIG (MaxAddresses);
|
||
|
||
} /* StSaveConfigInRegistry */
|
||
|