283 lines
7.3 KiB
C
283 lines
7.3 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_
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma const_seg()
|
|
#endif
|
|
|