]> git.lizzy.rs Git - rust.git/blob - library/std/src/os/windows/io/handle.rs
Tweak move error
[rust.git] / library / std / src / os / windows / io / handle.rs
1 //! Owned and borrowed OS handles.
2
3 #![unstable(feature = "io_safety", issue = "87074")]
4
5 use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6 use crate::convert::TryFrom;
7 use crate::fmt;
8 use crate::fs;
9 use crate::io;
10 use crate::marker::PhantomData;
11 use crate::mem::forget;
12 use crate::sys::c;
13 use crate::sys::cvt;
14 use crate::sys_common::{AsInner, FromInner, IntoInner};
15
16 /// A borrowed handle.
17 ///
18 /// This has a lifetime parameter to tie it to the lifetime of something that
19 /// owns the handle.
20 ///
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.
24 ///
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.
27 ///
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.
30 ///
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.
34 ///
35 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
36 #[derive(Copy, Clone)]
37 #[repr(transparent)]
38 #[unstable(feature = "io_safety", issue = "87074")]
39 pub struct BorrowedHandle<'handle> {
40     handle: RawHandle,
41     _phantom: PhantomData<&'handle OwnedHandle>,
42 }
43
44 /// An owned handle.
45 ///
46 /// This closes the handle on drop.
47 ///
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.
50 ///
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.
53 ///
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.
57 ///
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
60 ///
61 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
62 #[unstable(feature = "io_safety", issue = "87074")]
63 pub struct OwnedHandle {
64     handle: RawHandle,
65 }
66
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
70 /// FFI declarations.
71 ///
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.
76 ///
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`
79 /// as special.
80 ///
81 /// If this holds a valid handle, it will close the handle on drop.
82 #[repr(transparent)]
83 #[unstable(feature = "io_safety", issue = "87074")]
84 #[derive(Debug)]
85 pub struct HandleOrNull(OwnedHandle);
86
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
90 /// FFI declarations.
91 ///
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.
96 ///
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.
100 ///
101 /// If this holds a valid handle, it will close the handle on drop.
102 #[repr(transparent)]
103 #[unstable(feature = "io_safety", issue = "87074")]
104 #[derive(Debug)]
105 pub struct HandleOrInvalid(OwnedHandle);
106
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`).
110 //
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<'_> {}
120
121 impl BorrowedHandle<'_> {
122     /// Return a `BorrowedHandle` holding the given raw handle.
123     ///
124     /// # Safety
125     ///
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`.
128     ///
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.
131     ///
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.
134     ///
135     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
136     #[inline]
137     #[unstable(feature = "io_safety", issue = "87074")]
138     pub unsafe fn borrow_raw(handle: RawHandle) -> Self {
139         Self { handle, _phantom: PhantomData }
140     }
141 }
142
143 impl TryFrom<HandleOrNull> for OwnedHandle {
144     type Error = ();
145
146     #[inline]
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) }
150     }
151 }
152
153 impl OwnedHandle {
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)
158     }
159
160     pub(crate) fn duplicate(
161         &self,
162         access: c::DWORD,
163         inherit: bool,
164         options: c::DWORD,
165     ) -> io::Result<Self> {
166         let mut ret = 0 as c::HANDLE;
167         cvt(unsafe {
168             let cur_proc = c::GetCurrentProcess();
169             c::DuplicateHandle(
170                 cur_proc,
171                 self.as_raw_handle(),
172                 cur_proc,
173                 &mut ret,
174                 access,
175                 inherit as c::BOOL,
176                 options,
177             )
178         })?;
179         unsafe { Ok(Self::from_raw_handle(ret)) }
180     }
181 }
182
183 impl TryFrom<HandleOrInvalid> for OwnedHandle {
184     type Error = ();
185
186     #[inline]
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) }
190     }
191 }
192
193 impl AsRawHandle for BorrowedHandle<'_> {
194     #[inline]
195     fn as_raw_handle(&self) -> RawHandle {
196         self.handle
197     }
198 }
199
200 impl AsRawHandle for OwnedHandle {
201     #[inline]
202     fn as_raw_handle(&self) -> RawHandle {
203         self.handle
204     }
205 }
206
207 impl IntoRawHandle for OwnedHandle {
208     #[inline]
209     fn into_raw_handle(self) -> RawHandle {
210         let handle = self.handle;
211         forget(self);
212         handle
213     }
214 }
215
216 impl FromRawHandle for OwnedHandle {
217     #[inline]
218     unsafe fn from_raw_handle(handle: RawHandle) -> Self {
219         Self { handle }
220     }
221 }
222
223 impl HandleOrNull {
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
226     /// `CreateThread`.
227     ///
228     /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
229     /// use `INVALID_HANDLE_VALUE` to indicate failure.
230     ///
231     /// # Safety
232     ///
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.
236     ///
237     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
238     #[inline]
239     pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
240         Self(OwnedHandle::from_raw_handle(handle))
241     }
242 }
243
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`.
248     ///
249     /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
250     /// use null to indicate failure.
251     ///
252     /// # Safety
253     ///
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.
258     ///
259     /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
260     #[inline]
261     pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
262         Self(OwnedHandle::from_raw_handle(handle))
263     }
264 }
265
266 impl Drop for OwnedHandle {
267     #[inline]
268     fn drop(&mut self) {
269         unsafe {
270             let _ = c::CloseHandle(self.handle);
271         }
272     }
273 }
274
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()
278     }
279 }
280
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()
284     }
285 }
286
287 /// A trait to borrow the handle from an underlying object.
288 #[unstable(feature = "io_safety", issue = "87074")]
289 pub trait AsHandle {
290     /// Borrows the handle.
291     ///
292     /// # Example
293     ///
294     /// ```rust,no_run
295     /// # #![feature(io_safety)]
296     /// use std::fs::File;
297     /// # use std::io;
298     /// use std::os::windows::io::{AsHandle, BorrowedHandle};
299     ///
300     /// let mut f = File::open("foo.txt")?;
301     /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
302     /// # Ok::<(), io::Error>(())
303     /// ```
304     fn as_handle(&self) -> BorrowedHandle<'_>;
305 }
306
307 #[unstable(feature = "io_safety", issue = "87074")]
308 impl<T: AsHandle> AsHandle for &T {
309     #[inline]
310     fn as_handle(&self) -> BorrowedHandle<'_> {
311         T::as_handle(self)
312     }
313 }
314
315 #[unstable(feature = "io_safety", issue = "87074")]
316 impl<T: AsHandle> AsHandle for &mut T {
317     #[inline]
318     fn as_handle(&self) -> BorrowedHandle<'_> {
319         T::as_handle(self)
320     }
321 }
322
323 impl AsHandle for BorrowedHandle<'_> {
324     #[inline]
325     fn as_handle(&self) -> BorrowedHandle<'_> {
326         *self
327     }
328 }
329
330 impl AsHandle for OwnedHandle {
331     #[inline]
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
335         // of `&self`.
336         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
337     }
338 }
339
340 impl AsHandle for fs::File {
341     #[inline]
342     fn as_handle(&self) -> BorrowedHandle<'_> {
343         self.as_inner().as_handle()
344     }
345 }
346
347 impl From<fs::File> for OwnedHandle {
348     #[inline]
349     fn from(file: fs::File) -> OwnedHandle {
350         file.into_inner().into_inner().into_inner().into()
351     }
352 }
353
354 impl From<OwnedHandle> for fs::File {
355     #[inline]
356     fn from(owned: OwnedHandle) -> Self {
357         Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
358     }
359 }
360
361 impl AsHandle for crate::io::Stdin {
362     #[inline]
363     fn as_handle(&self) -> BorrowedHandle<'_> {
364         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
365     }
366 }
367
368 impl<'a> AsHandle for crate::io::StdinLock<'a> {
369     #[inline]
370     fn as_handle(&self) -> BorrowedHandle<'_> {
371         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
372     }
373 }
374
375 impl AsHandle for crate::io::Stdout {
376     #[inline]
377     fn as_handle(&self) -> BorrowedHandle<'_> {
378         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
379     }
380 }
381
382 impl<'a> AsHandle for crate::io::StdoutLock<'a> {
383     #[inline]
384     fn as_handle(&self) -> BorrowedHandle<'_> {
385         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
386     }
387 }
388
389 impl AsHandle for crate::io::Stderr {
390     #[inline]
391     fn as_handle(&self) -> BorrowedHandle<'_> {
392         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
393     }
394 }
395
396 impl<'a> AsHandle for crate::io::StderrLock<'a> {
397     #[inline]
398     fn as_handle(&self) -> BorrowedHandle<'_> {
399         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
400     }
401 }
402
403 impl AsHandle for crate::process::ChildStdin {
404     #[inline]
405     fn as_handle(&self) -> BorrowedHandle<'_> {
406         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
407     }
408 }
409
410 impl From<crate::process::ChildStdin> for OwnedHandle {
411     #[inline]
412     fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
413         unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
414     }
415 }
416
417 impl AsHandle for crate::process::ChildStdout {
418     #[inline]
419     fn as_handle(&self) -> BorrowedHandle<'_> {
420         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
421     }
422 }
423
424 impl From<crate::process::ChildStdout> for OwnedHandle {
425     #[inline]
426     fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
427         unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
428     }
429 }
430
431 impl AsHandle for crate::process::ChildStderr {
432     #[inline]
433     fn as_handle(&self) -> BorrowedHandle<'_> {
434         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
435     }
436 }
437
438 impl From<crate::process::ChildStderr> for OwnedHandle {
439     #[inline]
440     fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
441         unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
442     }
443 }
444
445 impl<T> AsHandle for crate::thread::JoinHandle<T> {
446     #[inline]
447     fn as_handle(&self) -> BorrowedHandle<'_> {
448         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
449     }
450 }
451
452 impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
453     #[inline]
454     fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
455         join_handle.into_inner().into_handle().into_inner()
456     }
457 }