Hook with Winapi

I have read the Rust Book and played a little.
Now I want to try to hook Microsoft Windows, application activation events with Winapi.
I’ve not found any examples of how to do it, but have the following code compiling:

Cargo.toml

[target.'cfg(target_os = "windows")'.dependencies.winapi]
version = "0.3.7"
features = [
    "winuser",
]

main.rs

use std::io;
use winapi::um::winuser::SetWindowsHookExA;
use winapi::um::winuser::UnhookWindowsHookEx;
use winapi::um::winuser::WH_CBT;
use winapi::um::winuser::HCBT_ACTIVATE;

fn main() {

    let hook_id = unsafe {
        SetWindowsHookExA(WH_CBT, Some(hook_callback), std::ptr::null_mut(), 0)
    };

    println!("hook_id: {:?}", hook_id);

    println!("Type \"exit\" to exit");
    loop {
        let mut command = String::new();

        io::stdin()
            .read_line(&mut command)
            .expect("Failed to read line");

        match command.trim() {
            "exit" => break,
            _ => println!("Type \"exit\" to exit"),
        };

    }

    unsafe {
        UnhookWindowsHookEx(hook_id);
    }
}

extern "system" fn hook_callback(code: i32, w_param: usize, l_param: isize) -> isize {
    println!("hook_callback {}, {}, {}", code, w_param, l_param);
    if code == HCBT_ACTIVATE {
        println!("Activate");
    }
    0
}

It runs, but the hook_id is 0x0 which seems wrong, and the hook_callback never fires.
Can anybody spot the problem?

Looking at the documentation for SetWindowsHookExA, my guess is you need to first get the current thread id unless you’re in the dll.

For that you can use GetCurrentThreadId. You’ll also need processthreadsapi added to features.