windows-nt/Source/XPSP1/NT/shell/osshell/cpls/powrprof/powrprof.c

1907 lines
56 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 1996
*
* TITLE: POWRPROF.C
*
* VERSION: 2.0
*
* AUTHOR: ReedB
*
* DATE: 17 Oct, 1996
*
* DESCRIPTION:
* User power management profile maintenance library. Implements persistent
* power mamagement data storage. To minimize registry storage and simplify
* user power profile management, power scheme's are divided into two parts,
* GLOBAL_POWER_POLICY and POWER_POLICY:
*
* User Level Registry Storage
* GLOBAL_POWER_POLICY = - Common scheme data.
* GLOBAL_MACHINE_POWER_POLICY - Per machine data.
* + GLOBAL_USER_POWER_POLICY - Per user data.
*
* POWER_POLICY = - Unique scheme data.
* MACHINE_POWER_POLICY - Per machine data.
* + USER_POWER_POLICY - Per user data.
*
* The interface to the power policy manager is by AC and DC
* SYSTEM_POWER_POLICY which is formed by merging the above structures.
*
*******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <initguid.h>
#include <devguid.h>
#include <string.h>
#include <regstr.h>
#include <commctrl.h>
#include <ntpoapi.h>
#include <setupapi.h>
#include <syssetup.h>
#include <setupbat.h>
#include "powrprofp.h"
#include "reghelp.h"
/*******************************************************************************
*
* G L O B A L D A T A
*
*******************************************************************************/
HINSTANCE g_hInstance; // Global instance handle of this DLL.
HANDLE g_hSemRegistry; // Registry semaphore.
UINT g_uiLastID; // The last ID value used, per machine.
// Variables and definitions to manage dynamic link to NtPowerInformation.
typedef NTSTATUS (NTAPI *PFNNTPOWERINFORMATION)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
#ifdef WINNT
// Global administrator power policy variables. Initialize to allow everything.
BOOLEAN g_bAdminOverrideActive = FALSE;
ADMINISTRATOR_POWER_POLICY g_app =
{
// Meaning of power action "sleep" Min, Max.
PowerSystemSleeping1, PowerSystemHibernate,
// Video policies Min, Max.
0, -1,
// Disk spindown policies Min, Max.
0, -1
};
#endif
// Debug strings for Power Policy Manager POWER_INFORMATION_LEVEL:
#ifdef DEBUG
LPTSTR lpszInfoLevel[] =
{
TEXT("SystemPowerPolicyAc"),
TEXT("SystemPowerPolicyDc"),
TEXT("VerifySystemPolicyAc"),
TEXT("VerifySystemPolicyDc"),
TEXT("SystemPowerCapabilities"),
TEXT("SystemBatteryState"),
TEXT("SystemPowerStateHandler"),
TEXT("ProcessorStateHandler"),
TEXT("SystemPowerPolicyCurrent"),
TEXT("AdministratorPowerPolicy"),
TEXT("SystemReserveHiberFile"),
TEXT("ProcessorInformation"),
TEXT("SystemPowerInformation"),
TEXT("ProcessorStateHandler2"),
TEXT("LastWakeTime"),
TEXT("LastSleepTime"),
TEXT("SystemExecutionState"),
TEXT("SystemPowerStateNotifyHandler"),
TEXT("ProcessorPowerPolicyAc"),
TEXT("ProcessorPowerPolicyDc"),
TEXT("VerifyProcessorPowerPolicyAc"),
TEXT("VerifyProcessorPowerPolicyDc"),
TEXT("ProcessorPowerPolicyCurrent")
};
int g_iShowValidationChanges;
int g_iShowCapabilities;
int g_iShowSetPPM;
#endif
// Global value for storing a single registry value name/path. Multithread
// protection is provided by the Registry semaphore.
TCHAR g_szRegValue[REGSTR_MAX_VALUE_LENGTH];
// Strings used to access the registry. REGSTR_* string constants can be
// found in sdk\inc\regstr.h, USER strings are under HKEY_CURRENT_USER,
// MACHINE strings are under HKEY_LOCAL_MACHINE.
TCHAR c_szREGSTR_PATH_MACHINE_POWERCFG[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg");
TCHAR c_szREGSTR_PATH_USER_POWERCFG[] = REGSTR_PATH_CONTROLPANEL TEXT("\\PowerCfg");
TCHAR c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg\\PowerPolicies");
TCHAR c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg\\ProcessorPolicies");
TCHAR c_szREGSTR_PATH_USER_POWERCFG_POLICIES[] = REGSTR_PATH_CONTROLPANEL TEXT("\\PowerCfg\\PowerPolicies");
TCHAR c_szREGSTR_VAL_GLOBALPOWERPOLICY[] = TEXT("GlobalPowerPolicy");
TCHAR c_szREGSTR_VAL_CURRENTPOWERPOLICY[] = TEXT("CurrentPowerPolicy");
// These values are provided to help OEM's meet disk drive warranty requirements.
TCHAR c_szREGSTR_VAL_SPINDOWNMAX[] = TEXT("DiskSpinDownMax");
TCHAR c_szREGSTR_VAL_SPINDOWNMIN[] = TEXT("DiskSpinDownMin");
// These values are provided to support administrator power policies.
TCHAR c_szREGSTR_VAL_ADMINMAXVIDEOTIMEOUT[] = TEXT("AdminMaxVideoTimeout");
TCHAR c_szREGSTR_VAL_ADMINMAXSLEEP[] = TEXT("AdminMaxSleep");
// This value manages the policy ID's.
TCHAR c_szREGSTR_VAL_LASTID[] = TEXT("LastID");
// This value turns on debug logging of PPM Validation Changes
#ifdef DEBUG
TCHAR c_szREGSTR_VAL_SHOWVALCHANGES[] = TEXT("ShowValidationChanges");
TCHAR c_szREGSTR_VAL_SHOWCAPABILITIES[] = TEXT("ShowCapabilities");
TCHAR c_szREGSTR_VAL_SHOWSETPPM[] = TEXT("ShowSetPPM");
#endif
/*******************************************************************************
*
* P U B L I C E N T R Y P O I N T S
*
*******************************************************************************/
/*******************************************************************************
*
* DllInitialize
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN DllInitialize(IN PVOID hmod, IN ULONG ulReason, IN PCONTEXT pctx OPTIONAL)
{
UNREFERENCED_PARAMETER(pctx);
switch (ulReason) {
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hmod);
g_hInstance = hmod;
#ifdef DEBUG
// Get the debug optional settings from HKCU.
ReadOptionalDebugSettings();
#endif
#ifdef WINNT
// Initialize an administrator power policy.
InitAdmin(&g_app);
#endif
// One time registry related initialization.
if (!RegistryInit(&g_uiLastID)) {
return FALSE;
}
break;
}
case DLL_PROCESS_DETACH:
CloseHandle(g_hSemRegistry);
g_hSemRegistry = NULL;
break;
}
return TRUE;
}
/*******************************************************************************
*
* IsAdminOverrideActive
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY papp)
{
#ifdef WINNT
if ((g_bAdminOverrideActive) && (papp)) {
memcpy(papp, &g_app, sizeof(g_app));
}
return g_bAdminOverrideActive;
#else
return FALSE;
#endif
}
/*******************************************************************************
*
* IsPwrSuspendAllowed
*
* DESCRIPTION:
* Called by Explorer to determine whether suspend is supported.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN IsPwrSuspendAllowed(VOID)
{
SYSTEM_POWER_CAPABILITIES spc;
if (GetPwrCapabilities(&spc)) {
if (spc.SystemS1 || spc.SystemS2 || spc.SystemS3) {
return TRUE;
}
}
return FALSE;
}
/*******************************************************************************
*
* IsPwrHibernateAllowed
*
* DESCRIPTION:
* Called by Explorer to determine whether hibernate is supported.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN IsPwrHibernateAllowed(VOID)
{
SYSTEM_POWER_CAPABILITIES spc;
if (GetPwrCapabilities(&spc)) {
if (spc.SystemS4 && spc.HiberFilePresent) {
return TRUE;
}
}
return FALSE;
}
/*******************************************************************************
*
* IsPwrShutdownAllowed
*
* DESCRIPTION:
* Called by Explorer to determine whether shutdown is supported.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN IsPwrShutdownAllowed(VOID)
{
SYSTEM_POWER_CAPABILITIES spc;
if (GetPwrCapabilities(&spc)) {
if (spc.SystemS5) {
return TRUE;
}
}
return FALSE;
}
/*******************************************************************************
*
* CanUserWritePwrScheme
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN CanUserWritePwrScheme(VOID)
{
DWORD dwSize;
TCHAR szNum[NUM_DEC_DIGITS];
LONG lErr;
// Read in the last ID this value must be present.
dwSize = sizeof(szNum);
// ReadWritePowerValue will set last error
if (ReadWritePowerValue(HKEY_LOCAL_MACHINE,
c_szREGSTR_PATH_MACHINE_POWERCFG,
c_szREGSTR_VAL_LASTID,
szNum, &dwSize, FALSE, TRUE))
{
// Write the value back out, this may fail if user doesn't have write access.
if (ReadWritePowerValue(HKEY_LOCAL_MACHINE,
c_szREGSTR_PATH_MACHINE_POWERCFG,
c_szREGSTR_VAL_LASTID,
szNum, &dwSize, TRUE, TRUE))
{
return TRUE;
}
else
{
lErr = GetLastError();
if (lErr != ERROR_ACCESS_DENIED)
{
DebugPrint( "CanUserWritePwrScheme, Unable to write last ID, Error: %d", lErr);
}
}
}
else
{
lErr = GetLastError();
DebugPrint( "CanUserWritePwrScheme, Unable to fetch last ID, Error: %d", lErr);
}
return FALSE;
}
/*******************************************************************************
*
* GetPwrDiskSpindownRange
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN GetPwrDiskSpindownRange(PUINT puiMax, PUINT puiMin)
{
if (!puiMax || !puiMin) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
c_szREGSTR_PATH_MACHINE_POWERCFG,
c_szREGSTR_VAL_SPINDOWNMAX,
puiMax) &&
ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
c_szREGSTR_PATH_MACHINE_POWERCFG,
c_szREGSTR_VAL_SPINDOWNMIN,
puiMin)) {
return TRUE;
}
return FALSE;
}
/*******************************************************************************
*
* EnumPwrSchemes
*
* DESCRIPTION:
* Calls back the PWRSCHEMESENUMPROC with the ID, a pointer to the name,
* the size in bytes of the name, a pointer to the description, the size in
* bytes of the description, a pointer to the power policies and a user
* defined value. Returns ERROR_SUCCESS on success, else error code. Callback
* data is not allocated and is only valid during the scope of the callback.
*
* Note: No calls to any other API's in this library should be made during
* the call back to PWRSCHEMESENUMPROC. The registry semaphore is held at
* this time and a deadlock will result.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN EnumPwrSchemes(
PWRSCHEMESENUMPROC lpfn,
LPARAM lParam
)
{
HKEY hKeyPolicyUser, hKeyPolicyMachine;
HKEY hKeyUser = INVALID_HANDLE_VALUE;
HKEY hKeyMachine = INVALID_HANDLE_VALUE;
DWORD dwDescSize;
DWORD dwSize, dwNameSize, dwIndex = 0;
BOOLEAN bOneCallBackOk = FALSE;
LONG lRet = ERROR_SUCCESS;
LPTSTR lpszDescBuf, lpszDesc;
TCHAR szNameBuf[MAX_NAME_LEN+1];
FILETIME ft;
UINT uiID;
MACHINE_POWER_POLICY mpp;
USER_POWER_POLICY upp;
POWER_POLICY pp;
if (!lpfn) {
SetLastError(ERROR_INVALID_PARAMETER);
goto WESPSP_exit;
}
// Wait on/take the registry semaphore.
if (!TakeRegSemaphore()) {
return FALSE;
}
// Allocate a description buffer.
lpszDescBuf = LocalAlloc(0, (MAX_DESC_LEN + 1) * sizeof(TCHAR));
if (!lpszDescBuf) {
goto WESPSP_exit;
}
if (ERROR_SUCCESS != OpenMachineUserKeys2(c_szREGSTR_PATH_USER_POWERCFG_POLICIES,
c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
&hKeyUser, &hKeyMachine))
{
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
return FALSE;
}
// Enumerate the schemes
while (lRet == ERROR_SUCCESS) {
dwSize = REGSTR_MAX_VALUE_LENGTH - 1;
if ((lRet = RegEnumKeyEx(hKeyUser,
dwIndex,
g_szRegValue,
&dwSize,
NULL,
NULL,
NULL,
&ft)) == ERROR_SUCCESS) {
// Open the Policies Key. The key name is the policies ID.
lpszDesc = NULL;
if (MyStrToInt(g_szRegValue, &uiID)) {
if ((lRet = RegOpenKeyEx(hKeyUser,
g_szRegValue,
0,
KEY_READ,
&hKeyPolicyUser)) == ERROR_SUCCESS) {
if ((lRet = RegOpenKeyEx(hKeyMachine,
g_szRegValue,
0,
KEY_READ,
&hKeyPolicyMachine)) == ERROR_SUCCESS) {
// Get the friendly name..
dwNameSize = MAX_NAME_SIZE;
if ((lRet = RegQueryValueEx(hKeyPolicyUser,
TEXT("Name"),
NULL,
NULL,
(PBYTE) szNameBuf,
&dwNameSize)) == ERROR_SUCCESS) {
// Descriptions are optional.
dwDescSize = MAX_DESC_SIZE;
if ((lRet = RegQueryValueEx(hKeyPolicyUser,
TEXT("Description"),
NULL,
NULL,
(PBYTE) lpszDescBuf,
&dwDescSize)) == ERROR_SUCCESS) {
lpszDesc = lpszDescBuf;
}
// Read the user and machine policies.
dwSize = sizeof(upp);
if ((lRet = RegQueryValueEx(hKeyPolicyUser,
TEXT("Policies"),
NULL,
NULL,
(PBYTE) &upp,
&dwSize)) == ERROR_SUCCESS) {
dwSize = sizeof(mpp);
if ((lRet = RegQueryValueEx(hKeyPolicyMachine,
TEXT("Policies"),
NULL,
NULL,
(PBYTE) &mpp,
&dwSize)) == ERROR_SUCCESS) {
// Merge the user and machine policies.
if (MergePolicies(&upp, &mpp, &pp)) {
// Call the enumerate proc.
if (!lpfn(uiID,
dwNameSize, szNameBuf,
dwDescSize, lpszDesc,
&pp, lParam)) {
RegCloseKey(hKeyPolicyMachine);
RegCloseKey(hKeyPolicyUser);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
break;
}
else {
bOneCallBackOk = TRUE;
}
}
}
}
}
RegCloseKey(hKeyPolicyMachine);
}
RegCloseKey(hKeyPolicyUser);
}
}
}
dwIndex++;
}
RegCloseKey(hKeyUser);
RegCloseKey(hKeyMachine);
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
if (lpszDescBuf) {
LocalFree(lpszDescBuf);
}
WESPSP_exit:
if (lRet != ERROR_NO_MORE_ITEMS) {
DebugPrint( "EnumPwrSchemes, failed, LastError: 0x%08X",
(lRet == ERROR_SUCCESS) ? GetLastError():lRet);
}
return bOneCallBackOk;
}
/*******************************************************************************
*
* ReadGlobalPwrPolicy
*
* DESCRIPTION:
* Function reads the users global power policy profile and returns it.
* If there is no such profile FALSE is returned. A global power policy
* profile is per user, and contains values which apply to all of a users
* power policies.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN ReadGlobalPwrPolicy(
PGLOBAL_POWER_POLICY pgpp
)
{
GLOBAL_MACHINE_POWER_POLICY gmpp;
GLOBAL_USER_POWER_POLICY gupp;
DWORD dwError = ReadPwrPolicyEx2(c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_PATH_MACHINE_POWERCFG, c_szREGSTR_VAL_GLOBALPOWERPOLICY,
NULL, NULL, &gupp, sizeof(gupp), &gmpp, sizeof(gmpp));
if (ERROR_SUCCESS == dwError)
{
return MergeGlobalPolicies(&gupp, &gmpp, pgpp); // Sets Last Error
}
else
{
SetLastError(dwError);
}
return FALSE;
}
/*******************************************************************************
*
* WritePwrScheme
*
* DESCRIPTION:
* Function to write a users power policy profile. If the profile already
* exists it is replaced. Otherwise a new profile is created.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN WritePwrScheme(
PUINT puiID,
LPTSTR lpszSchemeName,
LPTSTR lpszDescription,
PPOWER_POLICY lpScheme
)
{
MACHINE_POWER_POLICY mpp;
USER_POWER_POLICY upp;
if (SplitPolicies(lpScheme, &upp, &mpp))
{
// WritePwrPolicyEx will set the last error on failure.
return WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG_POLICIES,
c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
puiID,
lpszSchemeName,
lpszDescription,
&upp,
sizeof(upp),
&mpp,
sizeof(mpp));
}
return FALSE;
}
/*******************************************************************************
*
* WriteGlobalPwrPolicy
*
* DESCRIPTION:
* Function to write a users global power policy profile. If the profile
* already exists it is replaced. Otherwise a new profile is created.
* A global power policy profile is per user, and contains values which
* apply to all of a users power policies. Otherwise a new profile is created.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN WriteGlobalPwrPolicy (
PGLOBAL_POWER_POLICY pgpp
)
{
GLOBAL_MACHINE_POWER_POLICY gmpp;
GLOBAL_USER_POWER_POLICY gupp;
if (SplitGlobalPolicies(pgpp, &gupp, &gmpp)) // Will set last error
{
// WritePwrPolicyEx will set the last error on failure.
return WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_PATH_MACHINE_POWERCFG,
NULL,
c_szREGSTR_VAL_GLOBALPOWERPOLICY,
NULL,
&gupp,
sizeof(gupp),
&gmpp,
sizeof(gmpp));
}
return FALSE;
}
/*******************************************************************************
*
* DeletePwrScheme
*
* DESCRIPTION:
* Function to delete a users power policy profile. An attempt to delete the
* currently active power policy profile will fail with last error set to
* ERROR_ACCESS_DENIED.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN DeletePwrScheme(UINT uiID)
{
HKEY hKeyUser;
DWORD dwSize = REGSTR_MAX_VALUE_LENGTH * sizeof(TCHAR);
BOOLEAN bRet = FALSE;
LONG lRet = ERROR_SUCCESS;
TCHAR szNum[NUM_DEC_DIGITS];
int iCurrent;
HKEY hKeyCurrentUser;
// Wait on/take the registry semaphore.
if (!TakeRegSemaphore())
{
return FALSE;
}
if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser))
{
// Don't allow the currently active power policy profile to be deleted.
// ReadWritePowerValue will set last error
if (ReadWritePowerValue(hKeyCurrentUser,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_CURRENTPOWERPOLICY,
g_szRegValue, &dwSize, FALSE, FALSE) &&
MyStrToInt(g_szRegValue, &iCurrent))
{
if (uiID != (UINT) iCurrent)
{
// For now we only delete the user portion of a policy. We may
// want a ref count on the machine portion which allows deletion
// of the machine portion when no user portion references it.
lRet = RegOpenKey(hKeyCurrentUser, c_szREGSTR_PATH_USER_POWERCFG_POLICIES, &hKeyUser);
if (lRet == ERROR_SUCCESS)
{
wsprintf(szNum, TEXT("%d"), uiID);
lRet = RegDeleteKey(hKeyUser, szNum);
if (lRet == ERROR_SUCCESS)
{
bRet = TRUE;
}
RegCloseKey(hKeyUser);
}
}
else
{
SetLastError(ERROR_ACCESS_DENIED);
}
}
CloseCurrentUser(hKeyCurrentUser);
}
ReleaseSemaphore(g_hSemRegistry, 1, NULL);
if (!bRet)
{
DebugPrint( "DeletePwrScheme, failed, LastError: 0x%08X", (lRet == ERROR_SUCCESS) ? GetLastError():lRet);
}
return bRet;
}
/*******************************************************************************
*
* GetActivePwrScheme
*
* DESCRIPTION:
* Retrieves the ID of the currently active power policy profile. This value
* is set by SetActivePwrScheme.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN
GetActivePwrScheme(PUINT puiID)
{
BOOLEAN bRet = FALSE;
TCHAR szNum[NUM_DEC_DIGITS];
DWORD dwSize = SIZE_DEC_DIGITS;
HKEY hKey;
if (ERROR_SUCCESS == OpenCurrentUser2(&hKey))
{
// ReadWritePowerValue will set last error
if (ReadWritePowerValue(hKey,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_CURRENTPOWERPOLICY,
szNum, &dwSize, FALSE, TRUE) &&
MyStrToInt(szNum, puiID))
{
bRet = TRUE;
}
CloseCurrentUser(hKey);
}
return bRet;
}
/*******************************************************************************
*
* SetActivePwrScheme
*
* DESCRIPTION:
* Set the currently active power policy profile.
*
* PARAMETERS:
* uiID - ID of the new active power scheme.
* lpGlobalPolicy - Optional global policies to merge with active power scheme.
* lpPowerPolicy - Optional power policies to merge with active power scheme.
*
*******************************************************************************/
BOOLEAN
SetActivePwrScheme(
UINT uiID,
PGLOBAL_POWER_POLICY pgpp,
PPOWER_POLICY ppp
)
{
DWORD dwSize;
NTSTATUS ntsRetVal, status;
TCHAR szNum[NUM_DEC_DIGITS];
POWER_POLICY pp;
GLOBAL_POWER_POLICY gpp;
MACHINE_POWER_POLICY mpp;
USER_POWER_POLICY upp;
GLOBAL_MACHINE_POWER_POLICY gmpp;
GLOBAL_USER_POWER_POLICY gupp;
SYSTEM_POWER_POLICY sppAc, sppDc;
MACHINE_PROCESSOR_POWER_POLICY mppp;
HKEY hKeyCurrentUser;
DWORD dwError;
BOOLEAN bRet = FALSE;
// If a new scheme is not passed, fetch the target scheme.
if (!ppp)
{
if (!ReadPwrScheme(uiID, &pp)) // Will SetLastError
{
return FALSE;
}
ppp = &pp;
}
// If a new global policy is not passed, fetch the target global policy.
if (!pgpp)
{
if (!ReadGlobalPwrPolicy(&gpp)) // Sets last error
{
return FALSE;
}
pgpp = &gpp;
}
if (!ReadProcessorPwrScheme(uiID, &mppp)) {
return FALSE;
}
// Merge global policy and user scheme if a global policy was passed.
if (!MergeToSystemPowerPolicies(pgpp, ppp, &sppAc, &sppDc)) // Sets last error
{
return FALSE;
}
// Write out what was requested to the registry.
SplitPolicies(ppp, &upp, &mpp); // Will set last error
if (!WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG_POLICIES, c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
&uiID, NULL, NULL, &upp, sizeof(upp), &mpp, sizeof(mpp)))
{
// WritePwrPolicyEx will set the last error on failure.
return FALSE;
}
SplitGlobalPolicies(pgpp, &gupp, &gmpp); // Will set last error
if (!WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_PATH_MACHINE_POWERCFG,
NULL,
c_szREGSTR_VAL_GLOBALPOWERPOLICY,
NULL,
&gupp,
sizeof(gupp),
&gmpp,
sizeof(gmpp)))
{
// WritePwrPolicyEx will set the last error on failure.
return FALSE;
}
// Call down to the power policy manager to set the scheme.
// I'm working under the assumption that CallNtSetValidateAcDc will call SetLastError() with any
// error values.
status = CallNtSetValidateAcDc(FALSE, FALSE, &(mppp.ProcessorPolicyAc), &(mppp.ProcessorPolicyAc), &(mppp.ProcessorPolicyDc), &(mppp.ProcessorPolicyDc));
ntsRetVal = CallNtSetValidateAcDc(FALSE, TRUE, &sppAc, &sppAc, &sppDc, &sppDc);
//if ((ntsRetVal == STATUS_SUCCESS) && (status = STATUS_SUCCESS))
if ((ntsRetVal == STATUS_SUCCESS))
{
dwError = OpenCurrentUser2(&hKeyCurrentUser);
if (ERROR_SUCCESS == dwError)
{
// On success, set the current active power scheme in the registry.
wsprintf(szNum, TEXT("%d"), uiID);
// ReadWritePowerValue will set last error
bRet = ReadWritePowerValue(hKeyCurrentUser,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_CURRENTPOWERPOLICY,
szNum, NULL, TRUE, TRUE);
dwError = GetLastError();
CloseCurrentUser(hKeyCurrentUser);
SetLastError(dwError);
}
else
{
SetLastError(dwError);
}
}
return bRet;
}
/*******************************************************************************
*
* LoadCurrentPwrScheme
*
* DESCRIPTION:
* A Memphis only cover to call SetActivePwrScheme using RunDLL32 calling
* convention. Do not change parameter list.
*
* PARAMETERS:
*
*******************************************************************************/
void WINAPI LoadCurrentPwrScheme(
HWND hwnd,
HINSTANCE hAppInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
UINT uiID;
if (GetActivePwrScheme(&uiID)) {
SetActivePwrScheme(uiID, NULL, NULL);
}
}
/*******************************************************************************
*
* MergeLegacyPwrScheme
*
* DESCRIPTION:
* A Memphis only call to merge legacy power management registry info into the
* currently active power scheme.
* Called using the RunDLL32 calling convention. Do not change parameter list.
*
* PARAMETERS:
*
*******************************************************************************/
void WINAPI MergeLegacyPwrScheme(
HWND hwnd,
HINSTANCE hAppInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
DWORD dwSize, dwLegacy;
POWER_POLICY pp;
GLOBAL_POWER_POLICY gpp;
UINT uiID;
HKEY hKeyCurrentUser;
// Get the active power scheme from the registry.
if (!GetActivePwrScheme(&uiID))
{
return;
}
if (!ReadPwrScheme(uiID, &pp))
{
return;
}
if (!ReadGlobalPwrPolicy(&gpp))
{
return;
}
if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser))
{
// Get the legacy video monitor power down information.
if (ReadPowerIntOptional(hKeyCurrentUser,
REGSTR_PATH_SCREENSAVE,
REGSTR_VALUE_POWEROFFACTIVE,
&pp.user.VideoTimeoutAc))
{
DebugPrint( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VALUE_POWEROFFACTIVE, pp.user.VideoTimeoutAc);
pp.user.VideoTimeoutDc = pp.user.VideoTimeoutAc;
}
CloseCurrentUser(hKeyCurrentUser);
}
// Get the legacy disk spin down information.
if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
REGSTR_PATH_FILESYSTEM,
REGSTR_VAL_ACDRIVESPINDOWN,
&pp.user.SpindownTimeoutAc)) {
DebugPrint( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VAL_ACDRIVESPINDOWN, pp.user.SpindownTimeoutAc);
}
if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
REGSTR_PATH_FILESYSTEM,
REGSTR_VAL_BATDRIVESPINDOWN,
&pp.user.SpindownTimeoutDc)) {
DebugPrint( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VAL_BATDRIVESPINDOWN, pp.user.SpindownTimeoutDc);
}
// Get the legacy battery meter information.
dwSize = sizeof(dwLegacy);
if (ReadPowerValueOptional(HKEY_LOCAL_MACHINE,
REGSTR_PATH_VPOWERD,
REGSTR_VAL_VPOWERDFLAGS,
(LPTSTR)&dwLegacy, &dwSize)) {
if (dwLegacy & VPDF_SHOWMULTIBATT) {
gpp.user.GlobalFlags |= EnableSysTrayBatteryMeter;
}
else {
gpp.user.GlobalFlags &= ~EnableSysTrayBatteryMeter;
}
DebugPrint( "MergeLegacyPwrScheme, found legacy %s: %X", REGSTR_VAL_VPOWERDFLAGS, dwLegacy);
}
// Write out the modified active power scheme.
if (!WriteGlobalPwrPolicy(&gpp)) {
return;
}
WritePwrScheme(&uiID, NULL, NULL, &pp);
}
/*******************************************************************************
*
* GetPwrCapabilities
*
* DESCRIPTION:
* Get the system power capabilities from the Power Policy Manager.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN GetPwrCapabilities(PSYSTEM_POWER_CAPABILITIES lpspc)
{
NTSTATUS ntsRetVal = STATUS_SUCCESS;
if (!lpspc) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
ntsRetVal = CallNtPowerInformation(SystemPowerCapabilities, NULL, 0, lpspc,
sizeof(SYSTEM_POWER_CAPABILITIES));
if (ntsRetVal == STATUS_SUCCESS) {
#ifdef DEBUG
if (g_iShowCapabilities) {
DumpSystemPowerCapabilities("GetPwrCapabilities, returned:", lpspc);
}
#ifdef SIM_BATTERY
lpspc->SystemBatteriesPresent = TRUE;
#endif
#endif
return TRUE;
}
else {
return FALSE;
}
}
/*******************************************************************************
*
* CallNtPowerInformation
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
NTSTATUS CallNtPowerInformation(
POWER_INFORMATION_LEVEL InformationLevel,
PVOID InputBuffer OPTIONAL,
ULONG InputBufferLength,
PVOID OutputBuffer OPTIONAL,
ULONG OutputBufferLength
)
{
NTSTATUS ntsRetVal;
DWORD dwOldState, dwStatus;
DWORD dwErrorSave;
LPCTSTR PrivilegeName;
if (InformationLevel == SystemReserveHiberFile) {
PrivilegeName = SE_CREATE_PAGEFILE_NAME;
} else {
PrivilegeName = SE_SHUTDOWN_NAME;
}
SetLastError(0);
dwStatus = SetPrivilegeAttribute(PrivilegeName, SE_PRIVILEGE_ENABLED,
&dwOldState);
dwErrorSave = GetLastError();
ntsRetVal = NtPowerInformation(InformationLevel,
InputBuffer, InputBufferLength,
OutputBuffer, OutputBufferLength);
//
// If we were able to set the privilege, then reset it.
//
if (NT_SUCCESS(dwStatus) && dwErrorSave == 0) {
SetPrivilegeAttribute(PrivilegeName, dwOldState, NULL);
}
else {
DebugPrint( "CallNtPowerInformation, SetPrivilegeAttribute failed: 0x%08X", GetLastError());
}
#ifdef DEBUG
if ((ntsRetVal != STATUS_SUCCESS) && (InformationLevel <= ProcessorPowerPolicyCurrent)) {
DebugPrint( "NtPowerInformation, %s, failed: 0x%08X", lpszInfoLevel[InformationLevel], ntsRetVal);
}
else {
if (g_iShowSetPPM && InputBuffer) {
if ((InformationLevel == SystemPowerPolicyAc) ||
(InformationLevel == SystemPowerPolicyDc)) {
DumpSystemPowerPolicy("NtPowerInformation, Set to PPM, InputBuffer", InputBuffer);
}
}
}
#endif
return ntsRetVal;
}
/*******************************************************************************
*
* SetSuspendState
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN SetSuspendState(
BOOLEAN bHibernate,
BOOLEAN bForce,
BOOLEAN bWakeupEventsDisabled)
{
NTSTATUS ntsRetVal;
POWER_ACTION pa;
ULONG Flags;
DWORD dwOldState, dwStatus;
DWORD dwErrorSave;
SetLastError(0);
dwStatus = SetPrivilegeAttribute(SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED,
&dwOldState);
dwErrorSave = GetLastError();
if (bHibernate) {
pa = PowerActionHibernate;
}
else {
pa = PowerActionSleep;
}
Flags = POWER_ACTION_QUERY_ALLOWED | POWER_ACTION_UI_ALLOWED;
if (bForce) {
Flags |= POWER_ACTION_CRITICAL;
}
if (bWakeupEventsDisabled) {
Flags |= POWER_ACTION_DISABLE_WAKES;
}
ntsRetVal = NtInitiatePowerAction(pa, PowerSystemSleeping1, Flags, FALSE);
//
// If we were able to set the privilege, then reset it.
//
if (NT_SUCCESS(dwStatus) && dwErrorSave == 0) {
SetPrivilegeAttribute(SE_SHUTDOWN_NAME, dwOldState, NULL);
}
else {
DebugPrint( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError());
}
if (ntsRetVal == STATUS_SUCCESS) {
return TRUE;
}
else {
DebugPrint( "NtInitiatePowerAction, failed: 0x%08X", ntsRetVal);
return FALSE;
}
}
/*******************************************************************************
*
* P R I V A T E F U N C T I O N S
*
*******************************************************************************/
/*******************************************************************************
*
* ValidatePowerPolicies
*
* DESCRIPTION:
* Call down to the power policy manager to validate power policies.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN ValidatePowerPolicies(
PGLOBAL_POWER_POLICY pgpp,
PPOWER_POLICY ppp
)
{
POWER_POLICY ppValid;
GLOBAL_POWER_POLICY gppValid;
SYSTEM_POWER_POLICY sppAc, sppDc;
// Get current power policy data from the PPM.
if (!GetCurrentPowerPolicies(&gppValid, &ppValid)) {
return FALSE;
}
if (!pgpp) {
pgpp = &gppValid;
}
if (!ppp) {
ppp = &ppValid;
}
// Merge policy and global policy data.
if (!MergeToSystemPowerPolicies(pgpp, ppp, &sppAc, &sppDc)) {
return FALSE;
}
if (!ValidateSystemPolicies(&sppAc, &sppDc)) {
return FALSE;
}
return SplitFromSystemPowerPolicies(&sppAc, &sppDc, pgpp, ppp);
}
/*******************************************************************************
*
* ValidateSystemPolicies
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN ValidateSystemPolicies(
PSYSTEM_POWER_POLICY psppAc,
PSYSTEM_POWER_POLICY psppDc
)
{
DWORD dwLastErr;
NTSTATUS ntsRetVal;
// Call down to the power policy manager to validate the scheme.
ntsRetVal = CallNtSetValidateAcDc(TRUE, TRUE, psppAc, psppAc, psppDc, psppDc);
// Map any PPM errors to winerror.h values
switch (ntsRetVal) {
case STATUS_SUCCESS:
return TRUE;
case STATUS_PRIVILEGE_NOT_HELD:
dwLastErr = ERROR_ACCESS_DENIED;
break;
case STATUS_INVALID_PARAMETER:
dwLastErr = ERROR_INVALID_DATA;
break;
default:
dwLastErr = ERROR_GEN_FAILURE;
break;
}
SetLastError(dwLastErr);
return FALSE;
}
/*******************************************************************************
*
* GetCurrentPowerPolicies
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN GetCurrentPowerPolicies(PGLOBAL_POWER_POLICY pgpp, PPOWER_POLICY ppp)
{
SYSTEM_POWER_POLICY sppAc, sppDc;
if (!GetCurrentSystemPowerPolicies(&sppAc, &sppDc)) {
return FALSE;
}
return SplitFromSystemPowerPolicies(&sppAc, &sppDc, pgpp, ppp);
}
/*******************************************************************************
*
* GetCurrentSystemPowerPolicies
*
* DESCRIPTION:
* Call down to the power policy manager to get the current system power
* policies.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN GetCurrentSystemPowerPolicies(
PSYSTEM_POWER_POLICY psppAc,
PSYSTEM_POWER_POLICY psppDc
)
{
NTSTATUS ntsRetVal;
// Call down to the power policy manager to get system power policies.
ntsRetVal = CallNtSetValidateAcDc(FALSE, TRUE, NULL, psppAc, NULL, psppDc);
if (ntsRetVal == STATUS_SUCCESS) {
return TRUE;
}
else {
return FALSE;
}
}
#ifdef WINNT
/*******************************************************************************
*
* SetPrivilegeAttribute
*
* DESCRIPTION:
* This routine sets the security attributes for a given privilege.
*
* PARAMETERS:
* PrivilegeName - Name of the privilege we are manipulating.
* NewPrivilegeAttribute - The new attribute value to use.
* OldPrivilegeAttribute - Pointer to receive the old privilege value.
* OPTIONAL.
*
*******************************************************************************/
DWORD SetPrivilegeAttribute(
LPCTSTR PrivilegeName,
DWORD NewPrivilegeAttribute,
DWORD *OldPrivilegeAttribute
)
{
LUID PrivilegeValue;
TOKEN_PRIVILEGES TokenPrivileges, OldTokenPrivileges;
DWORD ReturnLength;
HANDLE TokenHandle;
// First, find out the LUID Value of the privilege
if(!LookupPrivilegeValue(NULL, PrivilegeName, &PrivilegeValue)) {
return GetLastError();
}
// Get the token handle
if (!OpenThreadToken (GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE, &TokenHandle)) {
if (!OpenProcessToken (GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&TokenHandle)) {
return GetLastError();
}
}
// Set up the privilege set we will need
TokenPrivileges.PrivilegeCount = 1;
TokenPrivileges.Privileges[0].Luid = PrivilegeValue;
TokenPrivileges.Privileges[0].Attributes = NewPrivilegeAttribute;
ReturnLength = sizeof(TOKEN_PRIVILEGES);
if (!AdjustTokenPrivileges(TokenHandle, FALSE,
&TokenPrivileges, sizeof(TOKEN_PRIVILEGES),
&OldTokenPrivileges, &ReturnLength)) {
CloseHandle(TokenHandle);
return GetLastError();
}
else {
if (OldPrivilegeAttribute != NULL) {
//
// If the privilege changed, store the old value. If it did
// not change, store the value passed in.
//
if( OldTokenPrivileges.PrivilegeCount != 0 ) {
*OldPrivilegeAttribute = OldTokenPrivileges.Privileges[0].Attributes;
} else {
*OldPrivilegeAttribute = NewPrivilegeAttribute;
}
}
CloseHandle(TokenHandle);
return NO_ERROR;
}
}
#endif
/*******************************************************************************
*
* CallNtSetValidateAcDc
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
NTSTATUS CallNtSetValidateAcDc(
BOOLEAN bValidate,
BOOLEAN bSystem,
PVOID InputBufferAc OPTIONAL,
PVOID OutputBufferAc OPTIONAL,
PVOID InputBufferDc OPTIONAL,
PVOID OutputBufferDc OPTIONAL
)
{
NTSTATUS ntsRetVal;
POWER_INFORMATION_LEVEL pil, pilAc, pilDc;
ULONG policyLength;
#ifdef DEBUG
SYSTEM_POWER_POLICY sppOrgAc, sppOrgDc;
#endif
#ifdef WINNT
DWORD dwOldState, dwStatus;
DWORD dwErrorSave;
SetLastError(0);
dwStatus = SetPrivilegeAttribute(SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED, &dwOldState);
dwErrorSave = GetLastError();
#endif
if (bSystem) {
if (bValidate) {
pil = pilAc = VerifySystemPolicyAc;
pilDc = VerifySystemPolicyDc;
} else {
pil = pilAc = SystemPowerPolicyAc;
pilDc = SystemPowerPolicyDc;
}
policyLength = sizeof(SYSTEM_POWER_POLICY);
} else {
if (bValidate) {
pil = pilAc = VerifyProcessorPowerPolicyAc;
pilDc = VerifyProcessorPowerPolicyDc;
} else {
pil = pilAc = ProcessorPowerPolicyAc;
pilDc = ProcessorPowerPolicyDc;
}
policyLength = sizeof(PROCESSOR_POWER_POLICY);
}
#ifdef DEBUG
if (InputBufferAc)
{
memcpy(&sppOrgAc, InputBufferAc, policyLength);
}
if (InputBufferDc)
{
memcpy(&sppOrgDc, InputBufferDc, policyLength);
}
#endif
ntsRetVal = NtPowerInformation(pilAc,
InputBufferAc,
policyLength,
OutputBufferAc,
policyLength);
if (ntsRetVal == STATUS_SUCCESS)
{
pil = pilDc;
ntsRetVal = NtPowerInformation(pilDc,
InputBufferDc,
policyLength,
OutputBufferDc,
policyLength);
}
#ifdef WINNT
// If we were able to set the privilege, then reset it.
if (NT_SUCCESS(dwStatus) && (dwErrorSave == ERROR_SUCCESS))
{
SetPrivilegeAttribute(SE_SHUTDOWN_NAME, dwOldState, NULL);
#ifdef DEBUG
if (InputBufferAc && OutputBufferAc)
{
DifSystemPowerPolicies("PPM modified AC policies", &sppOrgAc, OutputBufferAc);
}
if (InputBufferDc && OutputBufferDc)
{
DifSystemPowerPolicies("PPM modified DC policies", &sppOrgDc, OutputBufferDc);
}
#endif
}
else
{
DebugPrint( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError());
}
#endif
#ifdef DEBUG
if (ntsRetVal != STATUS_SUCCESS)
{
DebugPrint( "NtPowerInformation, %s, failed: 0x%08X", lpszInfoLevel[pil], ntsRetVal);
switch (pil)
{
case SystemPowerPolicyAc:
case VerifySystemPolicyAc:
DumpSystemPowerPolicy("InputBufferAc", InputBufferAc);
break;
case SystemPowerPolicyDc:
case VerifySystemPolicyDc:
DumpSystemPowerPolicy("InputBufferDc", InputBufferDc);
break;
}
}
else
{
if (g_iShowSetPPM && InputBufferAc && InputBufferDc && !bValidate)
{
DumpSystemPowerPolicy("CallNtSetValidateAcDc, Set AC to PPM", InputBufferAc);
DumpSystemPowerPolicy("CallNtSetValidateAcDc, Set DC to PPM", InputBufferDc);
}
}
#endif
return ntsRetVal;
}
/*******************************************************************************
*
* ReadPwrScheme
*
* DESCRIPTION:
* Function reads the specified user power policy profile and returns
* it. If there is no such profile FALSE is returned.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN ReadPwrScheme(
UINT uiID,
PPOWER_POLICY ppp
)
{
MACHINE_POWER_POLICY mpp;
USER_POWER_POLICY upp;
TCHAR szNum[NUM_DEC_DIGITS];
DWORD dwError;
wsprintf(szNum, TEXT("%d"), uiID);
dwError = ReadPwrPolicyEx2(c_szREGSTR_PATH_USER_POWERCFG_POLICIES, c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
szNum, NULL, 0, &upp, sizeof(upp), &mpp, sizeof(mpp));
if (ERROR_SUCCESS == dwError)
{
return MergePolicies(&upp, &mpp, ppp);
}
else
{
SetLastError(dwError);
}
return FALSE;
}
/*******************************************************************************
*
* ReadProcessorPwrScheme
*
* DESCRIPTION:
* Function reads the specified processor power policy profile and returns
* it. If there is no such profile FALSE is returned.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN
ReadProcessorPwrScheme(
UINT uiID,
PMACHINE_PROCESSOR_POWER_POLICY pmppp
)
{
TCHAR szNum[NUM_DEC_DIGITS];
DWORD dwError;
wsprintf(szNum, TEXT("%d"), uiID);
dwError = ReadProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
szNum,
pmppp,
sizeof(MACHINE_PROCESSOR_POWER_POLICY));
//
// It's legal for there to be no Processor Power Scheme that corresponds with
// uiID, as long as uiID is non-zero. If this is the case, just use a
// default scheme. (We use '1' as a default because this will be the
// default laptop scheme. Non-laptops probably won't have power controls
// on the processor, so it won't matter if we get a scheme that is too aggressive.)
//
if ((ERROR_SUCCESS != dwError) &&
(uiID != 0)) {
wsprintf(szNum, TEXT("%d"), 1);
dwError = ReadProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
szNum,
pmppp,
sizeof(MACHINE_PROCESSOR_POWER_POLICY));
}
if (ERROR_SUCCESS == dwError) {
return TRUE;
} else {
SetLastError(dwError);
return FALSE;
}
}
/*******************************************************************************
*
* WriteProcessorPwrScheme
*
* DESCRIPTION:
* Function writes the specified processor power policy profile
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN
WriteProcessorPwrScheme(
UINT uiID,
PMACHINE_PROCESSOR_POWER_POLICY pmppp
)
{
TCHAR szNum[NUM_DEC_DIGITS];
DWORD dwError;
wsprintf(szNum, TEXT("%d"), uiID);
dwError = WriteProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
szNum,
pmppp,
sizeof(MACHINE_PROCESSOR_POWER_POLICY));
if (ERROR_SUCCESS == dwError) {
return TRUE;
} else {
SetLastError(dwError);
return FALSE;
}
}
/*******************************************************************************
*
* MyStrToInt
*
* DESCRIPTION:
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN MyStrToInt(LPCTSTR lpSrc, PINT pi)
{
#define ISDIGIT(c) ((c) >= TEXT('0') && (c) <= TEXT('9'))
int n = 0;
BOOL bNeg = FALSE;
if (*lpSrc == TEXT('-')) {
bNeg = TRUE;
lpSrc++;
}
if (!ISDIGIT(*lpSrc)) {
DebugPrint( "MyStrToInt, non-integer string: %s", lpSrc);
return FALSE;
}
while (ISDIGIT(*lpSrc)) {
n *= 10;
n += *lpSrc - TEXT('0');
lpSrc++;
}
if (bNeg) {
*pi = -n;
}
else {
*pi = n;
}
return TRUE;
}
#ifndef WINNT
/*******************************************************************************
*
* DM32IsPCMCIAPresent
*
* DESCRIPTION:
* Memphis only test for existence of PCMCIA slots. From Jason Cobb.
*
* PARAMETERS:
*
*******************************************************************************/
DEFINE_GUID(GUID_DEVICEINTERFACE_PCMCIA,0x4d36e977L, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);
BOOLEAN DM32IsPCMCIAPresent(VOID)
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
BOOLEAN bRet = FALSE;
hDevInfo = SetupDiGetClassDevs((LPGUID)&GUID_DEVICEINTERFACE_PCMCIA,
NULL, NULL, 0);
if (hDevInfo != INVALID_HANDLE_VALUE) {
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(hDevInfo, 0, &DeviceInfoData)) {
bRet = TRUE;
}
else {
DebugPrint( "DM32IsPCMCIAPresent, SetupDiEnumDeviceInfo on PCMCIA failed");
}
SetupDiDestroyDeviceInfoList(hDevInfo);
}
else {
DebugPrint( "DM32IsPCMCIAPresent, SetupDiGetClassDevs on PCMCIA failed");
}
return bRet;
}
#endif
/*******************************************************************************
*
* RegistryInit
*
* DESCRIPTION:
* Do DLL load time registry related initialization.
*
* PARAMETERS:
*
*******************************************************************************/
BOOLEAN RegistryInit(PUINT puiLastId)
{
DWORD dwSize;
TCHAR szNum[NUM_DEC_DIGITS];
UINT uiCurPwrScheme;
// Read in the last ID this value must be present.
dwSize = sizeof(szNum);
// ReadWritePowerValue will set last error
if (!ReadWritePowerValue(HKEY_LOCAL_MACHINE,
c_szREGSTR_PATH_MACHINE_POWERCFG,
c_szREGSTR_VAL_LASTID,
szNum, &dwSize, FALSE, TRUE) ||
!MyStrToInt(szNum, &g_uiLastID)) {
DebugPrint( "RegistryInit, Unable to fetch last ID, registry is corrupt");
return FALSE;
}
#ifndef WINNT
// For Memphis only we check the HKCU current scheme entry. If it's not
// valid a new entry is written. If the machine has a PCMCIA slot we set
// Portable as the current scheme, otherwise it's Home/Office. Per RobMCK.
if (!GetActivePwrScheme(&uiCurPwrScheme)) {
DebugPrint( "RegistryInit, unable to validate currrent scheme");
if (DM32IsPCMCIAPresent()) {
uiCurPwrScheme = 1;
}
else {
uiCurPwrScheme = 0;
}
wsprintf(szNum, TEXT("%d"), uiCurPwrScheme);
DebugPrint( "RegistryInit, attempting to write new current ID: %s", szNum);
// ReadWritePowerValue will set last error
return ReadWritePowerValue(HKEY_CURRENT_USER,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_CURRENTPOWERPOLICY,
szNum, NULL, TRUE, TRUE);
}
#endif
return TRUE;
}
#ifdef DEBUG
/*******************************************************************************
*
* ReadOptionalDebugSettings
*
* DESCRIPTION:
* Debug only. Get the debug settings from HKCU registry entries into globals.
*
* PARAMETERS:
*
*******************************************************************************/
VOID ReadOptionalDebugSettings(VOID)
{
HKEY hKeyCurrentUser;
if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser))
{
// Optional debug logging of PPM policy validation changes.
ReadPowerIntOptional(hKeyCurrentUser,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_SHOWVALCHANGES,
&g_iShowValidationChanges);
// Optional debug logging of PPM capabilities.
ReadPowerIntOptional(hKeyCurrentUser,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_SHOWCAPABILITIES,
&g_iShowCapabilities);
// Optional debug logging of setting new policy to PPM.
ReadPowerIntOptional(hKeyCurrentUser,
c_szREGSTR_PATH_USER_POWERCFG,
c_szREGSTR_VAL_SHOWSETPPM,
&g_iShowSetPPM);
CloseCurrentUser(hKeyCurrentUser);
}
}
#endif
#ifdef WINNT
/*******************************************************************************
*
* InitAdmin
*
* DESCRIPTION:
* For NT only, initialize an administrator power policy which
* supports an optional administrative override of certain
* power policy settings. The PowerCfg.Cpl and PPM will use these
* override values during validation.
*
* PARAMETERS:
*
*******************************************************************************/
VOID InitAdmin(PADMINISTRATOR_POWER_POLICY papp)
{
INT i;
NTSTATUS ntsRetVal;
HKEY hKeyCurrentUser;
if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser))
{
if (ReadPowerIntOptional(hKeyCurrentUser, c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_VAL_ADMINMAXSLEEP, &i))
{
g_app.MaxSleep = (SYSTEM_POWER_STATE) i;
g_bAdminOverrideActive = TRUE;
}
if (ReadPowerIntOptional(hKeyCurrentUser, c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_VAL_ADMINMAXVIDEOTIMEOUT, &i))
{
g_app.MaxVideoTimeout = i;
g_bAdminOverrideActive = TRUE;
}
CloseCurrentUser(hKeyCurrentUser);
}
// If an administration override was set, call down to the power
// policy manager to set the administrator policy.
if (g_bAdminOverrideActive)
{
ntsRetVal = CallNtPowerInformation(AdministratorPowerPolicy, &g_app, sizeof(ADMINISTRATOR_POWER_POLICY),
&g_app, sizeof(ADMINISTRATOR_POWER_POLICY));
if (ntsRetVal != STATUS_SUCCESS)
{
DebugPrint( "DllInitialize, Set AdministratorPowerPolicy failed: 0x%08X", ntsRetVal);
}
}
}
#endif