1 //! Owned and borrowed OS handles.
3 #![unstable(feature = "io_safety", issue = "87074")]
5 use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6 use crate::convert::TryFrom;
10 use crate::marker::PhantomData;
11 use crate::mem::forget;
14 use crate::sys_common::{AsInner, FromInner, IntoInner};
16 /// A borrowed handle.
18 /// This has a lifetime parameter to tie it to the lifetime of something that
21 /// This uses `repr(transparent)` and has the representation of a host handle,
22 /// so it can be used in FFI in places where a handle is passed as an argument,
23 /// it is not captured or consumed.
25 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
26 /// sometimes a valid handle value. See [here] for the full story.
28 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
29 /// detached from processes, or when `windows_subsystem` is used.
31 /// This type's `.to_owned()` implementation returns another `BorrowedHandle`
32 /// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
33 /// handle, which is then borrowed under the same lifetime.
35 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
36 #[derive(Copy, Clone)]
38 #[unstable(feature = "io_safety", issue = "87074")]
39 pub struct BorrowedHandle<'handle> {
41 _phantom: PhantomData<&'handle OwnedHandle>,
46 /// This closes the handle on drop.
48 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
49 /// sometimes a valid handle value. See [here] for the full story.
51 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
52 /// detached from processes, or when `windows_subsystem` is used.
54 /// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
55 /// it must not be used with handles to open registry keys which need to be
56 /// closed with [`RegCloseKey`] instead.
58 /// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
59 /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
61 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
62 #[unstable(feature = "io_safety", issue = "87074")]
63 pub struct OwnedHandle {
67 /// FFI type for handles in return values or out parameters, where `NULL` is used
68 /// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses
69 /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
72 /// The only thing you can usefully do with a `HandleOrNull` is to convert it into an
73 /// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
74 /// `NULL`. This ensures that such FFI calls cannot start using the handle without
75 /// checking for `NULL` first.
77 /// This type concerns any value other than `NULL` to be valid, including `INVALID_HANDLE_VALUE`.
78 /// This is because APIs that use `NULL` as their sentry value don't treat `INVALID_HANDLE_VALUE`
81 /// If this holds a valid handle, it will close the handle on drop.
83 #[unstable(feature = "io_safety", issue = "87074")]
85 pub struct HandleOrNull(OwnedHandle);
87 /// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
88 /// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
89 /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
92 /// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an
93 /// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
94 /// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
95 /// checking for `INVALID_HANDLE_VALUE` first.
97 /// This type concerns any value other than `INVALID_HANDLE_VALUE` to be valid, including `NULL`.
98 /// This is because APIs that use `INVALID_HANDLE_VALUE` as their sentry value may return `NULL`
99 /// under `windows_subsystem = "windows"` or other situations where I/O devices are detached.
101 /// If this holds a valid handle, it will close the handle on drop.
103 #[unstable(feature = "io_safety", issue = "87074")]
105 pub struct HandleOrInvalid(OwnedHandle);
107 // The Windows [`HANDLE`] type may be transferred across and shared between
108 // thread boundaries (despite containing a `*mut void`, which in general isn't
109 // `Send` or `Sync`).
111 // [`HANDLE`]: std::os::windows::raw::HANDLE
112 unsafe impl Send for OwnedHandle {}
113 unsafe impl Send for HandleOrNull {}
114 unsafe impl Send for HandleOrInvalid {}
115 unsafe impl Send for BorrowedHandle<'_> {}
116 unsafe impl Sync for OwnedHandle {}
117 unsafe impl Sync for HandleOrNull {}
118 unsafe impl Sync for HandleOrInvalid {}
119 unsafe impl Sync for BorrowedHandle<'_> {}
121 impl BorrowedHandle<'_> {
122 /// Return a `BorrowedHandle` holding the given raw handle.
126 /// The resource pointed to by `handle` must be a valid open handle, it
127 /// must remain open for the duration of the returned `BorrowedHandle`.
129 /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
130 /// sometimes a valid handle value. See [here] for the full story.
132 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
133 /// detached from processes, or when `windows_subsystem` is used.
135 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
137 #[unstable(feature = "io_safety", issue = "87074")]
138 pub unsafe fn borrow_raw(handle: RawHandle) -> Self {
139 Self { handle, _phantom: PhantomData }
143 impl TryFrom<HandleOrNull> for OwnedHandle {
147 fn try_from(handle_or_null: HandleOrNull) -> Result<Self, ()> {
148 let owned_handle = handle_or_null.0;
149 if owned_handle.handle.is_null() { Err(()) } else { Ok(owned_handle) }
154 /// Creates a new `OwnedHandle` instance that shares the same underlying file handle
155 /// as the existing `OwnedHandle` instance.
156 pub fn try_clone(&self) -> crate::io::Result<Self> {
157 self.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)
160 pub(crate) fn duplicate(
165 ) -> io::Result<Self> {
166 let mut ret = 0 as c::HANDLE;
168 let cur_proc = c::GetCurrentProcess();
171 self.as_raw_handle(),
179 unsafe { Ok(Self::from_raw_handle(ret)) }
183 impl TryFrom<HandleOrInvalid> for OwnedHandle {
187 fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
188 let owned_handle = handle_or_invalid.0;
189 if owned_handle.handle == c::INVALID_HANDLE_VALUE { Err(()) } else { Ok(owned_handle) }
193 impl AsRawHandle for BorrowedHandle<'_> {
195 fn as_raw_handle(&self) -> RawHandle {
200 impl AsRawHandle for OwnedHandle {
202 fn as_raw_handle(&self) -> RawHandle {
207 impl IntoRawHandle for OwnedHandle {
209 fn into_raw_handle(self) -> RawHandle {
210 let handle = self.handle;
216 impl FromRawHandle for OwnedHandle {
218 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
224 /// Constructs a new instance of `Self` from the given `RawHandle` returned
225 /// from a Windows API that uses null to indicate failure, such as
228 /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
229 /// use `INVALID_HANDLE_VALUE` to indicate failure.
233 /// The passed `handle` value must either satisfy the safety requirements
234 /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
235 /// Windows APIs use null for errors; see [here] for the full story.
237 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
239 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
240 Self(OwnedHandle::from_raw_handle(handle))
244 impl HandleOrInvalid {
245 /// Constructs a new instance of `Self` from the given `RawHandle` returned
246 /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
247 /// failure, such as `CreateFileW`.
249 /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
250 /// use null to indicate failure.
254 /// The passed `handle` value must either satisfy the safety requirements
255 /// of [`FromRawHandle::from_raw_handle`], or be
256 /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
257 /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
259 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
261 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
262 Self(OwnedHandle::from_raw_handle(handle))
266 impl Drop for OwnedHandle {
270 let _ = c::CloseHandle(self.handle);
275 impl fmt::Debug for BorrowedHandle<'_> {
276 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277 f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
281 impl fmt::Debug for OwnedHandle {
282 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283 f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
287 /// A trait to borrow the handle from an underlying object.
288 #[unstable(feature = "io_safety", issue = "87074")]
290 /// Borrows the handle.
295 /// # #![feature(io_safety)]
296 /// use std::fs::File;
298 /// use std::os::windows::io::{AsHandle, BorrowedHandle};
300 /// let mut f = File::open("foo.txt")?;
301 /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
302 /// # Ok::<(), io::Error>(())
304 fn as_handle(&self) -> BorrowedHandle<'_>;
307 #[unstable(feature = "io_safety", issue = "87074")]
308 impl<T: AsHandle> AsHandle for &T {
310 fn as_handle(&self) -> BorrowedHandle<'_> {
315 #[unstable(feature = "io_safety", issue = "87074")]
316 impl<T: AsHandle> AsHandle for &mut T {
318 fn as_handle(&self) -> BorrowedHandle<'_> {
323 impl AsHandle for BorrowedHandle<'_> {
325 fn as_handle(&self) -> BorrowedHandle<'_> {
330 impl AsHandle for OwnedHandle {
332 fn as_handle(&self) -> BorrowedHandle<'_> {
333 // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
334 // invariants, and the `BorrowdHandle` is bounded by the lifetime
336 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
340 impl AsHandle for fs::File {
342 fn as_handle(&self) -> BorrowedHandle<'_> {
343 self.as_inner().as_handle()
347 impl From<fs::File> for OwnedHandle {
349 fn from(file: fs::File) -> OwnedHandle {
350 file.into_inner().into_inner().into_inner().into()
354 impl From<OwnedHandle> for fs::File {
356 fn from(owned: OwnedHandle) -> Self {
357 Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
361 impl AsHandle for crate::io::Stdin {
363 fn as_handle(&self) -> BorrowedHandle<'_> {
364 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
368 impl<'a> AsHandle for crate::io::StdinLock<'a> {
370 fn as_handle(&self) -> BorrowedHandle<'_> {
371 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
375 impl AsHandle for crate::io::Stdout {
377 fn as_handle(&self) -> BorrowedHandle<'_> {
378 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
382 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
384 fn as_handle(&self) -> BorrowedHandle<'_> {
385 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
389 impl AsHandle for crate::io::Stderr {
391 fn as_handle(&self) -> BorrowedHandle<'_> {
392 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
396 impl<'a> AsHandle for crate::io::StderrLock<'a> {
398 fn as_handle(&self) -> BorrowedHandle<'_> {
399 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
403 impl AsHandle for crate::process::ChildStdin {
405 fn as_handle(&self) -> BorrowedHandle<'_> {
406 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
410 impl From<crate::process::ChildStdin> for OwnedHandle {
412 fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
413 unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
417 impl AsHandle for crate::process::ChildStdout {
419 fn as_handle(&self) -> BorrowedHandle<'_> {
420 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
424 impl From<crate::process::ChildStdout> for OwnedHandle {
426 fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
427 unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
431 impl AsHandle for crate::process::ChildStderr {
433 fn as_handle(&self) -> BorrowedHandle<'_> {
434 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
438 impl From<crate::process::ChildStderr> for OwnedHandle {
440 fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
441 unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
445 impl<T> AsHandle for crate::thread::JoinHandle<T> {
447 fn as_handle(&self) -> BorrowedHandle<'_> {
448 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
452 impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
454 fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
455 join_handle.into_inner().into_handle().into_inner()