tool/goexe: refactor to use windows_sys
Updates #19255 Signed-off-by: Nathan Perry <nathan@tailscale.com> Change-Id: Idf69f23b5a61417d5fa3638a276d64856a6a6964
This commit is contained in:
committed by
Brad Fitzpatrick
parent
8a9840d6a8
commit
33cd8ea86b
BIN
Binary file not shown.
@@ -1,2 +1,5 @@
|
|||||||
|
[build]
|
||||||
|
target = "i686-pc-windows-gnu"
|
||||||
|
|
||||||
[target.i686-pc-windows-gnu]
|
[target.i686-pc-windows-gnu]
|
||||||
rustflags = ["-C", "link-args=-nostartfiles -lkernel32"]
|
rustflags = ["-C", "link-args=-nostartfiles -lkernel32"]
|
||||||
|
|||||||
Generated
+18
@@ -5,3 +5,21 @@ version = 4
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "go"
|
name = "go"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|||||||
@@ -3,6 +3,19 @@ name = "go"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
windows-sys = { version = "0.61", features = [
|
||||||
|
"Win32",
|
||||||
|
"Win32_System_LibraryLoader",
|
||||||
|
"Win32_System_Environment",
|
||||||
|
"Win32_Storage_FileSystem",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_Security",
|
||||||
|
"Win32_System_SystemInformation",
|
||||||
|
"Win32_System_IO",
|
||||||
|
"Win32_System_Console",
|
||||||
|
] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
lto = true
|
lto = true
|
||||||
|
|||||||
+45
-249
@@ -25,203 +25,21 @@
|
|||||||
// blocks inside each unsafe fn would be pure noise.
|
// blocks inside each unsafe fn would be pure noise.
|
||||||
#![allow(unsafe_op_in_unsafe_fn)]
|
#![allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
use core::ptr;
|
use core::ptr::{null, null_mut};
|
||||||
|
use windows_sys::w;
|
||||||
// Win32 constants.
|
use windows_sys::Win32::Foundation::{CloseHandle, GENERIC_READ, GENERIC_WRITE, INVALID_HANDLE_VALUE};
|
||||||
|
use windows_sys::Win32::Storage::FileSystem::{CreateDirectoryW, CreateFileW, DeleteFileW, GetFileAttributesW, ReadFile, WriteFile, CREATE_ALWAYS, FILE_SHARE_READ, INVALID_FILE_ATTRIBUTES, OPEN_EXISTING};
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
|
use windows_sys::Win32::System::Console::{GetStdHandle, STD_ERROR_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
||||||
const GENERIC_READ: u32 = 0x80000000;
|
use windows_sys::Win32::System::Environment::{GetCommandLineW, GetEnvironmentVariableW, SetEnvironmentVariableW};
|
||||||
const GENERIC_WRITE: u32 = 0x40000000;
|
use windows_sys::Win32::System::LibraryLoader::GetModuleFileNameW;
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew (dwCreationDisposition)
|
use windows_sys::Win32::System::SystemInformation::{GetNativeSystemInfo, PROCESSOR_ARCHITECTURE_AMD64, PROCESSOR_ARCHITECTURE_ARM64, PROCESSOR_ARCHITECTURE_INTEL};
|
||||||
const OPEN_EXISTING: u32 = 3;
|
use windows_sys::Win32::System::Threading::{ExitProcess, STARTF_USESTDHANDLES, CreateProcessW, STARTUPINFOW, PROCESS_INFORMATION, WaitForSingleObject, INFINITE, GetExitCodeProcess};
|
||||||
const CREATE_ALWAYS: u32 = 2;
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew (dwShareMode)
|
|
||||||
const FILE_SHARE_READ: u32 = 1;
|
|
||||||
/// Returned by CreateFileW on failure.
|
|
||||||
const INVALID_HANDLE_VALUE: isize = -1;
|
|
||||||
/// Returned by GetFileAttributesW when the file does not exist.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesw
|
|
||||||
const INVALID_FILE_ATTRIBUTES: u32 = 0xFFFFFFFF;
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
|
|
||||||
const INFINITE: u32 = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/console/getstdhandle
|
|
||||||
const STD_INPUT_HANDLE: u32 = (-10i32) as u32;
|
|
||||||
const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
|
|
||||||
const STD_ERROR_HANDLE: u32 = (-12i32) as u32;
|
|
||||||
|
|
||||||
/// Indicates that the hStdInput/hStdOutput/hStdError fields in STARTUPINFOW
|
|
||||||
/// contain valid handles.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfow
|
|
||||||
const STARTF_USESTDHANDLES: u32 = 0x00000100;
|
|
||||||
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
|
|
||||||
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;
|
|
||||||
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
|
|
||||||
const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12;
|
|
||||||
|
|
||||||
/// Exit code used when this wrapper panics, to distinguish from child
|
/// Exit code used when this wrapper panics, to distinguish from child
|
||||||
/// process failures.
|
/// process failures.
|
||||||
|
#[cfg(not(test))]
|
||||||
const EXIT_CODE_PANIC: u32 = 0xFE;
|
const EXIT_CODE_PANIC: u32 = 0xFE;
|
||||||
|
|
||||||
// Win32 struct definitions.
|
|
||||||
|
|
||||||
/// STARTUPINFOW — passed to CreateProcessW to configure the child process.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfow
|
|
||||||
#[repr(C)]
|
|
||||||
struct StartupInfoW {
|
|
||||||
cb: u32, // Size of this struct in bytes.
|
|
||||||
reserved: usize, // lpReserved (must be NULL).
|
|
||||||
desktop: usize, // lpDesktop
|
|
||||||
title: usize, // lpTitle
|
|
||||||
x: u32, // dwX
|
|
||||||
y: u32, // dwY
|
|
||||||
x_size: u32, // dwXSize
|
|
||||||
y_size: u32, // dwYSize
|
|
||||||
x_count_chars: u32, // dwXCountChars
|
|
||||||
y_count_chars: u32, // dwYCountChars
|
|
||||||
fill_attribute: u32,// dwFillAttribute
|
|
||||||
flags: u32, // dwFlags (e.g. STARTF_USESTDHANDLES)
|
|
||||||
show_window: u16, // wShowWindow
|
|
||||||
cb_reserved2: u16, // cbReserved2
|
|
||||||
reserved2: usize, // lpReserved2
|
|
||||||
std_input: isize, // hStdInput (HANDLE)
|
|
||||||
std_output: isize, // hStdOutput (HANDLE)
|
|
||||||
std_error: isize, // hStdError (HANDLE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PROCESS_INFORMATION — filled by CreateProcessW with handles to the new process/thread.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-process_information
|
|
||||||
#[repr(C)]
|
|
||||||
struct ProcessInformation {
|
|
||||||
process: isize, // hProcess (HANDLE)
|
|
||||||
thread: isize, // hThread (HANDLE)
|
|
||||||
process_id: u32, // dwProcessId
|
|
||||||
thread_id: u32, // dwThreadId
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SYSTEM_INFO — returned by GetNativeSystemInfo.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info
|
|
||||||
#[repr(C)]
|
|
||||||
struct SystemInfo {
|
|
||||||
processor_architecture: u16, // wProcessorArchitecture
|
|
||||||
_reserved: u16,
|
|
||||||
_page_size: u32,
|
|
||||||
_min_app_addr: usize,
|
|
||||||
_max_app_addr: usize,
|
|
||||||
_active_processor_mask: usize,
|
|
||||||
_number_of_processors: u32,
|
|
||||||
_processor_type: u32,
|
|
||||||
_allocation_granularity: u32,
|
|
||||||
_processor_level: u16,
|
|
||||||
_processor_revision: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Win32 API declarations (all from kernel32.dll unless noted).
|
|
||||||
|
|
||||||
unsafe extern "system" {
|
|
||||||
/// Returns the fully qualified path of the running executable.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew
|
|
||||||
fn GetModuleFileNameW(module: isize, filename: *mut u16, size: u32) -> u32;
|
|
||||||
|
|
||||||
/// Opens or creates a file, returning a HANDLE.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
|
|
||||||
fn CreateFileW(
|
|
||||||
name: *const u16,
|
|
||||||
access: u32,
|
|
||||||
share: u32,
|
|
||||||
security: usize,
|
|
||||||
disposition: u32,
|
|
||||||
flags: u32,
|
|
||||||
template: usize,
|
|
||||||
) -> isize;
|
|
||||||
|
|
||||||
/// Reads bytes from a file handle.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile
|
|
||||||
fn ReadFile(
|
|
||||||
file: isize,
|
|
||||||
buffer: *mut u8,
|
|
||||||
to_read: u32,
|
|
||||||
read: *mut u32,
|
|
||||||
overlapped: usize,
|
|
||||||
) -> i32;
|
|
||||||
|
|
||||||
/// Closes a kernel object handle.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
|
|
||||||
fn CloseHandle(handle: isize) -> i32;
|
|
||||||
|
|
||||||
/// Returns file attributes, or INVALID_FILE_ATTRIBUTES if not found.
|
|
||||||
/// Used here as a lightweight file-existence check.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileattributesw
|
|
||||||
fn GetFileAttributesW(name: *const u16) -> u32;
|
|
||||||
|
|
||||||
/// Retrieves the value of an environment variable.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getenvironmentvariablew
|
|
||||||
fn GetEnvironmentVariableW(name: *const u16, buffer: *mut u16, size: u32) -> u32;
|
|
||||||
|
|
||||||
/// Sets or deletes an environment variable (pass null value to delete).
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-setenvironmentvariablew
|
|
||||||
fn SetEnvironmentVariableW(name: *const u16, value: *const u16) -> i32;
|
|
||||||
|
|
||||||
/// Creates a new process and its primary thread.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
|
|
||||||
fn CreateProcessW(
|
|
||||||
app: *const u16,
|
|
||||||
cmd: *mut u16,
|
|
||||||
proc_attr: usize,
|
|
||||||
thread_attr: usize,
|
|
||||||
inherit: i32,
|
|
||||||
flags: u32,
|
|
||||||
env: usize,
|
|
||||||
dir: usize,
|
|
||||||
startup: *const StartupInfoW,
|
|
||||||
info: *mut ProcessInformation,
|
|
||||||
) -> i32;
|
|
||||||
|
|
||||||
/// Waits until a handle is signaled (process exits) or timeout elapses.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
|
|
||||||
fn WaitForSingleObject(handle: isize, ms: u32) -> u32;
|
|
||||||
|
|
||||||
/// Retrieves the exit code of a process.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
|
|
||||||
fn GetExitCodeProcess(process: isize, code: *mut u32) -> i32;
|
|
||||||
|
|
||||||
/// Terminates the calling process with the given exit code.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitprocess
|
|
||||||
fn ExitProcess(code: u32) -> !;
|
|
||||||
|
|
||||||
/// Returns a handle to stdin, stdout, or stderr.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/console/getstdhandle
|
|
||||||
fn GetStdHandle(id: u32) -> isize;
|
|
||||||
|
|
||||||
/// Returns a pointer to the command-line string for the current process.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinew
|
|
||||||
fn GetCommandLineW() -> *const u16;
|
|
||||||
|
|
||||||
/// Writes bytes to a file handle (used here for stderr output).
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile
|
|
||||||
fn WriteFile(
|
|
||||||
file: isize,
|
|
||||||
buffer: *const u8,
|
|
||||||
to_write: u32,
|
|
||||||
written: *mut u32,
|
|
||||||
overlapped: usize,
|
|
||||||
) -> i32;
|
|
||||||
|
|
||||||
/// Creates a directory.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createdirectoryw
|
|
||||||
fn CreateDirectoryW(path: *const u16, security: usize) -> i32;
|
|
||||||
|
|
||||||
/// Deletes a file.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilew
|
|
||||||
fn DeleteFileW(path: *const u16) -> i32;
|
|
||||||
|
|
||||||
/// Returns system info including processor architecture, using the
|
|
||||||
/// native architecture even when called from a WoW64 process.
|
|
||||||
/// https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo
|
|
||||||
fn GetNativeSystemInfo(info: *mut SystemInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A fixed-capacity UTF-16 buffer for building null-terminated wide strings
|
// A fixed-capacity UTF-16 buffer for building null-terminated wide strings
|
||||||
// to pass to Win32 APIs. All Win32-facing methods automatically null-terminate.
|
// to pass to Win32 APIs. All Win32-facing methods automatically null-terminate.
|
||||||
//
|
//
|
||||||
@@ -341,13 +159,6 @@ unsafe fn get_env<const N: usize>(name: &[u8], dst: &mut WBuf<N>) -> usize {
|
|||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unset an environment variable.
|
|
||||||
unsafe fn unset_env(name: &[u8]) {
|
|
||||||
let mut name_w = WBuf::<64>::new();
|
|
||||||
name_w.push_ascii(name);
|
|
||||||
SetEnvironmentVariableW(name_w.as_ptr(), ptr::null());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// C runtime entry point for MinGW/MSVC. Called before main() would be.
|
/// C runtime entry point for MinGW/MSVC. Called before main() would be.
|
||||||
/// We use #[no_main] so we define this directly.
|
/// We use #[no_main] so we define this directly.
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
@@ -358,7 +169,7 @@ pub extern "C" fn mainCRTStartup() -> ! {
|
|||||||
unsafe fn main_impl() -> ! {
|
unsafe fn main_impl() -> ! {
|
||||||
// Get our own exe path, e.g. "C:\Users\...\tailscale\tool\go.exe".
|
// Get our own exe path, e.g. "C:\Users\...\tailscale\tool\go.exe".
|
||||||
let mut exe = WBuf::<4096>::new();
|
let mut exe = WBuf::<4096>::new();
|
||||||
exe.len = GetModuleFileNameW(0, exe.buf.as_mut_ptr(), exe.buf.len() as u32) as usize;
|
exe.len = GetModuleFileNameW(null_mut(), exe.buf.as_mut_ptr(), exe.buf.len() as u32) as usize;
|
||||||
if exe.len == 0 {
|
if exe.len == 0 {
|
||||||
die(b"GetModuleFileNameW failed\n");
|
die(b"GetModuleFileNameW failed\n");
|
||||||
}
|
}
|
||||||
@@ -429,7 +240,7 @@ unsafe fn main_impl() -> ! {
|
|||||||
// Unset GOROOT to avoid breaking builds that depend on our Go
|
// Unset GOROOT to avoid breaking builds that depend on our Go
|
||||||
// fork's patches (e.g. net/). The Go toolchain sets GOROOT
|
// fork's patches (e.g. net/). The Go toolchain sets GOROOT
|
||||||
// internally from its own location.
|
// internally from its own location.
|
||||||
unset_env(b"GOROOT");
|
SetEnvironmentVariableW(w!("GOROOT"), null());
|
||||||
|
|
||||||
// Build the new command line by replacing argv[0] with the real
|
// Build the new command line by replacing argv[0] with the real
|
||||||
// go.exe path. We take the raw command line from GetCommandLineW
|
// go.exe path. We take the raw command line from GetCommandLineW
|
||||||
@@ -445,7 +256,7 @@ unsafe fn main_impl() -> ! {
|
|||||||
cmd.push_ptr(args_tail);
|
cmd.push_ptr(args_tail);
|
||||||
|
|
||||||
// Exec: create the child process, wait for it, and exit with its code.
|
// Exec: create the child process, wait for it, and exit with its code.
|
||||||
let code = run_and_wait(go_exe.as_ptr(), &mut cmd, ptr::null());
|
let code = run_and_wait(go_exe.as_ptr(), &mut cmd, null());
|
||||||
ExitProcess(code);
|
ExitProcess(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,20 +272,21 @@ unsafe fn download_toolchain(toolchain: &WBuf<4096>, rev: &[u8]) {
|
|||||||
let mut dir = WBuf::<4096>::new();
|
let mut dir = WBuf::<4096>::new();
|
||||||
get_env(b"USERPROFILE", &mut dir);
|
get_env(b"USERPROFILE", &mut dir);
|
||||||
dir.push_ascii(b"\\.cache");
|
dir.push_ascii(b"\\.cache");
|
||||||
CreateDirectoryW(dir.as_ptr(), 0);
|
CreateDirectoryW(dir.as_ptr(), null());
|
||||||
dir.push_ascii(b"\\tsgo");
|
dir.push_ascii(b"\\tsgo");
|
||||||
CreateDirectoryW(dir.as_ptr(), 0);
|
CreateDirectoryW(dir.as_ptr(), null());
|
||||||
|
|
||||||
// Create the toolchain directory itself.
|
// Create the toolchain directory itself.
|
||||||
let mut tc_dir = WBuf::<4096>::new();
|
let mut tc_dir = WBuf::<4096>::new();
|
||||||
tc_dir.push_wbuf(toolchain);
|
tc_dir.push_wbuf(toolchain);
|
||||||
CreateDirectoryW(tc_dir.as_ptr(), 0);
|
CreateDirectoryW(tc_dir.as_ptr(), null());
|
||||||
|
|
||||||
// Detect host architecture via GetNativeSystemInfo (gives real arch
|
// Detect host architecture via GetNativeSystemInfo (gives real arch
|
||||||
// even from a WoW64 32-bit process).
|
// even from a WoW64 32-bit process).
|
||||||
let mut si: SystemInfo = core::mem::zeroed();
|
let mut si = core::mem::zeroed();
|
||||||
GetNativeSystemInfo(&mut si);
|
GetNativeSystemInfo(&mut si);
|
||||||
let arch: &[u8] = match si.processor_architecture {
|
|
||||||
|
let arch: &[u8] = match si.Anonymous.Anonymous.wProcessorArchitecture as u16 {
|
||||||
PROCESSOR_ARCHITECTURE_AMD64 => b"amd64",
|
PROCESSOR_ARCHITECTURE_AMD64 => b"amd64",
|
||||||
PROCESSOR_ARCHITECTURE_ARM64 => b"arm64",
|
PROCESSOR_ARCHITECTURE_ARM64 => b"arm64",
|
||||||
PROCESSOR_ARCHITECTURE_INTEL => b"386",
|
PROCESSOR_ARCHITECTURE_INTEL => b"386",
|
||||||
@@ -507,7 +319,7 @@ unsafe fn download_toolchain(toolchain: &WBuf<4096>, rev: &[u8]) {
|
|||||||
cmd.push_ascii(b"\" ");
|
cmd.push_ascii(b"\" ");
|
||||||
cmd.push_ascii(&url[..u]);
|
cmd.push_ascii(&url[..u]);
|
||||||
|
|
||||||
let code = run_and_wait(ptr::null(), &mut cmd, ptr::null());
|
let code = run_and_wait(null(), &mut cmd, null());
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
die(b"curl failed to download Go toolchain\n");
|
die(b"curl failed to download Go toolchain\n");
|
||||||
}
|
}
|
||||||
@@ -519,7 +331,7 @@ unsafe fn download_toolchain(toolchain: &WBuf<4096>, rev: &[u8]) {
|
|||||||
cmd.push_wbuf(&tgz);
|
cmd.push_wbuf(&tgz);
|
||||||
cmd.push_ascii(b"\"");
|
cmd.push_ascii(b"\"");
|
||||||
|
|
||||||
let code = run_and_wait(ptr::null(), &mut cmd, tc_dir.as_ptr());
|
let code = run_and_wait(null(), &mut cmd, tc_dir.as_ptr());
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
die(b"tar failed to extract Go toolchain\n");
|
die(b"tar failed to extract Go toolchain\n");
|
||||||
}
|
}
|
||||||
@@ -527,10 +339,10 @@ unsafe fn download_toolchain(toolchain: &WBuf<4096>, rev: &[u8]) {
|
|||||||
// Write the .extracted marker file.
|
// Write the .extracted marker file.
|
||||||
let mut marker = WBuf::<4096>::new();
|
let mut marker = WBuf::<4096>::new();
|
||||||
marker.push_wbuf(toolchain).push_ascii(b".extracted");
|
marker.push_wbuf(toolchain).push_ascii(b".extracted");
|
||||||
let fh = CreateFileW(marker.as_ptr(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
|
let fh = CreateFileW(marker.as_ptr(), GENERIC_WRITE, 0, null(), CREATE_ALWAYS, 0, null_mut());
|
||||||
if fh != INVALID_HANDLE_VALUE {
|
if fh != INVALID_HANDLE_VALUE {
|
||||||
let mut written: u32 = 0;
|
let mut written: u32 = 0;
|
||||||
WriteFile(fh, rev.as_ptr(), rev.len() as u32, &mut written, 0);
|
WriteFile(fh, rev.as_ptr(), rev.len() as u32, &mut written, null_mut());
|
||||||
CloseHandle(fh);
|
CloseHandle(fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,42 +354,25 @@ unsafe fn download_toolchain(toolchain: &WBuf<4096>, rev: &[u8]) {
|
|||||||
/// If app is null, CreateProcessW searches PATH using the command line.
|
/// If app is null, CreateProcessW searches PATH using the command line.
|
||||||
/// If dir is null, the child inherits the current directory.
|
/// If dir is null, the child inherits the current directory.
|
||||||
unsafe fn run_and_wait(app: *const u16, cmd: &mut WBuf<32768>, dir: *const u16) -> u32 {
|
unsafe fn run_and_wait(app: *const u16, cmd: &mut WBuf<32768>, dir: *const u16) -> u32 {
|
||||||
let si = StartupInfoW {
|
let si = STARTUPINFOW {
|
||||||
cb: core::mem::size_of::<StartupInfoW>() as u32,
|
cb: size_of::<STARTUPINFOW>() as u32,
|
||||||
reserved: 0,
|
dwFlags: STARTF_USESTDHANDLES,
|
||||||
desktop: 0,
|
hStdInput: GetStdHandle(STD_INPUT_HANDLE),
|
||||||
title: 0,
|
hStdOutput: GetStdHandle(STD_OUTPUT_HANDLE),
|
||||||
x: 0,
|
hStdError: GetStdHandle(STD_ERROR_HANDLE),
|
||||||
y: 0,
|
..Default::default()
|
||||||
x_size: 0,
|
|
||||||
y_size: 0,
|
|
||||||
x_count_chars: 0,
|
|
||||||
y_count_chars: 0,
|
|
||||||
fill_attribute: 0,
|
|
||||||
flags: STARTF_USESTDHANDLES,
|
|
||||||
show_window: 0,
|
|
||||||
cb_reserved2: 0,
|
|
||||||
reserved2: 0,
|
|
||||||
std_input: GetStdHandle(STD_INPUT_HANDLE),
|
|
||||||
std_output: GetStdHandle(STD_OUTPUT_HANDLE),
|
|
||||||
std_error: GetStdHandle(STD_ERROR_HANDLE),
|
|
||||||
};
|
|
||||||
let mut pi = ProcessInformation {
|
|
||||||
process: 0,
|
|
||||||
thread: 0,
|
|
||||||
process_id: 0,
|
|
||||||
thread_id: 0,
|
|
||||||
};
|
};
|
||||||
|
let mut pi = PROCESS_INFORMATION::default();
|
||||||
|
|
||||||
if CreateProcessW(
|
if CreateProcessW(
|
||||||
app,
|
app,
|
||||||
cmd.as_mut_ptr(),
|
cmd.as_mut_ptr(),
|
||||||
0,
|
null(),
|
||||||
0,
|
null(),
|
||||||
1, // bInheritHandles = TRUE
|
1, // bInheritHandles = TRUE
|
||||||
0,
|
0,
|
||||||
0,
|
null(),
|
||||||
dir as usize,
|
dir,
|
||||||
&si,
|
&si,
|
||||||
&mut pi,
|
&mut pi,
|
||||||
) == 0
|
) == 0
|
||||||
@@ -585,11 +380,11 @@ unsafe fn run_and_wait(app: *const u16, cmd: &mut WBuf<32768>, dir: *const u16)
|
|||||||
die(b"CreateProcess failed\n");
|
die(b"CreateProcess failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitForSingleObject(pi.process, INFINITE);
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
let mut code: u32 = 1;
|
let mut code: u32 = 1;
|
||||||
GetExitCodeProcess(pi.process, &mut code);
|
GetExitCodeProcess(pi.hProcess, &mut code);
|
||||||
CloseHandle(pi.process);
|
CloseHandle(pi.hProcess);
|
||||||
CloseHandle(pi.thread);
|
CloseHandle(pi.hThread);
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +402,7 @@ unsafe fn fallback_pwsh(repo_root: &WBuf<4096>) -> ! {
|
|||||||
cmd.push_ptr(args_tail);
|
cmd.push_ptr(args_tail);
|
||||||
|
|
||||||
// Pass null for lpApplicationName so CreateProcessW searches PATH for "pwsh".
|
// Pass null for lpApplicationName so CreateProcessW searches PATH for "pwsh".
|
||||||
let code = run_and_wait(ptr::null(), &mut cmd, ptr::null());
|
let code = run_and_wait(null(), &mut cmd, null());
|
||||||
ExitProcess(code);
|
ExitProcess(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,16 +416,16 @@ unsafe fn read_file_trimmed<'a, const N: usize>(
|
|||||||
path.as_ptr(),
|
path.as_ptr(),
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
0,
|
null(),
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
0,
|
0,
|
||||||
0,
|
null_mut(),
|
||||||
);
|
);
|
||||||
if h == INVALID_HANDLE_VALUE {
|
if h == INVALID_HANDLE_VALUE {
|
||||||
die(b"cannot open go.toolchain.rev\n");
|
die(b"cannot open go.toolchain.rev\n");
|
||||||
}
|
}
|
||||||
let mut n: u32 = 0;
|
let mut n: u32 = 0;
|
||||||
ReadFile(h, buf.as_mut_ptr(), buf.len() as u32, &mut n, 0);
|
ReadFile(h, buf.as_mut_ptr(), buf.len() as u32, &mut n, null_mut());
|
||||||
CloseHandle(h);
|
CloseHandle(h);
|
||||||
|
|
||||||
let s = &buf[..n as usize];
|
let s = &buf[..n as usize];
|
||||||
@@ -670,7 +465,7 @@ unsafe fn skip_argv0(cmd: *const u16) -> *const u16 {
|
|||||||
unsafe fn stderr(msg: &[u8]) {
|
unsafe fn stderr(msg: &[u8]) {
|
||||||
let h = GetStdHandle(STD_ERROR_HANDLE);
|
let h = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
let mut n: u32 = 0;
|
let mut n: u32 = 0;
|
||||||
WriteFile(h, msg.as_ptr(), msg.len() as u32, &mut n, 0);
|
WriteFile(h, msg.as_ptr(), msg.len() as u32, &mut n, null_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write an error message to stderr and terminate with exit code 1.
|
/// Write an error message to stderr and terminate with exit code 1.
|
||||||
@@ -680,6 +475,7 @@ unsafe fn die(msg: &[u8]) -> ! {
|
|||||||
ExitProcess(1);
|
ExitProcess(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
unsafe { ExitProcess(EXIT_CODE_PANIC) }
|
unsafe { ExitProcess(EXIT_CODE_PANIC) }
|
||||||
|
|||||||
Reference in New Issue
Block a user