1 use std::io;
2 use std::ptr;
3 use widestring::WideCString;
4 use winapi::shared::winerror::WAIT_TIMEOUT;
5 use winapi::um::handleapi::CloseHandle;
6 use winapi::um::synchapi::{CreateMutexW, ReleaseMutex, WaitForSingleObject};
7 use winapi::um::winbase::{INFINITE, WAIT_ABANDONED, WAIT_OBJECT_0};
8 use winapi::um::winnt::HANDLE;
9 
10 use crate::error::*;
11 
12 #[derive(Debug)]
13 pub(crate) struct RawNamedLock {
14     handle: HANDLE,
15 }
16 
17 unsafe impl Sync for RawNamedLock {}
18 unsafe impl Send for RawNamedLock {}
19 
20 impl RawNamedLock {
create(name: &str) -> Result<RawNamedLock>21     pub(crate) fn create(name: &str) -> Result<RawNamedLock> {
22         let name = WideCString::from_str(name).unwrap();
23         let handle = unsafe { CreateMutexW(ptr::null_mut(), 0, name.as_ptr()) };
24 
25         if handle.is_null() {
26             Err(Error::CreateFailed(io::Error::last_os_error()))
27         } else {
28             Ok(RawNamedLock {
29                 handle,
30             })
31         }
32     }
33 
try_lock(&self) -> Result<()>34     pub(crate) fn try_lock(&self) -> Result<()> {
35         let rc = unsafe { WaitForSingleObject(self.handle, 0) };
36 
37         if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED {
38             Ok(())
39         } else if rc == WAIT_TIMEOUT {
40             Err(Error::WouldBlock)
41         } else {
42             Err(Error::LockFailed)
43         }
44     }
45 
lock(&self) -> Result<()>46     pub(crate) fn lock(&self) -> Result<()> {
47         let rc = unsafe { WaitForSingleObject(self.handle, INFINITE) };
48 
49         if rc == WAIT_OBJECT_0 || rc == WAIT_ABANDONED {
50             Ok(())
51         } else {
52             Err(Error::LockFailed)
53         }
54     }
55 
unlock(&self) -> Result<()>56     pub(crate) fn unlock(&self) -> Result<()> {
57         let rc = unsafe { ReleaseMutex(self.handle) };
58 
59         if rc == 0 {
60             Err(Error::UnlockFailed)
61         } else {
62             Ok(())
63         }
64     }
65 }
66 
67 impl Drop for RawNamedLock {
drop(&mut self)68     fn drop(&mut self) {
69         unsafe {
70             CloseHandle(self.handle);
71         }
72     }
73 }
74