Leaked source code of windows server 2003
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

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1996
  4. *
  5. * TITLE: POWRPROF.C
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 17 Oct, 1996
  12. *
  13. * DESCRIPTION:
  14. * User power management profile maintenance library. Implements persistent
  15. * power mamagement data storage. To minimize registry storage and simplify
  16. * user power profile management, power scheme's are divided into two parts,
  17. * GLOBAL_POWER_POLICY and POWER_POLICY:
  18. *
  19. * User Level Registry Storage
  20. * GLOBAL_POWER_POLICY = - Common scheme data.
  21. * GLOBAL_MACHINE_POWER_POLICY - Per machine data.
  22. * + GLOBAL_USER_POWER_POLICY - Per user data.
  23. *
  24. * POWER_POLICY = - Unique scheme data.
  25. * MACHINE_POWER_POLICY - Per machine data.
  26. * + USER_POWER_POLICY - Per user data.
  27. *
  28. * The interface to the power policy manager is by AC and DC
  29. * SYSTEM_POWER_POLICY which is formed by merging the above structures.
  30. *
  31. *******************************************************************************/
  32. #include <nt.h>
  33. #include <ntrtl.h>
  34. #include <nturtl.h>
  35. #include <windows.h>
  36. #include <tchar.h>
  37. #include <initguid.h>
  38. #include <devguid.h>
  39. #include <string.h>
  40. #include <regstr.h>
  41. #include <commctrl.h>
  42. #include <ntpoapi.h>
  43. #include <setupapi.h>
  44. #include <syssetup.h>
  45. #include <setupbat.h>
  46. #include "powrprofp.h"
  47. #include "reghelp.h"
  48. /*******************************************************************************
  49. *
  50. * G L O B A L D A T A
  51. *
  52. *******************************************************************************/
  53. HINSTANCE g_hInstance; // Global instance handle of this DLL.
  54. HANDLE g_hSemRegistry; // Registry semaphore.
  55. UINT g_uiLastID; // The last ID value used, per machine.
  56. // Variables and definitions to manage dynamic link to NtPowerInformation.
  57. typedef NTSTATUS (NTAPI *PFNNTPOWERINFORMATION)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
  58. #ifdef WINNT
  59. // Global administrator power policy variables. Initialize to allow everything.
  60. BOOLEAN g_bAdminOverrideActive = FALSE;
  61. ADMINISTRATOR_POWER_POLICY g_app =
  62. {
  63. // Meaning of power action "sleep" Min, Max.
  64. PowerSystemSleeping1, PowerSystemHibernate,
  65. // Video policies Min, Max.
  66. 0, -1,
  67. // Disk spindown policies Min, Max.
  68. 0, -1
  69. };
  70. #endif
  71. // Debug strings for Power Policy Manager POWER_INFORMATION_LEVEL:
  72. #ifdef DEBUG
  73. LPTSTR lpszInfoLevel[] =
  74. {
  75. TEXT("SystemPowerPolicyAc"),
  76. TEXT("SystemPowerPolicyDc"),
  77. TEXT("VerifySystemPolicyAc"),
  78. TEXT("VerifySystemPolicyDc"),
  79. TEXT("SystemPowerCapabilities"),
  80. TEXT("SystemBatteryState"),
  81. TEXT("SystemPowerStateHandler"),
  82. TEXT("ProcessorStateHandler"),
  83. TEXT("SystemPowerPolicyCurrent"),
  84. TEXT("AdministratorPowerPolicy"),
  85. TEXT("SystemReserveHiberFile"),
  86. TEXT("ProcessorInformation"),
  87. TEXT("SystemPowerInformation"),
  88. TEXT("ProcessorStateHandler2"),
  89. TEXT("LastWakeTime"),
  90. TEXT("LastSleepTime"),
  91. TEXT("SystemExecutionState"),
  92. TEXT("SystemPowerStateNotifyHandler"),
  93. TEXT("ProcessorPowerPolicyAc"),
  94. TEXT("ProcessorPowerPolicyDc"),
  95. TEXT("VerifyProcessorPowerPolicyAc"),
  96. TEXT("VerifyProcessorPowerPolicyDc"),
  97. TEXT("ProcessorPowerPolicyCurrent")
  98. };
  99. int g_iShowValidationChanges;
  100. int g_iShowCapabilities;
  101. int g_iShowSetPPM;
  102. #endif
  103. // Global value for storing a single registry value name/path. Multithread
  104. // protection is provided by the Registry semaphore.
  105. TCHAR g_szRegValue[REGSTR_MAX_VALUE_LENGTH];
  106. // Strings used to access the registry. REGSTR_* string constants can be
  107. // found in sdk\inc\regstr.h, USER strings are under HKEY_CURRENT_USER,
  108. // MACHINE strings are under HKEY_LOCAL_MACHINE.
  109. TCHAR c_szREGSTR_PATH_MACHINE_POWERCFG[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg");
  110. TCHAR c_szREGSTR_PATH_USER_POWERCFG[] = REGSTR_PATH_CONTROLPANEL TEXT("\\PowerCfg");
  111. TCHAR c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg\\PowerPolicies");
  112. TCHAR c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES[] = REGSTR_PATH_CONTROLSFOLDER TEXT("\\PowerCfg\\ProcessorPolicies");
  113. TCHAR c_szREGSTR_PATH_USER_POWERCFG_POLICIES[] = REGSTR_PATH_CONTROLPANEL TEXT("\\PowerCfg\\PowerPolicies");
  114. TCHAR c_szREGSTR_VAL_GLOBALPOWERPOLICY[] = TEXT("GlobalPowerPolicy");
  115. TCHAR c_szREGSTR_VAL_CURRENTPOWERPOLICY[] = TEXT("CurrentPowerPolicy");
  116. // These values are provided to help OEM's meet disk drive warranty requirements.
  117. TCHAR c_szREGSTR_VAL_SPINDOWNMAX[] = TEXT("DiskSpinDownMax");
  118. TCHAR c_szREGSTR_VAL_SPINDOWNMIN[] = TEXT("DiskSpinDownMin");
  119. // These values are provided to support administrator power policies.
  120. TCHAR c_szREGSTR_VAL_ADMINMAXVIDEOTIMEOUT[] = TEXT("AdminMaxVideoTimeout");
  121. TCHAR c_szREGSTR_VAL_ADMINMAXSLEEP[] = TEXT("AdminMaxSleep");
  122. // This value manages the policy ID's.
  123. TCHAR c_szREGSTR_VAL_LASTID[] = TEXT("LastID");
  124. // This value turns on debug logging of PPM Validation Changes
  125. #ifdef DEBUG
  126. TCHAR c_szREGSTR_VAL_SHOWVALCHANGES[] = TEXT("ShowValidationChanges");
  127. TCHAR c_szREGSTR_VAL_SHOWCAPABILITIES[] = TEXT("ShowCapabilities");
  128. TCHAR c_szREGSTR_VAL_SHOWSETPPM[] = TEXT("ShowSetPPM");
  129. #endif
  130. /*******************************************************************************
  131. *
  132. * P U B L I C E N T R Y P O I N T S
  133. *
  134. *******************************************************************************/
  135. /*******************************************************************************
  136. *
  137. * DllInitialize
  138. *
  139. * DESCRIPTION:
  140. *
  141. * PARAMETERS:
  142. *
  143. *******************************************************************************/
  144. BOOLEAN DllInitialize(IN PVOID hmod, IN ULONG ulReason, IN PCONTEXT pctx OPTIONAL)
  145. {
  146. UNREFERENCED_PARAMETER(pctx);
  147. switch (ulReason) {
  148. case DLL_PROCESS_ATTACH:
  149. {
  150. DisableThreadLibraryCalls(hmod);
  151. g_hInstance = hmod;
  152. #ifdef DEBUG
  153. // Get the debug optional settings from HKCU.
  154. ReadOptionalDebugSettings();
  155. #endif
  156. #ifdef WINNT
  157. // Initialize an administrator power policy.
  158. InitAdmin(&g_app);
  159. #endif
  160. // One time registry related initialization.
  161. if (!RegistryInit(&g_uiLastID)) {
  162. return FALSE;
  163. }
  164. break;
  165. }
  166. case DLL_PROCESS_DETACH:
  167. if (g_hSemRegistry) {
  168. CloseHandle(g_hSemRegistry);
  169. g_hSemRegistry = NULL;
  170. }
  171. break;
  172. }
  173. return TRUE;
  174. }
  175. /*******************************************************************************
  176. *
  177. * IsAdminOverrideActive
  178. *
  179. * DESCRIPTION:
  180. *
  181. * PARAMETERS:
  182. *
  183. *******************************************************************************/
  184. BOOLEAN IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY papp)
  185. {
  186. #ifdef WINNT
  187. if ((g_bAdminOverrideActive) && (papp)) {
  188. memcpy(papp, &g_app, sizeof(g_app));
  189. }
  190. return g_bAdminOverrideActive;
  191. #else
  192. return FALSE;
  193. #endif
  194. }
  195. /*******************************************************************************
  196. *
  197. * IsPwrSuspendAllowed
  198. *
  199. * DESCRIPTION:
  200. * Called by Explorer to determine whether suspend is supported.
  201. *
  202. * PARAMETERS:
  203. *
  204. *******************************************************************************/
  205. BOOLEAN IsPwrSuspendAllowed(VOID)
  206. {
  207. SYSTEM_POWER_CAPABILITIES spc;
  208. if (GetPwrCapabilities(&spc)) {
  209. if (spc.SystemS1 || spc.SystemS2 || spc.SystemS3) {
  210. return TRUE;
  211. }
  212. }
  213. return FALSE;
  214. }
  215. /*******************************************************************************
  216. *
  217. * IsPwrHibernateAllowed
  218. *
  219. * DESCRIPTION:
  220. * Called by Explorer to determine whether hibernate is supported.
  221. *
  222. * PARAMETERS:
  223. *
  224. *******************************************************************************/
  225. BOOLEAN IsPwrHibernateAllowed(VOID)
  226. {
  227. SYSTEM_POWER_CAPABILITIES spc;
  228. if (GetPwrCapabilities(&spc)) {
  229. if (spc.SystemS4 && spc.HiberFilePresent) {
  230. return TRUE;
  231. }
  232. }
  233. return FALSE;
  234. }
  235. /*******************************************************************************
  236. *
  237. * IsPwrShutdownAllowed
  238. *
  239. * DESCRIPTION:
  240. * Called by Explorer to determine whether shutdown is supported.
  241. *
  242. * PARAMETERS:
  243. *
  244. *******************************************************************************/
  245. BOOLEAN IsPwrShutdownAllowed(VOID)
  246. {
  247. SYSTEM_POWER_CAPABILITIES spc;
  248. if (GetPwrCapabilities(&spc)) {
  249. if (spc.SystemS5) {
  250. return TRUE;
  251. }
  252. }
  253. return FALSE;
  254. }
  255. /*******************************************************************************
  256. *
  257. * CanUserWritePwrScheme
  258. *
  259. * DESCRIPTION:
  260. *
  261. * PARAMETERS:
  262. *
  263. *******************************************************************************/
  264. BOOLEAN CanUserWritePwrScheme(VOID)
  265. {
  266. DWORD dwSize;
  267. TCHAR szNum[NUM_DEC_DIGITS];
  268. LONG lErr;
  269. // Read in the last ID this value must be present.
  270. dwSize = sizeof(szNum);
  271. // ReadWritePowerValue will set last error
  272. if (ReadWritePowerValue(HKEY_LOCAL_MACHINE,
  273. c_szREGSTR_PATH_MACHINE_POWERCFG,
  274. c_szREGSTR_VAL_LASTID,
  275. szNum, &dwSize, FALSE, TRUE))
  276. {
  277. // Write the value back out, this may fail if user doesn't have write access.
  278. if (ReadWritePowerValue(HKEY_LOCAL_MACHINE,
  279. c_szREGSTR_PATH_MACHINE_POWERCFG,
  280. c_szREGSTR_VAL_LASTID,
  281. szNum, &dwSize, TRUE, TRUE))
  282. {
  283. return TRUE;
  284. }
  285. else
  286. {
  287. lErr = GetLastError();
  288. if (lErr != ERROR_ACCESS_DENIED)
  289. {
  290. MYDBGPRINT(( "CanUserWritePwrScheme, Unable to write last ID, Error: %d", lErr));
  291. }
  292. }
  293. }
  294. else
  295. {
  296. lErr = GetLastError();
  297. MYDBGPRINT(( "CanUserWritePwrScheme, Unable to fetch last ID, Error: %d", lErr));
  298. }
  299. return FALSE;
  300. }
  301. /*******************************************************************************
  302. *
  303. * GetPwrDiskSpindownRange
  304. *
  305. * DESCRIPTION:
  306. *
  307. * PARAMETERS:
  308. *
  309. *******************************************************************************/
  310. BOOLEAN GetPwrDiskSpindownRange(PUINT puiMax, PUINT puiMin)
  311. {
  312. if (!puiMax || !puiMin) {
  313. SetLastError(ERROR_INVALID_PARAMETER);
  314. return FALSE;
  315. }
  316. if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
  317. c_szREGSTR_PATH_MACHINE_POWERCFG,
  318. c_szREGSTR_VAL_SPINDOWNMAX,
  319. puiMax) &&
  320. ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
  321. c_szREGSTR_PATH_MACHINE_POWERCFG,
  322. c_szREGSTR_VAL_SPINDOWNMIN,
  323. puiMin)) {
  324. return TRUE;
  325. }
  326. return FALSE;
  327. }
  328. /*******************************************************************************
  329. *
  330. * EnumPwrSchemes
  331. *
  332. * DESCRIPTION:
  333. * Calls back the PWRSCHEMESENUMPROC with the ID, a pointer to the name,
  334. * the size in bytes of the name, a pointer to the description, the size in
  335. * bytes of the description, a pointer to the power policies and a user
  336. * defined value. Returns ERROR_SUCCESS on success, else error code. Callback
  337. * data is not allocated and is only valid during the scope of the callback.
  338. *
  339. * Note: No calls to any other API's in this library should be made during
  340. * the call back to PWRSCHEMESENUMPROC. The registry semaphore is held at
  341. * this time and a deadlock will result.
  342. *
  343. * PARAMETERS:
  344. *
  345. *******************************************************************************/
  346. BOOLEAN EnumPwrSchemes(
  347. PWRSCHEMESENUMPROC lpfn,
  348. LPARAM lParam
  349. )
  350. {
  351. HKEY hKeyPolicyUser, hKeyPolicyMachine;
  352. HKEY hKeyUser = INVALID_HANDLE_VALUE;
  353. HKEY hKeyMachine = INVALID_HANDLE_VALUE;
  354. DWORD dwDescSize;
  355. DWORD dwSize, dwNameSize, dwIndex = 0;
  356. BOOLEAN bOneCallBackOk = FALSE;
  357. LONG lRet = ERROR_SUCCESS;
  358. LPTSTR lpszDescBuf, lpszDesc;
  359. TCHAR szNameBuf[MAX_NAME_LEN+1];
  360. FILETIME ft;
  361. UINT uiID;
  362. MACHINE_POWER_POLICY mpp;
  363. USER_POWER_POLICY upp;
  364. POWER_POLICY pp;
  365. if (!lpfn) {
  366. SetLastError(ERROR_INVALID_PARAMETER);
  367. goto WESPSP_exit;
  368. }
  369. // Wait on/take the registry semaphore.
  370. if (!TakeRegSemaphore()) {
  371. return FALSE;
  372. }
  373. // Allocate a description buffer.
  374. lpszDescBuf = LocalAlloc(0, (MAX_DESC_LEN + 1) * sizeof(TCHAR));
  375. if (!lpszDescBuf) {
  376. goto WESPSP_exit;
  377. }
  378. if (ERROR_SUCCESS != OpenMachineUserKeys2(
  379. c_szREGSTR_PATH_USER_POWERCFG_POLICIES,
  380. KEY_READ,
  381. c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
  382. KEY_READ,
  383. &hKeyUser,
  384. &hKeyMachine))
  385. {
  386. ReleaseSemaphore(g_hSemRegistry, 1, NULL);
  387. return FALSE;
  388. }
  389. // Enumerate the schemes
  390. while (lRet == ERROR_SUCCESS) {
  391. dwSize = REGSTR_MAX_VALUE_LENGTH - 1;
  392. if ((lRet = RegEnumKeyEx(hKeyUser,
  393. dwIndex,
  394. g_szRegValue,
  395. &dwSize,
  396. NULL,
  397. NULL,
  398. NULL,
  399. &ft)) == ERROR_SUCCESS) {
  400. // Open the Policies Key. The key name is the policies ID.
  401. lpszDesc = NULL;
  402. if (MyStrToInt(g_szRegValue, &uiID)) {
  403. if ((lRet = RegOpenKeyEx(hKeyUser,
  404. g_szRegValue,
  405. 0,
  406. KEY_READ,
  407. &hKeyPolicyUser)) == ERROR_SUCCESS) {
  408. if ((lRet = RegOpenKeyEx(hKeyMachine,
  409. g_szRegValue,
  410. 0,
  411. KEY_READ,
  412. &hKeyPolicyMachine)) == ERROR_SUCCESS) {
  413. // Get the friendly name..
  414. dwNameSize = MAX_NAME_SIZE;
  415. if ((lRet = RegQueryValueEx(hKeyPolicyUser,
  416. TEXT("Name"),
  417. NULL,
  418. NULL,
  419. (PBYTE) szNameBuf,
  420. &dwNameSize)) == ERROR_SUCCESS) {
  421. // Descriptions are optional.
  422. dwDescSize = MAX_DESC_SIZE;
  423. if ((lRet = RegQueryValueEx(hKeyPolicyUser,
  424. TEXT("Description"),
  425. NULL,
  426. NULL,
  427. (PBYTE) lpszDescBuf,
  428. &dwDescSize)) == ERROR_SUCCESS) {
  429. lpszDesc = lpszDescBuf;
  430. }
  431. // Read the user and machine policies.
  432. dwSize = sizeof(upp);
  433. if ((lRet = RegQueryValueEx(hKeyPolicyUser,
  434. TEXT("Policies"),
  435. NULL,
  436. NULL,
  437. (PBYTE) &upp,
  438. &dwSize)) == ERROR_SUCCESS) {
  439. dwSize = sizeof(mpp);
  440. if ((lRet = RegQueryValueEx(hKeyPolicyMachine,
  441. TEXT("Policies"),
  442. NULL,
  443. NULL,
  444. (PBYTE) &mpp,
  445. &dwSize)) == ERROR_SUCCESS) {
  446. // Merge the user and machine policies.
  447. if (MergePolicies(&upp, &mpp, &pp)) {
  448. // Call the enumerate proc.
  449. if (!lpfn(uiID,
  450. dwNameSize, szNameBuf,
  451. dwDescSize, lpszDesc,
  452. &pp, lParam)) {
  453. RegCloseKey(hKeyPolicyMachine);
  454. RegCloseKey(hKeyPolicyUser);
  455. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  456. break;
  457. }
  458. else {
  459. bOneCallBackOk = TRUE;
  460. }
  461. }
  462. }
  463. }
  464. }
  465. RegCloseKey(hKeyPolicyMachine);
  466. }
  467. RegCloseKey(hKeyPolicyUser);
  468. }
  469. }
  470. }
  471. dwIndex++;
  472. }
  473. RegCloseKey(hKeyUser);
  474. RegCloseKey(hKeyMachine);
  475. ReleaseSemaphore(g_hSemRegistry, 1, NULL);
  476. if (lpszDescBuf) {
  477. LocalFree(lpszDescBuf);
  478. }
  479. WESPSP_exit:
  480. if (lRet != ERROR_NO_MORE_ITEMS) {
  481. MYDBGPRINT(( "EnumPwrSchemes, failed, LastError: 0x%08X",
  482. (lRet == ERROR_SUCCESS) ? GetLastError():lRet));
  483. }
  484. return bOneCallBackOk;
  485. }
  486. /*******************************************************************************
  487. *
  488. * ReadGlobalPwrPolicy
  489. *
  490. * DESCRIPTION:
  491. * Function reads the users global power policy profile and returns it.
  492. * If there is no such profile FALSE is returned. A global power policy
  493. * profile is per user, and contains values which apply to all of a users
  494. * power policies.
  495. *
  496. * PARAMETERS:
  497. *
  498. *******************************************************************************/
  499. BOOLEAN ReadGlobalPwrPolicy(
  500. PGLOBAL_POWER_POLICY pgpp
  501. )
  502. {
  503. GLOBAL_MACHINE_POWER_POLICY gmpp;
  504. GLOBAL_USER_POWER_POLICY gupp;
  505. DWORD dwError = ReadPwrPolicyEx2(c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_PATH_MACHINE_POWERCFG, c_szREGSTR_VAL_GLOBALPOWERPOLICY,
  506. NULL, NULL, &gupp, sizeof(gupp), &gmpp, sizeof(gmpp));
  507. if (ERROR_SUCCESS == dwError)
  508. {
  509. return MergeGlobalPolicies(&gupp, &gmpp, pgpp); // Sets Last Error
  510. }
  511. else
  512. {
  513. SetLastError(dwError);
  514. }
  515. return FALSE;
  516. }
  517. /*******************************************************************************
  518. *
  519. * WritePwrScheme
  520. *
  521. * DESCRIPTION:
  522. * Function to write a users power policy profile. If the profile already
  523. * exists it is replaced. Otherwise a new profile is created.
  524. *
  525. * PARAMETERS:
  526. *
  527. * puiID - Index of the power scheme to be written.
  528. *
  529. * lpszSchemeName - String that specifies the name of the power scheme.
  530. *
  531. * lpszDescription - Pointer to a string that specifies the description
  532. * of the power scheme.
  533. *
  534. * lpScheme - Pointer to a POWER_POLICY structure that contains
  535. * the power policy settings to be written.
  536. *
  537. *******************************************************************************/
  538. BOOLEAN WritePwrScheme(
  539. PUINT puiID,
  540. LPTSTR lpszSchemeName,
  541. LPTSTR lpszDescription OPTIONAL,
  542. PPOWER_POLICY lpScheme
  543. )
  544. {
  545. MACHINE_POWER_POLICY mpp;
  546. USER_POWER_POLICY upp;
  547. if( (!puiID && !lpszSchemeName) ||
  548. !lpScheme ) {
  549. SetLastError(ERROR_INVALID_PARAMETER);
  550. return FALSE;
  551. }
  552. if (SplitPolicies(lpScheme, &upp, &mpp))
  553. {
  554. // WritePwrPolicyEx will set the last error on failure.
  555. return WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG_POLICIES,
  556. c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
  557. puiID,
  558. lpszSchemeName,
  559. lpszDescription,
  560. &upp,
  561. sizeof(upp),
  562. &mpp,
  563. sizeof(mpp));
  564. }
  565. return FALSE;
  566. }
  567. /*******************************************************************************
  568. *
  569. * WriteGlobalPwrPolicy
  570. *
  571. * DESCRIPTION:
  572. * Function to write a users global power policy profile. If the profile
  573. * already exists it is replaced. Otherwise a new profile is created.
  574. * A global power policy profile is per user, and contains values which
  575. * apply to all of a users power policies. Otherwise a new profile is created.
  576. *
  577. * PARAMETERS:
  578. *
  579. *******************************************************************************/
  580. BOOLEAN WriteGlobalPwrPolicy (
  581. PGLOBAL_POWER_POLICY pgpp
  582. )
  583. {
  584. GLOBAL_MACHINE_POWER_POLICY gmpp;
  585. GLOBAL_USER_POWER_POLICY gupp;
  586. if (SplitGlobalPolicies(pgpp, &gupp, &gmpp)) // Will set last error
  587. {
  588. // WritePwrPolicyEx will set the last error on failure.
  589. return WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG,
  590. c_szREGSTR_PATH_MACHINE_POWERCFG,
  591. NULL,
  592. c_szREGSTR_VAL_GLOBALPOWERPOLICY,
  593. NULL,
  594. &gupp,
  595. sizeof(gupp),
  596. &gmpp,
  597. sizeof(gmpp));
  598. }
  599. return FALSE;
  600. }
  601. /*******************************************************************************
  602. *
  603. * DeletePwrScheme
  604. *
  605. * DESCRIPTION:
  606. * Function to delete a users power policy profile. An attempt to delete the
  607. * currently active power policy profile will fail with last error set to
  608. * ERROR_ACCESS_DENIED.
  609. *
  610. * PARAMETERS:
  611. *
  612. *******************************************************************************/
  613. BOOLEAN DeletePwrScheme(UINT uiID)
  614. {
  615. HKEY hKeyUser;
  616. DWORD dwSize = REGSTR_MAX_VALUE_LENGTH * sizeof(TCHAR);
  617. BOOLEAN bRet = FALSE;
  618. LONG lRet = ERROR_SUCCESS;
  619. TCHAR szNum[NUM_DEC_DIGITS];
  620. int iCurrent;
  621. HKEY hKeyCurrentUser;
  622. // Wait on/take the registry semaphore.
  623. if (!TakeRegSemaphore())
  624. {
  625. return FALSE;
  626. }
  627. if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser, KEY_WRITE))
  628. {
  629. // Don't allow the currently active power policy profile to be deleted.
  630. // ReadWritePowerValue will set last error
  631. if (ReadWritePowerValue(hKeyCurrentUser,
  632. c_szREGSTR_PATH_USER_POWERCFG,
  633. c_szREGSTR_VAL_CURRENTPOWERPOLICY,
  634. g_szRegValue, &dwSize, FALSE, FALSE) &&
  635. MyStrToInt(g_szRegValue, &iCurrent))
  636. {
  637. if (uiID != (UINT) iCurrent)
  638. {
  639. // For now we only delete the user portion of a policy. We may
  640. // want a ref count on the machine portion which allows deletion
  641. // of the machine portion when no user portion references it.
  642. lRet = RegOpenKeyEx(hKeyCurrentUser,c_szREGSTR_PATH_USER_POWERCFG_POLICIES,0,KEY_WRITE,&hKeyUser);
  643. if (lRet == ERROR_SUCCESS)
  644. {
  645. _itot(uiID, szNum, 10 );
  646. lRet = RegDeleteKey(hKeyUser, szNum);
  647. if (lRet == ERROR_SUCCESS)
  648. {
  649. bRet = TRUE;
  650. }
  651. RegCloseKey(hKeyUser);
  652. }
  653. }
  654. else
  655. {
  656. SetLastError(ERROR_ACCESS_DENIED);
  657. }
  658. }
  659. CloseCurrentUser(hKeyCurrentUser);
  660. }
  661. ReleaseSemaphore(g_hSemRegistry, 1, NULL);
  662. if (!bRet)
  663. {
  664. MYDBGPRINT(( "DeletePwrScheme, failed, LastError: 0x%08X", (lRet == ERROR_SUCCESS) ? GetLastError():lRet));
  665. }
  666. return bRet;
  667. }
  668. /*******************************************************************************
  669. *
  670. * GetActivePwrScheme
  671. *
  672. * DESCRIPTION:
  673. * Retrieves the ID of the currently active power policy profile. This value
  674. * is set by SetActivePwrScheme.
  675. *
  676. * PARAMETERS:
  677. *
  678. *******************************************************************************/
  679. BOOLEAN
  680. GetActivePwrScheme(PUINT puiID)
  681. {
  682. BOOLEAN bRet = FALSE;
  683. TCHAR szNum[NUM_DEC_DIGITS];
  684. DWORD dwSize = SIZE_DEC_DIGITS;
  685. HKEY hKey;
  686. if (ERROR_SUCCESS == OpenCurrentUser2(&hKey, KEY_READ))
  687. {
  688. // ReadWritePowerValue will set last error
  689. if (ReadWritePowerValue(hKey,
  690. c_szREGSTR_PATH_USER_POWERCFG,
  691. c_szREGSTR_VAL_CURRENTPOWERPOLICY,
  692. szNum, &dwSize, FALSE, TRUE) &&
  693. MyStrToInt(szNum, puiID))
  694. {
  695. bRet = TRUE;
  696. }
  697. CloseCurrentUser(hKey);
  698. }
  699. return bRet;
  700. }
  701. /*******************************************************************************
  702. *
  703. * SetActivePwrScheme
  704. *
  705. * DESCRIPTION:
  706. * Set the currently active power policy profile.
  707. *
  708. * PARAMETERS:
  709. * uiID - ID of the new active power scheme.
  710. * lpGlobalPolicy - Optional global policies to merge with active power scheme.
  711. * lpPowerPolicy - Optional power policies to merge with active power scheme.
  712. *
  713. *******************************************************************************/
  714. BOOLEAN
  715. SetActivePwrScheme(
  716. UINT uiID,
  717. PGLOBAL_POWER_POLICY pgpp,
  718. PPOWER_POLICY ppp
  719. )
  720. {
  721. DWORD dwSize;
  722. NTSTATUS ntsRetVal, status;
  723. TCHAR szNum[NUM_DEC_DIGITS];
  724. POWER_POLICY pp;
  725. GLOBAL_POWER_POLICY gpp;
  726. MACHINE_POWER_POLICY mpp;
  727. USER_POWER_POLICY upp;
  728. GLOBAL_MACHINE_POWER_POLICY gmpp;
  729. GLOBAL_USER_POWER_POLICY gupp;
  730. SYSTEM_POWER_POLICY sppAc, sppDc;
  731. MACHINE_PROCESSOR_POWER_POLICY mppp;
  732. HKEY hKeyCurrentUser;
  733. DWORD dwError;
  734. BOOLEAN bRet = FALSE;
  735. // If a new scheme is not passed, fetch the target scheme.
  736. if (!ppp)
  737. {
  738. if (!ReadPwrScheme(uiID, &pp)) // Will SetLastError
  739. {
  740. return FALSE;
  741. }
  742. ppp = &pp;
  743. }
  744. // If a new global policy is not passed, fetch the target global policy.
  745. if (!pgpp)
  746. {
  747. if (!ReadGlobalPwrPolicy(&gpp)) // Sets last error
  748. {
  749. return FALSE;
  750. }
  751. pgpp = &gpp;
  752. }
  753. if (!ReadProcessorPwrScheme(uiID, &mppp)) {
  754. return FALSE;
  755. }
  756. // Merge global policy and user scheme if a global policy was passed.
  757. if (!MergeToSystemPowerPolicies(pgpp, ppp, &sppAc, &sppDc)) // Sets last error
  758. {
  759. return FALSE;
  760. }
  761. // Write out what was requested to the registry.
  762. SplitPolicies(ppp, &upp, &mpp); // Will set last error
  763. if (!WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG_POLICIES, c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
  764. &uiID, NULL, NULL, &upp, sizeof(upp), &mpp, sizeof(mpp)))
  765. {
  766. // WritePwrPolicyEx will set the last error on failure.
  767. return FALSE;
  768. }
  769. SplitGlobalPolicies(pgpp, &gupp, &gmpp); // Will set last error
  770. if (!WritePwrPolicyEx(c_szREGSTR_PATH_USER_POWERCFG,
  771. c_szREGSTR_PATH_MACHINE_POWERCFG,
  772. NULL,
  773. c_szREGSTR_VAL_GLOBALPOWERPOLICY,
  774. NULL,
  775. &gupp,
  776. sizeof(gupp),
  777. &gmpp,
  778. sizeof(gmpp)))
  779. {
  780. // WritePwrPolicyEx will set the last error on failure.
  781. return FALSE;
  782. }
  783. // Call down to the power policy manager to set the scheme.
  784. // I'm working under the assumption that CallNtSetValidateAcDc will call SetLastError() with any
  785. // error values.
  786. status = CallNtSetValidateAcDc(FALSE, FALSE, &(mppp.ProcessorPolicyAc), &(mppp.ProcessorPolicyAc), &(mppp.ProcessorPolicyDc), &(mppp.ProcessorPolicyDc));
  787. ntsRetVal = CallNtSetValidateAcDc(FALSE, TRUE, &sppAc, &sppAc, &sppDc, &sppDc);
  788. //if ((ntsRetVal == STATUS_SUCCESS) && (status = STATUS_SUCCESS))
  789. if ((ntsRetVal == STATUS_SUCCESS))
  790. {
  791. dwError = OpenCurrentUser2(&hKeyCurrentUser, KEY_WRITE);
  792. if (ERROR_SUCCESS == dwError)
  793. {
  794. // On success, set the current active power scheme in the registry.
  795. _itot(uiID, szNum, 10 );
  796. // ReadWritePowerValue will set last error
  797. bRet = ReadWritePowerValue(hKeyCurrentUser,
  798. c_szREGSTR_PATH_USER_POWERCFG,
  799. c_szREGSTR_VAL_CURRENTPOWERPOLICY,
  800. szNum, NULL, TRUE, TRUE);
  801. dwError = GetLastError();
  802. CloseCurrentUser(hKeyCurrentUser);
  803. SetLastError(dwError);
  804. }
  805. else
  806. {
  807. SetLastError(dwError);
  808. }
  809. }
  810. return bRet;
  811. }
  812. /*******************************************************************************
  813. *
  814. * LoadCurrentPwrScheme
  815. *
  816. * DESCRIPTION:
  817. * A Memphis only cover to call SetActivePwrScheme using RunDLL32 calling
  818. * convention. Do not change parameter list.
  819. *
  820. * PARAMETERS:
  821. *
  822. * NOTE: THIS API HAS BEEN DEPRECATED ON WINNT
  823. *******************************************************************************/
  824. void WINAPI LoadCurrentPwrScheme(
  825. HWND hwnd,
  826. HINSTANCE hAppInstance,
  827. LPSTR lpszCmdLine,
  828. int nCmdShow)
  829. {
  830. #ifndef WINNT
  831. UINT uiID;
  832. if (GetActivePwrScheme(&uiID)) {
  833. SetActivePwrScheme(uiID, NULL, NULL);
  834. }
  835. #else
  836. UNREFERENCED_PARAMETER(hwnd);
  837. UNREFERENCED_PARAMETER(hAppInstance);
  838. UNREFERENCED_PARAMETER(lpszCmdLine);
  839. UNREFERENCED_PARAMETER(nCmdShow);
  840. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  841. #endif
  842. }
  843. /*******************************************************************************
  844. *
  845. * MergeLegacyPwrScheme
  846. *
  847. * DESCRIPTION:
  848. * A Memphis only call to merge legacy power management registry info into the
  849. * currently active power scheme.
  850. * Called using the RunDLL32 calling convention. Do not change parameter list.
  851. *
  852. * PARAMETERS:
  853. *
  854. *******************************************************************************/
  855. void WINAPI MergeLegacyPwrScheme(
  856. HWND hwnd,
  857. HINSTANCE hAppInstance,
  858. LPSTR lpszCmdLine,
  859. int nCmdShow)
  860. {
  861. #ifndef WINNT
  862. DWORD dwSize, dwLegacy;
  863. POWER_POLICY pp;
  864. GLOBAL_POWER_POLICY gpp;
  865. UINT uiID;
  866. HKEY hKeyCurrentUser;
  867. // Get the active power scheme from the registry.
  868. if (!GetActivePwrScheme(&uiID))
  869. {
  870. return;
  871. }
  872. if (!ReadPwrScheme(uiID, &pp))
  873. {
  874. return;
  875. }
  876. if (!ReadGlobalPwrPolicy(&gpp))
  877. {
  878. return;
  879. }
  880. if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser))
  881. {
  882. // Get the legacy video monitor power down information.
  883. if (ReadPowerIntOptional(hKeyCurrentUser,
  884. REGSTR_PATH_SCREENSAVE,
  885. REGSTR_VALUE_POWEROFFACTIVE,
  886. &pp.user.VideoTimeoutAc))
  887. {
  888. MYDBGPRINT(( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VALUE_POWEROFFACTIVE, pp.user.VideoTimeoutAc));
  889. pp.user.VideoTimeoutDc = pp.user.VideoTimeoutAc;
  890. }
  891. CloseCurrentUser(hKeyCurrentUser);
  892. }
  893. // Get the legacy disk spin down information.
  894. if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
  895. REGSTR_PATH_FILESYSTEM,
  896. REGSTR_VAL_ACDRIVESPINDOWN,
  897. &pp.user.SpindownTimeoutAc)) {
  898. MYDBGPRINT(( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VAL_ACDRIVESPINDOWN, pp.user.SpindownTimeoutAc));
  899. }
  900. if (ReadPowerIntOptional(HKEY_LOCAL_MACHINE,
  901. REGSTR_PATH_FILESYSTEM,
  902. REGSTR_VAL_BATDRIVESPINDOWN,
  903. &pp.user.SpindownTimeoutDc)) {
  904. MYDBGPRINT(( "MergeLegacyPwrScheme, found legacy %s: %d", REGSTR_VAL_BATDRIVESPINDOWN, pp.user.SpindownTimeoutDc));
  905. }
  906. // Get the legacy battery meter information.
  907. dwSize = sizeof(dwLegacy);
  908. if (ReadPowerValueOptional(HKEY_LOCAL_MACHINE,
  909. REGSTR_PATH_VPOWERD,
  910. REGSTR_VAL_VPOWERDFLAGS,
  911. (LPTSTR)&dwLegacy, &dwSize)) {
  912. if (dwLegacy & VPDF_SHOWMULTIBATT) {
  913. gpp.user.GlobalFlags |= EnableSysTrayBatteryMeter;
  914. }
  915. else {
  916. gpp.user.GlobalFlags &= ~EnableSysTrayBatteryMeter;
  917. }
  918. MYDBGPRINT(( "MergeLegacyPwrScheme, found legacy %s: %X", REGSTR_VAL_VPOWERDFLAGS, dwLegacy));
  919. }
  920. // Write out the modified active power scheme.
  921. if (!WriteGlobalPwrPolicy(&gpp)) {
  922. return;
  923. }
  924. WritePwrScheme(&uiID, NULL, NULL, &pp);
  925. #else
  926. UNREFERENCED_PARAMETER(hwnd);
  927. UNREFERENCED_PARAMETER(hAppInstance);
  928. UNREFERENCED_PARAMETER(lpszCmdLine);
  929. UNREFERENCED_PARAMETER(nCmdShow);
  930. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  931. #endif
  932. }
  933. /*******************************************************************************
  934. *
  935. * GetPwrCapabilities
  936. *
  937. * DESCRIPTION:
  938. * Get the system power capabilities from the Power Policy Manager.
  939. *
  940. * PARAMETERS:
  941. *
  942. *******************************************************************************/
  943. BOOLEAN GetPwrCapabilities(PSYSTEM_POWER_CAPABILITIES lpspc)
  944. {
  945. NTSTATUS ntsRetVal = STATUS_SUCCESS;
  946. if (!lpspc) {
  947. SetLastError(ERROR_INVALID_PARAMETER);
  948. return FALSE;
  949. }
  950. ntsRetVal = CallNtPowerInformation(SystemPowerCapabilities, NULL, 0, lpspc,
  951. sizeof(SYSTEM_POWER_CAPABILITIES));
  952. if (ntsRetVal == STATUS_SUCCESS) {
  953. #ifdef DEBUG
  954. if (g_iShowCapabilities) {
  955. DumpSystemPowerCapabilities("GetPwrCapabilities, returned:", lpspc);
  956. }
  957. #ifdef SIM_BATTERY
  958. lpspc->SystemBatteriesPresent = TRUE;
  959. #endif
  960. #endif
  961. return TRUE;
  962. }
  963. else {
  964. return FALSE;
  965. }
  966. }
  967. /*******************************************************************************
  968. *
  969. * CallNtPowerInformation
  970. *
  971. * DESCRIPTION:
  972. *
  973. * PARAMETERS:
  974. *
  975. *******************************************************************************/
  976. NTSTATUS CallNtPowerInformation(
  977. POWER_INFORMATION_LEVEL InformationLevel,
  978. PVOID InputBuffer OPTIONAL,
  979. ULONG InputBufferLength,
  980. PVOID OutputBuffer OPTIONAL,
  981. ULONG OutputBufferLength
  982. )
  983. {
  984. NTSTATUS ntsRetVal;
  985. DWORD dwOldState, dwStatus;
  986. DWORD dwErrorSave;
  987. LPCTSTR PrivilegeName;
  988. if (InformationLevel == SystemReserveHiberFile) {
  989. PrivilegeName = SE_CREATE_PAGEFILE_NAME;
  990. } else {
  991. PrivilegeName = SE_SHUTDOWN_NAME;
  992. }
  993. SetLastError(0);
  994. dwStatus = SetPrivilegeAttribute(PrivilegeName, SE_PRIVILEGE_ENABLED,
  995. &dwOldState);
  996. dwErrorSave = GetLastError();
  997. ntsRetVal = NtPowerInformation(InformationLevel,
  998. InputBuffer, InputBufferLength,
  999. OutputBuffer, OutputBufferLength);
  1000. //
  1001. // If we were able to set the privilege, then reset it.
  1002. //
  1003. if (NT_SUCCESS(dwStatus) && dwErrorSave == 0) {
  1004. SetPrivilegeAttribute(PrivilegeName, dwOldState, NULL);
  1005. }
  1006. else {
  1007. MYDBGPRINT(( "CallNtPowerInformation, SetPrivilegeAttribute failed: 0x%08X", GetLastError()));
  1008. }
  1009. #ifdef DEBUG
  1010. if ((ntsRetVal != STATUS_SUCCESS) && (InformationLevel <= ProcessorPowerPolicyCurrent)) {
  1011. MYDBGPRINT(( "NtPowerInformation, %s, failed: 0x%08X", lpszInfoLevel[InformationLevel], ntsRetVal));
  1012. }
  1013. else {
  1014. if (g_iShowSetPPM && InputBuffer) {
  1015. if ((InformationLevel == SystemPowerPolicyAc) ||
  1016. (InformationLevel == SystemPowerPolicyDc)) {
  1017. DumpSystemPowerPolicy("NtPowerInformation, Set to PPM, InputBuffer", InputBuffer);
  1018. }
  1019. }
  1020. }
  1021. #endif
  1022. return ntsRetVal;
  1023. }
  1024. /*******************************************************************************
  1025. *
  1026. * SetSuspendState
  1027. *
  1028. * DESCRIPTION:
  1029. *
  1030. * PARAMETERS:
  1031. *
  1032. *******************************************************************************/
  1033. BOOLEAN SetSuspendState(
  1034. BOOLEAN bHibernate,
  1035. BOOLEAN bForce,
  1036. BOOLEAN bWakeupEventsDisabled)
  1037. {
  1038. NTSTATUS ntsRetVal;
  1039. POWER_ACTION pa;
  1040. ULONG Flags;
  1041. DWORD dwOldState, dwStatus;
  1042. DWORD dwErrorSave;
  1043. SetLastError(0);
  1044. dwStatus = SetPrivilegeAttribute(SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED,
  1045. &dwOldState);
  1046. dwErrorSave = GetLastError();
  1047. if (bHibernate) {
  1048. pa = PowerActionHibernate;
  1049. }
  1050. else {
  1051. pa = PowerActionSleep;
  1052. }
  1053. Flags = POWER_ACTION_QUERY_ALLOWED | POWER_ACTION_UI_ALLOWED;
  1054. if (bForce) {
  1055. Flags |= POWER_ACTION_CRITICAL;
  1056. }
  1057. if (bWakeupEventsDisabled) {
  1058. Flags |= POWER_ACTION_DISABLE_WAKES;
  1059. }
  1060. ntsRetVal = NtInitiatePowerAction(pa, PowerSystemSleeping1, Flags, FALSE);
  1061. //
  1062. // If we were able to set the privilege, then reset it.
  1063. //
  1064. if (NT_SUCCESS(dwStatus) && dwErrorSave == 0) {
  1065. SetPrivilegeAttribute(SE_SHUTDOWN_NAME, dwOldState, NULL);
  1066. }
  1067. else {
  1068. MYDBGPRINT(( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError()));
  1069. }
  1070. if (ntsRetVal == STATUS_SUCCESS) {
  1071. return TRUE;
  1072. }
  1073. else {
  1074. MYDBGPRINT(( "NtInitiatePowerAction, failed: 0x%08X", ntsRetVal));
  1075. return FALSE;
  1076. }
  1077. }
  1078. /*******************************************************************************
  1079. *
  1080. * P R I V A T E F U N C T I O N S
  1081. *
  1082. *******************************************************************************/
  1083. /*******************************************************************************
  1084. *
  1085. * ValidatePowerPolicies
  1086. *
  1087. * DESCRIPTION:
  1088. * Call down to the power policy manager to validate power policies.
  1089. *
  1090. * PARAMETERS:
  1091. *
  1092. *******************************************************************************/
  1093. BOOLEAN ValidatePowerPolicies(
  1094. PGLOBAL_POWER_POLICY pgpp,
  1095. PPOWER_POLICY ppp
  1096. )
  1097. {
  1098. POWER_POLICY ppValid;
  1099. GLOBAL_POWER_POLICY gppValid;
  1100. SYSTEM_POWER_POLICY sppAc, sppDc;
  1101. // Get current power policy data from the PPM.
  1102. if (!GetCurrentPowerPolicies(&gppValid, &ppValid)) {
  1103. return FALSE;
  1104. }
  1105. if (!pgpp) {
  1106. pgpp = &gppValid;
  1107. }
  1108. if (!ppp) {
  1109. ppp = &ppValid;
  1110. }
  1111. // Merge policy and global policy data.
  1112. if (!MergeToSystemPowerPolicies(pgpp, ppp, &sppAc, &sppDc)) {
  1113. return FALSE;
  1114. }
  1115. if (!ValidateSystemPolicies(&sppAc, &sppDc)) {
  1116. return FALSE;
  1117. }
  1118. return SplitFromSystemPowerPolicies(&sppAc, &sppDc, pgpp, ppp);
  1119. }
  1120. /*******************************************************************************
  1121. *
  1122. * ValidateSystemPolicies
  1123. *
  1124. * DESCRIPTION:
  1125. *
  1126. * PARAMETERS:
  1127. *
  1128. *******************************************************************************/
  1129. BOOLEAN ValidateSystemPolicies(
  1130. PSYSTEM_POWER_POLICY psppAc,
  1131. PSYSTEM_POWER_POLICY psppDc
  1132. )
  1133. {
  1134. DWORD dwLastErr;
  1135. NTSTATUS ntsRetVal;
  1136. // Call down to the power policy manager to validate the scheme.
  1137. ntsRetVal = CallNtSetValidateAcDc(TRUE, TRUE, psppAc, psppAc, psppDc, psppDc);
  1138. // Map any PPM errors to winerror.h values
  1139. switch (ntsRetVal) {
  1140. case STATUS_SUCCESS:
  1141. return TRUE;
  1142. case STATUS_PRIVILEGE_NOT_HELD:
  1143. dwLastErr = ERROR_ACCESS_DENIED;
  1144. break;
  1145. case STATUS_INVALID_PARAMETER:
  1146. dwLastErr = ERROR_INVALID_DATA;
  1147. break;
  1148. default:
  1149. dwLastErr = ERROR_GEN_FAILURE;
  1150. break;
  1151. }
  1152. SetLastError(dwLastErr);
  1153. return FALSE;
  1154. }
  1155. /*******************************************************************************
  1156. *
  1157. * GetCurrentPowerPolicies
  1158. *
  1159. * DESCRIPTION:
  1160. *
  1161. * PARAMETERS:
  1162. *
  1163. *******************************************************************************/
  1164. BOOLEAN GetCurrentPowerPolicies(PGLOBAL_POWER_POLICY pgpp, PPOWER_POLICY ppp)
  1165. {
  1166. SYSTEM_POWER_POLICY sppAc, sppDc;
  1167. if (!GetCurrentSystemPowerPolicies(&sppAc, &sppDc)) {
  1168. return FALSE;
  1169. }
  1170. return SplitFromSystemPowerPolicies(&sppAc, &sppDc, pgpp, ppp);
  1171. }
  1172. /*******************************************************************************
  1173. *
  1174. * GetCurrentSystemPowerPolicies
  1175. *
  1176. * DESCRIPTION:
  1177. * Call down to the power policy manager to get the current system power
  1178. * policies.
  1179. *
  1180. * PARAMETERS:
  1181. *
  1182. *******************************************************************************/
  1183. BOOLEAN GetCurrentSystemPowerPolicies(
  1184. PSYSTEM_POWER_POLICY psppAc,
  1185. PSYSTEM_POWER_POLICY psppDc
  1186. )
  1187. {
  1188. NTSTATUS ntsRetVal;
  1189. // Call down to the power policy manager to get system power policies.
  1190. ntsRetVal = CallNtSetValidateAcDc(FALSE, TRUE, NULL, psppAc, NULL, psppDc);
  1191. if (ntsRetVal == STATUS_SUCCESS) {
  1192. return TRUE;
  1193. }
  1194. else {
  1195. return FALSE;
  1196. }
  1197. }
  1198. #ifdef WINNT
  1199. /*******************************************************************************
  1200. *
  1201. * SetPrivilegeAttribute
  1202. *
  1203. * DESCRIPTION:
  1204. * This routine sets the security attributes for a given privilege.
  1205. *
  1206. * PARAMETERS:
  1207. * PrivilegeName - Name of the privilege we are manipulating.
  1208. * NewPrivilegeAttribute - The new attribute value to use.
  1209. * OldPrivilegeAttribute - Pointer to receive the old privilege value.
  1210. * OPTIONAL.
  1211. *
  1212. *******************************************************************************/
  1213. DWORD SetPrivilegeAttribute(
  1214. LPCTSTR PrivilegeName,
  1215. DWORD NewPrivilegeAttribute,
  1216. DWORD *OldPrivilegeAttribute
  1217. )
  1218. {
  1219. LUID PrivilegeValue;
  1220. TOKEN_PRIVILEGES TokenPrivileges, OldTokenPrivileges;
  1221. DWORD ReturnLength;
  1222. HANDLE TokenHandle;
  1223. // First, find out the LUID Value of the privilege
  1224. if(!LookupPrivilegeValue(NULL, PrivilegeName, &PrivilegeValue)) {
  1225. return GetLastError();
  1226. }
  1227. // Get the token handle
  1228. if (!OpenThreadToken (GetCurrentThread(),
  1229. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1230. FALSE, &TokenHandle)) {
  1231. if (!OpenProcessToken (GetCurrentProcess(),
  1232. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1233. &TokenHandle)) {
  1234. return GetLastError();
  1235. }
  1236. }
  1237. // Set up the privilege set we will need
  1238. TokenPrivileges.PrivilegeCount = 1;
  1239. TokenPrivileges.Privileges[0].Luid = PrivilegeValue;
  1240. TokenPrivileges.Privileges[0].Attributes = NewPrivilegeAttribute;
  1241. ReturnLength = sizeof(TOKEN_PRIVILEGES);
  1242. if (!AdjustTokenPrivileges(TokenHandle, FALSE,
  1243. &TokenPrivileges, sizeof(TOKEN_PRIVILEGES),
  1244. &OldTokenPrivileges, &ReturnLength)) {
  1245. CloseHandle(TokenHandle);
  1246. return GetLastError();
  1247. }
  1248. else {
  1249. if (OldPrivilegeAttribute != NULL) {
  1250. //
  1251. // If the privilege changed, store the old value. If it did
  1252. // not change, store the value passed in.
  1253. //
  1254. if( OldTokenPrivileges.PrivilegeCount != 0 ) {
  1255. *OldPrivilegeAttribute = OldTokenPrivileges.Privileges[0].Attributes;
  1256. } else {
  1257. *OldPrivilegeAttribute = NewPrivilegeAttribute;
  1258. }
  1259. }
  1260. CloseHandle(TokenHandle);
  1261. return NO_ERROR;
  1262. }
  1263. }
  1264. #endif
  1265. /*******************************************************************************
  1266. *
  1267. * CallNtSetValidateAcDc
  1268. *
  1269. * DESCRIPTION:
  1270. *
  1271. * PARAMETERS:
  1272. *
  1273. *******************************************************************************/
  1274. NTSTATUS CallNtSetValidateAcDc(
  1275. BOOLEAN bValidate,
  1276. BOOLEAN bSystem,
  1277. PVOID InputBufferAc OPTIONAL,
  1278. PVOID OutputBufferAc OPTIONAL,
  1279. PVOID InputBufferDc OPTIONAL,
  1280. PVOID OutputBufferDc OPTIONAL
  1281. )
  1282. {
  1283. NTSTATUS ntsRetVal;
  1284. POWER_INFORMATION_LEVEL pil, pilAc, pilDc;
  1285. ULONG policyLength;
  1286. #ifdef DEBUG
  1287. SYSTEM_POWER_POLICY sppOrgAc, sppOrgDc;
  1288. #endif
  1289. #ifdef WINNT
  1290. DWORD dwOldState, dwStatus;
  1291. DWORD dwErrorSave;
  1292. SetLastError(0);
  1293. dwStatus = SetPrivilegeAttribute(SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED, &dwOldState);
  1294. dwErrorSave = GetLastError();
  1295. #endif
  1296. if (bSystem) {
  1297. if (bValidate) {
  1298. pil = pilAc = VerifySystemPolicyAc;
  1299. pilDc = VerifySystemPolicyDc;
  1300. } else {
  1301. pil = pilAc = SystemPowerPolicyAc;
  1302. pilDc = SystemPowerPolicyDc;
  1303. }
  1304. policyLength = sizeof(SYSTEM_POWER_POLICY);
  1305. } else {
  1306. if (bValidate) {
  1307. pil = pilAc = VerifyProcessorPowerPolicyAc;
  1308. pilDc = VerifyProcessorPowerPolicyDc;
  1309. } else {
  1310. pil = pilAc = ProcessorPowerPolicyAc;
  1311. pilDc = ProcessorPowerPolicyDc;
  1312. }
  1313. policyLength = sizeof(PROCESSOR_POWER_POLICY);
  1314. }
  1315. #ifdef DEBUG
  1316. if (InputBufferAc)
  1317. {
  1318. memcpy(&sppOrgAc, InputBufferAc, policyLength);
  1319. }
  1320. if (InputBufferDc)
  1321. {
  1322. memcpy(&sppOrgDc, InputBufferDc, policyLength);
  1323. }
  1324. #endif
  1325. ntsRetVal = NtPowerInformation(pilAc,
  1326. InputBufferAc,
  1327. policyLength,
  1328. OutputBufferAc,
  1329. policyLength);
  1330. if (ntsRetVal == STATUS_SUCCESS)
  1331. {
  1332. pil = pilDc;
  1333. ntsRetVal = NtPowerInformation(pilDc,
  1334. InputBufferDc,
  1335. policyLength,
  1336. OutputBufferDc,
  1337. policyLength);
  1338. }
  1339. #ifdef WINNT
  1340. // If we were able to set the privilege, then reset it.
  1341. if (NT_SUCCESS(dwStatus) && (dwErrorSave == ERROR_SUCCESS))
  1342. {
  1343. SetPrivilegeAttribute(SE_SHUTDOWN_NAME, dwOldState, NULL);
  1344. #ifdef DEBUG
  1345. if (InputBufferAc && OutputBufferAc)
  1346. {
  1347. DifSystemPowerPolicies("PPM modified AC policies", &sppOrgAc, OutputBufferAc);
  1348. }
  1349. if (InputBufferDc && OutputBufferDc)
  1350. {
  1351. DifSystemPowerPolicies("PPM modified DC policies", &sppOrgDc, OutputBufferDc);
  1352. }
  1353. #endif
  1354. }
  1355. else
  1356. {
  1357. MYDBGPRINT(( "SetSuspendState, SetPrivilegeAttribute failed: 0x%08X", GetLastError()));
  1358. }
  1359. #endif
  1360. #ifdef DEBUG
  1361. if (ntsRetVal != STATUS_SUCCESS)
  1362. {
  1363. MYDBGPRINT(( "NtPowerInformation, %s, failed: 0x%08X", lpszInfoLevel[pil], ntsRetVal));
  1364. switch (pil)
  1365. {
  1366. case SystemPowerPolicyAc:
  1367. case VerifySystemPolicyAc:
  1368. DumpSystemPowerPolicy("InputBufferAc", InputBufferAc);
  1369. break;
  1370. case SystemPowerPolicyDc:
  1371. case VerifySystemPolicyDc:
  1372. DumpSystemPowerPolicy("InputBufferDc", InputBufferDc);
  1373. break;
  1374. }
  1375. }
  1376. else
  1377. {
  1378. if (g_iShowSetPPM && InputBufferAc && InputBufferDc && !bValidate)
  1379. {
  1380. DumpSystemPowerPolicy("CallNtSetValidateAcDc, Set AC to PPM", InputBufferAc);
  1381. DumpSystemPowerPolicy("CallNtSetValidateAcDc, Set DC to PPM", InputBufferDc);
  1382. }
  1383. }
  1384. #endif
  1385. return ntsRetVal;
  1386. }
  1387. /*******************************************************************************
  1388. *
  1389. * ReadPwrScheme
  1390. *
  1391. * DESCRIPTION:
  1392. * Function reads the specified user power policy profile and returns
  1393. * it. If there is no such profile FALSE is returned.
  1394. *
  1395. * PARAMETERS:
  1396. *
  1397. *******************************************************************************/
  1398. BOOLEAN ReadPwrScheme(
  1399. UINT uiID,
  1400. PPOWER_POLICY ppp
  1401. )
  1402. {
  1403. MACHINE_POWER_POLICY mpp;
  1404. USER_POWER_POLICY upp;
  1405. TCHAR szNum[NUM_DEC_DIGITS];
  1406. DWORD dwError;
  1407. _itot(uiID, szNum, 10 );
  1408. dwError = ReadPwrPolicyEx2(c_szREGSTR_PATH_USER_POWERCFG_POLICIES, c_szREGSTR_PATH_MACHINE_POWERCFG_POLICIES,
  1409. szNum, NULL, 0, &upp, sizeof(upp), &mpp, sizeof(mpp));
  1410. if (ERROR_SUCCESS == dwError)
  1411. {
  1412. return MergePolicies(&upp, &mpp, ppp);
  1413. }
  1414. else
  1415. {
  1416. SetLastError(dwError);
  1417. }
  1418. return FALSE;
  1419. }
  1420. /*******************************************************************************
  1421. *
  1422. * ReadProcessorPwrScheme
  1423. *
  1424. * DESCRIPTION:
  1425. * Function reads the specified processor power policy profile and returns
  1426. * it. If there is no such profile FALSE is returned.
  1427. *
  1428. * PARAMETERS:
  1429. *
  1430. *******************************************************************************/
  1431. BOOLEAN
  1432. ReadProcessorPwrScheme(
  1433. UINT uiID,
  1434. PMACHINE_PROCESSOR_POWER_POLICY pmppp
  1435. )
  1436. {
  1437. TCHAR szNum[NUM_DEC_DIGITS];
  1438. DWORD dwError;
  1439. _itot(uiID, szNum, 10 );
  1440. dwError = ReadProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
  1441. szNum,
  1442. pmppp,
  1443. sizeof(MACHINE_PROCESSOR_POWER_POLICY));
  1444. //
  1445. // It's legal for there to be no Processor Power Scheme that corresponds with
  1446. // uiID, as long as uiID is non-zero. If this is the case, just use a
  1447. // default scheme. (We use '1' as a default because this will be the
  1448. // default laptop scheme. Non-laptops probably won't have power controls
  1449. // on the processor, so it won't matter if we get a scheme that is too aggressive.)
  1450. //
  1451. if ((ERROR_SUCCESS != dwError) &&
  1452. (uiID != 0)) {
  1453. szNum[0] = TEXT('1');
  1454. szNum[1] = TEXT('\0');
  1455. dwError = ReadProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
  1456. szNum,
  1457. pmppp,
  1458. sizeof(MACHINE_PROCESSOR_POWER_POLICY));
  1459. }
  1460. if (ERROR_SUCCESS == dwError) {
  1461. return TRUE;
  1462. } else {
  1463. SetLastError(dwError);
  1464. return FALSE;
  1465. }
  1466. }
  1467. /*******************************************************************************
  1468. *
  1469. * WriteProcessorPwrScheme
  1470. *
  1471. * DESCRIPTION:
  1472. * Function writes the specified processor power policy profile
  1473. *
  1474. * PARAMETERS:
  1475. *
  1476. *******************************************************************************/
  1477. BOOLEAN
  1478. WriteProcessorPwrScheme(
  1479. UINT uiID,
  1480. PMACHINE_PROCESSOR_POWER_POLICY pmppp
  1481. )
  1482. {
  1483. TCHAR szNum[NUM_DEC_DIGITS];
  1484. DWORD dwError;
  1485. _itot(uiID, szNum, 10 );
  1486. dwError = WriteProcessorPwrPolicy(c_szREGSTR_PATH_MACHINE_PROCESSOR_POLICIES,
  1487. szNum,
  1488. pmppp,
  1489. sizeof(MACHINE_PROCESSOR_POWER_POLICY));
  1490. if (ERROR_SUCCESS == dwError) {
  1491. return TRUE;
  1492. } else {
  1493. SetLastError(dwError);
  1494. return FALSE;
  1495. }
  1496. }
  1497. /*******************************************************************************
  1498. *
  1499. * MyStrToInt
  1500. *
  1501. * DESCRIPTION:
  1502. *
  1503. * PARAMETERS:
  1504. *
  1505. *******************************************************************************/
  1506. BOOLEAN MyStrToInt(LPCTSTR lpSrc, PINT pi)
  1507. {
  1508. #define ISDIGIT(c) ((c) >= TEXT('0') && (c) <= TEXT('9'))
  1509. int n = 0;
  1510. BOOL bNeg = FALSE;
  1511. if (*lpSrc == TEXT('-')) {
  1512. bNeg = TRUE;
  1513. lpSrc++;
  1514. }
  1515. if (!ISDIGIT(*lpSrc)) {
  1516. MYDBGPRINT(( "MyStrToInt, non-integer string: %s", lpSrc));
  1517. return FALSE;
  1518. }
  1519. while (ISDIGIT(*lpSrc)) {
  1520. n *= 10;
  1521. n += *lpSrc - TEXT('0');
  1522. lpSrc++;
  1523. }
  1524. if (bNeg) {
  1525. *pi = -n;
  1526. }
  1527. else {
  1528. *pi = n;
  1529. }
  1530. return TRUE;
  1531. }
  1532. /*******************************************************************************
  1533. *
  1534. * RegistryInit
  1535. *
  1536. * DESCRIPTION:
  1537. * Do DLL load time registry related initialization.
  1538. *
  1539. * PARAMETERS:
  1540. *
  1541. *******************************************************************************/
  1542. BOOLEAN RegistryInit(PUINT puiLastId)
  1543. {
  1544. DWORD dwSize;
  1545. TCHAR szNum[NUM_DEC_DIGITS];
  1546. UINT uiCurPwrScheme;
  1547. // Read in the last ID this value must be present.
  1548. dwSize = sizeof(szNum);
  1549. // ReadWritePowerValue will set last error
  1550. if (!ReadWritePowerValue(HKEY_LOCAL_MACHINE,
  1551. c_szREGSTR_PATH_MACHINE_POWERCFG,
  1552. c_szREGSTR_VAL_LASTID,
  1553. szNum, &dwSize, FALSE, FALSE) ||
  1554. !MyStrToInt(szNum, &g_uiLastID)) {
  1555. MYDBGPRINT(( "RegistryInit, Unable to fetch last ID, registry is corrupt"));
  1556. return FALSE;
  1557. }
  1558. return TRUE;
  1559. }
  1560. #ifdef DEBUG
  1561. /*******************************************************************************
  1562. *
  1563. * ReadOptionalDebugSettings
  1564. *
  1565. * DESCRIPTION:
  1566. * Debug only. Get the debug settings from HKCU registry entries into globals.
  1567. *
  1568. * PARAMETERS:
  1569. *
  1570. *******************************************************************************/
  1571. VOID ReadOptionalDebugSettings(VOID)
  1572. {
  1573. HKEY hKeyCurrentUser;
  1574. if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser,KEY_READ))
  1575. {
  1576. // Optional debug logging of PPM policy validation changes.
  1577. ReadPowerIntOptional(hKeyCurrentUser,
  1578. c_szREGSTR_PATH_USER_POWERCFG,
  1579. c_szREGSTR_VAL_SHOWVALCHANGES,
  1580. &g_iShowValidationChanges);
  1581. // Optional debug logging of PPM capabilities.
  1582. ReadPowerIntOptional(hKeyCurrentUser,
  1583. c_szREGSTR_PATH_USER_POWERCFG,
  1584. c_szREGSTR_VAL_SHOWCAPABILITIES,
  1585. &g_iShowCapabilities);
  1586. // Optional debug logging of setting new policy to PPM.
  1587. ReadPowerIntOptional(hKeyCurrentUser,
  1588. c_szREGSTR_PATH_USER_POWERCFG,
  1589. c_szREGSTR_VAL_SHOWSETPPM,
  1590. &g_iShowSetPPM);
  1591. CloseCurrentUser(hKeyCurrentUser);
  1592. }
  1593. }
  1594. #endif
  1595. #ifdef WINNT
  1596. /*******************************************************************************
  1597. *
  1598. * InitAdmin
  1599. *
  1600. * DESCRIPTION:
  1601. * For NT only, initialize an administrator power policy which
  1602. * supports an optional administrative override of certain
  1603. * power policy settings. The PowerCfg.Cpl and PPM will use these
  1604. * override values during validation.
  1605. *
  1606. * PARAMETERS:
  1607. *
  1608. *******************************************************************************/
  1609. VOID InitAdmin(PADMINISTRATOR_POWER_POLICY papp)
  1610. {
  1611. INT i;
  1612. NTSTATUS ntsRetVal;
  1613. HKEY hKeyCurrentUser;
  1614. if (ERROR_SUCCESS == OpenCurrentUser2(&hKeyCurrentUser, KEY_READ))
  1615. {
  1616. if (ReadPowerIntOptional(hKeyCurrentUser, c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_VAL_ADMINMAXSLEEP, &i))
  1617. {
  1618. g_app.MaxSleep = (SYSTEM_POWER_STATE) i;
  1619. g_bAdminOverrideActive = TRUE;
  1620. }
  1621. if (ReadPowerIntOptional(hKeyCurrentUser, c_szREGSTR_PATH_USER_POWERCFG, c_szREGSTR_VAL_ADMINMAXVIDEOTIMEOUT, &i))
  1622. {
  1623. g_app.MaxVideoTimeout = i;
  1624. g_bAdminOverrideActive = TRUE;
  1625. }
  1626. CloseCurrentUser(hKeyCurrentUser);
  1627. }
  1628. // If an administration override was set, call down to the power
  1629. // policy manager to set the administrator policy.
  1630. if (g_bAdminOverrideActive)
  1631. {
  1632. ntsRetVal = CallNtPowerInformation(AdministratorPowerPolicy, &g_app, sizeof(ADMINISTRATOR_POWER_POLICY),
  1633. &g_app, sizeof(ADMINISTRATOR_POWER_POLICY));
  1634. if (ntsRetVal != STATUS_SUCCESS)
  1635. {
  1636. MYDBGPRINT(( "DllInitialize, Set AdministratorPowerPolicy failed: 0x%08X", ntsRetVal));
  1637. }
  1638. }
  1639. }
  1640. #endif