Skip to main content

std/os/windows/io/
raw.rs

1//! Windows-specific extensions to general I/O primitives.
2
3#![stable(feature = "rust1", since = "1.0.0")]
4
5use crate::macros::rustdoc_skip_body;
6#[cfg(doc)]
7use crate::os::windows::io::{AsHandle, AsSocket};
8use crate::os::windows::io::{OwnedHandle, OwnedSocket};
9use crate::os::windows::raw;
10use crate::sys::{AsInner, FromInner, IntoInner};
11use crate::{fs, io, net, ptr, sys};
12
13/// Raw HANDLEs.
14#[stable(feature = "rust1", since = "1.0.0")]
15pub type RawHandle = raw::HANDLE;
16
17/// Raw SOCKETs.
18#[stable(feature = "rust1", since = "1.0.0")]
19pub type RawSocket = raw::SOCKET;
20
21/// Extracts raw handles.
22#[stable(feature = "rust1", since = "1.0.0")]
23pub trait AsRawHandle {
24    /// Extracts the raw handle.
25    ///
26    /// This function is typically used to **borrow** an owned handle.
27    /// When used in this way, this method does **not** pass ownership of the
28    /// raw handle to the caller, and the handle is only guaranteed
29    /// to be valid while the original object has not yet been destroyed.
30    ///
31    /// This function may return null, such as when called on [`Stdin`],
32    /// [`Stdout`], or [`Stderr`] when the console is detached.
33    ///
34    /// However, borrowing is not strictly required. See [`AsHandle::as_handle`]
35    /// for an API which strictly borrows a handle.
36    ///
37    /// [`Stdin`]: io::Stdin
38    /// [`Stdout`]: io::Stdout
39    /// [`Stderr`]: io::Stderr
40    #[stable(feature = "rust1", since = "1.0.0")]
41    fn as_raw_handle(&self) -> RawHandle;
42}
43
44/// Constructs I/O objects from raw handles.
45#[stable(feature = "from_raw_os", since = "1.1.0")]
46pub trait FromRawHandle {
47    /// Constructs a new I/O object from the specified raw handle.
48    ///
49    /// This function is typically used to **consume ownership** of the handle
50    /// given, passing responsibility for closing the handle to the returned
51    /// object. When used in this way, the returned object
52    /// will take responsibility for closing it when the object goes out of
53    /// scope.
54    ///
55    /// However, consuming ownership is not strictly required. Use a
56    /// `From<OwnedHandle>::from` implementation for an API which strictly
57    /// consumes ownership.
58    ///
59    /// # Safety
60    ///
61    /// The `handle` passed in must:
62    ///   - be an [owned handle][io-safety]; in particular, it must be open.
63    ///   - be a handle for a resource that may be freed via [`CloseHandle`]
64    ///     (as opposed to `RegCloseKey` or other close functions).
65    ///
66    /// Note that the handle *may* have the value `INVALID_HANDLE_VALUE` (-1),
67    /// which is sometimes a valid handle value. See [here] for the full story.
68    ///
69    /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
70    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
71    /// [io-safety]: io#io-safety
72    #[stable(feature = "from_raw_os", since = "1.1.0")]
73    unsafe fn from_raw_handle(handle: RawHandle) -> Self;
74}
75
76/// A trait to express the ability to consume an object and acquire ownership of
77/// its raw `HANDLE`.
78#[stable(feature = "into_raw_os", since = "1.4.0")]
79pub trait IntoRawHandle {
80    /// Consumes this object, returning the raw underlying handle.
81    ///
82    /// This function is typically used to **transfer ownership** of the underlying
83    /// handle to the caller. When used in this way, callers are then the unique
84    /// owners of the handle and must close it once it's no longer needed.
85    ///
86    /// However, transferring ownership is not strictly required. Use a
87    /// `Into<OwnedHandle>::into` implementation for an API which strictly
88    /// transfers ownership.
89    #[must_use = "losing the raw handle may leak resources"]
90    #[stable(feature = "into_raw_os", since = "1.4.0")]
91    fn into_raw_handle(self) -> RawHandle;
92}
93
94#[stable(feature = "rust1", since = "1.0.0")]
95impl AsRawHandle for fs::File {
96    #[inline]
97    #[rustdoc_skip_body]
98    fn as_raw_handle(&self) -> RawHandle {
99        self.as_inner().as_raw_handle() as RawHandle
100    }
101}
102
103#[stable(feature = "asraw_stdio", since = "1.21.0")]
104impl AsRawHandle for io::Stdin {
105    fn as_raw_handle(&self) -> RawHandle {
106        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_INPUT_HANDLE) as RawHandle })
107    }
108}
109
110#[stable(feature = "asraw_stdio", since = "1.21.0")]
111impl AsRawHandle for io::Stdout {
112    fn as_raw_handle(&self) -> RawHandle {
113        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_OUTPUT_HANDLE) as RawHandle })
114    }
115}
116
117#[stable(feature = "asraw_stdio", since = "1.21.0")]
118impl AsRawHandle for io::Stderr {
119    fn as_raw_handle(&self) -> RawHandle {
120        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_ERROR_HANDLE) as RawHandle })
121    }
122}
123
124#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
125impl<'a> AsRawHandle for io::StdinLock<'a> {
126    fn as_raw_handle(&self) -> RawHandle {
127        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_INPUT_HANDLE) as RawHandle })
128    }
129}
130
131#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
132impl<'a> AsRawHandle for io::StdoutLock<'a> {
133    fn as_raw_handle(&self) -> RawHandle {
134        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_OUTPUT_HANDLE) as RawHandle })
135    }
136}
137
138#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
139impl<'a> AsRawHandle for io::StderrLock<'a> {
140    fn as_raw_handle(&self) -> RawHandle {
141        stdio_handle(unsafe { sys::c::GetStdHandle(sys::c::STD_ERROR_HANDLE) as RawHandle })
142    }
143}
144
145// Translate a handle returned from `GetStdHandle` into a handle to return to
146// the user.
147pub(super) fn stdio_handle(raw: RawHandle) -> RawHandle {
148    // `GetStdHandle` isn't expected to actually fail, so when it returns
149    // `INVALID_HANDLE_VALUE`, it means we were launched from a parent which
150    // didn't provide us with stdio handles, such as a parent with a detached
151    // console. In that case, return null to the user, which is consistent
152    // with what they'd get in the parent, and which avoids the problem that
153    // `INVALID_HANDLE_VALUE` aliases the current process handle.
154    if raw == sys::c::INVALID_HANDLE_VALUE { ptr::null_mut() } else { raw }
155}
156
157#[stable(feature = "from_raw_os", since = "1.1.0")]
158impl FromRawHandle for fs::File {
159    #[inline]
160    #[rustdoc_skip_body]
161    unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
162        unsafe {
163            let handle = handle as sys::c::HANDLE;
164            fs::File::from_inner(sys::fs::File::from_inner(FromInner::from_inner(
165                OwnedHandle::from_raw_handle(handle),
166            )))
167        }
168    }
169}
170
171#[stable(feature = "into_raw_os", since = "1.4.0")]
172impl IntoRawHandle for fs::File {
173    #[inline]
174    #[rustdoc_skip_body]
175    fn into_raw_handle(self) -> RawHandle {
176        self.into_inner().into_raw_handle() as *mut _
177    }
178}
179
180/// Extracts raw sockets.
181#[stable(feature = "rust1", since = "1.0.0")]
182pub trait AsRawSocket {
183    /// Extracts the raw socket.
184    ///
185    /// This function is typically used to **borrow** an owned socket.
186    /// When used in this way, this method does **not** pass ownership of the
187    /// raw socket to the caller, and the socket is only guaranteed
188    /// to be valid while the original object has not yet been destroyed.
189    ///
190    /// However, borrowing is not strictly required. See [`AsSocket::as_socket`]
191    /// for an API which strictly borrows a socket.
192    #[stable(feature = "rust1", since = "1.0.0")]
193    fn as_raw_socket(&self) -> RawSocket;
194}
195
196/// Creates I/O objects from raw sockets.
197#[stable(feature = "from_raw_os", since = "1.1.0")]
198pub trait FromRawSocket {
199    /// Constructs a new I/O object from the specified raw socket.
200    ///
201    /// This function is typically used to **consume ownership** of the socket
202    /// given, passing responsibility for closing the socket to the returned
203    /// object. When used in this way, the returned object
204    /// will take responsibility for closing it when the object goes out of
205    /// scope.
206    ///
207    /// However, consuming ownership is not strictly required. Use a
208    /// `From<OwnedSocket>::from` implementation for an API which strictly
209    /// consumes ownership.
210    ///
211    /// # Safety
212    ///
213    /// The `socket` passed in must:
214    ///   - be an [owned socket][io-safety]; in particular, it must be open.
215    ///   - be a socket that may be freed via [`closesocket`].
216    ///
217    /// [`closesocket`]: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-closesocket
218    /// [io-safety]: io#io-safety
219    #[stable(feature = "from_raw_os", since = "1.1.0")]
220    unsafe fn from_raw_socket(sock: RawSocket) -> Self;
221}
222
223/// A trait to express the ability to consume an object and acquire ownership of
224/// its raw `SOCKET`.
225#[stable(feature = "into_raw_os", since = "1.4.0")]
226pub trait IntoRawSocket {
227    /// Consumes this object, returning the raw underlying socket.
228    ///
229    /// This function is typically used to **transfer ownership** of the underlying
230    /// socket to the caller. When used in this way, callers are then the unique
231    /// owners of the socket and must close it once it's no longer needed.
232    ///
233    /// However, transferring ownership is not strictly required. Use a
234    /// `Into<OwnedSocket>::into` implementation for an API which strictly
235    /// transfers ownership.
236    #[must_use = "losing the raw socket may leak resources"]
237    #[stable(feature = "into_raw_os", since = "1.4.0")]
238    fn into_raw_socket(self) -> RawSocket;
239}
240
241#[stable(feature = "rust1", since = "1.0.0")]
242impl AsRawSocket for net::TcpStream {
243    #[inline]
244    #[rustdoc_skip_body]
245    fn as_raw_socket(&self) -> RawSocket {
246        self.as_inner().socket().as_raw_socket()
247    }
248}
249#[stable(feature = "rust1", since = "1.0.0")]
250impl AsRawSocket for net::TcpListener {
251    #[inline]
252    #[rustdoc_skip_body]
253    fn as_raw_socket(&self) -> RawSocket {
254        self.as_inner().socket().as_raw_socket()
255    }
256}
257#[stable(feature = "rust1", since = "1.0.0")]
258impl AsRawSocket for net::UdpSocket {
259    #[inline]
260    #[rustdoc_skip_body]
261    fn as_raw_socket(&self) -> RawSocket {
262        self.as_inner().socket().as_raw_socket()
263    }
264}
265
266#[stable(feature = "from_raw_os", since = "1.1.0")]
267impl FromRawSocket for net::TcpStream {
268    #[inline]
269    #[rustdoc_skip_body]
270    unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
271        unsafe {
272            let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
273            net::TcpStream::from_inner(sys::net::TcpStream::from_inner(sock))
274        }
275    }
276}
277#[stable(feature = "from_raw_os", since = "1.1.0")]
278impl FromRawSocket for net::TcpListener {
279    #[inline]
280    #[rustdoc_skip_body]
281    unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
282        unsafe {
283            let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
284            net::TcpListener::from_inner(sys::net::TcpListener::from_inner(sock))
285        }
286    }
287}
288#[stable(feature = "from_raw_os", since = "1.1.0")]
289impl FromRawSocket for net::UdpSocket {
290    #[inline]
291    #[rustdoc_skip_body]
292    unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
293        unsafe {
294            let sock = sys::net::Socket::from_inner(OwnedSocket::from_raw_socket(sock));
295            net::UdpSocket::from_inner(sys::net::UdpSocket::from_inner(sock))
296        }
297    }
298}
299
300#[stable(feature = "into_raw_os", since = "1.4.0")]
301impl IntoRawSocket for net::TcpStream {
302    #[inline]
303    #[rustdoc_skip_body]
304    fn into_raw_socket(self) -> RawSocket {
305        self.into_inner().into_socket().into_inner().into_raw_socket()
306    }
307}
308
309#[stable(feature = "into_raw_os", since = "1.4.0")]
310impl IntoRawSocket for net::TcpListener {
311    #[inline]
312    #[rustdoc_skip_body]
313    fn into_raw_socket(self) -> RawSocket {
314        self.into_inner().into_socket().into_inner().into_raw_socket()
315    }
316}
317
318#[stable(feature = "into_raw_os", since = "1.4.0")]
319impl IntoRawSocket for net::UdpSocket {
320    #[inline]
321    #[rustdoc_skip_body]
322    fn into_raw_socket(self) -> RawSocket {
323        self.into_inner().into_socket().into_inner().into_raw_socket()
324    }
325}
326
327#[stable(feature = "anonymous_pipe", since = "1.87.0")]
328impl AsRawHandle for io::PipeReader {
329    #[rustdoc_skip_body]
330    fn as_raw_handle(&self) -> RawHandle {
331        self.0.as_raw_handle()
332    }
333}
334
335#[stable(feature = "anonymous_pipe", since = "1.87.0")]
336impl FromRawHandle for io::PipeReader {
337    #[rustdoc_skip_body]
338    unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
339        unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
340    }
341}
342
343#[stable(feature = "anonymous_pipe", since = "1.87.0")]
344impl IntoRawHandle for io::PipeReader {
345    #[rustdoc_skip_body]
346    fn into_raw_handle(self) -> RawHandle {
347        self.0.into_raw_handle()
348    }
349}
350
351#[stable(feature = "anonymous_pipe", since = "1.87.0")]
352impl AsRawHandle for io::PipeWriter {
353    #[rustdoc_skip_body]
354    fn as_raw_handle(&self) -> RawHandle {
355        self.0.as_raw_handle()
356    }
357}
358
359#[stable(feature = "anonymous_pipe", since = "1.87.0")]
360impl FromRawHandle for io::PipeWriter {
361    #[rustdoc_skip_body]
362    unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
363        unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
364    }
365}
366
367#[stable(feature = "anonymous_pipe", since = "1.87.0")]
368impl IntoRawHandle for io::PipeWriter {
369    #[rustdoc_skip_body]
370    fn into_raw_handle(self) -> RawHandle {
371        self.0.into_raw_handle()
372    }
373}