summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/st/stcnfg.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/st/stcnfg.c
downloadNT4.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/st/stcnfg.c')
-rw-r--r--private/ntos/tdi/st/stcnfg.c1277
1 files changed, 1277 insertions, 0 deletions
diff --git a/private/ntos/tdi/st/stcnfg.c b/private/ntos/tdi/st/stcnfg.c
new file mode 100644
index 000000000..40438eedb
--- /dev/null
+++ b/private/ntos/tdi/st/stcnfg.c
@@ -0,0 +1,1277 @@
+/*++
+
+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 */
+