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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// Copyright (c) Mike Grier.
//! The faithful-execution contract every entry follows.
//!
//! An entry reports what Windows reported. It does not normalise a code, map it
//! onto a friendlier taxonomy, or decide that one failure "really means"
//! something else.
//!
//! # Why preservation is a constraint, not a preference
//!
//! `ERROR_FILE_NOT_FOUND` means three different things depending on which call
//! produced it and when: a missing directory from an open, an **empty**
//! directory from a first query, and a genuine failure from a later one. Only a
//! consumer holding that context can tell them apart. Any reclassification here
//! destroys information no layer above can reconstruct.
//!
//! # Why the code is snapshotted rather than read later
//!
//! `GetLastError` is thread state, and it is *volatile* thread state: almost
//! any subsequent Win32 call overwrites it, including cleanup a caller does not
//! think of as a call at all -- a `CloseHandle` in a `Drop`, a buffer being
//! released, a restoration guard unwinding. Reading it a few statements after
//! the failure is a race against the entry's own tidying up.
//!
//! So the read is not left to the caller's discipline. [`perform`] and its
//! convention-specific forms take the call as a closure and snapshot the code
//! **in the statement after it returns**, before anything else can run. Binding
//! to these functions is what makes the guarantee structural rather than a rule
//! each entry has to remember.
//!
//! # Scope: entries, not capture
//!
//! This governs the Win32 call an entry *performs*. It does not govern capture
//! failures -- [`crate::handle`], [`crate::security`], and [`crate::path`]
//! report a named stage plus a code, because there the useful question is which
//! part of building the request went wrong. Those happen on the calling thread,
//! before any entry runs.
use fmt;
use io;
use ;
/// A raw Win32 error code, exactly as Windows produced it.
///
/// Deliberately not an enum: the point of this type is that it carries whatever
/// Windows said, including codes this crate has never heard of.
///
/// # Example
///
/// ```
/// use windows_namespace_request_sys::Win32Error;
/// use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND;
///
/// let error = Win32Error::from_code(ERROR_FILE_NOT_FOUND);
/// assert_eq!(error.code(), ERROR_FILE_NOT_FOUND);
///
/// // The io::Error form is a re-presentation, not a reclassification: the raw
/// // code survives it.
/// assert_eq!(error.to_io_error().raw_os_error(), Some(ERROR_FILE_NOT_FOUND as i32));
///
/// // A code this crate has never heard of is carried just the same.
/// let unknown = Win32Error::from_code(0x0BAD_F00D);
/// assert_eq!(unknown.code(), 0x0BAD_F00D);
/// ```
;
/// What an entry's Win32 call produced: its result, or the raw code.
pub type Outcome<T> = ;
/// Performs `call` and, when `failed` says the result is a failure, snapshots
/// the thread's last error before anything else can run.
///
/// `failed` decides using only the returned value, because Win32's failure
/// conventions differ per call and none of them is inferable from the type. The
/// three the catalogue actually meets have named forms:
/// [`perform_bool`], [`perform_handle`], and [`perform_nonzero`]. Use this
/// general form for a call whose convention is none of those.
///
/// # Example
///
/// The guarantee this function exists for. Cleanup between the failing call and
/// the read is exactly what destroys a last-error code, and binding to
/// `perform` closes that window:
///
/// ```
/// use windows_namespace_request_sys::outcome::perform;
/// use windows_sys::Win32::Foundation::{
/// ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND, SetLastError,
/// };
///
/// let outcome = perform(
/// || {
/// // SAFETY: SetLastError writes only this thread's error slot.
/// unsafe { SetLastError(ERROR_FILE_NOT_FOUND) };
/// -1_i32
/// },
/// |result| *result < 0,
/// );
///
/// // Cleanup runs afterwards and clobbers the thread's error slot -- a Drop, a
/// // buffer release, a restoration guard. The snapshot is already taken.
/// // SAFETY: as above.
/// unsafe { SetLastError(ERROR_ACCESS_DENIED) };
///
/// assert_eq!(
/// outcome.expect_err("a negative result is a failure").code(),
/// ERROR_FILE_NOT_FOUND
/// );
/// ```
/// Performs a call whose `BOOL` return is `FALSE` on failure.
///
/// The successful value carries no information beyond "it worked", so it is
/// discarded rather than handed back as a bare integer.
///
/// # Errors
///
/// Returns the raw Win32 code when the call returns `FALSE`.
/// Performs a call whose `HANDLE` return is `INVALID_HANDLE_VALUE` on failure.
///
/// This is the convention of `CreateFileW`, `OpenFileById`, and
/// `FindFirstChangeNotificationW`.
///
/// # Errors
///
/// Returns the raw Win32 code when the call returns `INVALID_HANDLE_VALUE`.
///
/// # Example
///
/// The two handle conventions disagree about the same values, which is why both
/// exist by name. Using one where the other belongs turns a failure into a
/// plausible-looking handle:
///
/// ```
/// use std::ptr;
///
/// use windows_namespace_request_sys::outcome::{perform_handle, perform_nonnull_handle};
/// use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE;
///
/// // Under the INVALID_HANDLE_VALUE convention, null is a *success*.
/// assert!(perform_handle(ptr::null_mut).is_ok());
/// assert!(perform_handle(|| INVALID_HANDLE_VALUE).is_err());
///
/// // Under the null convention, the two swap.
/// assert!(perform_nonnull_handle(|| INVALID_HANDLE_VALUE).is_ok());
/// assert!(perform_nonnull_handle(ptr::null_mut).is_err());
/// ```
/// Performs a call whose `HANDLE` return is **null** on failure.
///
/// A distinct convention from [`perform_handle`], and getting the two the wrong
/// way round turns a failure into a plausible-looking handle. Both are provided
/// because Windows uses both.
///
/// # Errors
///
/// Returns the raw Win32 code when the call returns a null handle.
/// Performs a call whose numeric return is `0` on failure.
///
/// This is the convention of the sizing and length calls, such as
/// `GetFullPathNameW` and `GetFinalPathNameByHandleW`.
///
/// # Errors
///
/// Returns the raw Win32 code when the call returns `0`.