1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright (c) 2026 Mike Grier
//! What a handle can be asked about itself, and told: `GetHandleInformation` and
//! `SetHandleInformation`.
use io;
use BitOr;
use ;
use ;
/// The flags a handle carries: whether a child process created with handle inheritance gets a copy of
/// it, and whether closing it is refused.
///
/// A newtype over the Win32 bits, combined with `|`, because Windows defines the two the page
/// documents and this crate does not narrow what the call reports: a bit it has never heard of is
/// kept by [`from_bits`](Self::from_bits) and [`bits`](Self::bits) and is not an error.
///
/// # Example
///
/// ```
/// use win_handles_sys::HandleFlags;
///
/// let both = HandleFlags::INHERIT | HandleFlags::PROTECT_FROM_CLOSE;
/// assert!(both.contains(HandleFlags::INHERIT));
/// assert!(both.contains(HandleFlags::PROTECT_FROM_CLOSE));
/// assert!(!HandleFlags::INHERIT.contains(HandleFlags::PROTECT_FROM_CLOSE));
/// assert_eq!(HandleFlags::default(), HandleFlags::NONE);
/// ```
;
/// The flags `handle` carries: `GetHandleInformation`.
///
/// # Example
///
/// A handle `std` opens is not inheritable:
///
/// ```
/// use std::fs::File;
///
/// use win_handles_sys::{HandleFlags, get_handle_information};
///
/// let path = std::env::temp_dir().join(format!("wh-info-{}.tmp", std::process::id()));
/// let file = File::create(&path)?;
///
/// assert!(!get_handle_information(&file)?.contains(HandleFlags::INHERIT));
/// # drop(file);
/// # std::fs::remove_file(&path)?;
/// # Ok::<(), std::io::Error>(())
/// ```
///
/// # Errors
///
/// The error from `GetHandleInformation`. A handle that is open for the borrow, which `AsHandle`
/// guarantees, is not refused, so no test reaches it.
/// Changes the flags `handle` carries: `SetHandleInformation`.
///
/// `mask` names the flags to change, and `flags` gives each of them its new value: a flag in `mask` is set if it is
/// in `flags` and cleared if it is not. The page says "To set or clear the associated bit flag in dwFlags, you must
/// set a change mask bit flag in dwMask", so a flag in `flags` that is not in `mask` is left as it was, and so is
/// every flag the handle carries that is not in `mask`. The flags are the handle's and not its object's: a duplicate
/// of it has its own.
///
/// Nothing is refused before the call: the page calls no value of either argument invalid, and a bit it does not
/// name is the call's to judge ([`HandleFlags`]).
///
/// A handle given [`PROTECT_FROM_CLOSE`](HandleFlags::PROTECT_FROM_CLOSE) is not closed by `CloseHandle`, which is
/// what dropping an `OwnedHandle` calls, so one dropped while protected stays open for the life of the process.
/// Clear the flag first.
///
/// # Example
///
/// ```
/// use std::fs::File;
///
/// use win_handles_sys::{HandleFlags, get_handle_information, set_handle_information};
///
/// let path = std::env::temp_dir().join(format!("wh-set-{}.tmp", std::process::id()));
/// let file = File::create(&path)?;
///
/// // Make the handle inheritable, and leave every other flag as it was.
/// set_handle_information(&file, HandleFlags::INHERIT, HandleFlags::INHERIT)?;
/// assert!(get_handle_information(&file)?.contains(HandleFlags::INHERIT));
///
/// // A flag in `flags` but not in the mask is not changed.
/// set_handle_information(&file, HandleFlags::NONE, HandleFlags::PROTECT_FROM_CLOSE)?;
/// assert!(!get_handle_information(&file)?.contains(HandleFlags::PROTECT_FROM_CLOSE));
///
/// // A flag in the mask and not in `flags` is cleared.
/// set_handle_information(&file, HandleFlags::INHERIT, HandleFlags::NONE)?;
/// assert_eq!(get_handle_information(&file)?, HandleFlags::NONE);
/// # drop(file);
/// # std::fs::remove_file(&path)?;
/// # Ok::<(), std::io::Error>(())
/// ```
///
/// # Errors
///
/// The error from `SetHandleInformation`, which the page does not list. The current process's pseudo-handle, which
/// `std` allows a `BorrowedHandle` to hold, was refused with `ERROR_ACCESS_DENIED` where it was measured
/// (WH-D-3).