diff options
Diffstat (limited to 'library/std/src/sys/windows')
-rw-r--r-- | library/std/src/sys/windows/args.rs | 54 | ||||
-rw-r--r-- | library/std/src/sys/windows/c.rs | 59 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/condvar.rs | 10 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/mod.rs | 6 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/mutex.rs | 13 | ||||
-rw-r--r-- | library/std/src/sys/windows/locks/rwlock.rs | 18 | ||||
-rw-r--r-- | library/std/src/sys/windows/mod.rs | 4 | ||||
-rw-r--r-- | library/std/src/sys/windows/pipe.rs | 9 | ||||
-rw-r--r-- | library/std/src/sys/windows/process.rs | 34 | ||||
-rw-r--r-- | library/std/src/sys/windows/stdio_uwp.rs | 87 |
10 files changed, 77 insertions, 217 deletions
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs index 01f262982..6741ae46d 100644 --- a/library/std/src/sys/windows/args.rs +++ b/library/std/src/sys/windows/args.rs @@ -9,17 +9,16 @@ mod tests; use crate::ffi::OsString; use crate::fmt; use crate::io; -use crate::marker::PhantomData; use crate::num::NonZeroU16; use crate::os::windows::prelude::*; use crate::path::PathBuf; -use crate::ptr::NonNull; use crate::sys::c; use crate::sys::process::ensure_no_nuls; use crate::sys::windows::os::current_exe; +use crate::sys_common::wstr::WStrUnits; use crate::vec; -use core::iter; +use crate::iter; /// This is the const equivalent to `NonZeroU16::new(n).unwrap()` /// @@ -199,55 +198,6 @@ impl ExactSizeIterator for Args { } } -/// A safe iterator over a LPWSTR -/// (aka a pointer to a series of UTF-16 code units terminated by a NULL). -struct WStrUnits<'a> { - // The pointer must never be null... - lpwstr: NonNull<u16>, - // ...and the memory it points to must be valid for this lifetime. - lifetime: PhantomData<&'a [u16]>, -} -impl WStrUnits<'_> { - /// Create the iterator. Returns `None` if `lpwstr` is null. - /// - /// SAFETY: `lpwstr` must point to a null-terminated wide string that lives - /// at least as long as the lifetime of this struct. - unsafe fn new(lpwstr: *const u16) -> Option<Self> { - Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData }) - } - fn peek(&self) -> Option<NonZeroU16> { - // SAFETY: It's always safe to read the current item because we don't - // ever move out of the array's bounds. - unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) } - } - /// Advance the iterator while `predicate` returns true. - /// Returns the number of items it advanced by. - fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize { - let mut counter = 0; - while let Some(w) = self.peek() { - if !predicate(w) { - break; - } - counter += 1; - self.next(); - } - counter - } -} -impl Iterator for WStrUnits<'_> { - // This can never return zero as that marks the end of the string. - type Item = NonZeroU16; - fn next(&mut self) -> Option<NonZeroU16> { - // SAFETY: If NULL is reached we immediately return. - // Therefore it's safe to advance the pointer after that. - unsafe { - let next = self.peek()?; - self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1)); - Some(next) - } - } -} - #[derive(Debug)] pub(crate) enum Arg { /// Add quotes (if needed) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index be6fc2ebb..81461de4f 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -56,6 +56,7 @@ pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION; pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES; pub type LPSTARTUPINFO = *mut STARTUPINFO; pub type LPVOID = *mut c_void; +pub type LPCVOID = *const c_void; pub type LPWCH = *mut WCHAR; pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW; pub type LPWSADATA = *mut WSADATA; @@ -362,7 +363,7 @@ impl IO_STATUS_BLOCK { pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( dwErrorCode: DWORD, - dwNumberOfBytesTransfered: DWORD, + dwNumberOfBytesTransferred: DWORD, lpOverlapped: *mut OVERLAPPED, ); @@ -773,6 +774,16 @@ pub struct timeval { pub tv_usec: c_long, } +#[repr(C)] +#[derive(Copy, Clone)] +pub struct CONSOLE_READCONSOLE_CONTROL { + pub nLength: ULONG, + pub nInitialChars: ULONG, + pub dwCtrlWakeupMask: ULONG, + pub dwControlKeyState: ULONG, +} +pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; + // Desktop specific functions & types cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { @@ -802,17 +813,6 @@ if #[cfg(not(target_vendor = "uwp"))] { extern "system" fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; #[repr(C)] - #[derive(Copy, Clone)] - pub struct CONSOLE_READCONSOLE_CONTROL { - pub nLength: ULONG, - pub nInitialChars: ULONG, - pub dwCtrlWakeupMask: ULONG, - pub dwControlKeyState: ULONG, - } - - pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; - - #[repr(C)] pub struct BY_HANDLE_FILE_INFORMATION { pub dwFileAttributes: DWORD, pub ftCreationTime: FILETIME, @@ -827,7 +827,6 @@ if #[cfg(not(target_vendor = "uwp"))] { } pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; - pub type LPCVOID = *const c_void; pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; @@ -855,24 +854,6 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link(name = "kernel32")] extern "system" { - // Functions forbidden when targeting UWP - pub fn ReadConsoleW( - hConsoleInput: HANDLE, - lpBuffer: LPVOID, - nNumberOfCharsToRead: DWORD, - lpNumberOfCharsRead: LPDWORD, - pInputControl: PCONSOLE_READCONSOLE_CONTROL, - ) -> BOOL; - - pub fn WriteConsoleW( - hConsoleOutput: HANDLE, - lpBuffer: LPCVOID, - nNumberOfCharsToWrite: DWORD, - lpNumberOfCharsWritten: LPDWORD, - lpReserved: LPVOID, - ) -> BOOL; - - pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; // Allowed but unused by UWP pub fn GetFileInformationByHandle( hFile: HANDLE, @@ -914,6 +895,22 @@ if #[cfg(target_vendor = "uwp")] { extern "system" { pub fn GetCurrentProcessId() -> DWORD; + pub fn ReadConsoleW( + hConsoleInput: HANDLE, + lpBuffer: LPVOID, + nNumberOfCharsToRead: DWORD, + lpNumberOfCharsRead: LPDWORD, + pInputControl: PCONSOLE_READCONSOLE_CONTROL, + ) -> BOOL; + pub fn WriteConsoleW( + hConsoleOutput: HANDLE, + lpBuffer: LPCVOID, + nNumberOfCharsToWrite: DWORD, + lpNumberOfCharsWritten: LPDWORD, + lpReserved: LPVOID, + ) -> BOOL; + pub fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; diff --git a/library/std/src/sys/windows/locks/condvar.rs b/library/std/src/sys/windows/locks/condvar.rs index be9a2abbe..66fafa2c0 100644 --- a/library/std/src/sys/windows/locks/condvar.rs +++ b/library/std/src/sys/windows/locks/condvar.rs @@ -8,8 +8,6 @@ pub struct Condvar { inner: UnsafeCell<c::CONDITION_VARIABLE>, } -pub type MovableCondvar = Condvar; - unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} @@ -41,12 +39,12 @@ impl Condvar { } #[inline] - pub unsafe fn notify_one(&self) { - c::WakeConditionVariable(self.inner.get()) + pub fn notify_one(&self) { + unsafe { c::WakeConditionVariable(self.inner.get()) } } #[inline] - pub unsafe fn notify_all(&self) { - c::WakeAllConditionVariable(self.inner.get()) + pub fn notify_all(&self) { + unsafe { c::WakeAllConditionVariable(self.inner.get()) } } } diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs index 602a2d623..0e0f9eccb 100644 --- a/library/std/src/sys/windows/locks/mod.rs +++ b/library/std/src/sys/windows/locks/mod.rs @@ -1,6 +1,6 @@ mod condvar; mod mutex; mod rwlock; -pub use condvar::{Condvar, MovableCondvar}; -pub use mutex::{MovableMutex, Mutex}; -pub use rwlock::MovableRwLock; +pub use condvar::Condvar; +pub use mutex::Mutex; +pub use rwlock::RwLock; diff --git a/library/std/src/sys/windows/locks/mutex.rs b/library/std/src/sys/windows/locks/mutex.rs index 91207f5f4..ef2f84082 100644 --- a/library/std/src/sys/windows/locks/mutex.rs +++ b/library/std/src/sys/windows/locks/mutex.rs @@ -21,9 +21,6 @@ pub struct Mutex { srwlock: UnsafeCell<c::SRWLOCK>, } -// Windows SRW Locks are movable (while not borrowed). -pub type MovableMutex = Mutex; - unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} @@ -39,13 +36,15 @@ impl Mutex { } #[inline] - pub unsafe fn lock(&self) { - c::AcquireSRWLockExclusive(raw(self)); + pub fn lock(&self) { + unsafe { + c::AcquireSRWLockExclusive(raw(self)); + } } #[inline] - pub unsafe fn try_lock(&self) -> bool { - c::TryAcquireSRWLockExclusive(raw(self)) != 0 + pub fn try_lock(&self) -> bool { + unsafe { c::TryAcquireSRWLockExclusive(raw(self)) != 0 } } #[inline] diff --git a/library/std/src/sys/windows/locks/rwlock.rs b/library/std/src/sys/windows/locks/rwlock.rs index fa5ffe574..e69415baa 100644 --- a/library/std/src/sys/windows/locks/rwlock.rs +++ b/library/std/src/sys/windows/locks/rwlock.rs @@ -5,8 +5,6 @@ pub struct RwLock { inner: UnsafeCell<c::SRWLOCK>, } -pub type MovableRwLock = RwLock; - unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} @@ -16,20 +14,20 @@ impl RwLock { RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) } } #[inline] - pub unsafe fn read(&self) { - c::AcquireSRWLockShared(self.inner.get()) + pub fn read(&self) { + unsafe { c::AcquireSRWLockShared(self.inner.get()) } } #[inline] - pub unsafe fn try_read(&self) -> bool { - c::TryAcquireSRWLockShared(self.inner.get()) != 0 + pub fn try_read(&self) -> bool { + unsafe { c::TryAcquireSRWLockShared(self.inner.get()) != 0 } } #[inline] - pub unsafe fn write(&self) { - c::AcquireSRWLockExclusive(self.inner.get()) + pub fn write(&self) { + unsafe { c::AcquireSRWLockExclusive(self.inner.get()) } } #[inline] - pub unsafe fn try_write(&self) -> bool { - c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 + pub fn try_write(&self) -> bool { + unsafe { c::TryAcquireSRWLockExclusive(self.inner.get()) != 0 } } #[inline] pub unsafe fn read_unlock(&self) { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index eab9b9612..e67411e16 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -29,6 +29,7 @@ pub mod path; pub mod pipe; pub mod process; pub mod rand; +pub mod stdio; pub mod thread; pub mod thread_local_dtor; pub mod thread_local_key; @@ -36,12 +37,9 @@ pub mod thread_parker; pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { - pub mod stdio; pub mod stack_overflow; } else { - pub mod stdio_uwp; pub mod stack_overflow_uwp; - pub use self::stdio_uwp as stdio; pub use self::stack_overflow_uwp as stack_overflow; } } diff --git a/library/std/src/sys/windows/pipe.rs b/library/std/src/sys/windows/pipe.rs index 013c776c4..9f26acc45 100644 --- a/library/std/src/sys/windows/pipe.rs +++ b/library/std/src/sys/windows/pipe.rs @@ -324,17 +324,18 @@ impl AnonPipe { let mut async_result: Option<AsyncResult> = None; struct AsyncResult { error: u32, - transfered: u32, + transferred: u32, } // STEP 3: The callback. unsafe extern "system" fn callback( dwErrorCode: u32, - dwNumberOfBytesTransfered: u32, + dwNumberOfBytesTransferred: u32, lpOverlapped: *mut c::OVERLAPPED, ) { // Set `async_result` using a pointer smuggled through `hEvent`. - let result = AsyncResult { error: dwErrorCode, transfered: dwNumberOfBytesTransfered }; + let result = + AsyncResult { error: dwErrorCode, transferred: dwNumberOfBytesTransferred }; *(*lpOverlapped).hEvent.cast::<Option<AsyncResult>>() = Some(result); } @@ -365,7 +366,7 @@ impl AnonPipe { // STEP 4: Return the result. // `async_result` is always `Some` at this point match result.error { - c::ERROR_SUCCESS => Ok(result.transfered as usize), + c::ERROR_SUCCESS => Ok(result.transferred as usize), error => Err(io::Error::from_raw_os_error(error as _)), } } diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 9cbb4ef19..31e9b34fb 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -252,10 +252,6 @@ impl Command { ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); - let mut si = zeroed_startupinfo(); - si.cb = mem::size_of::<c::STARTUPINFO>() as c::DWORD; - si.dwFlags = c::STARTF_USESTDHANDLES; - let child_paths = if let Some(env) = maybe_env.as_ref() { env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str()) } else { @@ -314,9 +310,21 @@ impl Command { let stdin = stdin.to_handle(c::STD_INPUT_HANDLE, &mut pipes.stdin)?; let stdout = stdout.to_handle(c::STD_OUTPUT_HANDLE, &mut pipes.stdout)?; let stderr = stderr.to_handle(c::STD_ERROR_HANDLE, &mut pipes.stderr)?; - si.hStdInput = stdin.as_raw_handle(); - si.hStdOutput = stdout.as_raw_handle(); - si.hStdError = stderr.as_raw_handle(); + + let mut si = zeroed_startupinfo(); + si.cb = mem::size_of::<c::STARTUPINFO>() 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`. + // Otherwise skip this and allow the OS to apply its default behaviour. + // This provides more consistent behaviour between Win7 and Win8+. + let is_set = |stdio: &Handle| !stdio.as_raw_handle().is_null(); + if is_set(&stderr) || is_set(&stdout) || is_set(&stdin) { + si.dwFlags |= c::STARTF_USESTDHANDLES; + si.hStdInput = stdin.as_raw_handle(); + si.hStdOutput = stdout.as_raw_handle(); + si.hStdError = stderr.as_raw_handle(); + } unsafe { cvt(c::CreateProcessW( @@ -513,9 +521,6 @@ 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 { - // If no stdio handle is available, then inherit means that it - // should still be unavailable so propagate the - // INVALID_HANDLE_VALUE. Stdio::Inherit => match stdio::get_handle(stdio_id) { Ok(io) => unsafe { let io = Handle::from_raw_handle(io); @@ -523,7 +528,8 @@ impl Stdio { io.into_raw_handle(); ret }, - Err(..) => unsafe { Ok(Handle::from_raw_handle(c::INVALID_HANDLE_VALUE)) }, + // If no stdio handle is available, then propagate the null value. + Err(..) => unsafe { Ok(Handle::from_raw_handle(ptr::null_mut())) }, }, Stdio::MakePipe => { @@ -730,9 +736,9 @@ fn zeroed_startupinfo() -> c::STARTUPINFO { wShowWindow: 0, cbReserved2: 0, lpReserved2: ptr::null_mut(), - hStdInput: c::INVALID_HANDLE_VALUE, - hStdOutput: c::INVALID_HANDLE_VALUE, - hStdError: c::INVALID_HANDLE_VALUE, + hStdInput: ptr::null_mut(), + hStdOutput: ptr::null_mut(), + hStdError: ptr::null_mut(), } } diff --git a/library/std/src/sys/windows/stdio_uwp.rs b/library/std/src/sys/windows/stdio_uwp.rs deleted file mode 100644 index 32550f796..000000000 --- a/library/std/src/sys/windows/stdio_uwp.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![unstable(issue = "none", feature = "windows_stdio")] - -use crate::io; -use crate::mem::ManuallyDrop; -use crate::os::windows::io::FromRawHandle; -use crate::sys::c; -use crate::sys::handle::Handle; - -pub struct Stdin {} -pub struct Stdout; -pub struct Stderr; - -const MAX_BUFFER_SIZE: usize = 8192; -pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3; - -pub fn get_handle(handle_id: c::DWORD) -> io::Result<c::HANDLE> { - let handle = unsafe { c::GetStdHandle(handle_id) }; - if handle == c::INVALID_HANDLE_VALUE { - Err(io::Error::last_os_error()) - } else if handle.is_null() { - Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32)) - } else { - Ok(handle) - } -} - -fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> { - let handle = get_handle(handle_id)?; - // SAFETY: The handle returned from `get_handle` must be valid and non-null. - let handle = unsafe { Handle::from_raw_handle(handle) }; - ManuallyDrop::new(handle).write(data) -} - -impl Stdin { - pub const fn new() -> Stdin { - Stdin {} - } -} - -impl io::Read for Stdin { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - let handle = get_handle(c::STD_INPUT_HANDLE)?; - // SAFETY: The handle returned from `get_handle` must be valid and non-null. - let handle = unsafe { Handle::from_raw_handle(handle) }; - ManuallyDrop::new(handle).read(buf) - } -} - -impl Stdout { - pub const fn new() -> Stdout { - Stdout - } -} - -impl io::Write for Stdout { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - write(c::STD_OUTPUT_HANDLE, buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - write(c::STD_ERROR_HANDLE, buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub fn is_ebadf(err: &io::Error) -> bool { - err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32) -} - -pub fn panic_output() -> Option<impl io::Write> { - Some(Stderr::new()) -} |