Windows2000/private/ntos/ex/exinfo.c
2020-09-30 17:12:32 +02:00

229 lines
6.0 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
exinfo.c
Abstract:
This module implements the NT set anmd query system information services.
Author:
Ken Reneris (kenr) 19-July-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "exp.h"
#if _PNP_POWER_
#if defined(ALLOC_PRAGMA)
#pragma alloc_text(PAGE, ExpCheckSystemInformation)
#pragma alloc_text(PAGE, ExpCheckSystemInfoWork)
#endif // _PNP_POWER_
VOID
ExpCheckSystemInformation (
PVOID Context,
PVOID InformationClass,
PVOID Argument2
)
/*++
Routine Description:
Callback function invoked when something in the system information
may have changed.
Arguments:
Context - Where invoked from.
InformationClass - which class for the given context was set
(ignored for now)
Argument2
Return Value:
--*/
{
ExQueueWorkItem (&ExpCheckSystemInfoWorkItem, DelayedWorkQueue);
}
VOID
ExpCheckSystemInfoWork (
IN PVOID Context
)
/*++
Routine Description:
Verifies registery data for various system information classes
is up to date.
Arguments:
Return Value:
--*/
{
static struct {
SYSTEM_INFORMATION_CLASS InformationLevel;
ULONG BufferSize;
} RegistryInformation[] = {
SystemBasicInformation, sizeof (SYSTEM_BASIC_INFORMATION),
SystemPowerInformation, sizeof (SYSTEM_POWER_INFORMATION),
SystemProcessorSpeedInformation, sizeof (SYSTEM_PROCESSOR_SPEED_INFORMATION),
0, 0
};
struct {
KEY_VALUE_PARTIAL_INFORMATION Key;
union {
SYSTEM_BASIC_INFORMATION BasicInformation;
SYSTEM_POWER_INFORMATION PowerSettings;
SYSTEM_PROCESSOR_SPEED_INFORMATION ProcessorSpeed;
};
} RegistryBuffer, QueryBuffer;
ULONG Index, BufferSize, disposition, length;
NTSTATUS Status;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING unicodeString, ValueString;
HANDLE CurrentControlSet, SystemInformation, LevelInformation;
LARGE_INTEGER Interval;
BOOLEAN Rescan;
WCHAR wstr[10];
PAGED_CODE();
// Only one worked needed at a time needed to update the SystemInformation
// data in the registry
if (InterlockedIncrement (&ExpCheckSystemInfoBusy) != 0) {
return ;
}
RtlInitUnicodeString (&ValueString, ExpWstrSystemInformationValue);
// Open CurrentControlSet
InitializeObjectAttributes( &objectAttributes, &CmRegistryMachineSystemCurrentControlSet, OBJ_CASE_INSENSITIVE, NULL, NULL );
Status = NtOpenKey (&CurrentControlSet, KEY_READ | KEY_WRITE, &objectAttributes );
if (NT_SUCCESS(Status)) {
// Open SystemInformation
RtlInitUnicodeString( &unicodeString, ExpWstrSystemInformation );
InitializeObjectAttributes( &objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, CurrentControlSet, NULL );
Status = NtCreateKey ( &SystemInformation, KEY_READ | KEY_WRITE, &objectAttributes, 0, NULL, REG_OPTION_VOLATILE, &disposition );
NtClose (CurrentControlSet);
}
if (!NT_SUCCESS(Status)) {
InterlockedDecrement (&ExpCheckSystemInfoBusy);
return ;
}
// Loop and check SystemInformation data in registry
do {
Rescan = FALSE;
// Wait a moment
Interval.QuadPart = -3000000;
KeDelayExecutionThread (KernelMode, FALSE, &Interval);
// For now just check each SystemInformation level and update
// any level which is out of date
for (Index=0; RegistryInformation[Index].BufferSize; Index++) {
// Initialize registry data buffer
BufferSize = RegistryInformation[Index].BufferSize;
RtlZeroMemory (RegistryBuffer.Key.Data, BufferSize);
// Open appropiate SystemInformation level key
swprintf (wstr, L"%d", RegistryInformation[Index].InformationLevel);
RtlInitUnicodeString (&unicodeString, wstr);
InitializeObjectAttributes( &objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, SystemInformation, NULL );
Status = NtCreateKey ( &LevelInformation, KEY_READ | KEY_WRITE, &objectAttributes, 0, NULL, REG_OPTION_VOLATILE, &disposition );
// If key opened, read current data value from the registry
if (NT_SUCCESS(Status)) {
NtQueryValueKey (LevelInformation, &ValueString, KeyValuePartialInformation, &RegistryBuffer.Key, sizeof (RegistryBuffer), &length);
}
// Query current SystemInformation data
Status = NtQuerySystemInformation (RegistryInformation[Index].InformationLevel, &QueryBuffer.Key.Data, BufferSize, NULL);
// Check if current SystemInformation matches the registry
// information
if (NT_SUCCESS(Status) && !RtlEqualMemory (RegistryBuffer.Key.Data, QueryBuffer.Key.Data, BufferSize) ) {
// Did not match - update registry to current SystemInfomration
Status = NtSetValueKey (LevelInformation, &ValueString, 0L, REG_BINARY, QueryBuffer.Key.Data, BufferSize);
// Make notificant that this information level has changed
ExNotifyCallback (ExCbSetSystemInformation, (PVOID) RegistryInformation[Index].InformationLevel, (PVOID) NULL);
}
// Close this InformatiobLevel and check the next one
NtClose (LevelInformation);
}
// If no Rescan, remove our count from the busy flag
if (!Rescan &&
InterlockedDecrement (&ExpCheckSystemInfoBusy) >= 0) {
// Some other worker thread attempted to perform a scan. Reset
// counter to 1 and loop
ExInterlockedExchangeUlong ((PULONG) &ExpCheckSystemInfoBusy, 0, &ExpCheckSystemInfoLock);
Rescan = TRUE;
}
} while (Rescan);
// Cleanup
NtClose (SystemInformation);
}
#endif // _PNP_POWER_