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