cli: implement --no-sleep for windows

This commit is contained in:
Connor Peet 2023-01-20 18:57:11 -08:00
parent c321a36929
commit 758bc69404
No known key found for this signature in database
GPG key ID: CF8FD2EA0DBC61BD
5 changed files with 87 additions and 1 deletions

1
cli/Cargo.lock generated
View file

@ -265,6 +265,7 @@ dependencies = [
"tunnels",
"url",
"uuid",
"winapi",
"windows-service",
"winreg",
"zbus 3.4.0",

View file

@ -58,6 +58,7 @@ serde_json = { version = "1.0" }
[target.'cfg(windows)'.dependencies]
windows-service = "0.5"
winreg = "0.10"
winapi = "0.3.9"
[target.'cfg(target_os = "linux")'.dependencies]
tar = { version = "0.4" }

View file

@ -14,6 +14,8 @@ mod name_generator;
mod nosleep;
#[cfg(target_os = "macos")]
mod nosleep_macos;
#[cfg(target_os = "windows")]
mod nosleep_windows;
mod port_forwarder;
mod protocol;
#[cfg_attr(unix, path = "tunnels/server_bridge_unix.rs")]

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
#[cfg(target_os = "windows")]
pub type SleepInhibitor = NoOpSleepInhibitor;
pub type SleepInhibitor = super::nosleep_windows::SleepInhibitor;
#[cfg(target_os = "linux")]
pub type SleepInhibitor = NoOpSleepInhibitor;

View file

@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
use std::io;
use const_format::concatcp;
use winapi::{
ctypes::c_void,
um::{
handleapi::CloseHandle,
minwinbase::REASON_CONTEXT,
winbase::{PowerClearRequest, PowerCreateRequest, PowerSetRequest},
winnt::{
PowerRequestSystemRequired, POWER_REQUEST_CONTEXT_SIMPLE_STRING,
POWER_REQUEST_CONTEXT_VERSION, POWER_REQUEST_TYPE,
},
},
};
use crate::constants::APPLICATION_NAME;
struct Request(*mut c_void);
impl Request {
pub fn new() -> io::Result<Self> {
let mut reason: Vec<u16> = concatcp!(APPLICATION_NAME, " running tunnel")
.encode_utf16()
.collect();
let mut context = REASON_CONTEXT {
Version: POWER_REQUEST_CONTEXT_VERSION,
Flags: POWER_REQUEST_CONTEXT_SIMPLE_STRING,
..Default::default()
};
unsafe { *context.Reason.SimpleReasonString_mut() = reason.as_mut_ptr() };
let request = unsafe { PowerCreateRequest(&mut context) };
if request.is_null() {
return Err(io::Error::last_os_error());
}
Ok(Self(request))
}
pub fn set(&self, request_type: POWER_REQUEST_TYPE) -> io::Result<()> {
let result = unsafe { PowerSetRequest(self.0, request_type) };
if result == 0 {
return Err(io::Error::last_os_error());
}
Ok(())
}
}
impl Drop for Request {
fn drop(&mut self) {
unsafe {
CloseHandle(self.0);
}
}
}
pub struct SleepInhibitor {
request: Request,
}
impl SleepInhibitor {
pub fn new() -> io::Result<Self> {
let request = Request::new()?;
request.set(PowerRequestSystemRequired)?;
Ok(Self { request })
}
}
impl Drop for SleepInhibitor {
fn drop(&mut self) {
unsafe {
PowerClearRequest(self.request.0, PowerRequestSystemRequired);
}
}
}