]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/windows/c.rs
Auto merge of #102655 - joboet:windows_tls_opt, r=ChrisDenton
[rust.git] / library / std / src / sys / windows / c.rs
1 //! C definitions used by libnative that don't belong in liblibc
2
3 #![allow(nonstandard_style)]
4 #![cfg_attr(test, allow(dead_code))]
5 #![unstable(issue = "none", feature = "windows_c")]
6
7 use crate::ffi::CStr;
8 use crate::mem;
9 use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
10 use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull};
11 use crate::ptr;
12 use core::ffi::NonZero_c_ulong;
13
14 use libc::{c_void, size_t, wchar_t};
15
16 #[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this
17 mod errors;
18 pub use errors::*;
19
20 pub use self::EXCEPTION_DISPOSITION::*;
21 pub use self::FILE_INFO_BY_HANDLE_CLASS::*;
22
23 pub type DWORD_PTR = ULONG_PTR;
24 pub type DWORD = c_ulong;
25 pub type NonZeroDWORD = NonZero_c_ulong;
26 pub type HANDLE = LPVOID;
27 pub type HINSTANCE = HANDLE;
28 pub type HMODULE = HINSTANCE;
29 pub type HRESULT = LONG;
30 pub type BOOL = c_int;
31 pub type BYTE = u8;
32 pub type BOOLEAN = BYTE;
33 pub type GROUP = c_uint;
34 pub type LARGE_INTEGER = c_longlong;
35 pub type LONG = c_long;
36 pub type UINT = c_uint;
37 pub type WCHAR = u16;
38 pub type USHORT = c_ushort;
39 pub type SIZE_T = usize;
40 pub type WORD = u16;
41 pub type CHAR = c_char;
42 pub type CCHAR = c_char;
43 pub type ULONG_PTR = usize;
44 pub type ULONG = c_ulong;
45 pub type NTSTATUS = LONG;
46 pub type ACCESS_MASK = DWORD;
47
48 pub type LPBOOL = *mut BOOL;
49 pub type LPBYTE = *mut BYTE;
50 pub type LPCSTR = *const CHAR;
51 pub type LPCWSTR = *const WCHAR;
52 pub type LPDWORD = *mut DWORD;
53 pub type LPHANDLE = *mut HANDLE;
54 pub type LPOVERLAPPED = *mut OVERLAPPED;
55 pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
56 pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
57 pub type LPSTARTUPINFO = *mut STARTUPINFO;
58 pub type LPVOID = *mut c_void;
59 pub type LPWCH = *mut WCHAR;
60 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
61 pub type LPWSADATA = *mut WSADATA;
62 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
63 pub type LPWSTR = *mut WCHAR;
64 pub type LPFILETIME = *mut FILETIME;
65 pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
66 pub type LPWSABUF = *mut WSABUF;
67 pub type LPWSAOVERLAPPED = *mut c_void;
68 pub type LPWSAOVERLAPPED_COMPLETION_ROUTINE = *mut c_void;
69 pub type BCRYPT_ALG_HANDLE = LPVOID;
70
71 pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
72 pub type PLARGE_INTEGER = *mut c_longlong;
73 pub type PSRWLOCK = *mut SRWLOCK;
74 pub type LPINIT_ONCE = *mut INIT_ONCE;
75
76 pub type SOCKET = crate::os::windows::raw::SOCKET;
77 pub type socklen_t = c_int;
78 pub type ADDRESS_FAMILY = USHORT;
79
80 pub const TRUE: BOOL = 1;
81 pub const FALSE: BOOL = 0;
82
83 pub const CSTR_LESS_THAN: c_int = 1;
84 pub const CSTR_EQUAL: c_int = 2;
85 pub const CSTR_GREATER_THAN: c_int = 3;
86
87 pub const FILE_ATTRIBUTE_READONLY: DWORD = 0x1;
88 pub const FILE_ATTRIBUTE_DIRECTORY: DWORD = 0x10;
89 pub const FILE_ATTRIBUTE_REPARSE_POINT: DWORD = 0x400;
90 pub const INVALID_FILE_ATTRIBUTES: DWORD = DWORD::MAX;
91
92 pub const FILE_SHARE_DELETE: DWORD = 0x4;
93 pub const FILE_SHARE_READ: DWORD = 0x1;
94 pub const FILE_SHARE_WRITE: DWORD = 0x2;
95
96 pub const FILE_OPEN: ULONG = 0x00000001;
97 pub const FILE_OPEN_REPARSE_POINT: ULONG = 0x200000;
98 pub const OBJ_DONT_REPARSE: ULONG = 0x1000;
99
100 pub const CREATE_ALWAYS: DWORD = 2;
101 pub const CREATE_NEW: DWORD = 1;
102 pub const OPEN_ALWAYS: DWORD = 4;
103 pub const OPEN_EXISTING: DWORD = 3;
104 pub const TRUNCATE_EXISTING: DWORD = 5;
105
106 pub const FILE_LIST_DIRECTORY: DWORD = 0x1;
107 pub const FILE_WRITE_DATA: DWORD = 0x00000002;
108 pub const FILE_APPEND_DATA: DWORD = 0x00000004;
109 pub const FILE_WRITE_EA: DWORD = 0x00000010;
110 pub const FILE_WRITE_ATTRIBUTES: DWORD = 0x00000100;
111 pub const DELETE: DWORD = 0x10000;
112 pub const READ_CONTROL: DWORD = 0x00020000;
113 pub const SYNCHRONIZE: DWORD = 0x00100000;
114 pub const GENERIC_READ: DWORD = 0x80000000;
115 pub const GENERIC_WRITE: DWORD = 0x40000000;
116 pub const STANDARD_RIGHTS_WRITE: DWORD = READ_CONTROL;
117 pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE
118     | FILE_WRITE_DATA
119     | FILE_WRITE_ATTRIBUTES
120     | FILE_WRITE_EA
121     | FILE_APPEND_DATA
122     | SYNCHRONIZE;
123
124 pub const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
125 pub const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
126 pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
127
128 pub const FIONBIO: c_ulong = 0x8004667e;
129
130 #[repr(C)]
131 #[derive(Copy)]
132 pub struct WIN32_FIND_DATAW {
133     pub dwFileAttributes: DWORD,
134     pub ftCreationTime: FILETIME,
135     pub ftLastAccessTime: FILETIME,
136     pub ftLastWriteTime: FILETIME,
137     pub nFileSizeHigh: DWORD,
138     pub nFileSizeLow: DWORD,
139     pub dwReserved0: DWORD,
140     pub dwReserved1: DWORD,
141     pub cFileName: [wchar_t; 260], // #define MAX_PATH 260
142     pub cAlternateFileName: [wchar_t; 14],
143 }
144 impl Clone for WIN32_FIND_DATAW {
145     fn clone(&self) -> Self {
146         *self
147     }
148 }
149
150 pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01;
151 pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80;
152
153 pub const WSADESCRIPTION_LEN: usize = 256;
154 pub const WSASYS_STATUS_LEN: usize = 128;
155 pub const WSAPROTOCOL_LEN: DWORD = 255;
156 pub const INVALID_SOCKET: SOCKET = !0;
157
158 pub const MAX_PROTOCOL_CHAIN: DWORD = 7;
159
160 pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
161 pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
162 pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c;
163 pub const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
164 pub const SYMLINK_FLAG_RELATIVE: DWORD = 0x00000001;
165 pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
166
167 pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
168 pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
169
170 // Note that these are not actually HANDLEs, just values to pass to GetStdHandle
171 pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD;
172 pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
173 pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD;
174
175 pub const PROGRESS_CONTINUE: DWORD = 0;
176
177 pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT;
178
179 pub const INVALID_HANDLE_VALUE: HANDLE = ptr::invalid_mut(!0);
180
181 pub const FACILITY_NT_BIT: DWORD = 0x1000_0000;
182
183 pub const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
184 pub const FORMAT_MESSAGE_FROM_HMODULE: DWORD = 0x00000800;
185 pub const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
186
187 pub const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
188
189 pub const DLL_THREAD_DETACH: DWORD = 3;
190 pub const DLL_PROCESS_DETACH: DWORD = 0;
191
192 pub const INFINITE: DWORD = !0;
193
194 pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;
195
196 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { ptr: ptr::null_mut() };
197 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };
198 pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { ptr: ptr::null_mut() };
199
200 pub const INIT_ONCE_INIT_FAILED: DWORD = 0x00000004;
201
202 pub const DETACHED_PROCESS: DWORD = 0x00000008;
203 pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
204 pub const CREATE_UNICODE_ENVIRONMENT: DWORD = 0x00000400;
205 pub const STARTF_USESTDHANDLES: DWORD = 0x00000100;
206
207 pub const AF_INET: c_int = 2;
208 pub const AF_INET6: c_int = 23;
209 pub const SD_BOTH: c_int = 2;
210 pub const SD_RECEIVE: c_int = 0;
211 pub const SD_SEND: c_int = 1;
212 pub const SOCK_DGRAM: c_int = 2;
213 pub const SOCK_STREAM: c_int = 1;
214 pub const SOCKET_ERROR: c_int = -1;
215 pub const SOL_SOCKET: c_int = 0xffff;
216 pub const SO_LINGER: c_int = 0x0080;
217 pub const SO_RCVTIMEO: c_int = 0x1006;
218 pub const SO_SNDTIMEO: c_int = 0x1005;
219 pub const IPPROTO_IP: c_int = 0;
220 pub const IPPROTO_TCP: c_int = 6;
221 pub const IPPROTO_IPV6: c_int = 41;
222 pub const TCP_NODELAY: c_int = 0x0001;
223 pub const IP_TTL: c_int = 4;
224 pub const IPV6_V6ONLY: c_int = 27;
225 pub const SO_ERROR: c_int = 0x1007;
226 pub const SO_BROADCAST: c_int = 0x0020;
227 pub const IP_MULTICAST_LOOP: c_int = 11;
228 pub const IPV6_MULTICAST_LOOP: c_int = 11;
229 pub const IP_MULTICAST_TTL: c_int = 10;
230 pub const IP_ADD_MEMBERSHIP: c_int = 12;
231 pub const IP_DROP_MEMBERSHIP: c_int = 13;
232 pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
233 pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
234 pub const MSG_PEEK: c_int = 0x2;
235
236 #[repr(C)]
237 #[derive(Copy, Clone)]
238 pub struct linger {
239     pub l_onoff: c_ushort,
240     pub l_linger: c_ushort,
241 }
242
243 #[repr(C)]
244 pub struct ip_mreq {
245     pub imr_multiaddr: in_addr,
246     pub imr_interface: in_addr,
247 }
248
249 #[repr(C)]
250 pub struct ipv6_mreq {
251     pub ipv6mr_multiaddr: in6_addr,
252     pub ipv6mr_interface: c_uint,
253 }
254
255 pub const VOLUME_NAME_DOS: DWORD = 0x0;
256 pub const MOVEFILE_REPLACE_EXISTING: DWORD = 1;
257
258 pub const FILE_BEGIN: DWORD = 0;
259 pub const FILE_CURRENT: DWORD = 1;
260 pub const FILE_END: DWORD = 2;
261
262 pub const WAIT_OBJECT_0: DWORD = 0x00000000;
263 pub const WAIT_TIMEOUT: DWORD = 258;
264 pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
265
266 pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001;
267 pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002;
268 pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000;
269 pub const FILE_FLAG_OVERLAPPED: DWORD = 0x40000000;
270 pub const PIPE_WAIT: DWORD = 0x00000000;
271 pub const PIPE_TYPE_BYTE: DWORD = 0x00000000;
272 pub const PIPE_REJECT_REMOTE_CLIENTS: DWORD = 0x00000008;
273 pub const PIPE_READMODE_BYTE: DWORD = 0x00000000;
274
275 pub const FD_SETSIZE: usize = 64;
276
277 pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
278
279 pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
280 pub const STATUS_DELETE_PENDING: NTSTATUS = 0xc0000056_u32 as _;
281 pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _;
282
283 pub const STATUS_PENDING: NTSTATUS = 0x103 as _;
284 pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _;
285 pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _;
286
287 // Equivalent to the `NT_SUCCESS` C preprocessor macro.
288 // See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
289 pub fn nt_success(status: NTSTATUS) -> bool {
290     status >= 0
291 }
292
293 // "RNG\0"
294 pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0];
295 pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
296
297 #[repr(C)]
298 pub struct UNICODE_STRING {
299     pub Length: u16,
300     pub MaximumLength: u16,
301     pub Buffer: *mut u16,
302 }
303 impl UNICODE_STRING {
304     pub fn from_ref(slice: &[u16]) -> Self {
305         let len = slice.len() * mem::size_of::<u16>();
306         Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ }
307     }
308 }
309 #[repr(C)]
310 pub struct OBJECT_ATTRIBUTES {
311     pub Length: ULONG,
312     pub RootDirectory: HANDLE,
313     pub ObjectName: *const UNICODE_STRING,
314     pub Attributes: ULONG,
315     pub SecurityDescriptor: *mut c_void,
316     pub SecurityQualityOfService: *mut c_void,
317 }
318 impl Default for OBJECT_ATTRIBUTES {
319     fn default() -> Self {
320         Self {
321             Length: mem::size_of::<Self>() as _,
322             RootDirectory: ptr::null_mut(),
323             ObjectName: ptr::null_mut(),
324             Attributes: 0,
325             SecurityDescriptor: ptr::null_mut(),
326             SecurityQualityOfService: ptr::null_mut(),
327         }
328     }
329 }
330 #[repr(C)]
331 union IO_STATUS_BLOCK_union {
332     Status: NTSTATUS,
333     Pointer: *mut c_void,
334 }
335 impl Default for IO_STATUS_BLOCK_union {
336     fn default() -> Self {
337         let mut this = Self { Pointer: ptr::null_mut() };
338         this.Status = STATUS_PENDING;
339         this
340     }
341 }
342 #[repr(C)]
343 #[derive(Default)]
344 pub struct IO_STATUS_BLOCK {
345     u: IO_STATUS_BLOCK_union,
346     pub Information: usize,
347 }
348 impl IO_STATUS_BLOCK {
349     pub fn status(&self) -> NTSTATUS {
350         // SAFETY: If `self.u.Status` was set then this is obviously safe.
351         // If `self.u.Pointer` was set then this is the equivalent to converting
352         // the pointer to an integer, which is also safe.
353         // Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
354         // this module is to call the `default` method, which sets the `Status`.
355         unsafe { self.u.Status }
356     }
357 }
358
359 pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn(
360     dwErrorCode: DWORD,
361     dwNumberOfBytesTransfered: DWORD,
362     lpOverlapped: *mut OVERLAPPED,
363 );
364
365 type IO_APC_ROUTINE = unsafe extern "system" fn(
366     ApcContext: *mut c_void,
367     IoStatusBlock: *mut IO_STATUS_BLOCK,
368     Reserved: ULONG,
369 );
370
371 #[repr(C)]
372 #[cfg(not(target_pointer_width = "64"))]
373 pub struct WSADATA {
374     pub wVersion: WORD,
375     pub wHighVersion: WORD,
376     pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
377     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
378     pub iMaxSockets: u16,
379     pub iMaxUdpDg: u16,
380     pub lpVendorInfo: *mut u8,
381 }
382 #[repr(C)]
383 #[cfg(target_pointer_width = "64")]
384 pub struct WSADATA {
385     pub wVersion: WORD,
386     pub wHighVersion: WORD,
387     pub iMaxSockets: u16,
388     pub iMaxUdpDg: u16,
389     pub lpVendorInfo: *mut u8,
390     pub szDescription: [u8; WSADESCRIPTION_LEN + 1],
391     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
392 }
393
394 #[derive(Copy, Clone)]
395 #[repr(C)]
396 pub struct WSABUF {
397     pub len: ULONG,
398     pub buf: *mut CHAR,
399 }
400
401 #[repr(C)]
402 pub struct WSAPROTOCOL_INFO {
403     pub dwServiceFlags1: DWORD,
404     pub dwServiceFlags2: DWORD,
405     pub dwServiceFlags3: DWORD,
406     pub dwServiceFlags4: DWORD,
407     pub dwProviderFlags: DWORD,
408     pub ProviderId: GUID,
409     pub dwCatalogEntryId: DWORD,
410     pub ProtocolChain: WSAPROTOCOLCHAIN,
411     pub iVersion: c_int,
412     pub iAddressFamily: c_int,
413     pub iMaxSockAddr: c_int,
414     pub iMinSockAddr: c_int,
415     pub iSocketType: c_int,
416     pub iProtocol: c_int,
417     pub iProtocolMaxOffset: c_int,
418     pub iNetworkByteOrder: c_int,
419     pub iSecurityScheme: c_int,
420     pub dwMessageSize: DWORD,
421     pub dwProviderReserved: DWORD,
422     pub szProtocol: [u16; (WSAPROTOCOL_LEN as usize) + 1],
423 }
424
425 #[repr(C)]
426 #[derive(Copy, Clone)]
427 pub struct WIN32_FILE_ATTRIBUTE_DATA {
428     pub dwFileAttributes: DWORD,
429     pub ftCreationTime: FILETIME,
430     pub ftLastAccessTime: FILETIME,
431     pub ftLastWriteTime: FILETIME,
432     pub nFileSizeHigh: DWORD,
433     pub nFileSizeLow: DWORD,
434 }
435
436 #[repr(C)]
437 #[allow(dead_code)] // we only use some variants
438 pub enum FILE_INFO_BY_HANDLE_CLASS {
439     FileBasicInfo = 0,
440     FileStandardInfo = 1,
441     FileNameInfo = 2,
442     FileRenameInfo = 3,
443     FileDispositionInfo = 4,
444     FileAllocationInfo = 5,
445     FileEndOfFileInfo = 6,
446     FileStreamInfo = 7,
447     FileCompressionInfo = 8,
448     FileAttributeTagInfo = 9,
449     FileIdBothDirectoryInfo = 10,        // 0xA
450     FileIdBothDirectoryRestartInfo = 11, // 0xB
451     FileIoPriorityHintInfo = 12,         // 0xC
452     FileRemoteProtocolInfo = 13,         // 0xD
453     FileFullDirectoryInfo = 14,          // 0xE
454     FileFullDirectoryRestartInfo = 15,   // 0xF
455     FileStorageInfo = 16,                // 0x10
456     FileAlignmentInfo = 17,              // 0x11
457     FileIdInfo = 18,                     // 0x12
458     FileIdExtdDirectoryInfo = 19,        // 0x13
459     FileIdExtdDirectoryRestartInfo = 20, // 0x14
460     FileDispositionInfoEx = 21,          // 0x15, Windows 10 version 1607
461     MaximumFileInfoByHandlesClass,
462 }
463
464 #[repr(C)]
465 pub struct FILE_ATTRIBUTE_TAG_INFO {
466     pub FileAttributes: DWORD,
467     pub ReparseTag: DWORD,
468 }
469
470 #[repr(C)]
471 pub struct FILE_DISPOSITION_INFO {
472     pub DeleteFile: BOOLEAN,
473 }
474
475 pub const FILE_DISPOSITION_DELETE: DWORD = 0x1;
476 pub const FILE_DISPOSITION_POSIX_SEMANTICS: DWORD = 0x2;
477 pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: DWORD = 0x10;
478
479 #[repr(C)]
480 pub struct FILE_DISPOSITION_INFO_EX {
481     pub Flags: DWORD,
482 }
483
484 #[repr(C)]
485 #[derive(Default)]
486 pub struct FILE_ID_BOTH_DIR_INFO {
487     pub NextEntryOffset: DWORD,
488     pub FileIndex: DWORD,
489     pub CreationTime: LARGE_INTEGER,
490     pub LastAccessTime: LARGE_INTEGER,
491     pub LastWriteTime: LARGE_INTEGER,
492     pub ChangeTime: LARGE_INTEGER,
493     pub EndOfFile: LARGE_INTEGER,
494     pub AllocationSize: LARGE_INTEGER,
495     pub FileAttributes: DWORD,
496     pub FileNameLength: DWORD,
497     pub EaSize: DWORD,
498     pub ShortNameLength: CCHAR,
499     pub ShortName: [WCHAR; 12],
500     pub FileId: LARGE_INTEGER,
501     pub FileName: [WCHAR; 1],
502 }
503 #[repr(C)]
504 pub struct FILE_BASIC_INFO {
505     pub CreationTime: LARGE_INTEGER,
506     pub LastAccessTime: LARGE_INTEGER,
507     pub LastWriteTime: LARGE_INTEGER,
508     pub ChangeTime: LARGE_INTEGER,
509     pub FileAttributes: DWORD,
510 }
511
512 #[repr(C)]
513 pub struct FILE_END_OF_FILE_INFO {
514     pub EndOfFile: LARGE_INTEGER,
515 }
516
517 /// NB: Use carefully! In general using this as a reference is likely to get the
518 /// provenance wrong for the `rest` field!
519 #[repr(C)]
520 pub struct REPARSE_DATA_BUFFER {
521     pub ReparseTag: c_uint,
522     pub ReparseDataLength: c_ushort,
523     pub Reserved: c_ushort,
524     pub rest: (),
525 }
526
527 /// NB: Use carefully! In general using this as a reference is likely to get the
528 /// provenance wrong for the `PathBuffer` field!
529 #[repr(C)]
530 pub struct SYMBOLIC_LINK_REPARSE_BUFFER {
531     pub SubstituteNameOffset: c_ushort,
532     pub SubstituteNameLength: c_ushort,
533     pub PrintNameOffset: c_ushort,
534     pub PrintNameLength: c_ushort,
535     pub Flags: c_ulong,
536     pub PathBuffer: WCHAR,
537 }
538
539 /// NB: Use carefully! In general using this as a reference is likely to get the
540 /// provenance wrong for the `PathBuffer` field!
541 #[repr(C)]
542 pub struct MOUNT_POINT_REPARSE_BUFFER {
543     pub SubstituteNameOffset: c_ushort,
544     pub SubstituteNameLength: c_ushort,
545     pub PrintNameOffset: c_ushort,
546     pub PrintNameLength: c_ushort,
547     pub PathBuffer: WCHAR,
548 }
549
550 pub type LPPROGRESS_ROUTINE = crate::option::Option<
551     unsafe extern "system" fn(
552         TotalFileSize: LARGE_INTEGER,
553         TotalBytesTransferred: LARGE_INTEGER,
554         StreamSize: LARGE_INTEGER,
555         StreamBytesTransferred: LARGE_INTEGER,
556         dwStreamNumber: DWORD,
557         dwCallbackReason: DWORD,
558         hSourceFile: HANDLE,
559         hDestinationFile: HANDLE,
560         lpData: LPVOID,
561     ) -> DWORD,
562 >;
563
564 #[repr(C)]
565 pub struct CONDITION_VARIABLE {
566     pub ptr: LPVOID,
567 }
568 #[repr(C)]
569 pub struct SRWLOCK {
570     pub ptr: LPVOID,
571 }
572 #[repr(C)]
573 pub struct INIT_ONCE {
574     pub ptr: LPVOID,
575 }
576
577 #[repr(C)]
578 pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
579     pub ReparseTag: DWORD,
580     pub ReparseDataLength: DWORD,
581     pub Reserved: WORD,
582     pub ReparseTargetLength: WORD,
583     pub ReparseTargetMaximumLength: WORD,
584     pub Reserved1: WORD,
585     pub ReparseTarget: WCHAR,
586 }
587
588 #[repr(C)]
589 pub struct GUID {
590     pub Data1: DWORD,
591     pub Data2: WORD,
592     pub Data3: WORD,
593     pub Data4: [BYTE; 8],
594 }
595
596 #[repr(C)]
597 pub struct WSAPROTOCOLCHAIN {
598     pub ChainLen: c_int,
599     pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize],
600 }
601
602 #[repr(C)]
603 pub struct SECURITY_ATTRIBUTES {
604     pub nLength: DWORD,
605     pub lpSecurityDescriptor: LPVOID,
606     pub bInheritHandle: BOOL,
607 }
608
609 #[repr(C)]
610 pub struct PROCESS_INFORMATION {
611     pub hProcess: HANDLE,
612     pub hThread: HANDLE,
613     pub dwProcessId: DWORD,
614     pub dwThreadId: DWORD,
615 }
616
617 #[repr(C)]
618 pub struct STARTUPINFO {
619     pub cb: DWORD,
620     pub lpReserved: LPWSTR,
621     pub lpDesktop: LPWSTR,
622     pub lpTitle: LPWSTR,
623     pub dwX: DWORD,
624     pub dwY: DWORD,
625     pub dwXSize: DWORD,
626     pub dwYSize: DWORD,
627     pub dwXCountChars: DWORD,
628     pub dwYCountCharts: DWORD,
629     pub dwFillAttribute: DWORD,
630     pub dwFlags: DWORD,
631     pub wShowWindow: WORD,
632     pub cbReserved2: WORD,
633     pub lpReserved2: LPBYTE,
634     pub hStdInput: HANDLE,
635     pub hStdOutput: HANDLE,
636     pub hStdError: HANDLE,
637 }
638
639 #[repr(C)]
640 pub struct SOCKADDR {
641     pub sa_family: ADDRESS_FAMILY,
642     pub sa_data: [CHAR; 14],
643 }
644
645 #[repr(C)]
646 #[derive(Copy, Clone, Debug, Default)]
647 pub struct FILETIME {
648     pub dwLowDateTime: DWORD,
649     pub dwHighDateTime: DWORD,
650 }
651
652 #[repr(C)]
653 pub struct SYSTEM_INFO {
654     pub wProcessorArchitecture: WORD,
655     pub wReserved: WORD,
656     pub dwPageSize: DWORD,
657     pub lpMinimumApplicationAddress: LPVOID,
658     pub lpMaximumApplicationAddress: LPVOID,
659     pub dwActiveProcessorMask: DWORD_PTR,
660     pub dwNumberOfProcessors: DWORD,
661     pub dwProcessorType: DWORD,
662     pub dwAllocationGranularity: DWORD,
663     pub wProcessorLevel: WORD,
664     pub wProcessorRevision: WORD,
665 }
666
667 #[repr(C)]
668 pub struct OVERLAPPED {
669     pub Internal: *mut c_ulong,
670     pub InternalHigh: *mut c_ulong,
671     pub Offset: DWORD,
672     pub OffsetHigh: DWORD,
673     pub hEvent: HANDLE,
674 }
675
676 #[repr(C)]
677 #[allow(dead_code)] // we only use some variants
678 pub enum ADDRESS_MODE {
679     AddrMode1616,
680     AddrMode1632,
681     AddrModeReal,
682     AddrModeFlat,
683 }
684
685 #[repr(C)]
686 pub struct SOCKADDR_STORAGE_LH {
687     pub ss_family: ADDRESS_FAMILY,
688     pub __ss_pad1: [CHAR; 6],
689     pub __ss_align: i64,
690     pub __ss_pad2: [CHAR; 112],
691 }
692
693 #[repr(C)]
694 pub struct ADDRINFOA {
695     pub ai_flags: c_int,
696     pub ai_family: c_int,
697     pub ai_socktype: c_int,
698     pub ai_protocol: c_int,
699     pub ai_addrlen: size_t,
700     pub ai_canonname: *mut c_char,
701     pub ai_addr: *mut SOCKADDR,
702     pub ai_next: *mut ADDRINFOA,
703 }
704
705 #[repr(C)]
706 #[derive(Copy, Clone)]
707 pub struct sockaddr_in {
708     pub sin_family: ADDRESS_FAMILY,
709     pub sin_port: USHORT,
710     pub sin_addr: in_addr,
711     pub sin_zero: [CHAR; 8],
712 }
713
714 #[repr(C)]
715 #[derive(Copy, Clone)]
716 pub struct sockaddr_in6 {
717     pub sin6_family: ADDRESS_FAMILY,
718     pub sin6_port: USHORT,
719     pub sin6_flowinfo: c_ulong,
720     pub sin6_addr: in6_addr,
721     pub sin6_scope_id: c_ulong,
722 }
723
724 #[repr(C)]
725 #[derive(Copy, Clone)]
726 pub struct in_addr {
727     pub s_addr: u32,
728 }
729
730 #[repr(C)]
731 #[derive(Copy, Clone)]
732 pub struct in6_addr {
733     pub s6_addr: [u8; 16],
734 }
735
736 #[repr(C)]
737 #[derive(Copy, Clone)]
738 #[allow(dead_code)] // we only use some variants
739 pub enum EXCEPTION_DISPOSITION {
740     ExceptionContinueExecution,
741     ExceptionContinueSearch,
742     ExceptionNestedException,
743     ExceptionCollidedUnwind,
744 }
745
746 #[repr(C)]
747 #[derive(Copy)]
748 pub struct fd_set {
749     pub fd_count: c_uint,
750     pub fd_array: [SOCKET; FD_SETSIZE],
751 }
752
753 impl Clone for fd_set {
754     fn clone(&self) -> fd_set {
755         *self
756     }
757 }
758
759 #[repr(C)]
760 #[derive(Copy, Clone)]
761 pub struct timeval {
762     pub tv_sec: c_long,
763     pub tv_usec: c_long,
764 }
765
766 // Desktop specific functions & types
767 cfg_if::cfg_if! {
768 if #[cfg(not(target_vendor = "uwp"))] {
769     pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
770     pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
771     pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
772
773     #[repr(C)]
774     pub struct EXCEPTION_RECORD {
775         pub ExceptionCode: DWORD,
776         pub ExceptionFlags: DWORD,
777         pub ExceptionRecord: *mut EXCEPTION_RECORD,
778         pub ExceptionAddress: LPVOID,
779         pub NumberParameters: DWORD,
780         pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS],
781     }
782
783     pub enum CONTEXT {}
784
785     #[repr(C)]
786     pub struct EXCEPTION_POINTERS {
787         pub ExceptionRecord: *mut EXCEPTION_RECORD,
788         pub ContextRecord: *mut CONTEXT,
789     }
790
791     pub type PVECTORED_EXCEPTION_HANDLER =
792         extern "system" fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
793
794     #[repr(C)]
795     #[derive(Copy, Clone)]
796     pub struct CONSOLE_READCONSOLE_CONTROL {
797         pub nLength: ULONG,
798         pub nInitialChars: ULONG,
799         pub dwCtrlWakeupMask: ULONG,
800         pub dwControlKeyState: ULONG,
801     }
802
803     pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
804
805     #[repr(C)]
806     pub struct BY_HANDLE_FILE_INFORMATION {
807         pub dwFileAttributes: DWORD,
808         pub ftCreationTime: FILETIME,
809         pub ftLastAccessTime: FILETIME,
810         pub ftLastWriteTime: FILETIME,
811         pub dwVolumeSerialNumber: DWORD,
812         pub nFileSizeHigh: DWORD,
813         pub nFileSizeLow: DWORD,
814         pub nNumberOfLinks: DWORD,
815         pub nFileIndexHigh: DWORD,
816         pub nFileIndexLow: DWORD,
817     }
818
819     pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION;
820     pub type LPCVOID = *const c_void;
821
822     pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001;
823
824     pub const TOKEN_READ: DWORD = 0x20008;
825
826     #[link(name = "advapi32")]
827     extern "system" {
828         // Allowed but unused by UWP
829         pub fn OpenProcessToken(
830             ProcessHandle: HANDLE,
831             DesiredAccess: DWORD,
832             TokenHandle: *mut HANDLE,
833         ) -> BOOL;
834     }
835
836     #[link(name = "userenv")]
837     extern "system" {
838         // Allowed but unused by UWP
839         pub fn GetUserProfileDirectoryW(
840             hToken: HANDLE,
841             lpProfileDir: LPWSTR,
842             lpcchSize: *mut DWORD,
843         ) -> BOOL;
844     }
845
846     #[link(name = "kernel32")]
847     extern "system" {
848         // Functions forbidden when targeting UWP
849         pub fn ReadConsoleW(
850             hConsoleInput: HANDLE,
851             lpBuffer: LPVOID,
852             nNumberOfCharsToRead: DWORD,
853             lpNumberOfCharsRead: LPDWORD,
854             pInputControl: PCONSOLE_READCONSOLE_CONTROL,
855         ) -> BOOL;
856
857         pub fn WriteConsoleW(
858             hConsoleOutput: HANDLE,
859             lpBuffer: LPCVOID,
860             nNumberOfCharsToWrite: DWORD,
861             lpNumberOfCharsWritten: LPDWORD,
862             lpReserved: LPVOID,
863         ) -> BOOL;
864
865         pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
866         // Allowed but unused by UWP
867         pub fn GetFileInformationByHandle(
868             hFile: HANDLE,
869             lpFileInformation: LPBY_HANDLE_FILE_INFORMATION,
870         ) -> BOOL;
871         pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL;
872         pub fn AddVectoredExceptionHandler(
873             FirstHandler: ULONG,
874             VectoredHandler: PVECTORED_EXCEPTION_HANDLER,
875         ) -> LPVOID;
876         pub fn CreateHardLinkW(
877             lpSymlinkFileName: LPCWSTR,
878             lpTargetFileName: LPCWSTR,
879             lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
880         ) -> BOOL;
881         pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL;
882         pub fn GetWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
883     }
884 }
885 }
886
887 // UWP specific functions & types
888 cfg_if::cfg_if! {
889 if #[cfg(target_vendor = "uwp")] {
890     #[repr(C)]
891     pub struct FILE_STANDARD_INFO {
892         pub AllocationSize: LARGE_INTEGER,
893         pub EndOfFile: LARGE_INTEGER,
894         pub NumberOfLinks: DWORD,
895         pub DeletePending: BOOLEAN,
896         pub Directory: BOOLEAN,
897     }
898 }
899 }
900
901 // Shared between Desktop & UWP
902
903 #[link(name = "kernel32")]
904 extern "system" {
905     pub fn GetCurrentProcessId() -> DWORD;
906
907     pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT;
908     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
909     pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL;
910     pub fn SetFileTime(
911         hFile: BorrowedHandle<'_>,
912         lpCreationTime: Option<&FILETIME>,
913         lpLastAccessTime: Option<&FILETIME>,
914         lpLastWriteTime: Option<&FILETIME>,
915     ) -> BOOL;
916     pub fn SetLastError(dwErrCode: DWORD);
917     pub fn GetCommandLineW() -> LPWSTR;
918     pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD;
919     pub fn GetCurrentProcess() -> HANDLE;
920     pub fn GetCurrentThread() -> HANDLE;
921     pub fn GetStdHandle(which: DWORD) -> HANDLE;
922     pub fn ExitProcess(uExitCode: c_uint) -> !;
923     pub fn DeviceIoControl(
924         hDevice: HANDLE,
925         dwIoControlCode: DWORD,
926         lpInBuffer: LPVOID,
927         nInBufferSize: DWORD,
928         lpOutBuffer: LPVOID,
929         nOutBufferSize: DWORD,
930         lpBytesReturned: LPDWORD,
931         lpOverlapped: LPOVERLAPPED,
932     ) -> BOOL;
933     pub fn CreateThread(
934         lpThreadAttributes: LPSECURITY_ATTRIBUTES,
935         dwStackSize: SIZE_T,
936         lpStartAddress: extern "system" fn(*mut c_void) -> DWORD,
937         lpParameter: LPVOID,
938         dwCreationFlags: DWORD,
939         lpThreadId: LPDWORD,
940     ) -> HandleOrNull;
941     pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
942     pub fn SwitchToThread() -> BOOL;
943     pub fn Sleep(dwMilliseconds: DWORD);
944     pub fn SleepEx(dwMilliseconds: DWORD, bAlertable: BOOL) -> DWORD;
945     pub fn GetProcessId(handle: HANDLE) -> DWORD;
946     pub fn CopyFileExW(
947         lpExistingFileName: LPCWSTR,
948         lpNewFileName: LPCWSTR,
949         lpProgressRoutine: LPPROGRESS_ROUTINE,
950         lpData: LPVOID,
951         pbCancel: LPBOOL,
952         dwCopyFlags: DWORD,
953     ) -> BOOL;
954     pub fn FormatMessageW(
955         flags: DWORD,
956         lpSrc: LPVOID,
957         msgId: DWORD,
958         langId: DWORD,
959         buf: LPWSTR,
960         nsize: DWORD,
961         args: *const c_void,
962     ) -> DWORD;
963     pub fn TlsAlloc() -> DWORD;
964     pub fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
965     pub fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
966     pub fn TlsFree(dwTlsIndex: DWORD) -> BOOL;
967     pub fn GetLastError() -> DWORD;
968     pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL;
969     pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL;
970     pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL;
971     pub fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL;
972     pub fn CreateProcessW(
973         lpApplicationName: LPCWSTR,
974         lpCommandLine: LPWSTR,
975         lpProcessAttributes: LPSECURITY_ATTRIBUTES,
976         lpThreadAttributes: LPSECURITY_ATTRIBUTES,
977         bInheritHandles: BOOL,
978         dwCreationFlags: DWORD,
979         lpEnvironment: LPVOID,
980         lpCurrentDirectory: LPCWSTR,
981         lpStartupInfo: LPSTARTUPINFO,
982         lpProcessInformation: LPPROCESS_INFORMATION,
983     ) -> BOOL;
984     pub fn GetEnvironmentVariableW(n: LPCWSTR, v: LPWSTR, nsize: DWORD) -> DWORD;
985     pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL;
986     pub fn GetEnvironmentStringsW() -> LPWCH;
987     pub fn FreeEnvironmentStringsW(env_ptr: LPWCH) -> BOOL;
988     pub fn GetModuleFileNameW(hModule: HMODULE, lpFilename: LPWSTR, nSize: DWORD) -> DWORD;
989     pub fn CreateDirectoryW(
990         lpPathName: LPCWSTR,
991         lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
992     ) -> BOOL;
993     pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
994     pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD;
995     pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
996     pub fn DuplicateHandle(
997         hSourceProcessHandle: HANDLE,
998         hSourceHandle: HANDLE,
999         hTargetProcessHandle: HANDLE,
1000         lpTargetHandle: LPHANDLE,
1001         dwDesiredAccess: DWORD,
1002         bInheritHandle: BOOL,
1003         dwOptions: DWORD,
1004     ) -> BOOL;
1005     pub fn ReadFile(
1006         hFile: BorrowedHandle<'_>,
1007         lpBuffer: LPVOID,
1008         nNumberOfBytesToRead: DWORD,
1009         lpNumberOfBytesRead: LPDWORD,
1010         lpOverlapped: LPOVERLAPPED,
1011     ) -> BOOL;
1012     pub fn ReadFileEx(
1013         hFile: BorrowedHandle<'_>,
1014         lpBuffer: LPVOID,
1015         nNumberOfBytesToRead: DWORD,
1016         lpOverlapped: LPOVERLAPPED,
1017         lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
1018     ) -> BOOL;
1019     pub fn WriteFileEx(
1020         hFile: BorrowedHandle<'_>,
1021         lpBuffer: LPVOID,
1022         nNumberOfBytesToWrite: DWORD,
1023         lpOverlapped: LPOVERLAPPED,
1024         lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
1025     ) -> BOOL;
1026     pub fn CloseHandle(hObject: HANDLE) -> BOOL;
1027     pub fn MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: DWORD)
1028     -> BOOL;
1029     pub fn SetFilePointerEx(
1030         hFile: HANDLE,
1031         liDistanceToMove: LARGE_INTEGER,
1032         lpNewFilePointer: PLARGE_INTEGER,
1033         dwMoveMethod: DWORD,
1034     ) -> BOOL;
1035     pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL;
1036     pub fn CreateFileW(
1037         lpFileName: LPCWSTR,
1038         dwDesiredAccess: DWORD,
1039         dwShareMode: DWORD,
1040         lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
1041         dwCreationDisposition: DWORD,
1042         dwFlagsAndAttributes: DWORD,
1043         hTemplateFile: HANDLE,
1044     ) -> HandleOrInvalid;
1045
1046     pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE;
1047     pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL;
1048     pub fn FindClose(findFile: HANDLE) -> BOOL;
1049
1050     pub fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void;
1051     pub fn GetModuleHandleA(lpModuleName: LPCSTR) -> HMODULE;
1052     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
1053
1054     pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
1055     pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
1056
1057     pub fn CreateEventW(
1058         lpEventAttributes: LPSECURITY_ATTRIBUTES,
1059         bManualReset: BOOL,
1060         bInitialState: BOOL,
1061         lpName: LPCWSTR,
1062     ) -> HANDLE;
1063     pub fn WaitForMultipleObjects(
1064         nCount: DWORD,
1065         lpHandles: *const HANDLE,
1066         bWaitAll: BOOL,
1067         dwMilliseconds: DWORD,
1068     ) -> DWORD;
1069     pub fn CreateNamedPipeW(
1070         lpName: LPCWSTR,
1071         dwOpenMode: DWORD,
1072         dwPipeMode: DWORD,
1073         nMaxInstances: DWORD,
1074         nOutBufferSize: DWORD,
1075         nInBufferSize: DWORD,
1076         nDefaultTimeOut: DWORD,
1077         lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
1078     ) -> HANDLE;
1079     pub fn CancelIo(handle: HANDLE) -> BOOL;
1080     pub fn GetOverlappedResult(
1081         hFile: HANDLE,
1082         lpOverlapped: LPOVERLAPPED,
1083         lpNumberOfBytesTransferred: LPDWORD,
1084         bWait: BOOL,
1085     ) -> BOOL;
1086     pub fn CreateSymbolicLinkW(
1087         lpSymlinkFileName: LPCWSTR,
1088         lpTargetFileName: LPCWSTR,
1089         dwFlags: DWORD,
1090     ) -> BOOLEAN;
1091     pub fn GetFinalPathNameByHandleW(
1092         hFile: HANDLE,
1093         lpszFilePath: LPCWSTR,
1094         cchFilePath: DWORD,
1095         dwFlags: DWORD,
1096     ) -> DWORD;
1097     pub fn GetFileInformationByHandleEx(
1098         hFile: HANDLE,
1099         fileInfoClass: FILE_INFO_BY_HANDLE_CLASS,
1100         lpFileInformation: LPVOID,
1101         dwBufferSize: DWORD,
1102     ) -> BOOL;
1103     pub fn SetFileInformationByHandle(
1104         hFile: HANDLE,
1105         FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
1106         lpFileInformation: LPVOID,
1107         dwBufferSize: DWORD,
1108     ) -> BOOL;
1109     pub fn SleepConditionVariableSRW(
1110         ConditionVariable: PCONDITION_VARIABLE,
1111         SRWLock: PSRWLOCK,
1112         dwMilliseconds: DWORD,
1113         Flags: ULONG,
1114     ) -> BOOL;
1115
1116     pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
1117     pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
1118
1119     pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
1120     pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
1121     pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
1122     pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
1123     pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
1124     pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
1125
1126     pub fn InitOnceBeginInitialize(
1127         lpInitOnce: LPINIT_ONCE,
1128         dwFlags: DWORD,
1129         fPending: LPBOOL,
1130         lpContext: *mut LPVOID,
1131     ) -> BOOL;
1132     pub fn InitOnceComplete(lpInitOnce: LPINIT_ONCE, dwFlags: DWORD, lpContext: LPVOID) -> BOOL;
1133
1134     pub fn CompareStringOrdinal(
1135         lpString1: LPCWSTR,
1136         cchCount1: c_int,
1137         lpString2: LPCWSTR,
1138         cchCount2: c_int,
1139         bIgnoreCase: BOOL,
1140     ) -> c_int;
1141     pub fn GetFullPathNameW(
1142         lpFileName: LPCWSTR,
1143         nBufferLength: DWORD,
1144         lpBuffer: LPWSTR,
1145         lpFilePart: *mut LPWSTR,
1146     ) -> DWORD;
1147     pub fn GetFileAttributesW(lpFileName: LPCWSTR) -> DWORD;
1148 }
1149
1150 #[link(name = "ws2_32")]
1151 extern "system" {
1152     pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int;
1153     pub fn WSACleanup() -> c_int;
1154     pub fn WSAGetLastError() -> c_int;
1155     pub fn WSADuplicateSocketW(
1156         s: SOCKET,
1157         dwProcessId: DWORD,
1158         lpProtocolInfo: LPWSAPROTOCOL_INFO,
1159     ) -> c_int;
1160     pub fn WSASend(
1161         s: SOCKET,
1162         lpBuffers: LPWSABUF,
1163         dwBufferCount: DWORD,
1164         lpNumberOfBytesSent: LPDWORD,
1165         dwFlags: DWORD,
1166         lpOverlapped: LPWSAOVERLAPPED,
1167         lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE,
1168     ) -> c_int;
1169     pub fn WSARecv(
1170         s: SOCKET,
1171         lpBuffers: LPWSABUF,
1172         dwBufferCount: DWORD,
1173         lpNumberOfBytesRecvd: LPDWORD,
1174         lpFlags: LPDWORD,
1175         lpOverlapped: LPWSAOVERLAPPED,
1176         lpCompletionRoutine: LPWSAOVERLAPPED_COMPLETION_ROUTINE,
1177     ) -> c_int;
1178     pub fn WSASocketW(
1179         af: c_int,
1180         kind: c_int,
1181         protocol: c_int,
1182         lpProtocolInfo: LPWSAPROTOCOL_INFO,
1183         g: GROUP,
1184         dwFlags: DWORD,
1185     ) -> SOCKET;
1186     pub fn ioctlsocket(s: SOCKET, cmd: c_long, argp: *mut c_ulong) -> c_int;
1187     pub fn closesocket(socket: SOCKET) -> c_int;
1188     pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int;
1189     pub fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int;
1190     pub fn recvfrom(
1191         socket: SOCKET,
1192         buf: *mut c_void,
1193         len: c_int,
1194         flags: c_int,
1195         addr: *mut SOCKADDR,
1196         addrlen: *mut c_int,
1197     ) -> c_int;
1198     pub fn sendto(
1199         socket: SOCKET,
1200         buf: *const c_void,
1201         len: c_int,
1202         flags: c_int,
1203         addr: *const SOCKADDR,
1204         addrlen: c_int,
1205     ) -> c_int;
1206     pub fn shutdown(socket: SOCKET, how: c_int) -> c_int;
1207     pub fn accept(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> SOCKET;
1208     pub fn getsockopt(
1209         s: SOCKET,
1210         level: c_int,
1211         optname: c_int,
1212         optval: *mut c_char,
1213         optlen: *mut c_int,
1214     ) -> c_int;
1215     pub fn setsockopt(
1216         s: SOCKET,
1217         level: c_int,
1218         optname: c_int,
1219         optval: *const c_void,
1220         optlen: c_int,
1221     ) -> c_int;
1222     pub fn getsockname(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> c_int;
1223     pub fn getpeername(socket: SOCKET, address: *mut SOCKADDR, address_len: *mut c_int) -> c_int;
1224     pub fn bind(socket: SOCKET, address: *const SOCKADDR, address_len: socklen_t) -> c_int;
1225     pub fn listen(socket: SOCKET, backlog: c_int) -> c_int;
1226     pub fn connect(socket: SOCKET, address: *const SOCKADDR, len: c_int) -> c_int;
1227     pub fn getaddrinfo(
1228         node: *const c_char,
1229         service: *const c_char,
1230         hints: *const ADDRINFOA,
1231         res: *mut *mut ADDRINFOA,
1232     ) -> c_int;
1233     pub fn freeaddrinfo(res: *mut ADDRINFOA);
1234     pub fn select(
1235         nfds: c_int,
1236         readfds: *mut fd_set,
1237         writefds: *mut fd_set,
1238         exceptfds: *mut fd_set,
1239         timeout: *const timeval,
1240     ) -> c_int;
1241 }
1242
1243 #[link(name = "bcrypt")]
1244 extern "system" {
1245     // >= Vista / Server 2008
1246     // https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
1247     pub fn BCryptGenRandom(
1248         hAlgorithm: BCRYPT_ALG_HANDLE,
1249         pBuffer: *mut u8,
1250         cbBuffer: ULONG,
1251         dwFlags: ULONG,
1252     ) -> NTSTATUS;
1253     pub fn BCryptOpenAlgorithmProvider(
1254         phalgorithm: *mut BCRYPT_ALG_HANDLE,
1255         pszAlgId: LPCWSTR,
1256         pszimplementation: LPCWSTR,
1257         dwflags: ULONG,
1258     ) -> NTSTATUS;
1259     pub fn BCryptCloseAlgorithmProvider(hAlgorithm: BCRYPT_ALG_HANDLE, dwFlags: ULONG) -> NTSTATUS;
1260 }
1261
1262 // Functions that aren't available on every version of Windows that we support,
1263 // but we still use them and just provide some form of a fallback implementation.
1264 compat_fn_with_fallback! {
1265     pub static KERNEL32: &CStr = ansi_str!("kernel32");
1266
1267     // >= Win10 1607
1268     // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
1269     pub fn SetThreadDescription(hThread: HANDLE,
1270                                 lpThreadDescription: LPCWSTR) -> HRESULT {
1271         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
1272     }
1273
1274     // >= Win8 / Server 2012
1275     // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
1276     pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME)
1277                                           -> () {
1278         GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
1279     }
1280
1281     // >= Win11 / Server 2022
1282     // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
1283     pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD {
1284         GetTempPathW(nBufferLength, lpBuffer)
1285     }
1286 }
1287
1288 compat_fn_optional! {
1289     crate::sys::compat::load_synch_functions();
1290     pub fn WaitOnAddress(
1291         Address: LPVOID,
1292         CompareAddress: LPVOID,
1293         AddressSize: SIZE_T,
1294         dwMilliseconds: DWORD
1295     );
1296     pub fn WakeByAddressSingle(Address: LPVOID);
1297 }
1298
1299 compat_fn_with_fallback! {
1300     pub static NTDLL: &CStr = ansi_str!("ntdll");
1301
1302     pub fn NtCreateFile(
1303         FileHandle: *mut HANDLE,
1304         DesiredAccess: ACCESS_MASK,
1305         ObjectAttributes: *const OBJECT_ATTRIBUTES,
1306         IoStatusBlock: *mut IO_STATUS_BLOCK,
1307         AllocationSize: *mut i64,
1308         FileAttributes: ULONG,
1309         ShareAccess: ULONG,
1310         CreateDisposition: ULONG,
1311         CreateOptions: ULONG,
1312         EaBuffer: *mut c_void,
1313         EaLength: ULONG
1314     ) -> NTSTATUS {
1315         STATUS_NOT_IMPLEMENTED
1316     }
1317     pub fn NtReadFile(
1318         FileHandle: BorrowedHandle<'_>,
1319         Event: HANDLE,
1320         ApcRoutine: Option<IO_APC_ROUTINE>,
1321         ApcContext: *mut c_void,
1322         IoStatusBlock: &mut IO_STATUS_BLOCK,
1323         Buffer: *mut crate::mem::MaybeUninit<u8>,
1324         Length: ULONG,
1325         ByteOffset: Option<&LARGE_INTEGER>,
1326         Key: Option<&ULONG>
1327     ) -> NTSTATUS {
1328         STATUS_NOT_IMPLEMENTED
1329     }
1330     pub fn NtWriteFile(
1331         FileHandle: BorrowedHandle<'_>,
1332         Event: HANDLE,
1333         ApcRoutine: Option<IO_APC_ROUTINE>,
1334         ApcContext: *mut c_void,
1335         IoStatusBlock: &mut IO_STATUS_BLOCK,
1336         Buffer: *const u8,
1337         Length: ULONG,
1338         ByteOffset: Option<&LARGE_INTEGER>,
1339         Key: Option<&ULONG>
1340     ) -> NTSTATUS {
1341         STATUS_NOT_IMPLEMENTED
1342     }
1343     pub fn RtlNtStatusToDosError(
1344         Status: NTSTATUS
1345     ) -> ULONG {
1346         Status as ULONG
1347     }
1348     pub fn NtCreateKeyedEvent(
1349         KeyedEventHandle: LPHANDLE,
1350         DesiredAccess: ACCESS_MASK,
1351         ObjectAttributes: LPVOID,
1352         Flags: ULONG
1353     ) -> NTSTATUS {
1354         panic!("keyed events not available")
1355     }
1356     pub fn NtReleaseKeyedEvent(
1357         EventHandle: HANDLE,
1358         Key: LPVOID,
1359         Alertable: BOOLEAN,
1360         Timeout: PLARGE_INTEGER
1361     ) -> NTSTATUS {
1362         panic!("keyed events not available")
1363     }
1364     pub fn NtWaitForKeyedEvent(
1365         EventHandle: HANDLE,
1366         Key: LPVOID,
1367         Alertable: BOOLEAN,
1368         Timeout: PLARGE_INTEGER
1369     ) -> NTSTATUS {
1370         panic!("keyed events not available")
1371     }
1372 }