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.

2606 lines
68 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. pinfo.c
  5. Abstract:
  6. This module implements the generic power policy information interfaces
  7. Author:
  8. Ken Reneris (kenr) 17-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. //
  13. // Internal prototypes
  14. //
  15. VOID
  16. PopVerifyPowerPolicy (
  17. IN BOOLEAN Ac,
  18. IN PSYSTEM_POWER_POLICY InputPolicy,
  19. OUT PSYSTEM_POWER_POLICY PowerPolicy
  20. );
  21. VOID
  22. PopVerifyProcessorPowerPolicy (
  23. IN BOOLEAN Ac,
  24. IN PPROCESSOR_POWER_POLICY InputPolicy,
  25. OUT PPROCESSOR_POWER_POLICY PowerPolicy
  26. );
  27. VOID
  28. PopVerifyThrottle (
  29. IN PUCHAR Throttle,
  30. IN UCHAR Min
  31. );
  32. VOID
  33. PopApplyPolicy (
  34. IN BOOLEAN UpdateRegistry,
  35. IN BOOLEAN AcPolicy,
  36. IN PSYSTEM_POWER_POLICY NewPolicy,
  37. IN ULONG PolicyLength
  38. );
  39. VOID
  40. PopApplyProcessorPolicy (
  41. IN BOOLEAN UpdateRegistry,
  42. IN BOOLEAN AcPolicy,
  43. IN PPROCESSOR_POWER_POLICY NewPolicy,
  44. IN ULONG PolicyLength
  45. );
  46. VOID
  47. PopFilterCapabilities(
  48. IN PSYSTEM_POWER_CAPABILITIES SourceCapabilities,
  49. OUT PSYSTEM_POWER_CAPABILITIES FilteredCapabilities
  50. );
  51. BOOLEAN
  52. PopUserIsAdmin(
  53. VOID
  54. );
  55. #ifdef ALLOC_PRAGMA
  56. #pragma alloc_text(PAGE, NtPowerInformation)
  57. #pragma alloc_text(PAGE, PopApplyAdminPolicy)
  58. #pragma alloc_text(PAGE, PopApplyPolicy)
  59. #pragma alloc_text(PAGE, PopVerifyPowerPolicy)
  60. #pragma alloc_text(PAGE, PopVerifyPowerActionPolicy)
  61. #pragma alloc_text(PAGE, PopVerifySystemPowerState)
  62. #pragma alloc_text(PAGE, PopAdvanceSystemPowerState)
  63. #pragma alloc_text(PAGE, PopResetCurrentPolicies)
  64. #pragma alloc_text(PAGE, PopNotifyPolicyDevice)
  65. #pragma alloc_text(PAGE, PopConnectToPolicyDevice)
  66. #pragma alloc_text(PAGE, PopFilterCapabilities)
  67. #pragma alloc_text(PAGE, PopUserIsAdmin)
  68. #endif
  69. NTSTATUS
  70. NtPowerInformation (
  71. IN POWER_INFORMATION_LEVEL InformationLevel,
  72. IN PVOID InputBuffer OPTIONAL,
  73. IN ULONG InputBufferLength,
  74. OUT PVOID OutputBuffer OPTIONAL,
  75. IN ULONG OutputBufferLength
  76. )
  77. /*++
  78. Routine Description:
  79. This function optional sets, and gets current power policy information
  80. based on the InformationLevel.
  81. Arguments:
  82. InputBuffer - Input to set InformationLevel information.
  83. InputBufferLength - Size, in bytes, of InputBuffer
  84. OutputBuffer - Buffer to return InformationLevel information.
  85. OutputBufferLength - Size, in bytes, of OutputBuffer
  86. Return Value:
  87. Status
  88. --*/
  89. {
  90. NTSTATUS Status;
  91. PVOID ReturnBuffer;
  92. ULONG ReturnBufferLength;
  93. KPROCESSOR_MODE PreviousMode;
  94. PPOWER_STATE_HANDLER PowerHandler;
  95. PBOOLEAN CapFlag;
  96. PVOID CapBuffer;
  97. BOOLEAN Enable;
  98. ULONG HandlerType;
  99. SYSTEM_POWER_STATE RtcWake;
  100. BOOLEAN CheckForWork = InputBuffer ? TRUE : FALSE;
  101. union {
  102. PROCESSOR_POWER_POLICY ProcessorPolicy;
  103. SYSTEM_POWER_POLICY PowerPolicy;
  104. SYSTEM_BATTERY_STATE PowerState;
  105. SYSTEM_POWER_INFORMATION SysInfo;
  106. PROCESSOR_POWER_INFORMATION ProcInfo[MAXIMUM_PROCESSORS];
  107. SYSTEM_POWER_CAPABILITIES PowerCapabilities;
  108. EXECUTION_STATE SystemExecutionState;
  109. } Buf;
  110. PAGED_CODE();
  111. Status = STATUS_SUCCESS;
  112. ReturnBuffer = NULL;
  113. ReturnBufferLength = 0;
  114. CapBuffer = NULL;
  115. PreviousMode = KeGetPreviousMode();
  116. PopAcquirePolicyLock ();
  117. try {
  118. //
  119. // If caller is user mode make some verifications
  120. //
  121. if (PreviousMode != KernelMode) {
  122. //
  123. // Is caller attempting to set anything?
  124. //
  125. if (InputBuffer) {
  126. if (InformationLevel != VerifySystemPolicyAc &&
  127. InformationLevel != VerifySystemPolicyDc &&
  128. InformationLevel != VerifyProcessorPowerPolicyAc &&
  129. InformationLevel != VerifyProcessorPowerPolicyDc) {
  130. //
  131. // Make access check
  132. //
  133. if (InformationLevel == SystemReserveHiberFile) {
  134. //
  135. // Only allow callers that have create pagefile privilege
  136. // to enable/disable the hibernate file
  137. //
  138. if (!SeSinglePrivilegeCheck(SeCreatePagefilePrivilege,PreviousMode)) {
  139. ExRaiseStatus (STATUS_PRIVILEGE_NOT_HELD);
  140. }
  141. } else {
  142. if (!SeSinglePrivilegeCheck( SeShutdownPrivilege, PreviousMode )) {
  143. ExRaiseStatus (STATUS_PRIVILEGE_NOT_HELD);
  144. }
  145. }
  146. }
  147. //
  148. // Verify input addresses
  149. //
  150. ProbeForRead (
  151. InputBuffer,
  152. InputBufferLength,
  153. InputBufferLength >= sizeof (ULONG) ? sizeof(ULONG) : sizeof(UCHAR)
  154. );
  155. }
  156. //
  157. // Verify output addresses
  158. //
  159. if (OutputBuffer) {
  160. ProbeForWrite (OutputBuffer, OutputBufferLength, sizeof(ULONG));
  161. }
  162. }
  163. //
  164. // Handle request
  165. //
  166. switch (InformationLevel) {
  167. case SystemPowerPolicyAc:
  168. //
  169. // We can be asked to set the AC policy through this mechanism
  170. //
  171. if (InputBuffer) {
  172. PopApplyPolicy (
  173. TRUE,
  174. TRUE,
  175. (PSYSTEM_POWER_POLICY) InputBuffer,
  176. InputBufferLength
  177. );
  178. }
  179. //
  180. // Return current AC policy
  181. //
  182. ReturnBuffer = &PopAcPolicy;
  183. ReturnBufferLength = sizeof(PopAcPolicy);
  184. break;
  185. case SystemPowerPolicyDc:
  186. //
  187. // We can be asked to set the DC policy through this mechanism
  188. //
  189. if (InputBuffer) {
  190. PopApplyPolicy (
  191. TRUE,
  192. FALSE,
  193. (PSYSTEM_POWER_POLICY) InputBuffer,
  194. InputBufferLength
  195. );
  196. }
  197. //
  198. // Return current DC policy
  199. //
  200. ReturnBuffer = &PopDcPolicy;
  201. ReturnBufferLength = sizeof(PopDcPolicy);
  202. break;
  203. case ProcessorPowerPolicyAc:
  204. //
  205. // We can be asked to set the AC processor policy
  206. // through this mechanism
  207. //
  208. if (InputBuffer) {
  209. PopApplyProcessorPolicy(
  210. TRUE,
  211. TRUE,
  212. (PPROCESSOR_POWER_POLICY) InputBuffer,
  213. InputBufferLength
  214. );
  215. }
  216. //
  217. // Return current AC processor policy
  218. //
  219. ReturnBuffer = &PopAcProcessorPolicy;
  220. ReturnBufferLength = sizeof(PopAcProcessorPolicy);
  221. break;
  222. case ProcessorPowerPolicyDc:
  223. //
  224. // We can be asked to set the DC processor policy
  225. // through this mechanism
  226. //
  227. if (InputBuffer) {
  228. PopApplyProcessorPolicy(
  229. TRUE,
  230. FALSE,
  231. (PPROCESSOR_POWER_POLICY) InputBuffer,
  232. InputBufferLength
  233. );
  234. }
  235. //
  236. // Return current DC processor policy
  237. //
  238. ReturnBuffer = &PopDcProcessorPolicy;
  239. ReturnBufferLength = sizeof(PopDcProcessorPolicy);
  240. break;
  241. case AdministratorPowerPolicy:
  242. if (InputBuffer) {
  243. if (PopUserIsAdmin()) {
  244. PopApplyAdminPolicy(
  245. TRUE,
  246. (PADMINISTRATOR_POWER_POLICY) InputBuffer,
  247. InputBufferLength
  248. );
  249. PopResetCurrentPolicies ();
  250. } else {
  251. Status = STATUS_ACCESS_DENIED;
  252. }
  253. }
  254. //
  255. // Return administrator policy
  256. //
  257. ReturnBuffer = &PopAdminPolicy;
  258. ReturnBufferLength = sizeof(PopAdminPolicy);
  259. break;
  260. case VerifySystemPolicyAc:
  261. if (InputBuffer && OutputBuffer) {
  262. if (InputBufferLength >= sizeof (SYSTEM_POWER_POLICY)) {
  263. PopVerifyPowerPolicy (TRUE, InputBuffer, &Buf.PowerPolicy);
  264. ReturnBuffer = &Buf.PowerPolicy;
  265. ReturnBufferLength = sizeof(Buf.PowerPolicy);
  266. } else {
  267. Status = STATUS_BUFFER_TOO_SMALL;
  268. }
  269. } else {
  270. Status = STATUS_INVALID_PARAMETER;
  271. }
  272. break;
  273. case VerifySystemPolicyDc:
  274. if (InputBuffer && OutputBuffer) {
  275. if (InputBufferLength >= sizeof (SYSTEM_POWER_POLICY)) {
  276. PopVerifyPowerPolicy (FALSE, InputBuffer, &Buf.PowerPolicy);
  277. ReturnBuffer = &Buf.PowerPolicy;
  278. ReturnBufferLength = sizeof(Buf.PowerPolicy);
  279. } else {
  280. Status = STATUS_BUFFER_TOO_SMALL;
  281. }
  282. } else {
  283. Status = STATUS_INVALID_PARAMETER;
  284. }
  285. break;
  286. case VerifyProcessorPowerPolicyAc:
  287. if (InputBuffer && OutputBuffer) {
  288. if (InputBufferLength >= sizeof (PROCESSOR_POWER_POLICY)) {
  289. PopVerifyProcessorPowerPolicy(
  290. TRUE,
  291. InputBuffer,
  292. &Buf.ProcessorPolicy
  293. );
  294. ReturnBuffer = &Buf.ProcessorPolicy;
  295. ReturnBufferLength = sizeof(Buf.ProcessorPolicy);
  296. } else {
  297. Status = STATUS_BUFFER_TOO_SMALL;
  298. }
  299. } else {
  300. Status = STATUS_INVALID_PARAMETER;
  301. }
  302. break;
  303. case VerifyProcessorPowerPolicyDc:
  304. if (InputBuffer && OutputBuffer) {
  305. if (InputBufferLength >= sizeof (PROCESSOR_POWER_POLICY)) {
  306. PopVerifyProcessorPowerPolicy(
  307. FALSE,
  308. InputBuffer,
  309. &Buf.ProcessorPolicy
  310. );
  311. ReturnBuffer = &Buf.ProcessorPolicy;
  312. ReturnBufferLength = sizeof(Buf.ProcessorPolicy);
  313. } else {
  314. Status = STATUS_BUFFER_TOO_SMALL;
  315. }
  316. } else {
  317. Status = STATUS_INVALID_PARAMETER;
  318. }
  319. break;
  320. case SystemPowerPolicyCurrent:
  321. if (InputBuffer) {
  322. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  323. }
  324. //
  325. // Return current policy
  326. //
  327. ReturnBuffer = PopPolicy;
  328. ReturnBufferLength = sizeof(PopAcPolicy);
  329. break;
  330. case ProcessorPowerPolicyCurrent:
  331. if (InputBuffer) {
  332. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  333. }
  334. //
  335. // Return current policy
  336. //
  337. ReturnBuffer = PopProcessorPolicy;
  338. ReturnBufferLength = sizeof(PopAcProcessorPolicy);
  339. break;
  340. case SystemPowerCapabilities:
  341. // if we allow the simulation of capabilities (for testing), then
  342. // let it through
  343. if (InputBuffer) {
  344. if ((PopSimulate & POP_SIM_CAPABILITIES) && InputBufferLength == sizeof(PopCapabilities)) {
  345. memcpy (&PopCapabilities, InputBuffer, InputBufferLength);
  346. PopResetCurrentPolicies ();
  347. PopSetNotificationWork (PO_NOTIFY_CAPABILITIES);
  348. } else {
  349. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  350. }
  351. }
  352. PopCapabilities.FullWake = (PopFullWake & PO_FULL_WAKE_STATUS) ? TRUE : FALSE;
  353. PopCapabilities.DiskSpinDown =
  354. PopAttributes[POP_DISK_SPINDOWN_ATTRIBUTE].Count ? TRUE : FALSE;
  355. PopFilterCapabilities(&PopCapabilities, &Buf.PowerCapabilities);
  356. ReturnBuffer = &Buf.PowerCapabilities;
  357. ReturnBufferLength = sizeof(PopCapabilities);
  358. break;
  359. case SystemBatteryState:
  360. PopCurrentPowerState (&Buf.PowerState);
  361. ReturnBuffer = &Buf.PowerState;
  362. ReturnBufferLength = sizeof(Buf.PowerState);
  363. break;
  364. case SystemPowerStateHandler:
  365. //
  366. // Caller must be kernel mode with the proper parameters
  367. //
  368. if (PreviousMode != KernelMode || OutputBuffer || !InputBuffer) {
  369. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  370. }
  371. //
  372. // Handler can only be registered once
  373. //
  374. PowerHandler = (PPOWER_STATE_HANDLER) InputBuffer;
  375. HandlerType = PowerHandler->Type;
  376. if (HandlerType >= PowerStateMaximum) {
  377. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  378. }
  379. //
  380. // He can only be registered once UNLESS it's the
  381. // PowerStateShutdownOff handler. That's because
  382. // we've set a default shutdown handler and would
  383. // sure welcome someone else (e.g. hal) to come along
  384. // and overwrite our default.
  385. //
  386. if( (PopPowerStateHandlers[HandlerType].Handler) ) {
  387. //
  388. // There's already a handler here. The only way
  389. // we're going to let this request through is if
  390. // they're setting the PowerStateShutdownOff
  391. // handler *AND* the current handler is pointing
  392. // to PopShutdownHandler().
  393. //
  394. if( !((HandlerType == PowerStateShutdownOff) &&
  395. (PopPowerStateHandlers[HandlerType].Handler == PopShutdownHandler)) ) {
  396. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  397. }
  398. }
  399. //
  400. // Set new handler
  401. //
  402. PopPowerStateHandlers[HandlerType] = *PowerHandler;
  403. PopPowerStateHandlers[HandlerType].Spare[0] = 0;
  404. PopPowerStateHandlers[HandlerType].Spare[1] = 0;
  405. PopPowerStateHandlers[HandlerType].Spare[2] = 0;
  406. CapFlag = NULL;
  407. RtcWake = PowerSystemUnspecified;
  408. switch (HandlerType) {
  409. case PowerStateSleeping1:
  410. if (!(PopSimulate & POP_IGNORE_S1)) {
  411. CapFlag = &PopCapabilities.SystemS1;
  412. }
  413. RtcWake = PowerSystemSleeping1;
  414. break;
  415. case PowerStateSleeping2:
  416. if (!(PopSimulate & POP_IGNORE_S2)) {
  417. CapFlag = &PopCapabilities.SystemS2;
  418. }
  419. RtcWake = PowerSystemSleeping2;
  420. break;
  421. case PowerStateSleeping3:
  422. if (!(PopSimulate & POP_IGNORE_S3)) {
  423. CapFlag = &PopCapabilities.SystemS3;
  424. }
  425. RtcWake = PowerSystemSleeping3;
  426. break;
  427. case PowerStateSleeping4:
  428. if (!(PopSimulate & POP_IGNORE_S4)) {
  429. CapFlag = &PopCapabilities.SystemS4;
  430. }
  431. RtcWake = PowerSystemHibernate;
  432. break;
  433. case PowerStateShutdownOff:
  434. CapFlag = &PopCapabilities.SystemS5;
  435. break;
  436. default:
  437. break;
  438. }
  439. if (!PopPowerStateHandlers[HandlerType].RtcWake) {
  440. RtcWake = PowerSystemUnspecified;
  441. }
  442. if (RtcWake > PopCapabilities.RtcWake) {
  443. PopCapabilities.RtcWake = RtcWake;
  444. }
  445. if (CapFlag) {
  446. PopSetCapability (CapFlag);
  447. }
  448. break;
  449. case SystemPowerStateNotifyHandler:
  450. //
  451. // Caller must be kernel mode with the proper parameters
  452. //
  453. if (PreviousMode != KernelMode || OutputBuffer) {
  454. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  455. }
  456. //
  457. // Notify handler can only be registered once.
  458. //
  459. if (PopPowerStateNotifyHandler.Handler &&
  460. ((PPOWER_STATE_NOTIFY_HANDLER)InputBuffer)->Handler) {
  461. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  462. }
  463. //
  464. // Set new handler
  465. //
  466. ASSERT(InputBufferLength == sizeof(POWER_STATE_NOTIFY_HANDLER));
  467. RtlCopyMemory(&PopPowerStateNotifyHandler,
  468. InputBuffer,
  469. sizeof(POWER_STATE_NOTIFY_HANDLER));
  470. break;
  471. case ProcessorStateHandler:
  472. case ProcessorStateHandler2:
  473. //
  474. // Caller must be kernel mode with the proper parameters
  475. //
  476. if (PreviousMode != KernelMode || OutputBuffer || !InputBuffer) {
  477. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  478. }
  479. //
  480. // Install handlers
  481. //
  482. try {
  483. if (InformationLevel == ProcessorStateHandler2) {
  484. PopInitProcessorStateHandlers2 ((PPROCESSOR_STATE_HANDLER2) InputBuffer);
  485. } else {
  486. PopInitProcessorStateHandlers ((PPROCESSOR_STATE_HANDLER) InputBuffer);
  487. }
  488. } except (PopExceptionFilter(GetExceptionInformation(), FALSE)) {
  489. }
  490. //
  491. // Reset policies as capabilities may have changed
  492. //
  493. PopResetCurrentPolicies ();
  494. break;
  495. case SystemReserveHiberFile:
  496. //
  497. // If previous mode isn't kernel mode, change it
  498. //
  499. if (InputBufferLength != sizeof(BOOLEAN)) {
  500. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  501. }
  502. Enable = *((PBOOLEAN) InputBuffer);
  503. if (PreviousMode != KernelMode) {
  504. PopReleasePolicyLock (FALSE);
  505. Status = ZwPowerInformation(SystemReserveHiberFile,
  506. &Enable,
  507. sizeof (Enable),
  508. NULL,
  509. 0);
  510. PopAcquirePolicyLock ();
  511. break;
  512. }
  513. try {
  514. Status = PopEnableHiberFile (Enable);
  515. } except (PopExceptionFilter(GetExceptionInformation(), FALSE)) {
  516. }
  517. break;
  518. case SystemPowerInformation:
  519. Buf.SysInfo.MaxIdlenessAllowed = PopSIdle.Sensitivity;
  520. Buf.SysInfo.Idleness = PopSIdle.Idleness;
  521. Buf.SysInfo.TimeRemaining = (PopSIdle.Timeout - PopSIdle.Time) * SYS_IDLE_WORKER;
  522. Buf.SysInfo.CoolingMode = (UCHAR) PopCoolingMode;
  523. ReturnBuffer = &Buf.SysInfo;
  524. ReturnBufferLength = sizeof(Buf.SysInfo);
  525. break;
  526. case ProcessorInformation:
  527. {
  528. ULONG length;
  529. length = sizeof(PROCESSOR_POWER_INFORMATION) * MAXIMUM_PROCESSORS;
  530. if (length > OutputBufferLength) {
  531. length = OutputBufferLength;
  532. }
  533. PopProcessorInformation ( Buf.ProcInfo, length, &ReturnBufferLength );
  534. ReturnBuffer = &Buf.ProcInfo;
  535. break;
  536. }
  537. case LastWakeTime:
  538. //
  539. // This is output only
  540. //
  541. if (InputBuffer) {
  542. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  543. }
  544. ReturnBuffer = &PopAction.WakeTime;
  545. ReturnBufferLength = sizeof(PopAction.WakeTime);
  546. break;
  547. case LastSleepTime:
  548. //
  549. // This is output only
  550. //
  551. // We don't check for work here as USER calls into here while in a power callout
  552. // and if we check for work at that point, promotion to hibernate doesn't work right.
  553. //
  554. CheckForWork = FALSE;
  555. if (InputBuffer) {
  556. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  557. }
  558. ReturnBuffer = &PopAction.SleepTime;
  559. ReturnBufferLength = sizeof(PopAction.SleepTime);
  560. break;
  561. case SystemExecutionState:
  562. //
  563. // This is output only
  564. //
  565. if (InputBuffer) {
  566. ExRaiseStatus(STATUS_INVALID_PARAMETER);
  567. }
  568. Buf.SystemExecutionState = 0;
  569. ReturnBuffer = &Buf.SystemExecutionState;
  570. ReturnBufferLength = sizeof(Buf.SystemExecutionState);
  571. if (PopAttributes[POP_SYSTEM_ATTRIBUTE].Count) {
  572. Buf.SystemExecutionState |= ES_SYSTEM_REQUIRED;
  573. }
  574. if (PopAttributes[POP_DISPLAY_ATTRIBUTE].Count) {
  575. Buf.SystemExecutionState |= ES_DISPLAY_REQUIRED;
  576. }
  577. if (PopAttributes[POP_USER_ATTRIBUTE].Count) {
  578. Buf.SystemExecutionState |= ES_USER_PRESENT;
  579. }
  580. break;
  581. default:
  582. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  583. }
  584. //
  585. // If there's a return buffer, return it
  586. //
  587. if (NT_SUCCESS(Status) && OutputBuffer && ReturnBuffer) {
  588. if (OutputBufferLength < ReturnBufferLength) {
  589. Status = STATUS_BUFFER_TOO_SMALL;
  590. } else {
  591. memcpy (OutputBuffer, ReturnBuffer, ReturnBufferLength);
  592. }
  593. }
  594. } except (EXCEPTION_EXECUTE_HANDLER) {
  595. Status = GetExceptionCode();
  596. }
  597. //
  598. // Done. Release resources
  599. //
  600. if (CapBuffer) {
  601. ExFreePool(CapBuffer);
  602. }
  603. PopReleasePolicyLock (CheckForWork);
  604. return Status;
  605. }
  606. VOID
  607. PopApplyAdminPolicy (
  608. IN BOOLEAN UpdateRegistry,
  609. IN PADMINISTRATOR_POWER_POLICY NewPolicy,
  610. IN ULONG PolicyLength
  611. )
  612. /*++
  613. Routine Description:
  614. N.B. PopPolicyLock must be held.
  615. Arguments:
  616. UpdateRegistry - TRUE if the policy being applied should be set in the register
  617. as the current policy
  618. NewPolicy - The policy to apply
  619. Return Value:
  620. None
  621. --*/
  622. {
  623. ADMINISTRATOR_POWER_POLICY Policy;
  624. UNICODE_STRING UnicodeString;
  625. HANDLE handle;
  626. NTSTATUS Status;
  627. if (PolicyLength < sizeof (ADMINISTRATOR_POWER_POLICY)) {
  628. ExRaiseStatus (STATUS_BUFFER_TOO_SMALL);
  629. }
  630. if (PolicyLength > sizeof (ADMINISTRATOR_POWER_POLICY)) {
  631. ExRaiseStatus (STATUS_BUFFER_OVERFLOW);
  632. }
  633. memcpy (&Policy, NewPolicy, sizeof(Policy));
  634. //
  635. // Verify values fall within proper range
  636. //
  637. if (Policy.MinSleep < PowerSystemSleeping1 ||
  638. Policy.MinSleep > PowerSystemHibernate ||
  639. Policy.MinSleep < PowerSystemSleeping1 ||
  640. Policy.MaxSleep > PowerSystemHibernate ||
  641. Policy.MinSleep > Policy.MaxSleep ||
  642. Policy.MinVideoTimeout > Policy.MaxVideoTimeout ||
  643. Policy.MinSpindownTimeout > Policy.MaxSpindownTimeout) {
  644. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  645. }
  646. //
  647. // If the policy hasn't changed, return
  648. //
  649. if (!memcmp (&Policy, &PopAdminPolicy, sizeof(Policy))) {
  650. return ;
  651. }
  652. //
  653. // Change it
  654. //
  655. memcpy (&PopAdminPolicy, &Policy, sizeof(Policy));
  656. //
  657. // Update registry copy of policy
  658. //
  659. if (UpdateRegistry) {
  660. Status = PopOpenPowerKey (&handle);
  661. if (NT_SUCCESS(Status)) {
  662. RtlInitUnicodeString (&UnicodeString, PopAdminRegName);
  663. ZwSetValueKey (
  664. handle,
  665. &UnicodeString,
  666. 0L,
  667. REG_BINARY,
  668. &Policy,
  669. sizeof(ADMINISTRATOR_POWER_POLICY)
  670. );
  671. ZwClose (handle);
  672. }
  673. }
  674. }
  675. VOID
  676. PopApplyPolicy (
  677. IN BOOLEAN UpdateRegistry,
  678. IN BOOLEAN AcPolicy,
  679. IN PSYSTEM_POWER_POLICY NewPolicy,
  680. IN ULONG PolicyLength
  681. )
  682. /*++
  683. Routine Description:
  684. Update Dest policy to be Source policy.
  685. N.B. PopPolicyLock must be held.
  686. Arguments:
  687. UpdateRegistry - TRUE if the policy being applied should be set in the register
  688. as the current policy
  689. AcPolicy - TRUE if the new policy is for the systems AC policy, FALSE for the DC policy
  690. NewPolicy - The policy to apply
  691. Return Value:
  692. None
  693. --*/
  694. {
  695. ULONG i;
  696. BOOLEAN DischargeChanged;
  697. SYSTEM_POWER_POLICY OrigPolicy, Policy;
  698. PSYSTEM_POWER_POLICY SystemPolicy;
  699. PSYSTEM_POWER_LEVEL DPolicy, SPolicy;
  700. UNICODE_STRING UnicodeString;
  701. HANDLE handle;
  702. NTSTATUS Status;
  703. const WCHAR* RegName;
  704. //
  705. // Setup for system policy change
  706. //
  707. if (AcPolicy) {
  708. RegName = PopAcRegName;
  709. SystemPolicy = &PopAcPolicy;
  710. } else {
  711. RegName = PopDcRegName;
  712. SystemPolicy = &PopDcPolicy;
  713. }
  714. //
  715. // Convert policy to current system capabilities
  716. //
  717. if (PolicyLength < sizeof (SYSTEM_POWER_POLICY)) {
  718. ExRaiseStatus (STATUS_BUFFER_TOO_SMALL);
  719. }
  720. if (PolicyLength > sizeof (SYSTEM_POWER_POLICY)) {
  721. ExRaiseStatus (STATUS_BUFFER_OVERFLOW);
  722. }
  723. memcpy (&OrigPolicy, NewPolicy, sizeof (SYSTEM_POWER_POLICY));
  724. PopVerifyPowerPolicy (AcPolicy, &OrigPolicy, &Policy);
  725. //
  726. // If the policy hasn't changed, return
  727. //
  728. if (!memcmp (&Policy, SystemPolicy, sizeof(SYSTEM_POWER_POLICY))) {
  729. return ;
  730. }
  731. //
  732. // Check if any discharge setting has changed
  733. //
  734. DischargeChanged = FALSE;
  735. DPolicy = SystemPolicy->DischargePolicy;
  736. SPolicy = Policy.DischargePolicy;
  737. for (i=0; i < PO_NUM_POWER_LEVELS; i++) {
  738. if (SPolicy[i].Enable != DPolicy[i].Enable) {
  739. DischargeChanged = TRUE;
  740. break;
  741. }
  742. if (SPolicy[i].Enable && memcmp (&SPolicy[i], &DPolicy[i], sizeof (SYSTEM_POWER_LEVEL))) {
  743. DischargeChanged = TRUE;
  744. break;
  745. }
  746. }
  747. //
  748. // Change it
  749. //
  750. memcpy (SystemPolicy, &Policy, sizeof(SYSTEM_POWER_POLICY));
  751. //
  752. // If this is the active policy, changes need to take effect now
  753. //
  754. if (SystemPolicy == PopPolicy) {
  755. //
  756. // Changing the active policy
  757. //
  758. PopSetNotificationWork (PO_NOTIFY_POLICY | PO_NOTIFY_POLICY_CALLBACK);
  759. //
  760. // If any discharge policy has changed, reset the composite
  761. // battery triggers
  762. //
  763. if (DischargeChanged) {
  764. PopResetCBTriggers (PO_TRG_SET | PO_TRG_SYSTEM | PO_TRG_USER);
  765. }
  766. //
  767. // Recompute thermal throttle and cooling mode
  768. //
  769. PopApplyThermalThrottle ();
  770. //
  771. // Recompute system idle values
  772. //
  773. PopInitSIdle ();
  774. }
  775. //
  776. // Update registry copy of policy
  777. //
  778. if (UpdateRegistry) {
  779. Status = PopOpenPowerKey (&handle);
  780. if (NT_SUCCESS(Status)) {
  781. RtlInitUnicodeString (&UnicodeString, RegName);
  782. ZwSetValueKey (
  783. handle,
  784. &UnicodeString,
  785. 0L,
  786. REG_BINARY,
  787. &OrigPolicy,
  788. sizeof (SYSTEM_POWER_POLICY)
  789. );
  790. ZwClose (handle);
  791. }
  792. }
  793. }
  794. VOID
  795. PopApplyProcessorPolicy (
  796. IN BOOLEAN UpdateRegistry,
  797. IN BOOLEAN AcPolicy,
  798. IN PPROCESSOR_POWER_POLICY NewPolicy,
  799. IN ULONG PolicyLength
  800. )
  801. /*++
  802. Routine Description:
  803. Update Dest policy to be Source policy.
  804. N.B. PopPolicyLock must be held.
  805. Arguments:
  806. UpdateRegistry - TRUE if the policy being applied should be set in the register
  807. as the current policy
  808. AcPolicy - TRUE if the new policy is for the systems AC policy, FALSE for the DC policy
  809. NewPolicy - The policy to apply
  810. Return Value:
  811. None
  812. --*/
  813. {
  814. PROCESSOR_POWER_POLICY OrigPolicy;
  815. PROCESSOR_POWER_POLICY Policy;
  816. PPROCESSOR_POWER_POLICY SystemPolicy;
  817. UNICODE_STRING UnicodeString;
  818. HANDLE handle;
  819. NTSTATUS Status;
  820. const WCHAR* RegName;
  821. //
  822. // Setup for system policy change
  823. //
  824. if (AcPolicy) {
  825. RegName = PopAcProcessorRegName;
  826. SystemPolicy = &PopAcProcessorPolicy;
  827. } else {
  828. RegName = PopDcProcessorRegName;
  829. SystemPolicy = &PopDcProcessorPolicy;
  830. }
  831. //
  832. // Convert policy to current system capabilities
  833. //
  834. if (PolicyLength < sizeof (PROCESSOR_POWER_POLICY)) {
  835. ExRaiseStatus (STATUS_BUFFER_TOO_SMALL);
  836. }
  837. if (PolicyLength > sizeof (PROCESSOR_POWER_POLICY)) {
  838. ExRaiseStatus (STATUS_BUFFER_OVERFLOW);
  839. }
  840. memcpy (&OrigPolicy, NewPolicy, sizeof (PROCESSOR_POWER_POLICY));
  841. PopVerifyProcessorPowerPolicy (AcPolicy, &OrigPolicy, &Policy);
  842. //
  843. // If the policy hasn't changed, return
  844. //
  845. if (!memcmp (&Policy, SystemPolicy, sizeof(PROCESSOR_POWER_POLICY))) {
  846. return ;
  847. }
  848. //
  849. // Change it
  850. //
  851. memcpy (SystemPolicy, &Policy, sizeof(PROCESSOR_POWER_POLICY));
  852. //
  853. // If this is the active policy, changes need to take effect now
  854. //
  855. if (SystemPolicy == PopProcessorPolicy) {
  856. //
  857. // Changing the active policy
  858. //
  859. PopSetNotificationWork(
  860. PO_NOTIFY_PROCESSOR_POLICY | PO_NOTIFY_PROCESSOR_POLICY_CALLBACK
  861. );
  862. //
  863. // Recompute current throttle policy....
  864. //
  865. PopUpdateAllThrottles();
  866. PopIdleUpdateIdleHandlers();
  867. }
  868. //
  869. // Update registry copy of policy
  870. //
  871. if (UpdateRegistry) {
  872. Status = PopOpenPowerKey (&handle);
  873. if (NT_SUCCESS(Status)) {
  874. RtlInitUnicodeString (&UnicodeString, RegName);
  875. ZwSetValueKey (
  876. handle,
  877. &UnicodeString,
  878. 0L,
  879. REG_BINARY,
  880. &OrigPolicy,
  881. sizeof (PROCESSOR_POWER_POLICY)
  882. );
  883. ZwClose (handle);
  884. }
  885. }
  886. }
  887. VOID
  888. PopVerifyPowerPolicy (
  889. IN BOOLEAN Ac,
  890. IN PSYSTEM_POWER_POLICY InputPolicy,
  891. OUT PSYSTEM_POWER_POLICY PowerPolicy
  892. )
  893. /*++
  894. Routine Description:
  895. This function copies the InputPolicy to the output PowerPolicy and
  896. adjusts it to represent system capabilities and other requirements.
  897. If the input policy has some setting which can not be adjusted, an
  898. error status is raised.
  899. N.B. PopPolicyLock must be held.
  900. Arguments:
  901. Ac - Policy is to be adjusted as an AC or DC policy
  902. InputPolicy - The source policy to adjust
  903. PowerPolicy - The returned policy which can be used as is
  904. Return Value:
  905. None
  906. --*/
  907. {
  908. ULONG i;
  909. PSYSTEM_POWER_LEVEL DPolicy;
  910. PAGED_CODE();
  911. //
  912. // Setup initial output structure
  913. //
  914. memcpy (PowerPolicy, InputPolicy, sizeof (SYSTEM_POWER_POLICY));
  915. //
  916. // Only revision 1 currently supported
  917. //
  918. if (PowerPolicy->Revision != 1) {
  919. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  920. }
  921. //
  922. // some win9x upgrades or very old NT builds might have maxsleep set to S4. Fix that here.
  923. //
  924. if (PowerPolicy->MaxSleep > PowerSystemSleeping3) {
  925. PowerPolicy->MaxSleep = PowerSystemSleeping3;
  926. }
  927. //
  928. // Limit settings to administrator policy
  929. //
  930. if (PowerPolicy->MinSleep < PopAdminPolicy.MinSleep) {
  931. PowerPolicy->MinSleep = PopAdminPolicy.MinSleep;
  932. }
  933. if (PowerPolicy->MaxSleep > PopAdminPolicy.MaxSleep) {
  934. PowerPolicy->MaxSleep = PopAdminPolicy.MaxSleep;
  935. }
  936. if (PowerPolicy->VideoTimeout < PopAdminPolicy.MinVideoTimeout) {
  937. PowerPolicy->VideoTimeout = PopAdminPolicy.MinVideoTimeout;
  938. }
  939. if (PowerPolicy->VideoTimeout > PopAdminPolicy.MaxVideoTimeout) {
  940. PowerPolicy->VideoTimeout = PopAdminPolicy.MaxVideoTimeout;
  941. }
  942. if (PowerPolicy->SpindownTimeout < PopAdminPolicy.MinSpindownTimeout) {
  943. PowerPolicy->SpindownTimeout = PopAdminPolicy.MinSpindownTimeout;
  944. }
  945. if ((ULONG) PowerPolicy->SpindownTimeout > (ULONG) PopAdminPolicy.MaxSpindownTimeout) {
  946. PowerPolicy->SpindownTimeout = PopAdminPolicy.MaxSpindownTimeout;
  947. }
  948. //
  949. // Verify all the power action policies, and adjust all system
  950. // states to match what is supported by this platform
  951. //
  952. PopVerifyPowerActionPolicy(&PowerPolicy->PowerButton);
  953. PopVerifyPowerActionPolicy(&PowerPolicy->SleepButton);
  954. PopVerifyPowerActionPolicy(&PowerPolicy->LidClose);
  955. PopVerifyPowerActionPolicy(&PowerPolicy->Idle);
  956. PopVerifySystemPowerState(
  957. &PowerPolicy->LidOpenWake,
  958. SubstituteLightestOverallDownwardBounded
  959. );
  960. PopVerifySystemPowerState(
  961. &PowerPolicy->MinSleep,
  962. SubstituteLightestOverallDownwardBounded
  963. );
  964. PopVerifySystemPowerState(
  965. &PowerPolicy->MaxSleep,
  966. SubstituteLightestOverallDownwardBounded
  967. );
  968. PopVerifySystemPowerState(
  969. &PowerPolicy->ReducedLatencySleep,
  970. SubstituteLightestOverallDownwardBounded
  971. );
  972. for (i = 0; i < PO_NUM_POWER_LEVELS; i++) {
  973. DPolicy = &PowerPolicy->DischargePolicy[i];
  974. if (DPolicy->Enable) {
  975. PopVerifyPowerActionPolicy (
  976. &PowerPolicy->DischargePolicy[i].PowerPolicy
  977. );
  978. PopVerifySystemPowerState(
  979. &PowerPolicy->DischargePolicy[i].MinSystemState,
  980. SubstituteLightestOverallDownwardBounded
  981. );
  982. //
  983. // If the action is standby, make sure the min state is S3 or lighter
  984. //
  985. if ((PowerPolicy->DischargePolicy[i].PowerPolicy.Action == PowerActionSleep) &&
  986. (PowerPolicy->DischargePolicy[i].MinSystemState > PowerSystemSleeping3)) {
  987. PowerPolicy->DischargePolicy[i].MinSystemState = PowerSystemSleeping3;
  988. PopVerifySystemPowerState(
  989. &PowerPolicy->DischargePolicy[i].MinSystemState,
  990. SubstituteLightestOverallDownwardBounded
  991. );
  992. }
  993. if (DPolicy->BatteryLevel > 100) {
  994. DPolicy->BatteryLevel = 100;
  995. }
  996. }
  997. }
  998. PopVerifyPowerActionPolicy(&PowerPolicy->OverThrottled);
  999. //
  1000. // Adjust other values based on capabilities
  1001. //
  1002. if (!PopCapabilities.ProcessorThrottle) {
  1003. PowerPolicy->OptimizeForPower = FALSE;
  1004. PowerPolicy->FanThrottleTolerance = PO_NO_FAN_THROTTLE;
  1005. PowerPolicy->ForcedThrottle = PO_NO_FORCED_THROTTLE;
  1006. }
  1007. if (!PopCapabilities.ThermalControl) {
  1008. PowerPolicy->FanThrottleTolerance = PO_NO_FAN_THROTTLE;
  1009. }
  1010. //
  1011. // Sanity
  1012. //
  1013. if (!PowerPolicy->BroadcastCapacityResolution) {
  1014. PowerPolicy->BroadcastCapacityResolution = 100;
  1015. }
  1016. //
  1017. // If the system supports only S4 (legacy) there is no point in
  1018. // idly hibernating the system as we can't turn it off anyway.
  1019. //
  1020. if ((PowerPolicy->Idle.Action == PowerActionHibernate) &&
  1021. (!PopCapabilities.SystemS5)) {
  1022. PowerPolicy->Idle.Action = PowerActionNone;
  1023. }
  1024. if (PowerPolicy->Idle.Action == PowerActionNone) {
  1025. PowerPolicy->IdleTimeout = 0;
  1026. }
  1027. if (PowerPolicy->IdleTimeout &&
  1028. PowerPolicy->IdleTimeout < PO_MIN_IDLE_TIMEOUT) {
  1029. PowerPolicy->IdleTimeout = PO_MIN_IDLE_TIMEOUT;
  1030. }
  1031. if (PowerPolicy->IdleSensitivity > 100 - PO_MIN_IDLE_SENSITIVITY) {
  1032. PowerPolicy->IdleSensitivity = 100 - PO_MIN_IDLE_SENSITIVITY;
  1033. }
  1034. if ((PowerPolicy->IdleTimeout > 0) &&
  1035. (PowerPolicy->IdleSensitivity == 0)) {
  1036. //
  1037. // This is basically saying "timeout when the system has been idle
  1038. // for X minutes, but never declare the system idle" This makes no
  1039. // sense, so we will set the idle sensitivity to the minimum.
  1040. //
  1041. PowerPolicy->IdleSensitivity = 100 - PO_MIN_IDLE_SENSITIVITY;
  1042. }
  1043. if (PowerPolicy->MaxSleep < PowerPolicy->MinSleep) {
  1044. PowerPolicy->MaxSleep = PowerPolicy->MinSleep;
  1045. }
  1046. if (PowerPolicy->ReducedLatencySleep > PowerPolicy->MinSleep) {
  1047. PowerPolicy->ReducedLatencySleep = PowerPolicy->MinSleep;
  1048. }
  1049. //
  1050. // Ignore whatever the user said what the minimum throttle and force the
  1051. // system to pick whatever the hardware supports as the min throttle
  1052. //
  1053. PowerPolicy->MinThrottle = 0;
  1054. //
  1055. // Verify all the throttle percentages (in tenths of a percentage points,
  1056. // so 1000 decimal = 100.0% and 777 = 77.7%) in terms of both their maximum
  1057. // and minimum values. Note: Percent is based on POP_PERF_SCALE, which is
  1058. // currently 128. So, actually, 1280 decimal = 100.0%.
  1059. //
  1060. PopVerifyThrottle(&PowerPolicy->FanThrottleTolerance, PO_MAX_FAN_THROTTLE);
  1061. PopVerifyThrottle(&PowerPolicy->MinThrottle, PO_MIN_MIN_THROTTLE);
  1062. PopVerifyThrottle(&PowerPolicy->ForcedThrottle, PowerPolicy->MinThrottle);
  1063. if (PowerPolicy->FanThrottleTolerance != PO_NO_FAN_THROTTLE ||
  1064. PowerPolicy->ForcedThrottle != PO_NO_FORCED_THROTTLE) {
  1065. PowerPolicy->OptimizeForPower = TRUE;
  1066. }
  1067. }
  1068. VOID
  1069. PopVerifyProcessorPowerPolicy (
  1070. IN BOOLEAN Ac,
  1071. IN PPROCESSOR_POWER_POLICY InputPolicy,
  1072. OUT PPROCESSOR_POWER_POLICY PowerPolicy
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This function copies the InputPolicy to the output PowerPolicy and
  1077. adjusts it to represent processor capabilities and other requirements.
  1078. If the input policy has some setting which can not be adjusted, an
  1079. error status is raised.
  1080. N.B. PopPolicyLock must be held.
  1081. Arguments:
  1082. Ac - Policy is to be adjusted as an AC or DC policy
  1083. InputPolicy - The source policy to adjust
  1084. PowerPolicy - The returned policy which can be used as is
  1085. Return Value:
  1086. None
  1087. --*/
  1088. {
  1089. PPROCESSOR_POWER_POLICY_INFO pPolicy;
  1090. ULONG i;
  1091. PAGED_CODE();
  1092. //
  1093. // Setup initial output structure
  1094. //
  1095. memcpy (PowerPolicy, InputPolicy, sizeof(PROCESSOR_POWER_POLICY));
  1096. //
  1097. // Only revision 1 currently supported
  1098. //
  1099. if (PowerPolicy->Revision != 1) {
  1100. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1101. }
  1102. //
  1103. // Sanity check each level of the policy
  1104. //
  1105. for (i = 0; i < 3; i++) {
  1106. pPolicy = &(PowerPolicy->Policy[i]);
  1107. //
  1108. // We don't allow demotion to Idle0 unless the machine is MP
  1109. //
  1110. if (i == 0 && KeNumberProcessors == 1) {
  1111. pPolicy->DemotePercent = 0;
  1112. pPolicy->AllowDemotion = 0;
  1113. }
  1114. //
  1115. // Don't allow promotions past the last state
  1116. //
  1117. if (i == 2) {
  1118. pPolicy->PromotePercent = 0;
  1119. pPolicy->PromoteLimit = 0;
  1120. pPolicy->AllowPromotion = 0;
  1121. }
  1122. //
  1123. // Time check must be smaller than Demote Limit (if there is one)
  1124. //
  1125. if (pPolicy->TimeCheck < pPolicy->DemoteLimit) {
  1126. pPolicy->TimeCheck = pPolicy->DemoteLimit;
  1127. }
  1128. if (pPolicy->DemotePercent == 0 &&
  1129. pPolicy->AllowPromotion &&
  1130. pPolicy->TimeCheck < pPolicy->PromoteLimit) {
  1131. pPolicy->TimeCheck = pPolicy->PromoteLimit;
  1132. }
  1133. }
  1134. if (PowerPolicy->DynamicThrottle >= PO_THROTTLE_MAXIMUM) {
  1135. if (Ac) {
  1136. PowerPolicy->DynamicThrottle = PO_THROTTLE_NONE;
  1137. } else {
  1138. PowerPolicy->DynamicThrottle = PO_THROTTLE_CONSTANT;
  1139. }
  1140. }
  1141. }
  1142. VOID
  1143. PopVerifyThrottle (
  1144. IN PUCHAR Throttle,
  1145. IN UCHAR Min
  1146. )
  1147. {
  1148. ULONG i;
  1149. UCHAR t;
  1150. t = *Throttle;
  1151. //
  1152. // Make sure max is POP_PERF_SCALE%
  1153. //
  1154. if (t > POP_PERF_SCALE) {
  1155. t = POP_PERF_SCALE;
  1156. }
  1157. //
  1158. // Make sure it's not below the specificied min.
  1159. //
  1160. if (t < Min) {
  1161. t = Min;
  1162. }
  1163. //
  1164. // Round the throttle up to the first supported value
  1165. // Note that we don't need to check against ProcessorMinThrottle
  1166. // or any other value since PopRoundThrottle() will do that for us.
  1167. //
  1168. PopRoundThrottle(t, NULL, Throttle, NULL, NULL);
  1169. }
  1170. BOOLEAN
  1171. PopVerifyPowerActionPolicy (
  1172. IN PPOWER_ACTION_POLICY Action
  1173. )
  1174. /*++
  1175. Routine Description:
  1176. This function checks & edits the input Action to represent
  1177. system capabilities and other requirements.
  1178. N.B. PopPolicyLock must be held.
  1179. Arguments:
  1180. Action - Power action policy to check / verify
  1181. Return Value:
  1182. Boolean to indicate action was demoted to a disabled state
  1183. --*/
  1184. {
  1185. POWER_ACTION LastAction;
  1186. BOOLEAN Disabled;
  1187. BOOLEAN HiberSupport;
  1188. ULONG SleepCount;
  1189. NTSTATUS Status;
  1190. PNP_VETO_TYPE VetoType;
  1191. SYSTEM_POWER_CAPABILITIES PowerCapabilities;
  1192. PAGED_CODE();
  1193. Disabled = FALSE;
  1194. //
  1195. // Verify reserved flag bits are clear
  1196. //
  1197. if (Action->Flags & !(
  1198. POWER_ACTION_QUERY_ALLOWED |
  1199. POWER_ACTION_UI_ALLOWED |
  1200. POWER_ACTION_OVERRIDE_APPS |
  1201. POWER_ACTION_LOCK_CONSOLE |
  1202. POWER_ACTION_DISABLE_WAKES |
  1203. POWER_ACTION_CRITICAL)) {
  1204. //
  1205. // N.B. - Later POWER_ACTION_LIGHTEST_FIRST?
  1206. //
  1207. // reserved bit set in action flags
  1208. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1209. }
  1210. //
  1211. // If the action is critical, then do not notify any applications
  1212. //
  1213. if (Action->Flags & POWER_ACTION_CRITICAL) {
  1214. Action->Flags &= ~(POWER_ACTION_QUERY_ALLOWED | POWER_ACTION_UI_ALLOWED);
  1215. Action->Flags |= POWER_ACTION_OVERRIDE_APPS;
  1216. }
  1217. //
  1218. // If any legacy drivers are installed, then no sleeping states
  1219. // are allowed at all.
  1220. //
  1221. if ((Action->Action == PowerActionSleep) ||
  1222. (Action->Action == PowerActionHibernate)) {
  1223. Status = IoGetLegacyVetoList(NULL, &VetoType);
  1224. if (NT_SUCCESS(Status) &&
  1225. (VetoType != PNP_VetoTypeUnknown)) {
  1226. Action->Action = PowerActionNone;
  1227. return(TRUE);
  1228. }
  1229. }
  1230. //
  1231. // Some components may disable some capabilities. So filter them here.
  1232. //
  1233. PopFilterCapabilities(&PopCapabilities, &PowerCapabilities);
  1234. //
  1235. // Count the supported sleeping states
  1236. //
  1237. SleepCount = 0;
  1238. HiberSupport = FALSE;
  1239. if (PowerCapabilities.SystemS1) {
  1240. SleepCount += 1;
  1241. }
  1242. if (PowerCapabilities.SystemS2) {
  1243. SleepCount += 1;
  1244. }
  1245. if (PowerCapabilities.SystemS3) {
  1246. SleepCount += 1;
  1247. }
  1248. if (PowerCapabilities.SystemS4 && PowerCapabilities.HiberFilePresent) {
  1249. HiberSupport = TRUE;
  1250. }
  1251. //
  1252. // Verify the requested action is supported.
  1253. //
  1254. do {
  1255. LastAction = Action->Action;
  1256. switch (Action->Action) {
  1257. case PowerActionNone:
  1258. // can do nothing, not a problem
  1259. break;
  1260. case PowerActionReserved:
  1261. // used to be doze action. does not exist anymore make it sleep
  1262. Action->Action = PowerActionSleep;
  1263. break;
  1264. case PowerActionSleep:
  1265. //
  1266. // if no sleeping states supported, adjust action to be none
  1267. //
  1268. if (SleepCount < 1) {
  1269. Disabled = TRUE;
  1270. Action->Action = PowerActionNone;
  1271. }
  1272. break;
  1273. case PowerActionHibernate:
  1274. //
  1275. // if no hibernate support, try sleep
  1276. //
  1277. if (!HiberSupport) {
  1278. Action->Action = PowerActionSleep;
  1279. }
  1280. break;
  1281. case PowerActionShutdown:
  1282. case PowerActionShutdownReset:
  1283. // all systems support shutdown & shutdown reset
  1284. break;
  1285. case PowerActionShutdownOff:
  1286. // If action shutdown is not available, use Shutdown
  1287. if (!PowerCapabilities.SystemS5) {
  1288. Action->Action = PowerActionShutdown;
  1289. }
  1290. break;
  1291. case PowerActionWarmEject:
  1292. //
  1293. // This is a system action associated with an individual device.
  1294. //
  1295. break;
  1296. default:
  1297. // unknown power action setting
  1298. ExRaiseStatus (STATUS_INVALID_PARAMETER);
  1299. }
  1300. } while (LastAction != Action->Action);
  1301. return Disabled;
  1302. }
  1303. VOID
  1304. PopAdvanceSystemPowerState (
  1305. IN OUT PSYSTEM_POWER_STATE PowerState,
  1306. IN POP_SUBSTITUTION_POLICY SubstitutionPolicy,
  1307. IN SYSTEM_POWER_STATE LightestSystemState,
  1308. IN SYSTEM_POWER_STATE DeepestSystemState
  1309. )
  1310. /*++
  1311. Routine Description:
  1312. This function uses the substitution policy to advance the sleep state
  1313. (lighten or deepen) as appropriate.
  1314. N.B. PopPolicyLock must be held.
  1315. Arguments:
  1316. PowerState - System power state to advance.
  1317. SubstitutionPolicy - see definitions in pop.h.
  1318. Return Value:
  1319. None
  1320. --*/
  1321. {
  1322. SYSTEM_POWER_STATE State;
  1323. BOOLEAN HibernateAllowed;
  1324. PAGED_CODE();
  1325. //
  1326. // Verify value is valid
  1327. //
  1328. State = *PowerState;
  1329. if (State < PowerSystemSleeping1) {
  1330. ExRaiseStatus (STATUS_INVALID_PARAMETER_1);
  1331. }
  1332. if (State >= PowerSystemShutdown) {
  1333. //
  1334. // There is nowhere else to go for these states.
  1335. //
  1336. *PowerState = PowerSystemWorking;
  1337. return;
  1338. }
  1339. switch(SubstitutionPolicy) {
  1340. case SubstituteLightestOverallDownwardBounded:
  1341. *PowerState = (State - 1);
  1342. PopVerifySystemPowerState(PowerState, SubstitutionPolicy);
  1343. //
  1344. // There are three cases to consider:
  1345. // 1. We received in S1, which was previously validated. We try S0
  1346. // and it is automatically accepted. There are no other options
  1347. // as we started in the lightest overall (S1). Thus we are
  1348. // finished.
  1349. // 2. We passed in Sx-1 for verification, but got back Sx. This
  1350. // means we were already at the lightest state (Sx), and we've
  1351. // exhausted the possibilities. Thus we are finished and so
  1352. // we return PowerSystemWorking.
  1353. // 3. We passed in Sx-1 and didn't get Sx. This means we've advanced
  1354. // to another state, although it may be the last if Sx was S1, as
  1355. // rule (1) is actually a special case of this rule.
  1356. //
  1357. if (*PowerState == State) {
  1358. *PowerState = PowerSystemWorking;
  1359. }
  1360. break;
  1361. case SubstituteLightenSleep:
  1362. *PowerState = (State - 1);
  1363. PopVerifySystemPowerState(PowerState, SubstitutionPolicy);
  1364. break;
  1365. case SubstituteDeepenSleep:
  1366. //
  1367. // Per above, Deepen goes straight into Hibernate.
  1368. //
  1369. if (State == PowerSystemHibernate) {
  1370. *PowerState = PowerSystemWorking;
  1371. break;
  1372. }
  1373. *PowerState = (State + 1);
  1374. PopVerifySystemPowerState(PowerState, SubstitutionPolicy);
  1375. break;
  1376. default:
  1377. ExRaiseStatus (STATUS_INVALID_PARAMETER_2);
  1378. break;
  1379. }
  1380. if ((*PowerState != PowerSystemWorking) &&
  1381. ((*PowerState < LightestSystemState) ||
  1382. (*PowerState > DeepestSystemState))) {
  1383. *PowerState = PowerSystemWorking;
  1384. }
  1385. }
  1386. VOID
  1387. PopVerifySystemPowerState (
  1388. IN OUT PSYSTEM_POWER_STATE PowerState,
  1389. IN POP_SUBSTITUTION_POLICY SubstitutionPolicy
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This function checks & edits the input PowerState to represent
  1394. system capabilities and other requirements.
  1395. N.B. PopPolicyLock must be held.
  1396. Arguments:
  1397. PowerState - System power state to check / verify
  1398. SubstitutionPolicy - See definitions in pop.h
  1399. Return Value:
  1400. None
  1401. --*/
  1402. {
  1403. SYSTEM_POWER_STATE State;
  1404. BOOLEAN HibernateAllowed;
  1405. PAGED_CODE();
  1406. //
  1407. // Verify value is valid
  1408. //
  1409. State = *PowerState;
  1410. if (State == PowerSystemUnspecified || State > PowerSystemShutdown) {
  1411. ExRaiseStatus (STATUS_INVALID_PARAMETER_1);
  1412. }
  1413. //
  1414. // PowerSystemShutdown is not allowed in any structures. It is generated
  1415. // internally for the sole use of quering drivers before performing
  1416. // a system shutdown
  1417. //
  1418. if (State == PowerSystemShutdown) {
  1419. ExRaiseStatus (STATUS_INVALID_PARAMETER_1);
  1420. }
  1421. //
  1422. // The working state is always supported
  1423. //
  1424. if (State == PowerSystemWorking) {
  1425. return ;
  1426. }
  1427. //
  1428. // Verify the power state is supported. If not, pick the next best state
  1429. //
  1430. HibernateAllowed = TRUE;
  1431. switch(SubstitutionPolicy) {
  1432. case SubstituteLightestOverallDownwardBounded:
  1433. case SubstituteLightenSleep:
  1434. //
  1435. // In LightenSleep, we lighten the power state passed in until
  1436. // we reach PowerStateWorking. Then we give up.
  1437. //
  1438. // In LightestOverall, instead of stopping, we turn around and
  1439. // choose the lightest non-S0 sleep state overall, which may be
  1440. // deeper than the one passed in. Note that we do *not* progress
  1441. // into Hibernation though.
  1442. //
  1443. if (State == PowerSystemHibernate &&
  1444. (!PopCapabilities.SystemS4 || !PopCapabilities.HiberFilePresent)) {
  1445. State = PowerSystemSleeping3;
  1446. }
  1447. if (State == PowerSystemSleeping3 && !PopCapabilities.SystemS3) {
  1448. State = PowerSystemSleeping2;
  1449. }
  1450. if (State == PowerSystemSleeping2 && !PopCapabilities.SystemS2) {
  1451. State = PowerSystemSleeping1;
  1452. }
  1453. if (State == PowerSystemSleeping1 && !PopCapabilities.SystemS1) {
  1454. State = PowerSystemWorking;
  1455. }
  1456. if (State != PowerSystemWorking) {
  1457. break;
  1458. }
  1459. if (SubstitutionPolicy != SubstituteLightestOverallDownwardBounded) {
  1460. break;
  1461. }
  1462. //
  1463. // Rounding down lead to PowerSystemWorking. Try to rounding up
  1464. // towards deeper sleep states. Block the rounding at S3 however.
  1465. //
  1466. State = State + 1;
  1467. HibernateAllowed = FALSE;
  1468. //
  1469. // Fall through...
  1470. //
  1471. case SubstituteDeepenSleep:
  1472. if (State == PowerSystemSleeping1 && !PopCapabilities.SystemS1) {
  1473. State = PowerSystemSleeping2;
  1474. }
  1475. if (State == PowerSystemSleeping2 && !PopCapabilities.SystemS2) {
  1476. State = PowerSystemSleeping3;
  1477. }
  1478. if (State == PowerSystemSleeping3 && !PopCapabilities.SystemS3) {
  1479. State = PowerSystemHibernate;
  1480. }
  1481. if (State == PowerSystemHibernate &&
  1482. (!HibernateAllowed ||
  1483. !PopCapabilities.SystemS4 ||
  1484. !PopCapabilities.HiberFilePresent)) {
  1485. // nothing good supported, disable it
  1486. State = PowerSystemWorking;
  1487. }
  1488. break;
  1489. default:
  1490. ExRaiseStatus (STATUS_INVALID_PARAMETER_2);
  1491. break;
  1492. }
  1493. *PowerState = State;
  1494. }
  1495. VOID
  1496. PopResetCurrentPolicies (
  1497. VOID
  1498. )
  1499. /*++
  1500. Routine Description:
  1501. Reads the current policies from the registry and applies them.
  1502. N.B. PopPolicyLock must be held.
  1503. Arguments:
  1504. None
  1505. Return Value:
  1506. None
  1507. --*/
  1508. {
  1509. HANDLE handle;
  1510. NTSTATUS Status;
  1511. PSYSTEM_POWER_POLICY RegPolicy;
  1512. UNICODE_STRING UnicodeString;
  1513. ULONG Length;
  1514. struct {
  1515. KEY_VALUE_PARTIAL_INFORMATION Inf;
  1516. union {
  1517. SYSTEM_POWER_POLICY PowerPolicy;
  1518. } Data;
  1519. } PartialInformation;
  1520. ASSERT_POLICY_LOCK_OWNED();
  1521. //
  1522. // Initialize & open registry
  1523. //
  1524. RegPolicy = (PSYSTEM_POWER_POLICY) PartialInformation.Inf.Data;
  1525. Status = PopOpenPowerKey (&handle);
  1526. if (!NT_SUCCESS(Status)) {
  1527. return ;
  1528. }
  1529. //
  1530. // Read AC policy and apply it
  1531. //
  1532. RtlInitUnicodeString (&UnicodeString, PopAcRegName);
  1533. Status = ZwQueryValueKey (
  1534. handle,
  1535. &UnicodeString,
  1536. KeyValuePartialInformation,
  1537. &PartialInformation,
  1538. sizeof (PartialInformation),
  1539. &Length
  1540. );
  1541. Length -= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  1542. if (!NT_SUCCESS(Status)) {
  1543. PopDefaultPolicy (RegPolicy);
  1544. Length = sizeof(SYSTEM_POWER_POLICY);
  1545. }
  1546. try {
  1547. PopApplyPolicy (FALSE, TRUE, RegPolicy, Length);
  1548. } except (EXCEPTION_EXECUTE_HANDLER) {
  1549. ASSERT (GetExceptionCode());
  1550. }
  1551. //
  1552. // Read DC policy and apply it
  1553. //
  1554. RtlInitUnicodeString (&UnicodeString, PopDcRegName);
  1555. Status = ZwQueryValueKey (
  1556. handle,
  1557. &UnicodeString,
  1558. KeyValuePartialInformation,
  1559. &PartialInformation,
  1560. sizeof (PartialInformation),
  1561. &Length
  1562. );
  1563. Length -= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  1564. if (!NT_SUCCESS(Status)) {
  1565. PopDefaultPolicy (RegPolicy);
  1566. Length = sizeof(SYSTEM_POWER_POLICY);
  1567. }
  1568. try {
  1569. PopApplyPolicy (FALSE, FALSE, RegPolicy, Length);
  1570. } except (EXCEPTION_EXECUTE_HANDLER) {
  1571. ASSERT (GetExceptionCode());
  1572. }
  1573. ZwClose (handle);
  1574. }
  1575. NTSTATUS
  1576. PopNotifyPolicyDevice (
  1577. IN PVOID Notification,
  1578. IN PVOID Context
  1579. )
  1580. /*++
  1581. Routine Description:
  1582. This function is the notinficant handle for when a new
  1583. policy device appears.
  1584. Arguments:
  1585. Notification - PnP notification
  1586. Context - Context registered on notification
  1587. Return Value:
  1588. None
  1589. --*/
  1590. {
  1591. PDEVICE_INTERFACE_CHANGE_NOTIFICATION Change;
  1592. POP_POLICY_DEVICE_TYPE DeviceType;
  1593. HANDLE DriverHandle;
  1594. PDEVICE_OBJECT DeviceObject;
  1595. OBJECT_ATTRIBUTES ObjA;
  1596. IO_STATUS_BLOCK IOSB;
  1597. PIRP Irp;
  1598. PIO_STACK_LOCATION IrpSp;
  1599. PAGED_CODE();
  1600. Change = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION) Notification;
  1601. DeviceType = (POP_POLICY_DEVICE_TYPE) ((ULONG_PTR)Context);
  1602. //
  1603. // If it's not a device arrival, then we don't care
  1604. //
  1605. if (memcmp (&Change->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof (GUID))) {
  1606. return STATUS_SUCCESS;
  1607. }
  1608. PopAcquirePolicyLock ();
  1609. PopConnectToPolicyDevice (DeviceType, Change->SymbolicLinkName);
  1610. PopReleasePolicyLock (TRUE);
  1611. return STATUS_SUCCESS;
  1612. }
  1613. VOID
  1614. PopConnectToPolicyDevice (
  1615. IN POP_POLICY_DEVICE_TYPE DeviceType,
  1616. IN PUNICODE_STRING DriverName
  1617. )
  1618. /*++
  1619. Routine Description:
  1620. This function attempts to connect to the policy device specified.
  1621. If the device is opened, the devices status IRP is allocated and
  1622. sent to the device's IRP handler for initial dispatch.
  1623. Arguments:
  1624. DeviceType - Policy device type of device to connect
  1625. DeviceName - Device name to attempt to open
  1626. Return Value:
  1627. If the device is connected, the *PresetFlag is set to TRUE and
  1628. an initial IRP is queued for the IRP handler.
  1629. --*/
  1630. {
  1631. UNICODE_STRING UnicodeString;
  1632. HANDLE DriverHandle;
  1633. PDEVICE_OBJECT DeviceObject;
  1634. PFILE_OBJECT FileObject;
  1635. OBJECT_ATTRIBUTES ObjA;
  1636. IO_STATUS_BLOCK IOSB;
  1637. PIRP Irp;
  1638. PIO_STACK_LOCATION IrpSp;
  1639. PVOID Context;
  1640. POP_IRP_HANDLER IrpHandler;
  1641. PPOP_SWITCH_DEVICE SwitchDevice;
  1642. PPOP_THERMAL_ZONE ThermalZone;
  1643. NTSTATUS Status;
  1644. PAGED_CODE();
  1645. ASSERT_POLICY_LOCK_OWNED();
  1646. Irp = NULL;
  1647. //
  1648. // If this is a new battery, then handle the composite battery device is
  1649. // the device to open
  1650. //
  1651. if (DeviceType == PolicyDeviceBattery) {
  1652. //
  1653. // If the composite battery is already opened, kick the irp handler
  1654. //
  1655. if (PopCB.StatusIrp) {
  1656. // Don't need to kick the IRP handler. When a new battery is added,
  1657. // the battery tag for the composite battery will change, causing
  1658. // the irp to complete.
  1659. PoPrint(PO_WARN, ("PopConnectToPolicyDevice: Battery already connected - not done\n"));
  1660. return ;
  1661. }
  1662. //
  1663. // Try to open the composite battery now
  1664. //
  1665. RtlInitUnicodeString(&UnicodeString, PopCompositeBatteryName);
  1666. DriverName = &UnicodeString;
  1667. }
  1668. //
  1669. // Open the device
  1670. //
  1671. InitializeObjectAttributes(
  1672. &ObjA,
  1673. DriverName,
  1674. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  1675. 0,
  1676. 0
  1677. );
  1678. Status = ZwOpenFile(
  1679. &DriverHandle,
  1680. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  1681. &ObjA, // Object
  1682. &IOSB, // io status block
  1683. FILE_SHARE_READ | FILE_SHARE_WRITE, // share access
  1684. FILE_SYNCHRONOUS_IO_ALERT // open options
  1685. );
  1686. if (!NT_SUCCESS(Status)) {
  1687. PoPrint(PO_WARN, ("PopConnectToPolicyDevice: Device open failed\n"));
  1688. goto Done;
  1689. }
  1690. //
  1691. // Get a pointer to the device object
  1692. //
  1693. Status = ObReferenceObjectByHandle(
  1694. DriverHandle,
  1695. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, // desired access
  1696. NULL,
  1697. KernelMode,
  1698. &FileObject,
  1699. NULL
  1700. );
  1701. ASSERT (NT_SUCCESS(Status));
  1702. DeviceObject = IoGetAttachedDeviceReference(FileObject->DeviceObject);
  1703. ObDereferenceObject(FileObject);
  1704. ZwClose(DriverHandle);
  1705. //
  1706. // Get an IRP for the device
  1707. //
  1708. Irp = IoAllocateIrp ((CCHAR) (DeviceObject->StackSize + 1), FALSE);
  1709. if (!Irp) {
  1710. ObDereferenceObject(DeviceObject);
  1711. goto Done;
  1712. }
  1713. IrpSp = IoGetNextIrpStackLocation(Irp);
  1714. //
  1715. // Setup based on device type
  1716. //
  1717. Context = NULL;
  1718. IrpHandler = NULL;
  1719. switch (DeviceType) {
  1720. case PolicyDeviceSystemButton:
  1721. SwitchDevice = ExAllocatePoolWithTag(
  1722. NonPagedPool,
  1723. sizeof (*SwitchDevice),
  1724. POP_PSWT_TAG
  1725. );
  1726. if (!SwitchDevice) {
  1727. goto Done;
  1728. }
  1729. RtlZeroMemory (SwitchDevice, sizeof(*SwitchDevice));
  1730. SwitchDevice->IsInitializing = TRUE;
  1731. SwitchDevice->Opened = TRUE;
  1732. InsertTailList (&PopSwitches, &SwitchDevice->Link);
  1733. IrpHandler = PopSystemButtonHandler;
  1734. Context = SwitchDevice;
  1735. break;
  1736. case PolicyDeviceBattery:
  1737. //
  1738. // Loading up the composite battery - status irp is NULL.
  1739. //
  1740. PopSetCapability (&PopCapabilities.SystemBatteriesPresent);
  1741. IrpHandler = PopCompositeBatteryDeviceHandler;
  1742. PopCB.StatusIrp = Irp;
  1743. break;
  1744. case PolicyDeviceThermalZone:
  1745. //
  1746. // New thermal zone
  1747. //
  1748. ThermalZone = ExAllocatePoolWithTag (
  1749. NonPagedPool,
  1750. sizeof (*ThermalZone),
  1751. POP_THRM_TAG
  1752. );
  1753. if (!ThermalZone) {
  1754. goto Done;
  1755. }
  1756. //
  1757. // Initialize thermal zone structure
  1758. //
  1759. RtlZeroMemory(
  1760. ThermalZone,
  1761. sizeof(POP_THERMAL_ZONE)
  1762. );
  1763. KeInitializeTimer(&ThermalZone->PassiveTimer);
  1764. KeInitializeDpc(
  1765. &ThermalZone->PassiveDpc,
  1766. PopThermalZoneDpc,
  1767. ThermalZone
  1768. );
  1769. ThermalZone->Mode = PO_TZ_INVALID_MODE;
  1770. ThermalZone->ActivePoint = (UCHAR) -1;
  1771. ThermalZone->PendingActivePoint = (UCHAR) -1;
  1772. ThermalZone->Throttle = PO_TZ_NO_THROTTLE;
  1773. ThermalZone->OverThrottled.Type = PolicyDeviceThermalZone;
  1774. ThermalZone->OverThrottled.Flags = PO_TRG_SET;
  1775. ThermalZone->Irp = Irp;
  1776. //
  1777. // Setup the capabilities of the thermal zones and get ready to
  1778. // ask the thermal zone about itself...
  1779. //
  1780. PopSetCapability (&PopCapabilities.ThermalControl);
  1781. Context = ThermalZone;
  1782. IrpHandler = PopThermalDeviceHandler;
  1783. //
  1784. // Finally, add the thermal zone to the list of thermal zones
  1785. //
  1786. ExInterlockedInsertTailList(
  1787. &PopThermal,
  1788. &ThermalZone->Link,
  1789. &PopThermalLock
  1790. );
  1791. break;
  1792. default:
  1793. PopInternalError (POP_INFO);
  1794. }
  1795. //
  1796. // Fill in values for IrpHandler dispatch
  1797. //
  1798. IrpSp->Parameters.Others.Argument1 = (PVOID) DeviceObject;
  1799. IrpSp->Parameters.Others.Argument2 = (PVOID) Context;
  1800. IrpSp->Parameters.Others.Argument3 = (PVOID) IrpHandler;
  1801. IoSetNextIrpStackLocation (Irp);
  1802. //
  1803. // Fill in error to irp so irp handler will re-dispatch it
  1804. //
  1805. IrpSp = IoGetNextIrpStackLocation(Irp);
  1806. Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
  1807. IrpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  1808. IrpSp->Parameters.DeviceIoControl.IoControlCode = 0;
  1809. IrpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
  1810. IrpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
  1811. //
  1812. // Give irp to the completion handler which will dispatch it
  1813. //
  1814. PopCompletePolicyIrp (DeviceObject, Irp, Context);
  1815. Irp = NULL;
  1816. Done:
  1817. if (Irp) {
  1818. ObDereferenceObject( DeviceObject );
  1819. IoFreeIrp (Irp);
  1820. }
  1821. }
  1822. POWER_ACTION
  1823. PopMapInternalActionToIrpAction (
  1824. IN POWER_ACTION Action,
  1825. IN SYSTEM_POWER_STATE SystemPowerState,
  1826. IN BOOLEAN UnmapWarmEject
  1827. )
  1828. /*++
  1829. Routine Description:
  1830. This function maps an internal action and power state to the appropriate
  1831. PowerAction a driver should see in it's S-IRP.
  1832. Arguments:
  1833. Action - The action we are using internally
  1834. SystemPowerState - The system power state for that action
  1835. UnmapWarmEject - If TRUE, PowerActionWarmEject is converted to
  1836. PowerActionSleep or PowerActionHibernate as appropriate.
  1837. Return Value:
  1838. The appropriate PowerAction to place in the ShutdownType field of an S-IRP.
  1839. --*/
  1840. {
  1841. ASSERT( Action != PowerActionHibernate );
  1842. if (Action != PowerActionWarmEject) {
  1843. //
  1844. // We aren't doing a warm eject, so we simply return the original
  1845. // power action unless it's the sleep is S4, in which case we switch
  1846. // it to PowerActionHibernate.
  1847. //
  1848. return (SystemPowerState != PowerSystemHibernate) ? Action :
  1849. PowerActionHibernate;
  1850. }
  1851. if (UnmapWarmEject) {
  1852. //
  1853. // This is a warm eject operation, but not neccessarily for this device.
  1854. //
  1855. return (SystemPowerState != PowerSystemHibernate) ? PowerActionSleep :
  1856. PowerActionHibernate;
  1857. }
  1858. //
  1859. // This is a warm eject operation, so we should only see a sleep state
  1860. // (S1-S4). We do the check here because we could get a D0 request in
  1861. // response to our S IRP, and stamp D-IRPs with the current power action.
  1862. //
  1863. ASSERT((SystemPowerState >= PowerSystemSleeping1) &&
  1864. (SystemPowerState <= PowerSystemHibernate)) ;
  1865. return PowerActionWarmEject;
  1866. }
  1867. VOID
  1868. PopFilterCapabilities(
  1869. IN PSYSTEM_POWER_CAPABILITIES SourceCapabilities,
  1870. OUT PSYSTEM_POWER_CAPABILITIES FilteredCapabilities
  1871. )
  1872. /*++
  1873. Routine Description:
  1874. This routine filters the actual reported capabilities of the system into
  1875. the visible capabilities of the system. Some capabilities will be hidden
  1876. based on the presence of legacy drivers.
  1877. Arguments:
  1878. SourceCapabilities - Supplies the original capabilities
  1879. FilteredCapabilities - Returns the filtered capabilities.
  1880. Return Value:
  1881. None.
  1882. --*/
  1883. {
  1884. NTSTATUS Status;
  1885. PNP_VETO_TYPE VetoType;
  1886. PWSTR VetoList;
  1887. PAGED_CODE();
  1888. RtlCopyMemory(FilteredCapabilities, SourceCapabilities, sizeof(SYSTEM_POWER_CAPABILITIES));
  1889. //
  1890. // If any legacy drivers are installed, then no sleeping states
  1891. // are allowed at all.
  1892. //
  1893. Status = IoGetLegacyVetoList(&VetoList, &VetoType);
  1894. if (NT_SUCCESS(Status)) {
  1895. if (VetoType != PNP_VetoTypeUnknown) {
  1896. PoPrint(PO_WARN,
  1897. ("PopFilterCapabilities: disabling sleep states due to legacy %s: %ws\n",
  1898. (VetoType == PNP_VetoLegacyDriver) ? "driver" : "device",
  1899. VetoList));
  1900. FilteredCapabilities->SystemS1 = FALSE;
  1901. FilteredCapabilities->SystemS2 = FALSE;
  1902. FilteredCapabilities->SystemS3 = FALSE;
  1903. FilteredCapabilities->SystemS4 = FALSE;
  1904. }
  1905. if (VetoList != NULL) {
  1906. ExFreePool(VetoList);
  1907. }
  1908. }
  1909. //
  1910. // If we previously tried and failed to hibernate, then we need to
  1911. // disable any further attempts.
  1912. //
  1913. if( PopFailedHibernationAttempt ) {
  1914. FilteredCapabilities->SystemS4 = FALSE;
  1915. }
  1916. //
  1917. // If we are running in x86 PAE mode, then hibernation is disabled
  1918. //
  1919. #if defined(i386)
  1920. if (SharedUserData->ProcessorFeatures[PF_PAE_ENABLED]) {
  1921. FilteredCapabilities->SystemS4 = FALSE;
  1922. }
  1923. #endif
  1924. }
  1925. BOOLEAN
  1926. PopUserIsAdmin(
  1927. VOID
  1928. )
  1929. /*++
  1930. Routine Description:
  1931. Determines whether the current user is an administrator and therefore suitably
  1932. privileged to change the administrative power policy.
  1933. Arguments:
  1934. None
  1935. Return Value:
  1936. TRUE - user is an administrator
  1937. FALSE - user is not an administrator
  1938. --*/
  1939. {
  1940. SECURITY_SUBJECT_CONTEXT SubjectContext;
  1941. PACCESS_TOKEN Token;
  1942. BOOLEAN IsAdmin;
  1943. PAGED_CODE();
  1944. SeCaptureSubjectContext(&SubjectContext);
  1945. SeLockSubjectContext(&SubjectContext);
  1946. Token = SeQuerySubjectContextToken(&SubjectContext);
  1947. IsAdmin = SeTokenIsAdmin(Token);
  1948. SeUnlockSubjectContext(&SubjectContext);
  1949. SeReleaseSubjectContext(&SubjectContext);
  1950. return(IsAdmin);
  1951. }