use std::io;
use windows::{
Win32::{
Foundation::{CloseHandle, HANDLE, WAIT_ABANDONED, WAIT_OBJECT_0},
System::Threading::{CreateMutexW, INFINITE, ReleaseMutex, WaitForSingleObject},
},
core::{HSTRING, PCWSTR},
};
const MUTEX_NAME: &str = r"Local\windows-env-registry-lock";
pub struct NamedMutexGuard(HANDLE);
pub fn lock() -> io::Result<NamedMutexGuard> {
let name = HSTRING::from(MUTEX_NAME);
unsafe {
let handle = CreateMutexW(None, false, PCWSTR(name.as_ptr()))
.map_err(|e| io::Error::from_raw_os_error(e.code().0))?;
match WaitForSingleObject(handle, INFINITE) {
WAIT_OBJECT_0 | WAIT_ABANDONED => Ok(NamedMutexGuard(handle)),
other => {
let _ = CloseHandle(handle);
Err(io::Error::other(format!(
"WaitForSingleObject returned {other:?}"
)))
},
}
}
}
impl Drop for NamedMutexGuard {
fn drop(&mut self) {
unsafe {
let _ = ReleaseMutex(self.0);
let _ = CloseHandle(self.0);
}
}
}