interprocess_docfix/os/windows/
unnamed_pipe.rs1use super::imports::*;
10use super::FileHandleOps;
11use crate::unnamed_pipe::{UnnamedPipeReader as PubReader, UnnamedPipeWriter as PubWriter};
12use std::{
13 fmt::{self, Debug, Formatter},
14 io::{self, Read, Write},
15 mem::{size_of, zeroed, ManuallyDrop},
16 num::NonZeroUsize,
17 ptr,
18};
19
20#[non_exhaustive]
26#[derive(Copy, Clone, Debug)]
27pub struct UnnamedPipeCreationOptions {
28 pub inheritable: bool,
32 pub security_descriptor: LPVOID,
36 pub buffer_size_hint: Option<NonZeroUsize>,
38}
39impl UnnamedPipeCreationOptions {
40 pub const fn new() -> Self {
42 Self {
43 inheritable: true,
44 security_descriptor: ptr::null_mut(),
45 buffer_size_hint: None,
46 }
47 }
48 #[must_use = "this is not an in-place operation"]
54 pub fn inheritable(mut self, inheritable: bool) -> Self {
55 self.inheritable = inheritable;
56 self
57 }
58 #[must_use = "this is not an in-place operation"]
64 pub fn security_descriptor(mut self, security_descriptor: LPVOID) -> Self {
65 self.security_descriptor = security_descriptor;
66 self
67 }
68 #[must_use = "this is not an in-place operation"]
74 pub fn buffer_size_hint(mut self, buffer_size_hint: Option<NonZeroUsize>) -> Self {
75 self.buffer_size_hint = buffer_size_hint;
76 self
77 }
78
79 pub fn extract_security_attributes(self) -> SECURITY_ATTRIBUTES {
83 let mut security_attributes = unsafe { zeroed::<SECURITY_ATTRIBUTES>() };
85 security_attributes.nLength = size_of::<SECURITY_ATTRIBUTES>() as u32;
86 security_attributes.lpSecurityDescriptor = self.security_descriptor;
87 security_attributes.bInheritHandle = self.inheritable as i32;
88 security_attributes
89 }
90
91 pub unsafe fn build(self) -> io::Result<(PubWriter, PubReader)> {
99 let hint_raw = match self.buffer_size_hint {
100 Some(num) => num.get(),
101 None => 0,
102 } as u32;
103 let [mut writer, mut reader] = [INVALID_HANDLE_VALUE; 2];
104 let success = unsafe {
105 CreatePipe(
106 &mut reader as *mut _,
107 &mut writer as *mut _,
108 &mut self.extract_security_attributes() as *mut _,
109 hint_raw,
110 )
111 } != 0;
112 if success {
113 let (writer, reader) = unsafe {
114 let writer = PubWriter {
116 inner: UnnamedPipeWriter::from_raw_handle(writer),
117 };
118 let reader = PubReader {
119 inner: UnnamedPipeReader::from_raw_handle(reader),
120 };
121 (writer, reader)
122 };
123 Ok((writer, reader))
124 } else {
125 Err(io::Error::last_os_error())
126 }
127 }
128}
129impl Default for UnnamedPipeCreationOptions {
130 fn default() -> Self {
131 Self::new()
132 }
133}
134unsafe impl Send for UnnamedPipeCreationOptions {}
135unsafe impl Sync for UnnamedPipeCreationOptions {}
136
137pub(crate) fn pipe() -> io::Result<(PubWriter, PubReader)> {
138 unsafe { UnnamedPipeCreationOptions::default().build() }
139}
140
141pub(crate) struct UnnamedPipeReader(FileHandleOps);
142impl Read for UnnamedPipeReader {
143 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
144 self.0.read(buf)
145 }
146}
147#[cfg(windows)]
148impl AsRawHandle for UnnamedPipeReader {
149 fn as_raw_handle(&self) -> HANDLE {
150 self.0.as_raw_handle()
151 }
152}
153#[cfg(windows)]
154impl IntoRawHandle for UnnamedPipeReader {
155 fn into_raw_handle(self) -> HANDLE {
156 let self_ = ManuallyDrop::new(self);
157 self_.as_raw_handle()
158 }
159}
160#[cfg(windows)]
161impl FromRawHandle for UnnamedPipeReader {
162 unsafe fn from_raw_handle(handle: HANDLE) -> Self {
163 let fho = unsafe {
164 FileHandleOps::from_raw_handle(handle)
166 };
167 Self(fho)
168 }
169}
170impl Debug for UnnamedPipeReader {
171 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
172 f.debug_struct("UnnamedPipeReader")
173 .field("handle", &self.as_raw_handle())
174 .finish()
175 }
176}
177
178pub(crate) struct UnnamedPipeWriter(FileHandleOps);
179impl Write for UnnamedPipeWriter {
180 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
181 self.0.write(buf)
182 }
183 fn flush(&mut self) -> io::Result<()> {
184 self.0.flush()
185 }
186}
187#[cfg(windows)]
188impl AsRawHandle for UnnamedPipeWriter {
189 fn as_raw_handle(&self) -> HANDLE {
190 self.0.as_raw_handle()
191 }
192}
193#[cfg(windows)]
194impl IntoRawHandle for UnnamedPipeWriter {
195 fn into_raw_handle(self) -> HANDLE {
196 let self_ = ManuallyDrop::new(self);
197 self_.as_raw_handle()
198 }
199}
200#[cfg(windows)]
201impl FromRawHandle for UnnamedPipeWriter {
202 unsafe fn from_raw_handle(handle: HANDLE) -> Self {
203 Self(FileHandleOps(handle))
204 }
205}
206impl Debug for UnnamedPipeWriter {
207 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
208 f.debug_struct("UnnamedPipeWriter")
209 .field("handle", &self.as_raw_handle())
210 .finish()
211 }
212}