]> git.proxmox.com Git - rustc.git/blame - library/std/src/sys/windows/c.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / library / std / src / sys / windows / c.rs
CommitLineData
1a4d82fc
JJ
1//! C definitions used by libnative that don't belong in liblibc
2
b7449926 3#![allow(nonstandard_style)]
7453a54e 4#![cfg_attr(test, allow(dead_code))]
dfeec247 5#![unstable(issue = "none", feature = "windows_c")]
4b012472 6#![allow(clippy::style)]
1a4d82fc 7
064997fb 8use crate::ffi::CStr;
3c0e092e 9use crate::mem;
49aad941
FG
10pub use crate::os::raw::c_int;
11use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort, c_void};
12use crate::os::windows::io::{AsRawHandle, BorrowedHandle};
532ac7d7 13use crate::ptr;
5e7ed085 14use core::ffi::NonZero_c_ulong;
532ac7d7 15
49aad941
FG
16mod windows_sys;
17pub use windows_sys::*;
136023e0 18
92a42be0 19pub type DWORD = c_ulong;
17df50a5 20pub type NonZeroDWORD = NonZero_c_ulong;
92a42be0 21pub type LARGE_INTEGER = c_longlong;
fe692bf9 22#[cfg_attr(target_vendor = "uwp", allow(unused))]
92a42be0
SL
23pub type LONG = c_long;
24pub type UINT = c_uint;
25pub type WCHAR = u16;
26pub type USHORT = c_ushort;
27pub type SIZE_T = usize;
28pub type WORD = u16;
29pub type CHAR = c_char;
92a42be0 30pub type ULONG = c_ulong;
fc512014 31pub type ACCESS_MASK = DWORD;
92a42be0 32
9ffffee4 33pub type LPCVOID = *const c_void;
92a42be0
SL
34pub type LPHANDLE = *mut HANDLE;
35pub type LPOVERLAPPED = *mut OVERLAPPED;
92a42be0 36pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
92a42be0
SL
37pub type LPVOID = *mut c_void;
38pub type LPWCH = *mut WCHAR;
92a42be0 39pub type LPWSTR = *mut WCHAR;
92a42be0 40
92a42be0
SL
41pub type PLARGE_INTEGER = *mut c_longlong;
42pub type PSRWLOCK = *mut SRWLOCK;
43
92a42be0
SL
44pub type socklen_t = c_int;
45pub type ADDRESS_FAMILY = USHORT;
49aad941
FG
46pub use FD_SET as fd_set;
47pub use LINGER as linger;
48pub use TIMEVAL as timeval;
92a42be0 49
4b012472
FG
50pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _);
51
ed00b5ec
FG
52// https://learn.microsoft.com/en-us/cpp/c-runtime-library/exit-success-exit-failure?view=msvc-170
53pub const EXIT_SUCCESS: u32 = 0;
54pub const EXIT_FAILURE: u32 = 1;
55
49aad941
FG
56pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
57pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
58pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
3c0e092e 59
49aad941
FG
60// Some windows_sys types have different signs than the types we use.
61pub const OBJ_DONT_REPARSE: u32 = windows_sys::OBJ_DONT_REPARSE as u32;
62pub const FRS_ERR_SYSVOL_POPULATE_TIMEOUT: u32 =
63 windows_sys::FRS_ERR_SYSVOL_POPULATE_TIMEOUT as u32;
64pub const AF_INET: c_int = windows_sys::AF_INET as c_int;
65pub const AF_INET6: c_int = windows_sys::AF_INET6 as c_int;
94222f64 66
54a0048b
SL
67#[repr(C)]
68pub struct ip_mreq {
69 pub imr_multiaddr: in_addr,
70 pub imr_interface: in_addr,
71}
72
73#[repr(C)]
74pub struct ipv6_mreq {
75 pub ipv6mr_multiaddr: in6_addr,
76 pub ipv6mr_interface: c_uint,
77}
92a42be0 78
3c0e092e
XL
79// Equivalent to the `NT_SUCCESS` C preprocessor macro.
80// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
81pub fn nt_success(status: NTSTATUS) -> bool {
82 status >= 0
83}
fc512014 84
3c0e092e
XL
85impl UNICODE_STRING {
86 pub fn from_ref(slice: &[u16]) -> Self {
4b012472 87 let len = mem::size_of_val(slice);
3c0e092e
XL
88 Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ }
89 }
90}
49aad941 91
3c0e092e
XL
92impl Default for OBJECT_ATTRIBUTES {
93 fn default() -> Self {
94 Self {
95 Length: mem::size_of::<Self>() as _,
96 RootDirectory: ptr::null_mut(),
97 ObjectName: ptr::null_mut(),
98 Attributes: 0,
99 SecurityDescriptor: ptr::null_mut(),
100 SecurityQualityOfService: ptr::null_mut(),
101 }
102 }
103}
49aad941 104
04454e1e 105impl IO_STATUS_BLOCK {
49aad941
FG
106 pub const PENDING: Self =
107 IO_STATUS_BLOCK { Anonymous: IO_STATUS_BLOCK_0 { Status: STATUS_PENDING }, Information: 0 };
04454e1e 108 pub fn status(&self) -> NTSTATUS {
49aad941
FG
109 // SAFETY: If `self.Anonymous.Status` was set then this is obviously safe.
110 // If `self.Anonymous.Pointer` was set then this is the equivalent to converting
04454e1e
FG
111 // the pointer to an integer, which is also safe.
112 // Currently the only safe way to construct `IO_STATUS_BLOCK` outside of
113 // this module is to call the `default` method, which sets the `Status`.
49aad941 114 unsafe { self.Anonymous.Status }
3c0e092e
XL
115 }
116}
117
f2b60f7d
FG
118/// NB: Use carefully! In general using this as a reference is likely to get the
119/// provenance wrong for the `rest` field!
9346a6ac
AL
120#[repr(C)]
121pub struct REPARSE_DATA_BUFFER {
92a42be0
SL
122 pub ReparseTag: c_uint,
123 pub ReparseDataLength: c_ushort,
124 pub Reserved: c_ushort,
9346a6ac
AL
125 pub rest: (),
126}
127
f2b60f7d
FG
128/// NB: Use carefully! In general using this as a reference is likely to get the
129/// provenance wrong for the `PathBuffer` field!
9346a6ac
AL
130#[repr(C)]
131pub struct SYMBOLIC_LINK_REPARSE_BUFFER {
92a42be0
SL
132 pub SubstituteNameOffset: c_ushort,
133 pub SubstituteNameLength: c_ushort,
134 pub PrintNameOffset: c_ushort,
135 pub PrintNameLength: c_ushort,
136 pub Flags: c_ulong,
137 pub PathBuffer: WCHAR,
9346a6ac
AL
138}
139
7453a54e
SL
140#[repr(C)]
141pub struct MOUNT_POINT_REPARSE_BUFFER {
142 pub SubstituteNameOffset: c_ushort,
143 pub SubstituteNameLength: c_ushort,
144 pub PrintNameOffset: c_ushort,
145 pub PrintNameLength: c_ushort,
146 pub PathBuffer: WCHAR,
147}
c1a9b12d
SL
148#[repr(C)]
149pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
92a42be0
SL
150 pub ReparseTag: DWORD,
151 pub ReparseDataLength: DWORD,
152 pub Reserved: WORD,
153 pub ReparseTargetLength: WORD,
154 pub ReparseTargetMaximumLength: WORD,
155 pub Reserved1: WORD,
156 pub ReparseTarget: WCHAR,
c1a9b12d
SL
157}
158
92a42be0
SL
159#[repr(C)]
160pub struct SOCKADDR_STORAGE_LH {
161 pub ss_family: ADDRESS_FAMILY,
162 pub __ss_pad1: [CHAR; 6],
163 pub __ss_align: i64,
164 pub __ss_pad2: [CHAR; 112],
165}
166
92a42be0
SL
167#[repr(C)]
168#[derive(Copy, Clone)]
169pub struct sockaddr_in {
170 pub sin_family: ADDRESS_FAMILY,
171 pub sin_port: USHORT,
172 pub sin_addr: in_addr,
173 pub sin_zero: [CHAR; 8],
174}
175
176#[repr(C)]
177#[derive(Copy, Clone)]
178pub struct sockaddr_in6 {
179 pub sin6_family: ADDRESS_FAMILY,
180 pub sin6_port: USHORT,
181 pub sin6_flowinfo: c_ulong,
182 pub sin6_addr: in6_addr,
183 pub sin6_scope_id: c_ulong,
184}
185
186#[repr(C)]
187#[derive(Copy, Clone)]
188pub struct in_addr {
189 pub s_addr: u32,
190}
191
192#[repr(C)]
193#[derive(Copy, Clone)]
194pub struct in6_addr {
195 pub s6_addr: [u8; 16],
196}
197
17df50a5 198// Desktop specific functions & types
416331ca
XL
199cfg_if::cfg_if! {
200if #[cfg(not(target_vendor = "uwp"))] {
49aad941 201 pub const EXCEPTION_CONTINUE_SEARCH: i32 = 0;
c1a9b12d 202}
c295e0f8
XL
203}
204
49aad941
FG
205pub unsafe extern "system" fn WriteFileEx(
206 hFile: BorrowedHandle<'_>,
207 lpBuffer: *mut ::core::ffi::c_void,
208 nNumberOfBytesToWrite: u32,
209 lpOverlapped: *mut OVERLAPPED,
210 lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
211) -> BOOL {
212 windows_sys::WriteFileEx(
213 hFile.as_raw_handle(),
214 lpBuffer.cast::<u8>(),
215 nNumberOfBytesToWrite,
216 lpOverlapped,
217 lpCompletionRoutine,
218 )
219}
220
221pub unsafe extern "system" fn ReadFileEx(
222 hFile: BorrowedHandle<'_>,
223 lpBuffer: *mut ::core::ffi::c_void,
224 nNumberOfBytesToRead: u32,
225 lpOverlapped: *mut OVERLAPPED,
226 lpCompletionRoutine: LPOVERLAPPED_COMPLETION_ROUTINE,
227) -> BOOL {
228 windows_sys::ReadFileEx(
229 hFile.as_raw_handle(),
781aab86 230 lpBuffer.cast::<u8>(),
49aad941
FG
231 nNumberOfBytesToRead,
232 lpOverlapped,
233 lpCompletionRoutine,
234 )
235}
236
237// POSIX compatibility shims.
238pub unsafe fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int {
239 windows_sys::recv(socket, buf.cast::<u8>(), len, flags)
240}
241pub unsafe fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int {
242 windows_sys::send(socket, buf.cast::<u8>(), len, flags)
243}
244pub unsafe fn recvfrom(
245 socket: SOCKET,
246 buf: *mut c_void,
247 len: c_int,
248 flags: c_int,
249 addr: *mut SOCKADDR,
250 addrlen: *mut c_int,
251) -> c_int {
252 windows_sys::recvfrom(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
253}
254pub unsafe fn sendto(
255 socket: SOCKET,
256 buf: *const c_void,
257 len: c_int,
258 flags: c_int,
259 addr: *const SOCKADDR,
260 addrlen: c_int,
261) -> c_int {
262 windows_sys::sendto(socket, buf.cast::<u8>(), len, flags, addr, addrlen)
263}
264pub unsafe fn getaddrinfo(
265 node: *const c_char,
266 service: *const c_char,
267 hints: *const ADDRINFOA,
268 res: *mut *mut ADDRINFOA,
269) -> c_int {
270 windows_sys::getaddrinfo(node.cast::<u8>(), service.cast::<u8>(), hints, res)
271}
272
fe692bf9
FG
273cfg_if::cfg_if! {
274if #[cfg(not(target_vendor = "uwp"))] {
49aad941
FG
275pub unsafe fn NtReadFile(
276 filehandle: BorrowedHandle<'_>,
277 event: HANDLE,
278 apcroutine: PIO_APC_ROUTINE,
279 apccontext: *mut c_void,
280 iostatusblock: &mut IO_STATUS_BLOCK,
281 buffer: *mut crate::mem::MaybeUninit<u8>,
282 length: ULONG,
283 byteoffset: Option<&LARGE_INTEGER>,
284 key: Option<&ULONG>,
285) -> NTSTATUS {
286 windows_sys::NtReadFile(
287 filehandle.as_raw_handle(),
288 event,
289 apcroutine,
290 apccontext,
291 iostatusblock,
292 buffer.cast::<c_void>(),
293 length,
294 byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
295 key.map(|k| k as *const u32).unwrap_or(ptr::null()),
296 )
297}
298pub unsafe fn NtWriteFile(
299 filehandle: BorrowedHandle<'_>,
300 event: HANDLE,
301 apcroutine: PIO_APC_ROUTINE,
302 apccontext: *mut c_void,
303 iostatusblock: &mut IO_STATUS_BLOCK,
304 buffer: *const u8,
305 length: ULONG,
306 byteoffset: Option<&LARGE_INTEGER>,
307 key: Option<&ULONG>,
308) -> NTSTATUS {
309 windows_sys::NtWriteFile(
310 filehandle.as_raw_handle(),
311 event,
312 apcroutine,
313 apccontext,
314 iostatusblock,
315 buffer.cast::<c_void>(),
316 length,
317 byteoffset.map(|o| o as *const i64).unwrap_or(ptr::null()),
318 key.map(|k| k as *const u32).unwrap_or(ptr::null()),
319 )
353b0b11 320}
fe692bf9
FG
321}
322}
353b0b11 323
ea8adc8c
XL
324// Functions that aren't available on every version of Windows that we support,
325// but we still use them and just provide some form of a fallback implementation.
064997fb 326compat_fn_with_fallback! {
4b012472 327 pub static KERNEL32: &CStr = c"kernel32";
c1a9b12d 328
5869c6ff
XL
329 // >= Win10 1607
330 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription
49aad941 331 pub fn SetThreadDescription(hthread: HANDLE, lpthreaddescription: PCWSTR) -> HRESULT {
ea8adc8c
XL
332 SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
333 }
5869c6ff
XL
334
335 // >= Win8 / Server 2012
336 // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
49aad941
FG
337 pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {
338 GetSystemTimeAsFileTime(lpsystemtimeasfiletime)
ba9703b0 339 }
a2a8927a
XL
340
341 // >= Win11 / Server 2022
342 // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
49aad941
FG
343 pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 {
344 GetTempPathW(bufferlength, buffer)
a2a8927a 345 }
1a4d82fc 346}
5869c6ff 347
064997fb 348compat_fn_optional! {
f2b60f7d 349 crate::sys::compat::load_synch_functions();
fc512014 350 pub fn WaitOnAddress(
49aad941
FG
351 address: *const ::core::ffi::c_void,
352 compareaddress: *const ::core::ffi::c_void,
353 addresssize: usize,
354 dwmilliseconds: u32
355 ) -> BOOL;
356 pub fn WakeByAddressSingle(address: *const ::core::ffi::c_void);
fc512014
XL
357}
358
064997fb 359compat_fn_with_fallback! {
4b012472 360 pub static NTDLL: &CStr = c"ntdll";
064997fb 361
fc512014
XL
362 pub fn NtCreateKeyedEvent(
363 KeyedEventHandle: LPHANDLE,
364 DesiredAccess: ACCESS_MASK,
365 ObjectAttributes: LPVOID,
366 Flags: ULONG
367 ) -> NTSTATUS {
368 panic!("keyed events not available")
369 }
370 pub fn NtReleaseKeyedEvent(
371 EventHandle: HANDLE,
372 Key: LPVOID,
373 Alertable: BOOLEAN,
374 Timeout: PLARGE_INTEGER
375 ) -> NTSTATUS {
376 panic!("keyed events not available")
377 }
378 pub fn NtWaitForKeyedEvent(
379 EventHandle: HANDLE,
380 Key: LPVOID,
381 Alertable: BOOLEAN,
382 Timeout: PLARGE_INTEGER
383 ) -> NTSTATUS {
384 panic!("keyed events not available")
385 }
fe692bf9
FG
386
387 // These functions are available on UWP when lazily loaded. They will fail WACK if loaded statically.
388 #[cfg(target_vendor = "uwp")]
389 pub fn NtCreateFile(
390 filehandle: *mut HANDLE,
391 desiredaccess: FILE_ACCESS_RIGHTS,
392 objectattributes: *const OBJECT_ATTRIBUTES,
393 iostatusblock: *mut IO_STATUS_BLOCK,
394 allocationsize: *const i64,
395 fileattributes: FILE_FLAGS_AND_ATTRIBUTES,
396 shareaccess: FILE_SHARE_MODE,
397 createdisposition: NTCREATEFILE_CREATE_DISPOSITION,
398 createoptions: NTCREATEFILE_CREATE_OPTIONS,
399 eabuffer: *const ::core::ffi::c_void,
400 ealength: u32
401 ) -> NTSTATUS {
402 STATUS_NOT_IMPLEMENTED
403 }
404 #[cfg(target_vendor = "uwp")]
405 pub fn NtReadFile(
406 filehandle: BorrowedHandle<'_>,
407 event: HANDLE,
408 apcroutine: PIO_APC_ROUTINE,
409 apccontext: *mut c_void,
410 iostatusblock: &mut IO_STATUS_BLOCK,
411 buffer: *mut crate::mem::MaybeUninit<u8>,
412 length: ULONG,
413 byteoffset: Option<&LARGE_INTEGER>,
414 key: Option<&ULONG>
415 ) -> NTSTATUS {
416 STATUS_NOT_IMPLEMENTED
417 }
418 #[cfg(target_vendor = "uwp")]
419 pub fn NtWriteFile(
420 filehandle: BorrowedHandle<'_>,
421 event: HANDLE,
422 apcroutine: PIO_APC_ROUTINE,
423 apccontext: *mut c_void,
424 iostatusblock: &mut IO_STATUS_BLOCK,
425 buffer: *const u8,
426 length: ULONG,
427 byteoffset: Option<&LARGE_INTEGER>,
428 key: Option<&ULONG>
429 ) -> NTSTATUS {
430 STATUS_NOT_IMPLEMENTED
431 }
432 #[cfg(target_vendor = "uwp")]
433 pub fn RtlNtStatusToDosError(Status: NTSTATUS) -> u32 {
434 Status as u32
435 }
436}
437
438// # Arm32 shim
439//
440// AddVectoredExceptionHandler and WSAStartup use platform-specific types.
441// However, Microsoft no longer supports thumbv7a so definitions for those targets
442// are not included in the win32 metadata. We work around that by defining them here.
443//
444// Where possible, these definitions should be kept in sync with https://docs.rs/windows-sys
445cfg_if::cfg_if! {
446if #[cfg(not(target_vendor = "uwp"))] {
447 #[link(name = "kernel32")]
448 extern "system" {
449 pub fn AddVectoredExceptionHandler(
450 first: u32,
451 handler: PVECTORED_EXCEPTION_HANDLER,
452 ) -> *mut c_void;
453 }
454 pub type PVECTORED_EXCEPTION_HANDLER = Option<
455 unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32,
456 >;
457 #[repr(C)]
458 pub struct EXCEPTION_POINTERS {
459 pub ExceptionRecord: *mut EXCEPTION_RECORD,
460 pub ContextRecord: *mut CONTEXT,
461 }
462 #[cfg(target_arch = "arm")]
463 pub enum CONTEXT {}
464}}
465
466#[link(name = "ws2_32")]
467extern "system" {
468 pub fn WSAStartup(wversionrequested: u16, lpwsadata: *mut WSADATA) -> i32;
469}
470#[cfg(target_arch = "arm")]
471#[repr(C)]
472pub struct WSADATA {
473 pub wVersion: u16,
474 pub wHighVersion: u16,
475 pub szDescription: [u8; 257],
476 pub szSystemStatus: [u8; 129],
477 pub iMaxSockets: u16,
478 pub iMaxUdpDg: u16,
479 pub lpVendorInfo: PSTR,
fc512014 480}