1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::{to_win_string, Error, MailslotName};
use std::{
fs::File,
io::Read,
os::windows::io::{AsRawHandle, FromRawHandle},
};
use winapi::um::{
handleapi::INVALID_HANDLE_VALUE,
winbase::{CreateMailslotW, GetMailslotInfo},
winnt::{MAILSLOT_NO_MESSAGE, MAILSLOT_WAIT_FOREVER},
};
pub struct MailslotServer {
handle: File,
}
impl MailslotServer {
pub fn new(name: &MailslotName) -> Result<Self, Error> {
Ok(Self {
handle: make_mail_slot(&name.to_string())?,
})
}
pub fn get_next_unread(&mut self) -> Result<Option<Vec<u8>>, Error> {
if let Some(next_len) = self.get_next_length()? {
let mut buf = vec![0; next_len as _];
self.handle
.read_exact(&mut buf)
.expect("failed to read file");
Ok(Some(buf))
} else {
Ok(None)
}
}
pub(crate) fn get_next_length(&self) -> Result<Option<u32>, Error> {
let mut msg_size = 0;
let mut msg_count = 0;
let info = unsafe {
GetMailslotInfo(
self.handle.as_raw_handle() as _,
0 as _,
&mut msg_size,
&mut msg_count,
0 as _,
)
};
if info == 0 {
Err(Error::last_os_error())
} else if msg_size == MAILSLOT_NO_MESSAGE || msg_count == 0 {
Ok(None)
} else {
Ok(Some(msg_size))
}
}
}
pub fn make_mail_slot(name: &str) -> Result<File, Error> {
let name = to_win_string(name);
unsafe {
let slot = CreateMailslotW(name.as_ptr() as _, 0, MAILSLOT_WAIT_FOREVER, 0 as _);
if slot == INVALID_HANDLE_VALUE {
Err(Error::Io(::std::io::Error::last_os_error()))
} else {
Ok(std::fs::File::from_raw_handle(slot as _))
}
}
}