Skip to main content

windows_erg/pipes/
anonymous.rs

1use std::io;
2
3use windows::Win32::Foundation::HANDLE;
4use windows::Win32::Storage::FileSystem::{ReadFile, WriteFile};
5use windows::Win32::System::Pipes::CreatePipe;
6
7use crate::utils::OwnedHandle;
8use crate::{Error, Result};
9
10use super::security_attrs::NativePipeSecurityAttributes;
11use super::types::PipeSecurityOptions;
12
13/// Builder for anonymous pipe configuration.
14#[derive(Debug, Clone)]
15pub struct AnonymousPipeBuilder {
16    buffer_size: u32,
17    security: PipeSecurityOptions,
18}
19
20impl AnonymousPipeBuilder {
21    /// Create a new anonymous pipe builder.
22    pub fn new() -> Self {
23        Self {
24            buffer_size: 4096,
25            security: PipeSecurityOptions::default(),
26        }
27    }
28
29    /// Set requested pipe buffer size.
30    pub fn buffer_size(mut self, buffer_size: u32) -> Self {
31        self.buffer_size = buffer_size;
32        self
33    }
34
35    /// Set security options.
36    pub fn security(mut self, security: PipeSecurityOptions) -> Self {
37        self.security = security;
38        self
39    }
40
41    /// Build anonymous pipe configuration.
42    pub fn build(self) -> AnonymousPipeConfig {
43        AnonymousPipeConfig {
44            buffer_size: self.buffer_size,
45            security: self.security,
46        }
47    }
48}
49
50impl Default for AnonymousPipeBuilder {
51    fn default() -> Self {
52        Self::new()
53    }
54}
55
56/// Anonymous pipe runtime configuration.
57#[derive(Debug, Clone)]
58pub struct AnonymousPipeConfig {
59    buffer_size: u32,
60    security: PipeSecurityOptions,
61}
62
63impl AnonymousPipeConfig {
64    /// Return configured buffer size.
65    pub fn buffer_size(&self) -> u32 {
66        self.buffer_size
67    }
68
69    /// Return configured security options.
70    pub fn security(&self) -> PipeSecurityOptions {
71        self.security.clone()
72    }
73
74    /// Create an anonymous pipe pair.
75    pub fn create(&self) -> Result<(AnonymousPipeReader, AnonymousPipeWriter)> {
76        let mut read_handle = HANDLE::default();
77        let mut write_handle = HANDLE::default();
78
79        let security_attributes =
80            NativePipeSecurityAttributes::from_options(&self.security, "<anonymous>")?;
81
82        unsafe {
83            CreatePipe(
84                &mut read_handle,
85                &mut write_handle,
86                security_attributes.as_option_ptr(),
87                self.buffer_size,
88            )
89        }
90        .map_err(|e| {
91            Error::Pipe(crate::error::PipeError::Create(
92                crate::error::PipeCreateError::with_code("<anonymous>", "create", e.code().0),
93            ))
94        })?;
95
96        Ok((
97            AnonymousPipeReader {
98                handle: OwnedHandle::new(read_handle),
99            },
100            AnonymousPipeWriter {
101                handle: OwnedHandle::new(write_handle),
102            },
103        ))
104    }
105}
106
107/// Read endpoint for an anonymous pipe.
108#[derive(Debug)]
109pub struct AnonymousPipeReader {
110    handle: OwnedHandle,
111}
112
113impl AnonymousPipeReader {
114    /// Return raw handle value.
115    pub fn raw_handle(&self) -> HANDLE {
116        self.handle.raw()
117    }
118}
119
120impl io::Read for AnonymousPipeReader {
121    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
122        let mut read = 0u32;
123        unsafe { ReadFile(self.handle.raw(), Some(buf), Some(&mut read), None) }
124            .map_err(|e| io::Error::from_raw_os_error(e.code().0))?;
125        Ok(read as usize)
126    }
127}
128
129/// Write endpoint for an anonymous pipe.
130#[derive(Debug)]
131pub struct AnonymousPipeWriter {
132    handle: OwnedHandle,
133}
134
135impl AnonymousPipeWriter {
136    /// Return raw handle value.
137    pub fn raw_handle(&self) -> HANDLE {
138        self.handle.raw()
139    }
140}
141
142impl io::Write for AnonymousPipeWriter {
143    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
144        let mut written = 0u32;
145        unsafe { WriteFile(self.handle.raw(), Some(buf), Some(&mut written), None) }
146            .map_err(|e| io::Error::from_raw_os_error(e.code().0))?;
147        Ok(written as usize)
148    }
149
150    fn flush(&mut self) -> io::Result<()> {
151        Ok(())
152    }
153}