diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /library/std/src/sys/windows | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/sys/windows')
-rw-r--r-- | library/std/src/sys/windows/args.rs | 4 | ||||
-rw-r--r-- | library/std/src/sys/windows/c.rs | 6 | ||||
-rw-r--r-- | library/std/src/sys/windows/c/windows_sys.lst | 21 | ||||
-rw-r--r-- | library/std/src/sys/windows/c/windows_sys.rs | 201 | ||||
-rw-r--r-- | library/std/src/sys/windows/handle.rs | 9 | ||||
-rw-r--r-- | library/std/src/sys/windows/mod.rs | 5 | ||||
-rw-r--r-- | library/std/src/sys/windows/net.rs | 38 | ||||
-rw-r--r-- | library/std/src/sys/windows/os_str.rs | 8 | ||||
-rw-r--r-- | library/std/src/sys/windows/path.rs | 28 | ||||
-rw-r--r-- | library/std/src/sys/windows/pipe.rs | 8 | ||||
-rw-r--r-- | library/std/src/sys/windows/process.rs | 151 |
11 files changed, 323 insertions, 156 deletions
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index 6b597f499..ee7dba6e5 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -226,7 +226,7 @@ pub(crate) fn append_arg(cmd: &mut Vec<u16>, arg: &Arg, force_quotes: bool) -> i // that it actually gets passed through on the command line or otherwise // it will be dropped entirely when parsed on the other end. ensure_no_nuls(arg)?; - let arg_bytes = arg.as_os_str_bytes(); + let arg_bytes = arg.as_encoded_bytes(); let (quote, escape) = match quote { Quote::Always => (true, true), Quote::Auto => { @@ -298,7 +298,7 @@ pub(crate) fn make_bat_command_line( const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>"; let force_quotes = match arg { Arg::Regular(arg) if !force_quotes => { - arg.as_os_str_bytes().iter().any(|c| SPECIAL.contains(c)) + arg.as_encoded_bytes().iter().any(|c| SPECIAL.contains(c)) } _ => force_quotes, }; diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index d9ccba0e9..f3637cbb9 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -46,10 +46,6 @@ pub use FD_SET as fd_set; pub use LINGER as linger; pub use TIMEVAL as timeval; -pub type CONDITION_VARIABLE = RTL_CONDITION_VARIABLE; -pub type SRWLOCK = RTL_SRWLOCK; -pub type INIT_ONCE = RTL_RUN_ONCE; - pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() }; pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() }; pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() }; @@ -224,7 +220,7 @@ pub unsafe extern "system" fn ReadFileEx( ) -> BOOL { windows_sys::ReadFileEx( hFile.as_raw_handle(), - lpBuffer, + lpBuffer.cast::<u8>(), nNumberOfBytesToRead, lpOverlapped, lpCompletionRoutine, diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 631aedd26..0aca37e2d 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -1,3 +1,6 @@ +--out windows_sys.rs +--config flatten std +--filter // tidy-alphabetical-start Windows.Wdk.Storage.FileSystem.FILE_COMPLETE_IF_OPLOCKED Windows.Wdk.Storage.FileSystem.FILE_CONTAINS_EXTENDED_CREATE_INFORMATION @@ -2108,7 +2111,6 @@ Windows.Win32.Networking.WinSock.WSABASEERR Windows.Win32.Networking.WinSock.WSABUF Windows.Win32.Networking.WinSock.WSACleanup Windows.Win32.Networking.WinSock.WSADATA -Windows.Win32.Networking.WinSock.WSADATA Windows.Win32.Networking.WinSock.WSADuplicateSocketW Windows.Win32.Networking.WinSock.WSAEACCES Windows.Win32.Networking.WinSock.WSAEADDRINUSE @@ -2328,7 +2330,6 @@ Windows.Win32.Storage.FileSystem.FileStandardInfo Windows.Win32.Storage.FileSystem.FileStorageInfo Windows.Win32.Storage.FileSystem.FileStreamInfo Windows.Win32.Storage.FileSystem.FindClose -Windows.Win32.Storage.FileSystem.FindFileHandle Windows.Win32.Storage.FileSystem.FindFirstFileW Windows.Win32.Storage.FileSystem.FindNextFileW Windows.Win32.Storage.FileSystem.FlushFileBuffers @@ -2420,8 +2421,6 @@ Windows.Win32.System.Console.STD_OUTPUT_HANDLE Windows.Win32.System.Console.WriteConsoleW Windows.Win32.System.Diagnostics.Debug.ARM64_NT_NEON128 Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT -Windows.Win32.System.Diagnostics.Debug.CONTEXT Windows.Win32.System.Diagnostics.Debug.EXCEPTION_RECORD Windows.Win32.System.Diagnostics.Debug.FACILITY_CODE Windows.Win32.System.Diagnostics.Debug.FACILITY_NT_BIT @@ -2435,7 +2434,6 @@ Windows.Win32.System.Diagnostics.Debug.FORMAT_MESSAGE_OPTIONS Windows.Win32.System.Diagnostics.Debug.FormatMessageW Windows.Win32.System.Diagnostics.Debug.M128A Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT -Windows.Win32.System.Diagnostics.Debug.XSAVE_FORMAT Windows.Win32.System.Environment.FreeEnvironmentStringsW Windows.Win32.System.Environment.GetCommandLineW Windows.Win32.System.Environment.GetCurrentDirectoryW @@ -2456,7 +2454,6 @@ Windows.Win32.System.Kernel.ExceptionContinueExecution Windows.Win32.System.Kernel.ExceptionContinueSearch Windows.Win32.System.Kernel.ExceptionNestedException Windows.Win32.System.Kernel.FLOATING_SAVE_AREA -Windows.Win32.System.Kernel.FLOATING_SAVE_AREA Windows.Win32.System.Kernel.OBJ_DONT_REPARSE Windows.Win32.System.LibraryLoader.GetModuleFileNameW Windows.Win32.System.LibraryLoader.GetModuleHandleA @@ -2482,6 +2479,7 @@ Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime Windows.Win32.System.SystemInformation.GetWindowsDirectoryW Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE Windows.Win32.System.SystemInformation.SYSTEM_INFO +Windows.Win32.System.SystemServices.ALL_PROCESSOR_GROUPS Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH Windows.Win32.System.SystemServices.DLL_THREAD_DETACH Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS @@ -2510,9 +2508,11 @@ Windows.Win32.System.Threading.CreateProcessW Windows.Win32.System.Threading.CreateThread Windows.Win32.System.Threading.DEBUG_ONLY_THIS_PROCESS Windows.Win32.System.Threading.DEBUG_PROCESS +Windows.Win32.System.Threading.DeleteProcThreadAttributeList Windows.Win32.System.Threading.DETACHED_PROCESS Windows.Win32.System.Threading.ExitProcess Windows.Win32.System.Threading.EXTENDED_STARTUPINFO_PRESENT +Windows.Win32.System.Threading.GetActiveProcessorCount Windows.Win32.System.Threading.GetCurrentProcess Windows.Win32.System.Threading.GetCurrentProcessId Windows.Win32.System.Threading.GetCurrentThread @@ -2524,8 +2524,10 @@ Windows.Win32.System.Threading.INFINITE Windows.Win32.System.Threading.INHERIT_CALLER_PRIORITY Windows.Win32.System.Threading.INHERIT_PARENT_AFFINITY Windows.Win32.System.Threading.INIT_ONCE_INIT_FAILED +Windows.Win32.System.Threading.InitializeProcThreadAttributeList Windows.Win32.System.Threading.InitOnceBeginInitialize Windows.Win32.System.Threading.InitOnceComplete +Windows.Win32.System.Threading.LPPROC_THREAD_ATTRIBUTE_LIST Windows.Win32.System.Threading.LPTHREAD_START_ROUTINE Windows.Win32.System.Threading.NORMAL_PRIORITY_CLASS Windows.Win32.System.Threading.OpenProcessToken @@ -2539,9 +2541,6 @@ Windows.Win32.System.Threading.PROFILE_USER Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS Windows.Win32.System.Threading.ReleaseSRWLockExclusive Windows.Win32.System.Threading.ReleaseSRWLockShared -Windows.Win32.System.Threading.RTL_CONDITION_VARIABLE -Windows.Win32.System.Threading.RTL_RUN_ONCE -Windows.Win32.System.Threading.RTL_SRWLOCK Windows.Win32.System.Threading.SetThreadStackGuarantee Windows.Win32.System.Threading.Sleep Windows.Win32.System.Threading.SleepConditionVariableSRW @@ -2561,6 +2560,7 @@ Windows.Win32.System.Threading.STARTF_USEPOSITION Windows.Win32.System.Threading.STARTF_USESHOWWINDOW Windows.Win32.System.Threading.STARTF_USESIZE Windows.Win32.System.Threading.STARTF_USESTDHANDLES +Windows.Win32.System.Threading.STARTUPINFOEXW Windows.Win32.System.Threading.STARTUPINFOW Windows.Win32.System.Threading.STARTUPINFOW_FLAGS Windows.Win32.System.Threading.SwitchToThread @@ -2575,12 +2575,11 @@ Windows.Win32.System.Threading.TlsGetValue Windows.Win32.System.Threading.TlsSetValue Windows.Win32.System.Threading.TryAcquireSRWLockExclusive Windows.Win32.System.Threading.TryAcquireSRWLockShared +Windows.Win32.System.Threading.UpdateProcThreadAttribute Windows.Win32.System.Threading.WaitForMultipleObjects Windows.Win32.System.Threading.WaitForSingleObject Windows.Win32.System.Threading.WakeAllConditionVariable Windows.Win32.System.Threading.WakeConditionVariable -Windows.Win32.System.WindowsProgramming.IO_STATUS_BLOCK -Windows.Win32.System.WindowsProgramming.OBJECT_ATTRIBUTES Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE Windows.Win32.UI.Shell.GetUserProfileDirectoryW // tidy-alphabetical-end diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index 023770871..851d15915 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -4,7 +4,7 @@ // regenerate the bindings. // // ignore-tidy-filelength -// Bindings generated by `windows-bindgen` 0.49.0 +// Bindings generated by `windows-bindgen` 0.51.1 #![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)] #[link(name = "advapi32")] @@ -32,11 +32,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn AcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn AcquireSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -156,6 +156,10 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { + pub fn DeleteProcThreadAttributeList(lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST) -> (); +} +#[link(name = "kernel32")] +extern "system" { pub fn DeviceIoControl( hdevice: HANDLE, dwiocontrolcode: u32, @@ -185,18 +189,15 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn FindClose(hfindfile: FindFileHandle) -> BOOL; + pub fn FindClose(hfindfile: HANDLE) -> BOOL; } #[link(name = "kernel32")] extern "system" { - pub fn FindFirstFileW( - lpfilename: PCWSTR, - lpfindfiledata: *mut WIN32_FIND_DATAW, - ) -> FindFileHandle; + pub fn FindFirstFileW(lpfilename: PCWSTR, lpfindfiledata: *mut WIN32_FIND_DATAW) -> HANDLE; } #[link(name = "kernel32")] extern "system" { - pub fn FindNextFileW(hfindfile: FindFileHandle, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; + pub fn FindNextFileW(hfindfile: HANDLE, lpfindfiledata: *mut WIN32_FIND_DATAW) -> BOOL; } #[link(name = "kernel32")] extern "system" { @@ -220,6 +221,10 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { + pub fn GetActiveProcessorCount(groupnumber: u16) -> u32; +} +#[link(name = "kernel32")] +extern "system" { pub fn GetCommandLineW() -> PCWSTR; } #[link(name = "kernel32")] @@ -356,7 +361,7 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceBeginInitialize( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, fpending: *mut BOOL, lpcontext: *mut *mut ::core::ffi::c_void, @@ -365,13 +370,22 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn InitOnceComplete( - lpinitonce: *mut RTL_RUN_ONCE, + lpinitonce: *mut INIT_ONCE, dwflags: u32, lpcontext: *const ::core::ffi::c_void, ) -> BOOL; } #[link(name = "kernel32")] extern "system" { + pub fn InitializeProcThreadAttributeList( + lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST, + dwattributecount: u32, + dwflags: u32, + lpsize: *mut usize, + ) -> BOOL; +} +#[link(name = "kernel32")] +extern "system" { pub fn MoveFileExW( lpexistingfilename: PCWSTR, lpnewfilename: PCWSTR, @@ -411,7 +425,7 @@ extern "system" { extern "system" { pub fn ReadFile( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpnumberofbytesread: *mut u32, lpoverlapped: *mut OVERLAPPED, @@ -421,7 +435,7 @@ extern "system" { extern "system" { pub fn ReadFileEx( hfile: HANDLE, - lpbuffer: *mut ::core::ffi::c_void, + lpbuffer: *mut u8, nnumberofbytestoread: u32, lpoverlapped: *mut OVERLAPPED, lpcompletionroutine: LPOVERLAPPED_COMPLETION_ROUTINE, @@ -429,11 +443,11 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockExclusive(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn ReleaseSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> (); + pub fn ReleaseSRWLockShared(srwlock: *mut SRWLOCK) -> (); } #[link(name = "kernel32")] extern "system" { @@ -500,8 +514,8 @@ extern "system" { #[link(name = "kernel32")] extern "system" { pub fn SleepConditionVariableSRW( - conditionvariable: *mut RTL_CONDITION_VARIABLE, - srwlock: *mut RTL_SRWLOCK, + conditionvariable: *mut CONDITION_VARIABLE, + srwlock: *mut SRWLOCK, dwmilliseconds: u32, flags: u32, ) -> BOOL; @@ -536,11 +550,23 @@ extern "system" { } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockExclusive(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn TryAcquireSRWLockExclusive(srwlock: *mut SRWLOCK) -> BOOLEAN; +} +#[link(name = "kernel32")] +extern "system" { + pub fn TryAcquireSRWLockShared(srwlock: *mut SRWLOCK) -> BOOLEAN; } #[link(name = "kernel32")] extern "system" { - pub fn TryAcquireSRWLockShared(srwlock: *mut RTL_SRWLOCK) -> BOOLEAN; + pub fn UpdateProcThreadAttribute( + lpattributelist: LPPROC_THREAD_ATTRIBUTE_LIST, + dwflags: u32, + attribute: usize, + lpvalue: *const ::core::ffi::c_void, + cbsize: usize, + lppreviousvalue: *mut ::core::ffi::c_void, + lpreturnsize: *const usize, + ) -> BOOL; } #[link(name = "kernel32")] extern "system" { @@ -549,19 +575,19 @@ extern "system" { lphandles: *const HANDLE, bwaitall: BOOL, dwmilliseconds: u32, - ) -> WIN32_ERROR; + ) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR; + pub fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WAIT_EVENT; } #[link(name = "kernel32")] extern "system" { - pub fn WakeAllConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeAllConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { - pub fn WakeConditionVariable(conditionvariable: *mut RTL_CONDITION_VARIABLE) -> (); + pub fn WakeConditionVariable(conditionvariable: *mut CONDITION_VARIABLE) -> (); } #[link(name = "kernel32")] extern "system" { @@ -822,6 +848,7 @@ impl ::core::clone::Clone for ADDRINFOA { pub const AF_INET: ADDRESS_FAMILY = 2u16; pub const AF_INET6: ADDRESS_FAMILY = 23u16; pub const AF_UNSPEC: ADDRESS_FAMILY = 0u16; +pub const ALL_PROCESSOR_GROUPS: u32 = 65535u32; #[repr(C)] pub union ARM64_NT_NEON128 { pub Anonymous: ARM64_NT_NEON128_0, @@ -874,7 +901,17 @@ impl ::core::clone::Clone for BY_HANDLE_FILE_INFORMATION { } pub const CALLBACK_CHUNK_FINISHED: LPPROGRESS_ROUTINE_CALLBACK_REASON = 0u32; pub const CALLBACK_STREAM_SWITCH: LPPROGRESS_ROUTINE_CALLBACK_REASON = 1u32; -pub type COMPARESTRING_RESULT = u32; +pub type COMPARESTRING_RESULT = i32; +#[repr(C)] +pub struct CONDITION_VARIABLE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for CONDITION_VARIABLE {} +impl ::core::clone::Clone for CONDITION_VARIABLE { + fn clone(&self) -> Self { + *self + } +} pub type CONSOLE_MODE = u32; #[repr(C)] pub struct CONSOLE_READCONSOLE_CONTROL { @@ -892,7 +929,7 @@ impl ::core::clone::Clone for CONSOLE_READCONSOLE_CONTROL { #[repr(C)] #[cfg(target_arch = "aarch64")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Cpsr: u32, pub Anonymous: CONTEXT_0, pub Sp: u64, @@ -979,7 +1016,7 @@ pub struct CONTEXT { pub P4Home: u64, pub P5Home: u64, pub P6Home: u64, - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub MxCsr: u32, pub SegCs: u16, pub SegDs: u16, @@ -1075,7 +1112,7 @@ impl ::core::clone::Clone for CONTEXT_0_0 { #[repr(C)] #[cfg(target_arch = "x86")] pub struct CONTEXT { - pub ContextFlags: u32, + pub ContextFlags: CONTEXT_FLAGS, pub Dr0: u32, pub Dr1: u32, pub Dr2: u32, @@ -1109,6 +1146,7 @@ impl ::core::clone::Clone for CONTEXT { *self } } +pub type CONTEXT_FLAGS = u32; pub const CP_UTF8: u32 = 65001u32; pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32; pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32; @@ -1126,9 +1164,9 @@ pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32; pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32; pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32; pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32; -pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2u32; -pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3u32; -pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1u32; +pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2i32; +pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3i32; +pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1i32; pub const DEBUG_ONLY_THIS_PROCESS: PROCESS_CREATION_FLAGS = 2u32; pub const DEBUG_PROCESS: PROCESS_CREATION_FLAGS = 1u32; pub const DELETE: FILE_ACCESS_RIGHTS = 65536u32; @@ -3344,7 +3382,6 @@ pub const FileRenameInfoEx: FILE_INFO_BY_HANDLE_CLASS = 22i32; pub const FileStandardInfo: FILE_INFO_BY_HANDLE_CLASS = 1i32; pub const FileStorageInfo: FILE_INFO_BY_HANDLE_CLASS = 16i32; pub const FileStreamInfo: FILE_INFO_BY_HANDLE_CLASS = 7i32; -pub type FindFileHandle = *mut ::core::ffi::c_void; pub type GENERIC_ACCESS_RIGHTS = u32; pub const GENERIC_ALL: GENERIC_ACCESS_RIGHTS = 268435456u32; pub const GENERIC_EXECUTE: GENERIC_ACCESS_RIGHTS = 536870912u32; @@ -3358,6 +3395,12 @@ pub struct GUID { pub data3: u16, pub data4: [u8; 8], } +impl ::core::marker::Copy for GUID {} +impl ::core::clone::Clone for GUID { + fn clone(&self) -> Self { + *self + } +} impl GUID { pub const fn from_u128(uuid: u128) -> Self { Self { @@ -3368,12 +3411,6 @@ impl GUID { } } } -impl ::core::marker::Copy for GUID {} -impl ::core::clone::Clone for GUID { - fn clone(&self) -> Self { - *self - } -} pub type HANDLE = *mut ::core::ffi::c_void; pub type HANDLE_FLAGS = u32; pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32; @@ -3406,6 +3443,16 @@ impl ::core::clone::Clone for IN6_ADDR_0 { pub const INFINITE: u32 = 4294967295u32; pub const INHERIT_CALLER_PRIORITY: PROCESS_CREATION_FLAGS = 131072u32; pub const INHERIT_PARENT_AFFINITY: PROCESS_CREATION_FLAGS = 65536u32; +#[repr(C)] +pub union INIT_ONCE { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for INIT_ONCE {} +impl ::core::clone::Clone for INIT_ONCE { + fn clone(&self) -> Self { + *self + } +} pub const INIT_ONCE_INIT_FAILED: u32 = 4u32; pub const INVALID_FILE_ATTRIBUTES: u32 = 4294967295u32; pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::invalid_mut(-1i32 as _); @@ -3567,6 +3614,7 @@ pub type LPOVERLAPPED_COMPLETION_ROUTINE = ::core::option::Option< lpoverlapped: *mut OVERLAPPED, ) -> (), >; +pub type LPPROC_THREAD_ATTRIBUTE_LIST = *mut ::core::ffi::c_void; pub type LPPROGRESS_ROUTINE = ::core::option::Option< unsafe extern "system" fn( totalfilesize: i64, @@ -3633,10 +3681,10 @@ pub type NTSTATUS = i32; pub struct OBJECT_ATTRIBUTES { pub Length: u32, pub RootDirectory: HANDLE, - pub ObjectName: *mut UNICODE_STRING, + pub ObjectName: *const UNICODE_STRING, pub Attributes: u32, - pub SecurityDescriptor: *mut ::core::ffi::c_void, - pub SecurityQualityOfService: *mut ::core::ffi::c_void, + pub SecurityDescriptor: *const ::core::ffi::c_void, + pub SecurityQualityOfService: *const ::core::ffi::c_void, } impl ::core::marker::Copy for OBJECT_ATTRIBUTES {} impl ::core::clone::Clone for OBJECT_ATTRIBUTES { @@ -3686,8 +3734,8 @@ pub type PCSTR = *const u8; pub type PCWSTR = *const u16; pub type PIO_APC_ROUTINE = ::core::option::Option< unsafe extern "system" fn( - apccontext: *const ::core::ffi::c_void, - iostatusblock: *const IO_STATUS_BLOCK, + apccontext: *mut ::core::ffi::c_void, + iostatusblock: *mut IO_STATUS_BLOCK, reserved: u32, ) -> (), >; @@ -3729,36 +3777,6 @@ pub type PSTR = *mut u8; pub type PWSTR = *mut u16; pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; -#[repr(C)] -pub struct RTL_CONDITION_VARIABLE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_CONDITION_VARIABLE {} -impl ::core::clone::Clone for RTL_CONDITION_VARIABLE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub union RTL_RUN_ONCE { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_RUN_ONCE {} -impl ::core::clone::Clone for RTL_RUN_ONCE { - fn clone(&self) -> Self { - *self - } -} -#[repr(C)] -pub struct RTL_SRWLOCK { - pub Ptr: *mut ::core::ffi::c_void, -} -impl ::core::marker::Copy for RTL_SRWLOCK {} -impl ::core::clone::Clone for RTL_SRWLOCK { - fn clone(&self) -> Self { - *self - } -} pub const SD_BOTH: WINSOCK_SHUTDOWN_HOW = 2i32; pub const SD_RECEIVE: WINSOCK_SHUTDOWN_HOW = 0i32; pub const SD_SEND: WINSOCK_SHUTDOWN_HOW = 1i32; @@ -3795,10 +3813,7 @@ impl ::core::clone::Clone for SOCKADDR { *self } } -#[cfg(target_pointer_width = "32")] -pub type SOCKET = u32; -#[cfg(target_pointer_width = "64")] -pub type SOCKET = u64; +pub type SOCKET = usize; pub const SOCKET_ERROR: i32 = -1i32; pub const SOCK_DGRAM: WINSOCK_SOCKET_TYPE = 2i32; pub const SOCK_RAW: WINSOCK_SOCKET_TYPE = 3i32; @@ -3812,6 +3827,16 @@ pub const SO_LINGER: i32 = 128i32; pub const SO_RCVTIMEO: i32 = 4102i32; pub const SO_SNDTIMEO: i32 = 4101i32; pub const SPECIFIC_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 65535u32; +#[repr(C)] +pub struct SRWLOCK { + pub Ptr: *mut ::core::ffi::c_void, +} +impl ::core::marker::Copy for SRWLOCK {} +impl ::core::clone::Clone for SRWLOCK { + fn clone(&self) -> Self { + *self + } +} pub const STACK_SIZE_PARAM_IS_A_RESERVATION: THREAD_CREATION_FLAGS = 65536u32; pub const STANDARD_RIGHTS_ALL: FILE_ACCESS_RIGHTS = 2031616u32; pub const STANDARD_RIGHTS_EXECUTE: FILE_ACCESS_RIGHTS = 131072u32; @@ -3833,6 +3858,17 @@ pub const STARTF_USESHOWWINDOW: STARTUPINFOW_FLAGS = 1u32; pub const STARTF_USESIZE: STARTUPINFOW_FLAGS = 2u32; pub const STARTF_USESTDHANDLES: STARTUPINFOW_FLAGS = 256u32; #[repr(C)] +pub struct STARTUPINFOEXW { + pub StartupInfo: STARTUPINFOW, + pub lpAttributeList: LPPROC_THREAD_ATTRIBUTE_LIST, +} +impl ::core::marker::Copy for STARTUPINFOEXW {} +impl ::core::clone::Clone for STARTUPINFOEXW { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] pub struct STARTUPINFOW { pub cb: u32, pub lpReserved: PWSTR, @@ -3971,12 +4007,13 @@ impl ::core::clone::Clone for UNICODE_STRING { pub const VOLUME_NAME_DOS: GETFINALPATHNAMEBYHANDLE_FLAGS = 0u32; pub const VOLUME_NAME_GUID: GETFINALPATHNAMEBYHANDLE_FLAGS = 1u32; pub const VOLUME_NAME_NONE: GETFINALPATHNAMEBYHANDLE_FLAGS = 4u32; -pub const WAIT_ABANDONED: WIN32_ERROR = 128u32; -pub const WAIT_ABANDONED_0: WIN32_ERROR = 128u32; -pub const WAIT_FAILED: WIN32_ERROR = 4294967295u32; -pub const WAIT_IO_COMPLETION: WIN32_ERROR = 192u32; -pub const WAIT_OBJECT_0: WIN32_ERROR = 0u32; -pub const WAIT_TIMEOUT: WIN32_ERROR = 258u32; +pub const WAIT_ABANDONED: WAIT_EVENT = 128u32; +pub const WAIT_ABANDONED_0: WAIT_EVENT = 128u32; +pub type WAIT_EVENT = u32; +pub const WAIT_FAILED: WAIT_EVENT = 4294967295u32; +pub const WAIT_IO_COMPLETION: WAIT_EVENT = 192u32; +pub const WAIT_OBJECT_0: WAIT_EVENT = 0u32; +pub const WAIT_TIMEOUT: WAIT_EVENT = 258u32; pub const WC_ERR_INVALID_CHARS: u32 = 128u32; pub type WIN32_ERROR = u32; #[repr(C)] diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 84c1fbde3..56d0d6c08 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -143,13 +143,8 @@ impl Handle { ) -> io::Result<Option<usize>> { 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_raw_handle(), - buf.as_ptr() as c::LPVOID, - len, - &mut amt, - overlapped, - )); + let res = + cvt(c::ReadFile(self.as_raw_handle(), buf.as_mut_ptr(), len, &mut amt, overlapped)); match res { Ok(_) => Ok(Some(amt as usize)), Err(e) => { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index bcc172b0f..b609ad247 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -60,6 +60,11 @@ pub unsafe fn cleanup() { net::cleanup(); } +#[inline] +pub fn is_interrupted(_errno: i32) -> bool { + false +} + pub fn decode_error_kind(errno: i32) -> ErrorKind { use ErrorKind::*; diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 1ae42cb7e..abdcab424 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -117,7 +117,7 @@ impl Socket { }; if socket != c::INVALID_SOCKET { - unsafe { Ok(Self::from_raw_socket(socket)) } + unsafe { Ok(Self::from_raw(socket)) } } else { let error = unsafe { c::WSAGetLastError() }; @@ -133,7 +133,7 @@ impl Socket { } unsafe { - let socket = Self::from_raw_socket(socket); + let socket = Self::from_raw(socket); socket.0.set_no_inherit()?; Ok(socket) } @@ -144,7 +144,7 @@ impl Socket { self.set_nonblocking(true)?; let result = { let (addr, len) = addr.into_inner(); - let result = unsafe { c::connect(self.as_raw_socket(), addr.as_ptr(), len) }; + let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; cvt(result).map(drop) }; self.set_nonblocking(false)?; @@ -170,7 +170,7 @@ impl Socket { let fds = { let mut fds = unsafe { mem::zeroed::<c::fd_set>() }; fds.fd_count = 1; - fds.fd_array[0] = self.as_raw_socket(); + fds.fd_array[0] = self.as_raw(); fds }; @@ -202,11 +202,11 @@ impl Socket { } pub fn accept(&self, storage: *mut c::SOCKADDR, len: *mut c_int) -> io::Result<Socket> { - let socket = unsafe { c::accept(self.as_raw_socket(), storage, len) }; + let socket = unsafe { c::accept(self.as_raw(), storage, len) }; match socket { c::INVALID_SOCKET => Err(last_error()), - _ => unsafe { Ok(Self::from_raw_socket(socket)) }, + _ => unsafe { Ok(Self::from_raw(socket)) }, } } @@ -218,9 +218,8 @@ impl Socket { // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. let length = cmp::min(buf.capacity(), i32::MAX as usize) as i32; - let result = unsafe { - c::recv(self.as_raw_socket(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) - }; + let result = + unsafe { c::recv(self.as_raw(), buf.as_mut().as_mut_ptr() as *mut _, length, flags) }; match result { c::SOCKET_ERROR => { @@ -257,7 +256,7 @@ impl Socket { let mut flags = 0; let result = unsafe { c::WSARecv( - self.as_raw_socket(), + self.as_raw(), bufs.as_mut_ptr() as *mut c::WSABUF, length, &mut nread, @@ -305,7 +304,7 @@ impl Socket { // do the same on windows to map a shut down socket to returning EOF. let result = unsafe { c::recvfrom( - self.as_raw_socket(), + self.as_raw(), buf.as_mut_ptr() as *mut _, length, flags, @@ -341,7 +340,7 @@ impl Socket { let mut nwritten = 0; let result = unsafe { c::WSASend( - self.as_raw_socket(), + self.as_raw(), bufs.as_ptr() as *const c::WSABUF as *mut _, length, &mut nwritten, @@ -392,14 +391,14 @@ impl Socket { Shutdown::Read => c::SD_RECEIVE, Shutdown::Both => c::SD_BOTH, }; - let result = unsafe { c::shutdown(self.as_raw_socket(), how) }; + let result = unsafe { c::shutdown(self.as_raw(), how) }; cvt(result).map(drop) } pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as c_ulong; let result = - unsafe { c::ioctlsocket(self.as_raw_socket(), c::FIONBIO as c_int, &mut nonblocking) }; + unsafe { c::ioctlsocket(self.as_raw(), c::FIONBIO as c_int, &mut nonblocking) }; cvt(result).map(drop) } @@ -433,8 +432,15 @@ impl Socket { } // This is used by sys_common code to abstract over Windows and Unix. - pub fn as_raw(&self) -> RawSocket { - self.as_inner().as_raw_socket() + pub fn as_raw(&self) -> c::SOCKET { + debug_assert_eq!(mem::size_of::<c::SOCKET>(), mem::size_of::<RawSocket>()); + debug_assert_eq!(mem::align_of::<c::SOCKET>(), mem::align_of::<RawSocket>()); + self.as_inner().as_raw_socket() as c::SOCKET + } + pub unsafe fn from_raw(raw: c::SOCKET) -> Self { + debug_assert_eq!(mem::size_of::<c::SOCKET>(), mem::size_of::<RawSocket>()); + debug_assert_eq!(mem::align_of::<c::SOCKET>(), mem::align_of::<RawSocket>()); + Self::from_raw_socket(raw as RawSocket) } } diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 4708657a9..237854fac 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -64,12 +64,12 @@ impl fmt::Display for Slice { impl Buf { #[inline] - pub fn into_os_str_bytes(self) -> Vec<u8> { + pub fn into_encoded_bytes(self) -> Vec<u8> { self.inner.into_bytes() } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: Vec<u8>) -> Self { + pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } } @@ -162,12 +162,12 @@ impl Buf { impl Slice { #[inline] - pub fn as_os_str_bytes(&self) -> &[u8] { + pub fn as_encoded_bytes(&self) -> &[u8] { self.inner.as_bytes() } #[inline] - pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice { + pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice { mem::transmute(Wtf8::from_bytes_unchecked(s)) } diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index c9c2d10e6..8c0e07b35 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -22,12 +22,12 @@ pub fn is_verbatim_sep(b: u8) -> bool { /// Returns true if `path` looks like a lone filename. pub(crate) fn is_file_name(path: &OsStr) -> bool { - !path.as_os_str_bytes().iter().copied().any(is_sep_byte) + !path.as_encoded_bytes().iter().copied().any(is_sep_byte) } pub(crate) fn has_trailing_slash(path: &OsStr) -> bool { - let is_verbatim = path.as_os_str_bytes().starts_with(br"\\?\"); + let is_verbatim = path.as_encoded_bytes().starts_with(br"\\?\"); let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte }; - if let Some(&c) = path.as_os_str_bytes().last() { is_separator(c) } else { false } + if let Some(&c) = path.as_encoded_bytes().last() { is_separator(c) } else { false } } /// Appends a suffix to a path. @@ -49,7 +49,7 @@ impl<'a, const LEN: usize> PrefixParser<'a, LEN> { fn get_prefix(path: &OsStr) -> [u8; LEN] { let mut prefix = [0; LEN]; // SAFETY: Only ASCII characters are modified. - for (i, &ch) in path.as_os_str_bytes().iter().take(LEN).enumerate() { + for (i, &ch) in path.as_encoded_bytes().iter().take(LEN).enumerate() { prefix[i] = if ch == b'/' { b'\\' } else { ch }; } prefix @@ -82,7 +82,7 @@ impl<'a> PrefixParserSlice<'a, '_> { } fn prefix_bytes(&self) -> &'a [u8] { - &self.path.as_os_str_bytes()[..self.index] + &self.path.as_encoded_bytes()[..self.index] } fn finish(self) -> &'a OsStr { @@ -90,7 +90,7 @@ impl<'a> PrefixParserSlice<'a, '_> { // &[u8] and back. This is safe to do because (1) we only look at ASCII // contents of the encoding and (2) new &OsStr values are produced only // from ASCII-bounded slices of existing &OsStr values. - unsafe { OsStr::from_os_str_bytes_unchecked(&self.path.as_os_str_bytes()[self.index..]) } + unsafe { OsStr::from_encoded_bytes_unchecked(&self.path.as_encoded_bytes()[self.index..]) } } } @@ -162,7 +162,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> { drive.is_ascii_alphabetic() } - match path.as_os_str_bytes() { + match path.as_encoded_bytes() { [drive, b':', ..] if is_valid_drive_letter(drive) => Some(drive.to_ascii_uppercase()), _ => None, } @@ -171,7 +171,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> { // Parses a drive prefix exactly, e.g. "C:" fn parse_drive_exact(path: &OsStr) -> Option<u8> { // only parse two bytes: the drive letter and the drive separator - if path.as_os_str_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) { + if path.as_encoded_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) { parse_drive(path) } else { None @@ -185,15 +185,15 @@ fn parse_drive_exact(path: &OsStr) -> Option<u8> { fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { let separator = if verbatim { is_verbatim_sep } else { is_sep_byte }; - match path.as_os_str_bytes().iter().position(|&x| separator(x)) { + match path.as_encoded_bytes().iter().position(|&x| separator(x)) { Some(separator_start) => { let separator_end = separator_start + 1; - let component = &path.as_os_str_bytes()[..separator_start]; + let component = &path.as_encoded_bytes()[..separator_start]; // Panic safe // The max `separator_end` is `bytes.len()` and `bytes[bytes.len()..]` is a valid index. - let path = &path.as_os_str_bytes()[separator_end..]; + let path = &path.as_encoded_bytes()[separator_end..]; // SAFETY: `path` is a valid wtf8 encoded slice and each of the separators ('/', '\') // is encoded in a single byte, therefore `bytes[separator_start]` and @@ -201,8 +201,8 @@ fn parse_next_component(path: &OsStr, verbatim: bool) -> (&OsStr, &OsStr) { // `bytes[..separator_start]` and `bytes[separator_end..]` are valid wtf8 slices. unsafe { ( - OsStr::from_os_str_bytes_unchecked(component), - OsStr::from_os_str_bytes_unchecked(path), + OsStr::from_encoded_bytes_unchecked(component), + OsStr::from_encoded_bytes_unchecked(path), ) } } @@ -323,7 +323,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { // Verbatim paths should not be modified. if prefix.map(|x| x.is_verbatim()).unwrap_or(false) { // NULs in verbatim paths are rejected for consistency. - if path.as_os_str_bytes().contains(&0) { + if path.as_encoded_bytes().contains(&0) { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "strings passed to WinAPI cannot contain NULs", diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index d07147ecc..7624e746f 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -12,7 +12,7 @@ use crate::sys::c; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; use crate::sys::hashmap_random_keys; -use crate::sys_common::IntoInner; +use crate::sys_common::{FromInner, IntoInner}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -28,6 +28,12 @@ impl IntoInner<Handle> for AnonPipe { } } +impl FromInner<Handle> for AnonPipe { + fn from_inner(inner: Handle) -> AnonPipe { + Self { inner } + } +} + pub struct Pipes { pub ours: AnonPipe, pub theirs: AnonPipe, diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 2dd0c67ac..cd5bf7f15 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -11,6 +11,7 @@ use crate::ffi::{OsStr, OsString}; use crate::fmt; use crate::io::{self, Error, ErrorKind}; use crate::mem; +use crate::mem::MaybeUninit; use crate::num::NonZeroI32; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; @@ -166,10 +167,12 @@ pub struct Command { stdout: Option<Stdio>, stderr: Option<Stdio>, force_quotes_enabled: bool, + proc_thread_attributes: BTreeMap<usize, ProcThreadAttributeValue>, } pub enum Stdio { Inherit, + InheritSpecific { from_stdio_id: c::DWORD }, Null, MakePipe, Pipe(AnonPipe), @@ -195,6 +198,7 @@ impl Command { stdout: None, stderr: None, force_quotes_enabled: false, + proc_thread_attributes: Default::default(), } } @@ -245,6 +249,17 @@ impl Command { self.cwd.as_ref().map(|cwd| Path::new(cwd)) } + pub unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>( + &mut self, + attribute: usize, + value: T, + ) { + self.proc_thread_attributes.insert( + attribute, + ProcThreadAttributeValue { size: mem::size_of::<T>(), data: Box::new(value) }, + ); + } + pub fn spawn( &mut self, default: Stdio, @@ -308,7 +323,6 @@ 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::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`. @@ -322,6 +336,27 @@ impl Command { si.hStdError = stderr.as_raw_handle(); } + let si_ptr: *mut c::STARTUPINFOW; + + let mut proc_thread_attribute_list; + let mut si_ex; + + if !self.proc_thread_attributes.is_empty() { + si.cb = mem::size_of::<c::STARTUPINFOEXW>() as u32; + flags |= c::EXTENDED_STARTUPINFO_PRESENT; + + proc_thread_attribute_list = + make_proc_thread_attribute_list(&self.proc_thread_attributes)?; + si_ex = c::STARTUPINFOEXW { + StartupInfo: si, + lpAttributeList: proc_thread_attribute_list.0.as_mut_ptr() as _, + }; + si_ptr = &mut si_ex as *mut _ as _; + } else { + si.cb = mem::size_of::<c::STARTUPINFOW>() as c::DWORD; + si_ptr = &mut si as *mut _ as _; + } + unsafe { cvt(c::CreateProcessW( program.as_ptr(), @@ -332,7 +367,7 @@ impl Command { flags, envp, dirp, - &si, + si_ptr, &mut pi, )) }?; @@ -395,7 +430,7 @@ fn resolve_exe<'a>( // Test if the file name has the `exe` extension. // This does a case-insensitive `ends_with`. let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() { - exe_path.as_os_str_bytes()[exe_path.len() - EXE_SUFFIX.len()..] + exe_path.as_encoded_bytes()[exe_path.len() - EXE_SUFFIX.len()..] .eq_ignore_ascii_case(EXE_SUFFIX.as_bytes()) } else { false @@ -425,7 +460,7 @@ fn resolve_exe<'a>( // From the `CreateProcessW` docs: // > If the file name does not contain an extension, .exe is appended. // Note that this rule only applies when searching paths. - let has_extension = exe_path.as_os_str_bytes().contains(&b'.'); + let has_extension = exe_path.as_encoded_bytes().contains(&b'.'); // Search the directories given by `search_paths`. let result = search_paths(parent_paths, child_paths, |mut path| { @@ -521,17 +556,19 @@ fn program_exists(path: &Path) -> Option<Vec<u16>> { impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>) -> io::Result<Handle> { - match *self { - Stdio::Inherit => match stdio::get_handle(stdio_id) { - Ok(io) => unsafe { - let io = Handle::from_raw_handle(io); - let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); - io.into_raw_handle(); - ret - }, - // If no stdio handle is available, then propagate the null value. - Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) }, + let use_stdio_id = |stdio_id| match stdio::get_handle(stdio_id) { + Ok(io) => unsafe { + let io = Handle::from_raw_handle(io); + let ret = io.duplicate(0, true, c::DUPLICATE_SAME_ACCESS); + io.into_raw_handle(); + ret }, + // If no stdio handle is available, then propagate the null value. + Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) }, + }; + match *self { + Stdio::Inherit => use_stdio_id(stdio_id), + Stdio::InheritSpecific { from_stdio_id } => use_stdio_id(from_stdio_id), Stdio::MakePipe => { let ours_readable = stdio_id != c::STD_INPUT_HANDLE; @@ -579,6 +616,18 @@ impl From<File> for Stdio { } } +impl From<io::Stdout> for Stdio { + fn from(_: io::Stdout) -> Stdio { + Stdio::InheritSpecific { from_stdio_id: c::STD_OUTPUT_HANDLE } + } +} + +impl From<io::Stderr> for Stdio { + fn from(_: io::Stderr) -> Stdio { + Stdio::InheritSpecific { from_stdio_id: c::STD_ERROR_HANDLE } + } +} + //////////////////////////////////////////////////////////////////////////////// // Processes //////////////////////////////////////////////////////////////////////////////// @@ -831,6 +880,80 @@ fn make_dirp(d: Option<&OsString>) -> io::Result<(*const u16, Vec<u16>)> { } } +struct ProcThreadAttributeList(Box<[MaybeUninit<u8>]>); + +impl Drop for ProcThreadAttributeList { + fn drop(&mut self) { + let lp_attribute_list = self.0.as_mut_ptr() as _; + unsafe { c::DeleteProcThreadAttributeList(lp_attribute_list) } + } +} + +/// Wrapper around the value data to be used as a Process Thread Attribute. +struct ProcThreadAttributeValue { + data: Box<dyn Send + Sync>, + size: usize, +} + +fn make_proc_thread_attribute_list( + attributes: &BTreeMap<usize, ProcThreadAttributeValue>, +) -> io::Result<ProcThreadAttributeList> { + // To initialize our ProcThreadAttributeList, we need to determine + // how many bytes to allocate for it. The Windows API simplifies this process + // by allowing us to call `InitializeProcThreadAttributeList` with + // a null pointer to retrieve the required size. + let mut required_size = 0; + let Ok(attribute_count) = attributes.len().try_into() else { + return Err(io::const_io_error!( + ErrorKind::InvalidInput, + "maximum number of ProcThreadAttributes exceeded", + )); + }; + unsafe { + c::InitializeProcThreadAttributeList( + ptr::null_mut(), + attribute_count, + 0, + &mut required_size, + ) + }; + + let mut proc_thread_attribute_list = ProcThreadAttributeList( + vec![MaybeUninit::uninit(); required_size as usize].into_boxed_slice(), + ); + + // Once we've allocated the necessary memory, it's safe to invoke + // `InitializeProcThreadAttributeList` to properly initialize the list. + cvt(unsafe { + c::InitializeProcThreadAttributeList( + proc_thread_attribute_list.0.as_mut_ptr() as *mut _, + attribute_count, + 0, + &mut required_size, + ) + })?; + + // # Add our attributes to the buffer. + // It's theoretically possible for the attribute count to exceed a u32 value. + // Therefore, we ensure that we don't add more attributes than the buffer was initialized for. + for (&attribute, value) in attributes.iter().take(attribute_count as usize) { + let value_ptr = &*value.data as *const (dyn Send + Sync) as _; + cvt(unsafe { + c::UpdateProcThreadAttribute( + proc_thread_attribute_list.0.as_mut_ptr() as _, + 0, + attribute, + value_ptr, + value.size, + ptr::null_mut(), + ptr::null_mut(), + ) + })?; + } + + Ok(proc_thread_attribute_list) +} + pub struct CommandArgs<'a> { iter: crate::slice::Iter<'a, Arg>, } |