Skip to content

Instantly share code, notes, and snippets.

@Ciantic
Created March 23, 2023 22:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ciantic/016c0410eba7ac30f310b47c71fc262e to your computer and use it in GitHub Desktop.
Save Ciantic/016c0410eba7ac30f310b47c71fc262e to your computer and use it in GitHub Desktop.
Just code I haven't used yet
use std::sync::mpsc::Sender;
use windows::{
core::Result,
s,
Win32::{
Foundation::{HANDLE, HWND, LPARAM, LRESULT, WPARAM},
System::{
LibraryLoader::GetModuleHandleA,
Power::{
RegisterPowerSettingNotification, UnregisterPowerSettingNotification,
POWERBROADCAST_SETTING,
},
SystemServices::{GUID_CONSOLE_DISPLAY_STATE, GUID_POWERSCHEME_PERSONALITY},
Threading::GetCurrentThreadId,
},
UI::WindowsAndMessaging::{
CallNextHookEx, CreateWindowExA, DefWindowProcA, DispatchMessageA, GetMessageA,
LoadCursorW, PostMessageA, PostQuitMessage, PostThreadMessageA, RegisterClassA,
SetWindowsHookExW, UnhookWindowsHookEx, CREATESTRUCTA, CS_HREDRAW, CS_VREDRAW,
CW_USEDEFAULT, IDC_ARROW, MSG, PBT_APMBATTERYLOW, PBT_APMOEMEVENT,
PBT_APMPOWERSTATUSCHANGE, PBT_APMQUERYSUSPEND, PBT_APMQUERYSUSPENDFAILED,
PBT_APMRESUMEAUTOMATIC, PBT_APMRESUMECRITICAL, PBT_APMRESUMESUSPEND, PBT_APMSUSPEND,
PBT_POWERSETTINGCHANGE, WH_CBT, WH_SHELL, WINDOW_EX_STYLE, WM_CLOSE, WM_CREATE,
WM_DESTROY, WM_POWERBROADCAST, WM_USER, WNDCLASSA, WS_OVERLAPPEDWINDOW,
},
},
};
#[derive(Debug)]
pub enum SetHookEvent {
TaskbarIsActivated,
}
static mut HOOK_SENDER: Option<Sender<SetHookEvent>> = None;
/// Create power events listener window, return type is function that will post
/// quit message to window stopping the thread.
pub fn create_hook_listener(
hhook_sender: Sender<SetHookEvent>,
) -> windows::core::Result<Box<impl FnOnce()>> {
let (thread_id_sender, thread_id_listener) = std::sync::mpsc::sync_channel(0);
let thrd = std::thread::spawn(move || unsafe {
let thread_id = GetCurrentThreadId();
let hhook = unsafe { SetWindowsHookExW(WH_CBT, Some(hookproc), None, 0).unwrap() };
thread_id_sender.send(thread_id).unwrap();
println!("HHOOK: {:?}", hhook);
let mut message = MSG::default();
while GetMessageA(&mut message, None, 0, 0).into() {
if message.message == WM_USER + 10 {
println!("Got quit");
PostQuitMessage(0);
}
DispatchMessageA(&message);
}
UnhookWindowsHookEx(hhook);
});
// Wait for thread to start
let thread_id = thread_id_listener.recv().unwrap();
unsafe {
HOOK_SENDER = Some(hhook_sender);
}
return Ok(Box::new(move || unsafe {
PostThreadMessageA(
thread_id,
WM_USER + 10,
WPARAM::default(),
LPARAM::default(),
);
thrd.join().unwrap();
}));
}
extern "system" fn hookproc(ncode: i32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
println!("HERE");
unsafe { CallNextHookEx(None, ncode, wparam, lparam) }
}
#[cfg(feature = "integration-tests")]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hhook() {
let (hhook_sender, hhook_receiver) = std::sync::mpsc::channel::<SetHookEvent>();
let stop_listening = create_hook_listener(hhook_sender).unwrap();
// Wait for keypress
let mut input = String::new();
println!("⛔ Press ENTER to exit...");
std::io::stdin().read_line(&mut input).unwrap();
stop_listening();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment