test: exinfo.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# exinfo.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1989  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     exinfo.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the NT set anmd query system information services.
    00012
    00013 Author:
    00014
    00015     Ken Reneris (kenr) 19-July-1994
    00016
    00017 Environment:
    00018
    00019     Kernel mode only.
    00020
    00021 Revision History:
    00022
    00023 --*/
    00024
    00025 #include "exp.h"
    00026
    00027 #if _PNP_POWER_
    00028 #if defined(ALLOC_PRAGMA)
    00029 #pragma alloc_text(PAGE, ExpCheckSystemInformation)
    00030 #pragma alloc_text(PAGE, ExpCheckSystemInfoWork)
    00031 #endif // _PNP_POWER_
    00032
    00033 VOID
    00034 ExpCheckSystemInformation (
    00035     PVOID       Context,
    00036     PVOID       InformationClass,
    00037     PVOID       Argument2
    00038     )
    00039 /*++
    00040
    00041 Routine Description:
    00042
    00043     Callback function invoked when something in the system information
    00044     may have changed.
    00045
    00046 Arguments:
    00047
    00048     Context - Where invoked from.
    00049
    00050     InformationClass - which class for the given context was set
    00051         (ignored for now)
    00052
    00053     Argument2
    00054
    00055 Return Value:
    00056
    00057 --*/
    00058 {
    00059     ExQueueWorkItem (&ExpCheckSystemInfoWorkItem, DelayedWorkQueue);
    00060 }
    00061
    00062
    00063 VOID
    00064 ExpCheckSystemInfoWork (
    00065     IN PVOID Context
    00066     )
    00067 /*++
    00068
    00069 Routine Description:
    00070
    00071     Verifies registery data for various system information classes
    00072     is up to date.
    00073
    00074 Arguments:
    00075
    00076 Return Value:
    00077
    00078 --*/
    00079 {
    00080     static struct {
    00081         SYSTEM_INFORMATION_CLASS         InformationLevel;
    00082         ULONG                            BufferSize;
    00083     } RegistryInformation[] = {
    00084         SystemBasicInformation,          sizeof (SYSTEM_BASIC_INFORMATION),
    00085         SystemPowerInformation,          sizeof (SYSTEM_POWER_INFORMATION),
    00086         SystemProcessorSpeedInformation, sizeof (SYSTEM_PROCESSOR_SPEED_INFORMATION),
    00087         0,                               0
    00088     };
    00089
    00090     struct {
    00091         KEY_VALUE_PARTIAL_INFORMATION   Key;
    00092         union {
    00093             SYSTEM_BASIC_INFORMATION BasicInformation;
    00094             SYSTEM_POWER_INFORMATION PowerSettings;
    00095             SYSTEM_PROCESSOR_SPEED_INFORMATION  ProcessorSpeed;
    00096         };
    00097     } RegistryBuffer, QueryBuffer;
    00098
    00099     ULONG               Index, BufferSize, disposition, length;
    00100     NTSTATUS            Status;
    00101     OBJECT_ATTRIBUTES   objectAttributes;
    00102     UNICODE_STRING      unicodeString, ValueString;
    00103     HANDLE              CurrentControlSet, SystemInformation, LevelInformation;
    00104     LARGE_INTEGER       Interval;
    00105     BOOLEAN             Rescan;
    00106     WCHAR               wstr[10];
    00107
    00108     PAGED_CODE();
    00109
    00110     //
    00111     // Only one worked needed at a time needed to update the SystemInformation
    00112     // data in the registry
    00113     //
    00114
    00115     if (InterlockedIncrement (&ExpCheckSystemInfoBusy) != 0) {
    00116         return ;
    00117     }
    00118
    00119     RtlInitUnicodeString (&ValueString,  ExpWstrSystemInformationValue);
    00120
    00121     //
    00122     // Open CurrentControlSet
    00123     //
    00124
    00125     InitializeObjectAttributes( &objectAttributes,
    00126                                 &CmRegistryMachineSystemCurrentControlSet,
    00127                                 OBJ_CASE_INSENSITIVE,
    00128                                 NULL,
    00129                                 NULL );
    00130
    00131     Status = NtOpenKey (&CurrentControlSet,
    00132                         KEY_READ | KEY_WRITE,
    00133                         &objectAttributes );
    00134
    00135     if (NT_SUCCESS(Status)) {
    00136
    00137         //
    00138         // Open SystemInformation
    00139         //
    00140
    00141         RtlInitUnicodeString( &unicodeString, ExpWstrSystemInformation );
    00142         InitializeObjectAttributes( &objectAttributes,
    00143                                     &unicodeString,
    00144                                     OBJ_CASE_INSENSITIVE,
    00145                                     CurrentControlSet,
    00146                                     NULL );
    00147
    00148         Status = NtCreateKey ( &SystemInformation,
    00149                                KEY_READ | KEY_WRITE,
    00150                                &objectAttributes,
    00151                                0,
    00152                                NULL,
    00153                                REG_OPTION_VOLATILE,
    00154                                &disposition );
    00155
    00156         NtClose (CurrentControlSet);
    00157     }
    00158
    00159     if (!NT_SUCCESS(Status)) {
    00160         InterlockedDecrement (&ExpCheckSystemInfoBusy);
    00161         return ;
    00162     }
    00163
    00164     //
    00165     // Loop and check SystemInformation data in registry
    00166     //
    00167
    00168     do {
    00169         Rescan = FALSE;
    00170
    00171         //
    00172         // Wait a moment
    00173         //
    00174
    00175         Interval.QuadPart = -3000000;
    00176         KeDelayExecutionThread (KernelMode, FALSE, &Interval);
    00177
    00178         //
    00179         // For now just check each SystemInformation level and update
    00180         // any level which is out of date
    00181         //
    00182
    00183         for (Index=0; RegistryInformation[Index].BufferSize; Index++) {
    00184
    00185             //
    00186             // Initialize registry data buffer
    00187             //
    00188
    00189             BufferSize = RegistryInformation[Index].BufferSize;
    00190             RtlZeroMemory (RegistryBuffer.Key.Data, BufferSize);
    00191
    00192             //
    00193             // Open appropiate SystemInformation level key
    00194             //
    00195
    00196             swprintf (wstr, L"%d", RegistryInformation[Index].InformationLevel);
    00197             RtlInitUnicodeString (&unicodeString, wstr);
    00198             InitializeObjectAttributes( &objectAttributes,
    00199                                         &unicodeString,
    00200                                         OBJ_CASE_INSENSITIVE,
    00201                                         SystemInformation,
    00202                                         NULL );
    00203
    00204             Status = NtCreateKey ( &LevelInformation,
    00205                                    KEY_READ | KEY_WRITE,
    00206                                    &objectAttributes,
    00207                                    0,
    00208                                    NULL,
    00209                                    REG_OPTION_VOLATILE,
    00210                                    &disposition );
    00211
    00212             //
    00213             // If key opened, read current data value from the registry
    00214             //
    00215
    00216             if (NT_SUCCESS(Status)) {
    00217                 NtQueryValueKey (
    00218                     LevelInformation,
    00219                     &ValueString,
    00220                     KeyValuePartialInformation,
    00221                     &RegistryBuffer.Key,
    00222                     sizeof (RegistryBuffer),
    00223                     &length
    00224                     );
    00225             }
    00226
    00227             //
    00228             // Query current SystemInformation data
    00229             //
    00230
    00231             Status = NtQuerySystemInformation (
    00232                             RegistryInformation[Index].InformationLevel,
    00233                             &QueryBuffer.Key.Data,
    00234                             BufferSize,
    00235                             NULL
    00236                         );
    00237
    00238             //
    00239             // Check if current SystemInformation matches the registry
    00240             // information
    00241             //
    00242
    00243             if (NT_SUCCESS(Status)  &&
    00244                 !RtlEqualMemory (RegistryBuffer.Key.Data,
    00245                                  QueryBuffer.Key.Data,
    00246                                  BufferSize) ) {
    00247
    00248                 //
    00249                 // Did not match - update registry to current SystemInfomration
    00250                 //
    00251
    00252                 Status = NtSetValueKey (
    00253                             LevelInformation,
    00254                             &ValueString,
    00255                             0L,
    00256                             REG_BINARY,
    00257                             QueryBuffer.Key.Data,
    00258                             BufferSize
    00259                             );
    00260
    00261                 //
    00262                 // Make notificant that this information level has changed
    00263                 //
    00264
    00265                 ExNotifyCallback (
    00266                     ExCbSetSystemInformation,
    00267                     (PVOID) RegistryInformation[Index].InformationLevel,
    00268                     (PVOID) NULL
    00269                 );
    00270             }
    00271
    00272             //
    00273             // Close this InformatiobLevel and check the next one
    00274             //
    00275
    00276             NtClose (LevelInformation);
    00277         }
    00278
    00279         //
    00280         // If no Rescan, remove our count from the busy flag
    00281         //
    00282
    00283         if (!Rescan &&
    00284             InterlockedDecrement (&ExpCheckSystemInfoBusy) >= 0) {
    00285
    00286             //
    00287             // Some other worker thread attempted to perform a scan.  Reset
    00288             // counter to 1 and loop
    00289             //
    00290
    00291             ExInterlockedExchangeUlong ((PULONG) &ExpCheckSystemInfoBusy, 0, &ExpCheckSystemInfoLock);
    00292             Rescan = TRUE;
    00293         }
    00294
    00295     } while (Rescan);
    00296
    00297     //
    00298     // Cleanup
    00299     //
    00300
    00301     NtClose (SystemInformation);
    00302 }
    00303
    00304 #endif  // _PNP_POWER_