Auto merge of #110152 - ChrisDenton:windows-sys, r=thomcc
Start using `windows sys` for Windows FFI bindings in std
Switch to using windows-sys for FFI. In order to avoid some currently contentious issues, this uses windows-bindgen to generate a smaller set of bindings instead of using the full crate.
Unlike the windows-sys crate, the generated bindings uses `*mut c_void` for handle types instead of `isize`. This to sidestep opsem concerns about mixing pointer types and integers between languages. Note that `SOCKET` remains defined as an integer but instead of being a usize, it's changed to fit the [standard library definition](a41fc00eaf/library/std/src/os/windows/raw.rs (L12-L16)
):
```rust
#[cfg(target_pointer_width = "32")]
pub type SOCKET = u32;
#[cfg(target_pointer_width = "64")]
pub type SOCKET = u64;
```
The generated bindings also customizes the `#[link]` imports. I hope to switch to using raw-dylib but I don't want to tie that too closely with the switch to windows-sys.
---
Changes outside of the bindings are, for the most part, fairly minimal (e.g. some differences in `*mut` vs. `*const` or a few types differ). One issue is that our own bindings sometimes mix in higher level types, like `BorrowedHandle`. This is pretty adhoc though.
This commit is contained in:
commit
7e7483d26e
23 changed files with 7180 additions and 3091 deletions
29
Cargo.lock
29
Cargo.lock
|
@ -1443,6 +1443,13 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generate-windows-sys"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
|
@ -5509,6 +5516,22 @@ dependencies = [
|
|||
"windows-targets 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-bindgen"
|
||||
version = "0.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6935fb09b84ee57929ae92518b475f5dfdfbeb87c5334756acc28ee8e202b60"
|
||||
dependencies = [
|
||||
"windows-metadata",
|
||||
"windows-tokens",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-metadata"
|
||||
version = "0.49.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f5bca94a32bf1e6a376522b6601275a3b611ee885ec0f1b6a05f17e8cfd3385"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.42.0"
|
||||
|
@ -5572,6 +5595,12 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-tokens"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b34c9a3b28cb41db7385546f7f9a8179348dffc89923dde66857b1ba5312f6b4"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.2"
|
||||
|
|
|
@ -39,6 +39,7 @@ members = [
|
|||
"src/tools/collect-license-metadata",
|
||||
"src/tools/generate-copyright",
|
||||
"src/tools/suggest-tests",
|
||||
"src/tools/generate-windows-sys",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
|
|
@ -110,7 +110,7 @@ impl BorrowedSocket<'_> {
|
|||
/// object as the existing `BorrowedSocket` instance.
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub fn try_clone_to_owned(&self) -> io::Result<OwnedSocket> {
|
||||
let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFO>() };
|
||||
let mut info = unsafe { mem::zeroed::<c::WSAPROTOCOL_INFOW>() };
|
||||
let result = unsafe {
|
||||
c::WSADuplicateSocketW(self.as_raw_socket(), c::GetCurrentProcessId(), &mut info)
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
2590
library/std/src/sys/windows/c/windows_sys.lst
Normal file
2590
library/std/src/sys/windows/c/windows_sys.lst
Normal file
File diff suppressed because it is too large
Load diff
4276
library/std/src/sys/windows/c/windows_sys.rs
Normal file
4276
library/std/src/sys/windows/c/windows_sys.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -114,17 +114,20 @@ impl Module {
|
|||
/// (e.g. kernel32 and ntdll).
|
||||
pub unsafe fn new(name: &CStr) -> Option<Self> {
|
||||
// SAFETY: A CStr is always null terminated.
|
||||
let module = c::GetModuleHandleA(name.as_ptr());
|
||||
let module = c::GetModuleHandleA(name.as_ptr().cast::<u8>());
|
||||
NonNull::new(module).map(Self)
|
||||
}
|
||||
|
||||
// Try to get the address of a function.
|
||||
pub fn proc_address(self, name: &CStr) -> Option<NonNull<c_void>> {
|
||||
// SAFETY:
|
||||
// `self.0` will always be a valid module.
|
||||
// A CStr is always null terminated.
|
||||
let proc = unsafe { c::GetProcAddress(self.0.as_ptr(), name.as_ptr()) };
|
||||
NonNull::new(proc)
|
||||
unsafe {
|
||||
// SAFETY:
|
||||
// `self.0` will always be a valid module.
|
||||
// A CStr is always null terminated.
|
||||
let proc = c::GetProcAddress(self.0.as_ptr(), name.as_ptr().cast::<u8>());
|
||||
// SAFETY: `GetProcAddress` returns None on null.
|
||||
proc.map(|p| NonNull::new_unchecked(p as *mut c_void))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,6 +202,7 @@ macro_rules! compat_fn_optional {
|
|||
)+) => (
|
||||
$(
|
||||
pub mod $symbol {
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
use crate::ffi::c_void;
|
||||
use crate::mem;
|
||||
|
|
|
@ -89,6 +89,12 @@ pub struct FileTimes {
|
|||
accessed: Option<c::FILETIME>,
|
||||
modified: Option<c::FILETIME>,
|
||||
}
|
||||
impl core::fmt::Debug for c::FILETIME {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64;
|
||||
f.debug_tuple("FILETIME").field(&time).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder;
|
||||
|
@ -290,6 +296,7 @@ impl File {
|
|||
ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
let handle = unsafe { HandleOrInvalid::from_raw_handle(handle) };
|
||||
if let Ok(handle) = handle.try_into() {
|
||||
Ok(File { handle: Handle::from_inner(handle) })
|
||||
} else {
|
||||
|
@ -501,7 +508,8 @@ impl File {
|
|||
}
|
||||
|
||||
fn readlink(&self) -> io::Result<PathBuf> {
|
||||
let mut space = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
|
||||
let mut space =
|
||||
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
|
||||
let (_bytes, buf) = self.reparse_point(&mut space)?;
|
||||
unsafe {
|
||||
let (path_buffer, subst_off, subst_len, relative) = match (*buf).ReparseTag {
|
||||
|
@ -589,7 +597,11 @@ impl File {
|
|||
));
|
||||
}
|
||||
cvt(unsafe {
|
||||
c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref())
|
||||
let accessed =
|
||||
times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
|
||||
let modified =
|
||||
times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
|
||||
c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified)
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -618,9 +630,9 @@ impl File {
|
|||
/// then errors will be `ERROR_NOT_SUPPORTED` or `ERROR_INVALID_PARAMETER`.
|
||||
fn posix_delete(&self) -> io::Result<()> {
|
||||
let mut info = c::FILE_DISPOSITION_INFO_EX {
|
||||
Flags: c::FILE_DISPOSITION_DELETE
|
||||
| c::FILE_DISPOSITION_POSIX_SEMANTICS
|
||||
| c::FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
|
||||
Flags: c::FILE_DISPOSITION_FLAG_DELETE
|
||||
| c::FILE_DISPOSITION_FLAG_POSIX_SEMANTICS
|
||||
| c::FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE,
|
||||
};
|
||||
let size = mem::size_of_val(&info);
|
||||
cvt(unsafe {
|
||||
|
@ -791,15 +803,15 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<
|
|||
// See https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntcreatefile
|
||||
unsafe {
|
||||
let mut handle = ptr::null_mut();
|
||||
let mut io_status = c::IO_STATUS_BLOCK::default();
|
||||
let name_str = c::UNICODE_STRING::from_ref(name);
|
||||
let mut io_status = c::IO_STATUS_BLOCK::PENDING;
|
||||
let mut name_str = c::UNICODE_STRING::from_ref(name);
|
||||
use crate::sync::atomic::{AtomicU32, Ordering};
|
||||
// The `OBJ_DONT_REPARSE` attribute ensures that we haven't been
|
||||
// tricked into following a symlink. However, it may not be available in
|
||||
// earlier versions of Windows.
|
||||
static ATTRIBUTES: AtomicU32 = AtomicU32::new(c::OBJ_DONT_REPARSE);
|
||||
let object = c::OBJECT_ATTRIBUTES {
|
||||
ObjectName: &name_str,
|
||||
let mut object = c::OBJECT_ATTRIBUTES {
|
||||
ObjectName: &mut name_str,
|
||||
RootDirectory: parent.as_raw_handle(),
|
||||
Attributes: ATTRIBUTES.load(Ordering::Relaxed),
|
||||
..c::OBJECT_ATTRIBUTES::default()
|
||||
|
@ -807,7 +819,7 @@ fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<
|
|||
let status = c::NtCreateFile(
|
||||
&mut handle,
|
||||
access,
|
||||
&object,
|
||||
&mut object,
|
||||
&mut io_status,
|
||||
crate::ptr::null_mut(),
|
||||
0,
|
||||
|
@ -1368,7 +1380,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
|||
_dwCallbackReason: c::DWORD,
|
||||
_hSourceFile: c::HANDLE,
|
||||
_hDestinationFile: c::HANDLE,
|
||||
lpData: c::LPVOID,
|
||||
lpData: c::LPCVOID,
|
||||
) -> c::DWORD {
|
||||
if dwStreamNumber == 1 {
|
||||
*(lpData as *mut i64) = StreamBytesTransferred;
|
||||
|
@ -1415,9 +1427,10 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
|
|||
let f = File::open(junction, &opts)?;
|
||||
let h = f.as_inner().as_raw_handle();
|
||||
unsafe {
|
||||
let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
|
||||
let mut data =
|
||||
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
|
||||
let data_ptr = data.0.as_mut_ptr();
|
||||
let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||
let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize);
|
||||
let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
|
||||
// Zero the header to ensure it's fully initialized, including reserved parameters.
|
||||
*db = mem::zeroed();
|
||||
|
|
|
@ -144,7 +144,7 @@ impl Handle {
|
|||
let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
|
||||
let mut amt = 0;
|
||||
let res = cvt(c::ReadFile(
|
||||
self.as_handle(),
|
||||
self.as_raw_handle(),
|
||||
buf.as_ptr() as c::LPVOID,
|
||||
len,
|
||||
&mut amt,
|
||||
|
@ -235,7 +235,7 @@ impl Handle {
|
|||
len: usize,
|
||||
offset: Option<u64>,
|
||||
) -> io::Result<usize> {
|
||||
let mut io_status = c::IO_STATUS_BLOCK::default();
|
||||
let mut io_status = c::IO_STATUS_BLOCK::PENDING;
|
||||
|
||||
// The length is clamped at u32::MAX.
|
||||
let len = cmp::min(len, c::DWORD::MAX as usize) as c::DWORD;
|
||||
|
@ -283,7 +283,7 @@ impl Handle {
|
|||
///
|
||||
/// If `offset` is `None` then the current file position is used.
|
||||
fn synchronous_write(&self, buf: &[u8], offset: Option<u64>) -> io::Result<usize> {
|
||||
let mut io_status = c::IO_STATUS_BLOCK::default();
|
||||
let mut io_status = c::IO_STATUS_BLOCK::PENDING;
|
||||
|
||||
// The length is clamped at u32::MAX.
|
||||
let len = cmp::min(buf.len(), c::DWORD::MAX as usize) as c::DWORD;
|
||||
|
|
|
@ -17,10 +17,7 @@ impl<'a> IoSlice<'a> {
|
|||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
assert!(buf.len() <= c::ULONG::MAX as usize);
|
||||
IoSlice {
|
||||
vec: c::WSABUF {
|
||||
len: buf.len() as c::ULONG,
|
||||
buf: buf.as_ptr() as *mut u8 as *mut c::CHAR,
|
||||
},
|
||||
vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_ptr() as *mut u8 },
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +51,7 @@ impl<'a> IoSliceMut<'a> {
|
|||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
assert!(buf.len() <= c::ULONG::MAX as usize);
|
||||
IoSliceMut {
|
||||
vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() as *mut c::CHAR },
|
||||
vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() },
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ impl Socket {
|
|||
&mut nread,
|
||||
&mut flags,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -347,7 +347,7 @@ impl Socket {
|
|||
&mut nwritten,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
)
|
||||
};
|
||||
cvt(result).map(|_| nwritten as usize)
|
||||
|
|
|
@ -373,7 +373,7 @@ impl AnonPipe {
|
|||
|
||||
// Asynchronous read of the pipe.
|
||||
// If successful, `callback` will be called once it completes.
|
||||
let result = io(self.inner.as_handle(), buf, len, &mut overlapped, callback);
|
||||
let result = io(self.inner.as_handle(), buf, len, &mut overlapped, Some(callback));
|
||||
if result == c::FALSE {
|
||||
// We can return here because the call failed.
|
||||
// After this we must not return until the I/O completes.
|
||||
|
|
|
@ -308,7 +308,7 @@ impl Command {
|
|||
let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?;
|
||||
|
||||
let mut si = zeroed_startupinfo();
|
||||
si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD;
|
||||
si.cb = mem::size_of::<c::STARTUPINFOW>() as c::DWORD;
|
||||
|
||||
// If at least one of stdin, stdout or stderr are set (i.e. are non null)
|
||||
// then set the `hStd` fields in `STARTUPINFO`.
|
||||
|
@ -332,7 +332,7 @@ impl Command {
|
|||
flags,
|
||||
envp,
|
||||
dirp,
|
||||
&mut si,
|
||||
&si,
|
||||
&mut pi,
|
||||
))
|
||||
}?;
|
||||
|
@ -720,8 +720,8 @@ impl From<u32> for ExitCode {
|
|||
}
|
||||
}
|
||||
|
||||
fn zeroed_startupinfo() -> c::STARTUPINFO {
|
||||
c::STARTUPINFO {
|
||||
fn zeroed_startupinfo() -> c::STARTUPINFOW {
|
||||
c::STARTUPINFOW {
|
||||
cb: 0,
|
||||
lpReserved: ptr::null_mut(),
|
||||
lpDesktop: ptr::null_mut(),
|
||||
|
@ -731,7 +731,7 @@ fn zeroed_startupinfo() -> c::STARTUPINFO {
|
|||
dwXSize: 0,
|
||||
dwYSize: 0,
|
||||
dwXCountChars: 0,
|
||||
dwYCountCharts: 0,
|
||||
dwYCountChars: 0,
|
||||
dwFillAttribute: 0,
|
||||
dwFlags: 0,
|
||||
wShowWindow: 0,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::ffi::c_void;
|
||||
use crate::io;
|
||||
use crate::mem;
|
||||
use crate::ptr;
|
||||
|
@ -25,8 +26,9 @@ pub fn hashmap_random_keys() -> (u64, u64) {
|
|||
#[inline(never)]
|
||||
fn fallback_rng() -> (u64, u64) {
|
||||
let mut v = (0, 0);
|
||||
let ret =
|
||||
unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
|
||||
let ret = unsafe {
|
||||
c::RtlGenRandom(&mut v as *mut _ as *mut c_void, mem::size_of_val(&v) as c::ULONG)
|
||||
};
|
||||
|
||||
if ret != 0 { v } else { panic!("fallback RNG broken: {}", io::Error::last_os_error()) }
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ impl Handler {
|
|||
}
|
||||
}
|
||||
|
||||
extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG {
|
||||
unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG {
|
||||
unsafe {
|
||||
let rec = &(*(*ExceptionInfo).ExceptionRecord);
|
||||
let code = rec.ExceptionCode;
|
||||
|
@ -34,7 +34,7 @@ extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -
|
|||
}
|
||||
|
||||
pub unsafe fn init() {
|
||||
if c::AddVectoredExceptionHandler(0, vectored_handler).is_null() {
|
||||
if c::AddVectoredExceptionHandler(0, Some(vectored_handler)).is_null() {
|
||||
panic!("failed to install exception handler");
|
||||
}
|
||||
// Set the thread stack guarantee for the main thread.
|
||||
|
|
|
@ -180,7 +180,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
|
|||
let result = c::MultiByteToWideChar(
|
||||
c::CP_UTF8, // CodePage
|
||||
c::MB_ERR_INVALID_CHARS, // dwFlags
|
||||
utf8.as_ptr() as c::LPCCH, // lpMultiByteStr
|
||||
utf8.as_ptr(), // lpMultiByteStr
|
||||
utf8.len() as c::c_int, // cbMultiByte
|
||||
utf16.as_mut_ptr() as c::LPWSTR, // lpWideCharStr
|
||||
utf16.len() as c::c_int, // cchWideChar
|
||||
|
@ -344,7 +344,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
|
|||
// See #38274 and https://stackoverflow.com/questions/43836040/win-api-readconsole.
|
||||
const CTRL_Z: u16 = 0x1A;
|
||||
const CTRL_Z_MASK: c::ULONG = 1 << CTRL_Z;
|
||||
let mut input_control = c::CONSOLE_READCONSOLE_CONTROL {
|
||||
let input_control = c::CONSOLE_READCONSOLE_CONTROL {
|
||||
nLength: crate::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
|
||||
nInitialChars: 0,
|
||||
dwCtrlWakeupMask: CTRL_Z_MASK,
|
||||
|
@ -360,7 +360,7 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
|
|||
buf.as_mut_ptr() as c::LPVOID,
|
||||
buf.len() as u32,
|
||||
&mut amount,
|
||||
&mut input_control as c::PCONSOLE_READCONSOLE_CONTROL,
|
||||
&input_control,
|
||||
)
|
||||
})?;
|
||||
|
||||
|
@ -385,14 +385,14 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
|
|||
|
||||
let result = unsafe {
|
||||
c::WideCharToMultiByte(
|
||||
c::CP_UTF8, // CodePage
|
||||
c::WC_ERR_INVALID_CHARS, // dwFlags
|
||||
utf16.as_ptr(), // lpWideCharStr
|
||||
utf16.len() as c::c_int, // cchWideChar
|
||||
utf8.as_mut_ptr() as c::LPSTR, // lpMultiByteStr
|
||||
utf8.len() as c::c_int, // cbMultiByte
|
||||
ptr::null(), // lpDefaultChar
|
||||
ptr::null_mut(), // lpUsedDefaultChar
|
||||
c::CP_UTF8, // CodePage
|
||||
c::WC_ERR_INVALID_CHARS, // dwFlags
|
||||
utf16.as_ptr(), // lpWideCharStr
|
||||
utf16.len() as c::c_int, // cchWideChar
|
||||
utf8.as_mut_ptr(), // lpMultiByteStr
|
||||
utf8.len() as c::c_int, // cbMultiByte
|
||||
ptr::null(), // lpDefaultChar
|
||||
ptr::null_mut(), // lpUsedDefaultChar
|
||||
)
|
||||
};
|
||||
if result == 0 {
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::ffi::CStr;
|
|||
use crate::io;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::os::windows::io::AsRawHandle;
|
||||
use crate::os::windows::io::HandleOrNull;
|
||||
use crate::ptr;
|
||||
use crate::sys::c;
|
||||
use crate::sys::handle::Handle;
|
||||
|
@ -32,12 +33,12 @@ impl Thread {
|
|||
let ret = c::CreateThread(
|
||||
ptr::null_mut(),
|
||||
stack,
|
||||
thread_start,
|
||||
Some(thread_start),
|
||||
p as *mut _,
|
||||
c::STACK_SIZE_PARAM_IS_A_RESERVATION,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
|
||||
let ret = HandleOrNull::from_raw_handle(ret);
|
||||
return if let Ok(handle) = ret.try_into() {
|
||||
Ok(Thread { handle: Handle::from_inner(handle) })
|
||||
} else {
|
||||
|
|
|
@ -838,6 +838,7 @@ impl<'a> Builder<'a> {
|
|||
run::Miri,
|
||||
run::CollectLicenseMetadata,
|
||||
run::GenerateCopyright,
|
||||
run::GenerateWindowsSys,
|
||||
),
|
||||
Kind::Setup => describe!(setup::Profile, setup::Hook, setup::Link, setup::Vscode),
|
||||
Kind::Clean => describe!(clean::CleanAll, clean::Rustc, clean::Std),
|
||||
|
|
|
@ -253,3 +253,25 @@ impl Step for GenerateCopyright {
|
|||
dest
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct GenerateWindowsSys;
|
||||
|
||||
impl Step for GenerateWindowsSys {
|
||||
type Output = ();
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/generate-windows-sys")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
run.builder.ensure(GenerateWindowsSys);
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
let mut cmd = builder.tool_cmd(Tool::GenerateWindowsSys);
|
||||
cmd.arg(&builder.src);
|
||||
builder.run(&mut cmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,6 +301,7 @@ bootstrap_tool!(
|
|||
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata";
|
||||
GenerateCopyright, "src/tools/generate-copyright", "generate-copyright";
|
||||
SuggestTests, "src/tools/suggest-tests", "suggest-tests";
|
||||
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
|
||||
);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
||||
|
|
7
src/tools/generate-windows-sys/Cargo.toml
Normal file
7
src/tools/generate-windows-sys/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "generate-windows-sys"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies.windows-bindgen]
|
||||
version = "0.49"
|
37
src/tools/generate-windows-sys/src/main.rs
Normal file
37
src/tools/generate-windows-sys/src/main.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
use std::fs;
|
||||
use std::io::{self, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// This is printed to the file before the rest of the contents.
|
||||
const PRELUDE: &str = r#"// This file is autogenerated.
|
||||
//
|
||||
// To add bindings, edit windows_sys.lst then use `./x run generate-windows-sys` to
|
||||
// regenerate the bindings.
|
||||
//
|
||||
// ignore-tidy-filelength
|
||||
"#;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let mut path: PathBuf =
|
||||
std::env::args_os().nth(1).expect("a path to the rust repository is required").into();
|
||||
path.push("library/std/src/sys/windows/c/windows_sys.lst");
|
||||
|
||||
// Load the list of APIs
|
||||
let buffer = fs::read_to_string(&path)?;
|
||||
let names: Vec<&str> = buffer
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
let line = line.trim();
|
||||
if line.is_empty() || line.starts_with("//") { None } else { Some(line) }
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Write the bindings to windows-sys.rs
|
||||
let bindings = windows_bindgen::standalone_std(&names);
|
||||
path.set_extension("rs");
|
||||
let mut f = std::fs::File::create(&path)?;
|
||||
f.write_all(PRELUDE.as_bytes())?;
|
||||
f.write_all(bindings.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Reference in a new issue