1use std::ffi::c_void;
2
3use crate::preset::{PROCESS_RESTORE, PROCESS_THROTTLE, PROCESS_UNTHROTTLE};
4use windows::Win32::{
5 Foundation::{CloseHandle, HANDLE},
6 System::Threading::{
7 GetProcessInformation, OpenProcess, ProcessPowerThrottling, SetPriorityClass,
8 SetProcessInformation, IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, PROCESS_CREATION_FLAGS,
9 PROCESS_INFORMATION_CLASS, PROCESS_POWER_THROTTLING_CURRENT_VERSION,
10 PROCESS_POWER_THROTTLING_EXECUTION_SPEED, PROCESS_POWER_THROTTLING_STATE,
11 PROCESS_SET_INFORMATION,
12 },
13};
14
15unsafe fn toggle_efficiency_mode_impl(
16 hprocess: HANDLE,
17 processinformation: *const c_void,
18 processinformationclass: PROCESS_INFORMATION_CLASS,
19 processinformationsize: u32,
20 dwpriorityclass: PROCESS_CREATION_FLAGS,
21) -> Result<(), windows_result::Error> {
22 unsafe {
23 SetProcessInformation(
24 hprocess,
25 processinformationclass,
26 processinformation,
27 processinformationsize,
28 )?;
29 SetPriorityClass(hprocess, dwpriorityclass)?;
30 }
31
32 Ok(())
33}
34
35pub fn toggle_efficiency_mode(pid: u32, enable: Option<bool>) -> Result<(), windows_result::Error> {
50 let hprocess = unsafe { OpenProcess(PROCESS_SET_INFORMATION, false, pid)? };
51 let result = unsafe { toggle_efficiency_mode_handle(hprocess, enable) };
52 let _ = unsafe { CloseHandle(hprocess) };
53
54 result
55}
56
57pub unsafe fn toggle_efficiency_mode_handle(
87 hprocess: HANDLE,
88 enable: Option<bool>,
89) -> Result<(), windows_result::Error> {
90 let new_state = match enable {
91 Some(true) => PROCESS_THROTTLE,
92 Some(false) => PROCESS_UNTHROTTLE,
93 None => PROCESS_RESTORE,
94 };
95
96 let processinformationclass = ProcessPowerThrottling;
97 let processinformation = &new_state as *const _ as *const c_void;
98 let processinformationsize = size_of::<PROCESS_POWER_THROTTLING_STATE>() as u32;
99
100 let dwpriorityclass = if let Some(true) = enable {
101 IDLE_PRIORITY_CLASS
102 } else {
103 NORMAL_PRIORITY_CLASS
104 };
105
106 unsafe {
107 toggle_efficiency_mode_impl(
108 hprocess,
109 processinformation,
110 processinformationclass,
111 processinformationsize,
112 dwpriorityclass,
113 )
114 }
115}
116
117pub unsafe fn ecoqos_enabled(hprocess: HANDLE) -> Result<bool, windows_result::Error> {
123 let mut process_info = PROCESS_POWER_THROTTLING_STATE {
124 Version: PROCESS_POWER_THROTTLING_CURRENT_VERSION,
125 ControlMask: 0,
126 StateMask: 0,
127 };
128
129 unsafe {
130 GetProcessInformation(
131 hprocess,
132 ProcessPowerThrottling,
133 &mut process_info as *mut _ as *mut _,
134 size_of::<PROCESS_POWER_THROTTLING_STATE>() as u32,
135 )?;
136 }
137
138 Ok(
139 process_info.StateMask & PROCESS_POWER_THROTTLING_EXECUTION_SPEED
140 == PROCESS_POWER_THROTTLING_EXECUTION_SPEED,
141 )
142}