Source code of Windows XP (NT5)
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.

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