]> git.proxmox.com Git - rustc.git/blobdiff - library/std/src/os/windows/io/handle.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / library / std / src / os / windows / io / handle.rs
index 8df6c54a4144e9f42c1314bbb07d12d333d16cdf..ee30cc8be6b57c442c6114d9918aa9bbdc66d0e5 100644 (file)
@@ -9,6 +9,7 @@ use crate::fs;
 use crate::io;
 use crate::marker::PhantomData;
 use crate::mem::forget;
+use crate::ptr;
 use crate::sys::c;
 use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -28,6 +29,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
 /// And, it *may* have the value `NULL` (0), which can occur when consoles are
 /// detached from processes, or when `windows_subsystem` is used.
 ///
+/// This type's `.to_owned()` implementation returns another `BorrowedHandle`
+/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
+/// handle, which is then borrowed under the same lifetime.
+///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
 #[derive(Copy, Clone)]
 #[repr(transparent)]
@@ -55,6 +60,7 @@ pub struct BorrowedHandle<'handle> {
 /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
 ///
 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
+#[repr(transparent)]
 #[unstable(feature = "io_safety", issue = "87074")]
 pub struct OwnedHandle {
     handle: RawHandle,
@@ -131,7 +137,7 @@ impl BorrowedHandle<'_> {
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     #[unstable(feature = "io_safety", issue = "87074")]
-    pub unsafe fn borrow_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn borrow_raw(handle: RawHandle) -> Self {
         Self { handle, _phantom: PhantomData }
     }
 }
@@ -142,7 +148,15 @@ impl TryFrom<HandleOrNull> for OwnedHandle {
     #[inline]
     fn try_from(handle_or_null: HandleOrNull) -> Result<Self, ()> {
         let owned_handle = handle_or_null.0;
-        if owned_handle.handle.is_null() { Err(()) } else { Ok(owned_handle) }
+        if owned_handle.handle.is_null() {
+            // Don't call `CloseHandle`; it'd be harmless, except that it could
+            // overwrite the `GetLastError` error.
+            forget(owned_handle);
+
+            Err(())
+        } else {
+            Ok(owned_handle)
+        }
     }
 }
 
@@ -159,12 +173,22 @@ impl OwnedHandle {
         inherit: bool,
         options: c::DWORD,
     ) -> io::Result<Self> {
-        let mut ret = 0 as c::HANDLE;
+        let handle = self.as_raw_handle();
+
+        // `Stdin`, `Stdout`, and `Stderr` can all hold null handles, such as
+        // in a process with a detached console. `DuplicateHandle` would fail
+        // if we passed it a null handle, but we can treat null as a valid
+        // handle which doesn't do any I/O, and allow it to be duplicated.
+        if handle.is_null() {
+            return unsafe { Ok(Self::from_raw_handle(handle)) };
+        }
+
+        let mut ret = ptr::null_mut();
         cvt(unsafe {
             let cur_proc = c::GetCurrentProcess();
             c::DuplicateHandle(
                 cur_proc,
-                self.as_raw_handle(),
+                handle,
                 cur_proc,
                 &mut ret,
                 access,
@@ -182,7 +206,15 @@ impl TryFrom<HandleOrInvalid> for OwnedHandle {
     #[inline]
     fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, ()> {
         let owned_handle = handle_or_invalid.0;
-        if owned_handle.handle == c::INVALID_HANDLE_VALUE { Err(()) } else { Ok(owned_handle) }
+        if owned_handle.handle == c::INVALID_HANDLE_VALUE {
+            // Don't call `CloseHandle`; it'd be harmless, except that it could
+            // overwrite the `GetLastError` error.
+            forget(owned_handle);
+
+            Err(())
+        } else {
+            Ok(owned_handle)
+        }
     }
 }
 
@@ -210,29 +242,13 @@ impl IntoRawHandle for OwnedHandle {
 }
 
 impl FromRawHandle for OwnedHandle {
-    /// Constructs a new instance of `Self` from the given raw handle.
-    ///
-    /// # Safety
-    ///
-    /// The resource pointed to by `handle` must be open and suitable for
-    /// assuming ownership. The resource must not require any cleanup other
-    /// than `CloseHandle`.
-    ///
-    /// In particular, it must not be used with handles to open registry
-    /// keys which need to be closed with [`RegCloseKey`] instead.
-    ///
-    /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
-    /// sometimes a valid handle value. See [here] for the full story.
-    ///
-    /// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
-    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self { handle }
     }
 }
 
-impl FromRawHandle for HandleOrNull {
+impl HandleOrNull {
     /// Constructs a new instance of `Self` from the given `RawHandle` returned
     /// from a Windows API that uses null to indicate failure, such as
     /// `CreateThread`.
@@ -242,18 +258,18 @@ impl FromRawHandle for HandleOrNull {
     ///
     /// # Safety
     ///
-    /// The resource pointed to by `handle` must be either open and otherwise
-    /// unowned, or null. Note that not all Windows APIs use null for errors;
-    /// see [here] for the full story.
+    /// The passed `handle` value must either satisfy the safety requirements
+    /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
+    /// Windows APIs use null for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
-    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
     }
 }
 
-impl FromRawHandle for HandleOrInvalid {
+impl HandleOrInvalid {
     /// Constructs a new instance of `Self` from the given `RawHandle` returned
     /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
     /// failure, such as `CreateFileW`.
@@ -263,14 +279,14 @@ impl FromRawHandle for HandleOrInvalid {
     ///
     /// # Safety
     ///
-    /// The resource pointed to by `handle` must be either open and otherwise
-    /// unowned, null, or equal to `INVALID_HANDLE_VALUE` (-1). Note that not
-    /// all Windows APIs use `INVALID_HANDLE_VALUE` for errors; see [here] for
-    /// the full story.
+    /// The passed `handle` value must either satisfy the safety requirements
+    /// of [`FromRawHandle::from_raw_handle`], or be
+    /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
+    /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
     ///
     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
     #[inline]
-    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
+    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
         Self(OwnedHandle::from_raw_handle(handle))
     }
 }
@@ -345,7 +361,7 @@ impl AsHandle for OwnedHandle {
         // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
         // invariants, and the `BorrowdHandle` is bounded by the lifetime
         // of `&self`.
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -373,49 +389,49 @@ impl From<OwnedHandle> for fs::File {
 impl AsHandle for crate::io::Stdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdinLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::io::Stderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl<'a> AsHandle for crate::io::StderrLock<'a> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
 impl AsHandle for crate::process::ChildStdin {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -429,7 +445,7 @@ impl From<crate::process::ChildStdin> for OwnedHandle {
 impl AsHandle for crate::process::ChildStdout {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -443,7 +459,7 @@ impl From<crate::process::ChildStdout> for OwnedHandle {
 impl AsHandle for crate::process::ChildStderr {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }
 
@@ -457,7 +473,7 @@ impl From<crate::process::ChildStderr> for OwnedHandle {
 impl<T> AsHandle for crate::thread::JoinHandle<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
-        unsafe { BorrowedHandle::borrow_raw_handle(self.as_raw_handle()) }
+        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
     }
 }