2 extern crate windows_service
;
9 atomic
::{AtomicBool
, Ordering
},
13 time
::{self, Duration
},
16 use windows
::Win32
::Foundation
::{ERROR_SERVICE_DOES_NOT_EXIST
, WIN32_ERROR
};
17 use windows_service
::{
19 ServiceAccess
, ServiceControl
, ServiceControlAccept
, ServiceErrorControl
, ServiceExitCode
,
20 ServiceInfo
, ServiceStartType
, ServiceState
, ServiceStatus
, ServiceType
,
22 service_control_handler
::{self, ServiceControlHandlerResult
, ServiceStatusHandle
},
24 service_manager
::{ServiceManager
, ServiceManagerAccess
},
26 use wmi
::{COMLibrary
, Variant
, WMIConnection
};
30 define_windows_service!(ffi_service_main
, service_main
);
33 #![allow(warnings, unused)]
34 include!(concat!(env!("OUT_DIR"), "/ols_api.rs"));
38 #![allow(warnings, unused)]
39 include!(concat!(env!("OUT_DIR"), "/intel_arc.rs"));
48 mod corsair_vengeance
;
51 // mod roccat; Disabled.
56 fn main() -> Result
<(), windows_service
::Error
> {
57 let args
: Vec
<String
> = env
::args().collect();
59 println!("Temperature to RGB");
61 if args
.contains(&"--no-service".to_string()) {
62 let completed
: Arc
<AtomicBool
> = Arc
::new(AtomicBool
::new(false));
63 main_loop
::main_loop(completed
.clone());
64 } else if args
.contains(&"--tests".to_string()) {
66 } else if args
.contains(&"--install-service".to_string()) {
67 println!("Installing service...");
69 } else if args
.contains(&"--uninstall-service".to_string()) {
70 println!("Uninstalling service...");
73 service_dispatcher
::start(consts
::SERVICE_NAME
, ffi_service_main
)?
;
79 fn install_service() -> windows_service
::Result
<()> {
80 let manager_access
= ServiceManagerAccess
::CONNECT
| ServiceManagerAccess
::CREATE_SERVICE
;
81 let service_manager
= ServiceManager
::local_computer(None
::<&str>, manager_access
)?
;
83 let service_binary_path
= std
::env
::current_exe()
85 .with_file_name("temp_2_rgb.exe");
87 println!("Installing service: {service_binary_path:?}");
89 let service_info
= ServiceInfo
{
90 name
: OsString
::from(consts
::SERVICE_NAME
),
91 display_name
: OsString
::from(consts
::SERVICE_NAME
),
92 service_type
: ServiceType
::OWN_PROCESS
,
93 start_type
: ServiceStartType
::AutoStart
,
94 error_control
: ServiceErrorControl
::Normal
,
95 executable_path
: service_binary_path
,
96 launch_arguments
: vec
![],
98 account_name
: None
, // run as System
99 account_password
: None
,
101 let service
= service_manager
.create_service(&service_info
, ServiceAccess
::CHANGE_CONFIG
)?
;
102 service
.set_description(
103 "A service to set the color of hardware according to the temperatur of GPU and CPU",
108 fn uninstall_service() -> windows_service
::Result
<()> {
109 let manager_access
= ServiceManagerAccess
::CONNECT
;
110 let service_manager
= ServiceManager
::local_computer(None
::<&str>, manager_access
)?
;
112 let service_access
= ServiceAccess
::QUERY_STATUS
| ServiceAccess
::STOP
| ServiceAccess
::DELETE
;
113 let service
= service_manager
.open_service(consts
::SERVICE_NAME
, service_access
)?
;
115 // The service will be marked for deletion as long as this function call succeeds.
116 // However, it will not be deleted from the database until it is stopped and all open handles to it are closed.
119 // Our handle to it is not closed yet. So we can still query it.
120 if service
.query_status()?
.current_state
!= ServiceState
::Stopped
{
121 // If the service cannot be stopped, it will be deleted when the system restarts.
125 // Explicitly close our open handle to the service. This is automatically called when `service` goes out of scope.
128 // Win32 API does not give us a way to wait for service deletion.
129 // To check if the service is deleted from the database, we have to poll it ourselves.
130 let start
= time
::Instant
::now();
131 let timeout
= Duration
::from_secs(5);
132 while start
.elapsed() < timeout
{
133 if let Err(windows_service
::Error
::Winapi(e
)) =
134 service_manager
.open_service(consts
::SERVICE_NAME
, ServiceAccess
::QUERY_STATUS
)
136 let WIN32_ERROR(error_num
) = ERROR_SERVICE_DOES_NOT_EXIST
;
137 if e
.raw_os_error() == Some(error_num
as i32) {
138 println!("{} is deleted.", consts
::SERVICE_NAME
);
142 sleep(Duration
::from_secs(1));
144 println!("{} is marked for deletion.", consts
::SERVICE_NAME
);
149 fn service_main(arguments
: Vec
<OsString
>) {
150 if let Err(error
) = run_service(arguments
) {
151 println!("Error: {error}");
155 fn run_service(arguments
: Vec
<OsString
>) -> Result
<(), windows_service
::Error
> {
156 let completed
: Arc
<AtomicBool
> = Arc
::new(AtomicBool
::new(false));
158 let completed_event_handler
= Arc
::clone(&completed
);
159 let event_handler
= move |control_event
| -> ServiceControlHandlerResult
{
160 match control_event
{
161 ServiceControl
::Stop
=> {
162 completed_event_handler
.store(true, Ordering
::Relaxed
);
163 // Handle stop event and return control back to the system.
164 ServiceControlHandlerResult
::NoError
166 // ServiceControl::Shutdown => {
167 // completed_event_handler.store(true, Ordering::Relaxed);
168 // // Handle stop event and return control back to the system.
169 // ServiceControlHandlerResult::NoError
171 // ServiceControl::Preshutdown => {
172 // completed_event_handler.store(true, Ordering::Relaxed);
173 // ServiceControlHandlerResult::NoError
175 // ServiceControl::PowerEvent(param) => {
176 // ServiceControlHandlerResult::NotImplemented
178 // All services must accept Interrogate even if it's a no-op.
179 ServiceControl
::Interrogate
=> ServiceControlHandlerResult
::NoError
,
180 _
=> ServiceControlHandlerResult
::NotImplemented
,
184 // Register system service event handler
185 let status_handle
= service_control_handler
::register(consts
::SERVICE_NAME
, event_handler
)?
;
187 let running_status
= ServiceStatus
{
188 // Should match the one from system service registry
189 service_type
: ServiceType
::OWN_PROCESS
,
192 current_state
: ServiceState
::Running
,
194 // Accept stop events when running
195 controls_accepted
: ServiceControlAccept
::STOP
, // | ServiceControlAccept::SHUTDOWN,
197 // Used to report an error when starting or stopping only, otherwise must be zero
198 exit_code
: ServiceExitCode
::Win32(0),
200 // Only used for pending states, otherwise must be zero
203 // Only used for pending states, otherwise must be zero
204 wait_hint
: Duration
::default(),
209 status_handle
.set_service_status(running_status
)?
;
211 main_loop
::main_loop(completed
.clone());
213 status_handle
.set_service_status(ServiceStatus
{
214 service_type
: ServiceType
::OWN_PROCESS
,
215 current_state
: ServiceState
::Stopped
,
216 controls_accepted
: ServiceControlAccept
::empty(),
217 exit_code
: ServiceExitCode
::Win32(0),
219 wait_hint
: Duration
::default(),
227 println!("Running some tests...");
230 // list_usb_devices();
237 println!("Press any key to continue...");
238 std
::io
::stdin().read_line(&mut String
::new()).unwrap();
242 let com_con
= COMLibrary
::new().unwrap();
243 let wmi_con
= WMIConnection
::new(com_con
.into()).unwrap();
245 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE '%SMBUS%' OR Description LIKE '%SM BUS%'").unwrap();
246 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPSignedDriver WHERE Description LIKE 'Intel(R) NF I2C Host Controller'").unwrap();
247 let results
: Vec
<HashMap
<String
, Variant
>> = wmi_con
248 .raw_query("SELECT * FROM Win32_PnPSignedDriver")
250 //let results: Vec<HashMap<String, Variant>> = wmi_con.raw_query("SELECT * FROM Win32_PnPAllocatedResource").unwrap();
253 println!("-------------------");
254 println!("{:#?}", os
);
257 fn list_usb_devices() {
258 let api
= hidapi
::HidApi
::new().unwrap();
259 for device
in api
.device_list() {
260 println!("{:?}", device
);
261 println!("name: {}", device
.product_string().unwrap());
262 println!("interface number: {}", device
.interface_number());
263 println!("page: {}", device
.usage_page());
264 println!("usage: {}", device
.usage());
269 // fn test_roccat() {
270 // let api = hidapi::HidApi::new().unwrap();
271 // let roccat_device = roccat::get_device(&api);
273 // let manufacturer = roccat_device.get_manufacturer_string().unwrap();
274 // dbg!(manufacturer);
276 // let product = roccat_device.get_product_string().unwrap();
279 // let serial = roccat_device.get_serial_number_string().unwrap();
282 // roccat::init(&roccat_device);
283 // roccat::set_color(
294 let api
= hidapi
::HidApi
::new().unwrap();
296 let b650e_device
= b650_e
::get_device(&api
);
298 println!("Firmware: {}", b650_e
::get_firmware_string(&b650e_device
));
300 let configuration
= b650_e
::get_configuration_table(&b650e_device
);
301 println!("Configuration:");
303 print!("{:02X} ", configuration
[i
]);
304 if (i
+ 1) % 6 == 0 {
309 // Only once, at start.
310 b650_e
::set_fixed_mode(&b650e_device
);
320 b650_e
::save_current_color(&b650e_device
);
324 let corsair_controllers
= [
325 corsair_vengeance
::Controller
::new(0x19),
326 corsair_vengeance
::Controller
::new(0x1B),
328 for controller
in corsair_controllers
{
329 controller
.set_color(&RGB
{
338 // a770::set_rgb(255, 0, 0);
339 let mut a770
= a770
::A770
::new();
340 a770
.set_color(255, 0, 0);
343 fn test_read_temp() {
344 let sensors
= sensors_jiji
::Sensors
::new();
345 println!("temp cpu: {}", sensors
.read_cpu_temp());
346 println!("temp gpu: {}", sensors
.read_gpu_temp());