/******************************************************************************* * * (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 #include #include #include #include #include #include #include #include #include #include #include #include #include #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: if (g_hSemRegistry) { 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) { MYDBGPRINT(( "CanUserWritePwrScheme, Unable to write last ID, Error: %d", lErr)); } } } else { lErr = GetLastError(); MYDBGPRINT(( "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, KEY_READ, c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES, KEY_READ, &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) { MYDBGPRINT(( "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: * * puiID - Index of the power scheme to be written. * * lpszSchemeName - String that specifies the name of the power scheme. * * lpszDescription - Pointer to a string that specifies the description * of the power scheme. * * lpScheme - Pointer to a POWER_POLICY structure that contains * the power policy settings to be written. * *******************************************************************************/ BOOLEAN WritePwrScheme( PUINT puiID, LPTSTR lpszSchemeName, LPTSTR lpszDescription OPTIONAL, PPOWER_POLICY lpScheme ) { MACHINE_POWER_POLICY mpp; USER_POWER_POLICY upp; if( (!puiID && !lpszSchemeName) || !lpScheme ) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } 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, KEY_WRITE)) { // 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 = RegOpenKeyEx(hKeyCurrentUser,c_szREGSTR_PATH_USER_POWERCFG_POLICIES,0,KEY_WRITE,&hKeyUser); if (lRet == ERROR_SUCCESS) { _itot(uiID, szNum, 10 ); 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) { MYDBGPRINT(( "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, KEY_READ)) { // 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, KEY_WRITE); if (ERROR_SUCCESS == dwError) { // On success, set the current active power scheme in the registry. _itot(uiID, szNum, 10 ); // 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: * * NOTE: THIS API HAS BEEN DEPRECATED ON WINNT *******************************************************************************/ void WINAPI LoadCurrentPwrScheme( HWND hwnd, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow) { #ifndef WINNT UINT uiID; if (GetActivePwrScheme(&uiID)) { SetActivePwrScheme(uiID, NULL, NULL); } #else UNREFERENCED_PARAMETER(hwnd); UNREFERENCED_PARAMETER(hAppInstance); UNREFERENCED_PARAMETER(lpszCmdLine); UNREFERENCED_PARAMETER(nCmdShow); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); #endif } /******************************************************************************* * * 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) { #ifndef WINNT 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)) { MYDBGPRINT(( "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)) { MYDBGPRINT(( "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)) { MYDBGPRINT(( "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; } MYDBGPRINT(( "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); #else UNREFERENCED_PARAMETER(hwnd); UNREFERENCED_PARAMETER(hAppInstance); UNREFERENCED_PARAMETER(lpszCmdLine); UNREFERENCED_PARAMETER(nCmdShow); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); #endif } /******************************************************************************* * * 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 { MYDBGPRINT(( "CallNtPowerInformation, SetPrivilegeAttribute failed: 0x%08X", GetLastError())); } #ifdef DEBUG if ((ntsRetVal != STATUS_SUCCESS) && (InformationLevel <= ProcessorPowerPolicyCurrent)) { MYDBGPRINT(( "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 { MYDBGPRINT(( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError())); } if (ntsRetVal == STATUS_SUCCESS) { return TRUE; } else { MYDBGPRINT(( "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 { MYDBGPRINT(( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError())); } #endif #ifdef DEBUG if (ntsRetVal != STATUS_SUCCESS) { MYDBGPRINT(( "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; _itot(uiID, szNum, 10 ); 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; _itot(uiID, szNum, 10 ); 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)) { szNum[0] = TEXT('1'); szNum[1] = TEXT('\0'); 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; _itot(uiID, szNum, 10 ); 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)) { MYDBGPRINT(( "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; } /******************************************************************************* * * 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, FALSE) || !MyStrToInt(szNum, &g_uiLastID)) { MYDBGPRINT(( "RegistryInit, Unable to fetch last ID, registry is corrupt")); return FALSE; } 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,KEY_READ)) { // 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, KEY_READ)) { 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) { MYDBGPRINT(( "DllInitialize, Set AdministratorPowerPolicy failed: 0x%08X", ntsRetVal)); } } } #endif