windows-nt/Source/XPSP1/NT/base/ntos/ex/exinfo.c
2020-09-26 16:20:57 +08:00

278 lines
7.2 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
exinfo.c
Abstract:
This module implements the NT set and 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_
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("PAGECONST")
#endif
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:
--*/
{
PAGED_CODE();
if (InterlockedIncrement(&ExpCheckSystemInfoBusy) == 1) {
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;
} const 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;
WCHAR wstr[10];
PAGED_CODE();
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)) {
ExpCheckSystemInfoBusy = 0;
return ;
}
//
// Loop and check SystemInformation data in registry
//
do {
//
// 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);
}
} while (InterlockedDecrement(&ExpCheckSystemInfoBusy));
//
// Cleanup
//
NtClose (SystemInformation);
}
#endif // _PNP_POWER_