You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1890 lines
58 KiB
1890 lines
58 KiB
/*******************************************************************************
|
|
*
|
|
* (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 <tchar.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:
|
|
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
|