diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2022-11-28 17:28:54 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-28 17:28:54 -0500 |
commit | 2d4c46c975eb916dc622cc729a1a8d397582a76f (patch) | |
tree | 445e819117acd2f94ffc9d7da7ed8e3e604435d0 /cli/util/windows.rs | |
parent | f526513d74d34ac254aa40ef9b73238cb21c395b (diff) |
refactor: create util folder, move nap_sym to napi/sym, move http_cache to cache folder (#16857)
Diffstat (limited to 'cli/util/windows.rs')
-rw-r--r-- | cli/util/windows.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/cli/util/windows.rs b/cli/util/windows.rs new file mode 100644 index 000000000..0801ff2f5 --- /dev/null +++ b/cli/util/windows.rs @@ -0,0 +1,90 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. + +/// Ensures that stdin, stdout, and stderr are open and have valid HANDLEs +/// associated with them. There are many places where a `std::fs::File` is +/// constructed from a stdio handle; if the handle is null this causes a panic. +pub fn ensure_stdio_open() { + #[cfg(windows)] + // SAFETY: winapi calls + unsafe { + use std::mem::size_of; + use winapi::shared::minwindef::DWORD; + use winapi::shared::minwindef::FALSE; + use winapi::shared::minwindef::TRUE; + use winapi::shared::ntdef::NULL; + use winapi::shared::winerror::ERROR_INVALID_HANDLE; + use winapi::um::errhandlingapi::GetLastError; + use winapi::um::fileapi::CreateFileA; + use winapi::um::fileapi::OPEN_EXISTING; + use winapi::um::handleapi::GetHandleInformation; + use winapi::um::handleapi::INVALID_HANDLE_VALUE; + use winapi::um::minwinbase::SECURITY_ATTRIBUTES; + use winapi::um::processenv::GetStdHandle; + use winapi::um::processenv::SetStdHandle; + use winapi::um::winbase::STD_ERROR_HANDLE; + use winapi::um::winbase::STD_INPUT_HANDLE; + use winapi::um::winbase::STD_OUTPUT_HANDLE; + use winapi::um::winnt::FILE_ATTRIBUTE_NORMAL; + use winapi::um::winnt::FILE_GENERIC_READ; + use winapi::um::winnt::FILE_GENERIC_WRITE; + use winapi::um::winnt::FILE_READ_ATTRIBUTES; + use winapi::um::winnt::FILE_SHARE_READ; + use winapi::um::winnt::FILE_SHARE_WRITE; + + for std_handle in [STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE] { + // Check whether stdio handle is open. + let is_valid = match GetStdHandle(std_handle) { + NULL | INVALID_HANDLE_VALUE => false, + handle => { + // The stdio handle is open; check whether its handle is valid. + let mut flags: DWORD = 0; + match GetHandleInformation(handle, &mut flags) { + TRUE => true, + FALSE if GetLastError() == ERROR_INVALID_HANDLE => false, + FALSE => { + panic!("GetHandleInformation failed (error {})", GetLastError()); + } + _ => unreachable!(), + } + } + }; + + if !is_valid { + // Open NUL device. + let desired_access = match std_handle { + STD_INPUT_HANDLE => FILE_GENERIC_READ, + _ => FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES, + }; + let security_attributes = SECURITY_ATTRIBUTES { + nLength: size_of::<SECURITY_ATTRIBUTES>() as DWORD, + lpSecurityDescriptor: NULL, + bInheritHandle: TRUE, + }; + let file_handle = CreateFileA( + b"\\\\?\\NUL\0" as *const _ as *mut _, + desired_access, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &security_attributes as *const _ as *mut _, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL, + ); + match file_handle { + NULL => unreachable!(), + INVALID_HANDLE_VALUE => { + panic!("Could not open NUL device (error {})", GetLastError()); + } + _ => {} + } + + // Assign the opened NUL handle to the missing stdio handle. + let success = SetStdHandle(std_handle, file_handle); + match success { + TRUE => {} + FALSE => panic!("SetStdHandle failed (error {})", GetLastError()), + _ => unreachable!(), + } + } + } + } +} |