mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-03-08 01:04:43 +01:00
std.os.windows: delete unused APIs
Intention is to go through std.Io for these things.
This commit is contained in:
parent
5571c08e66
commit
9b415761dd
6 changed files with 36 additions and 398 deletions
|
|
@ -48,7 +48,7 @@ pub const Error = error{
|
|||
LockViolation,
|
||||
} || Io.Cancelable || Io.UnexpectedError;
|
||||
|
||||
pub const SizeError = std.os.windows.GetFileSizeError || File.StatError || error{
|
||||
pub const SizeError = File.StatError || error{
|
||||
/// Occurs if, for example, the file handle is a network socket and therefore does not have a size.
|
||||
Streaming,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13960,8 +13960,19 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child
|
|||
fn childCleanupWindows(child: *process.Child) void {
|
||||
const handle = child.id orelse return;
|
||||
|
||||
if (child.request_resource_usage_statistics)
|
||||
child.resource_usage_statistics.rusage = windows.GetProcessMemoryInfo(handle) catch null;
|
||||
if (child.request_resource_usage_statistics) {
|
||||
var vmc: windows.VM_COUNTERS = undefined;
|
||||
switch (windows.ntdll.NtQueryInformationProcess(
|
||||
handle,
|
||||
.VmCounters,
|
||||
&vmc,
|
||||
@sizeOf(windows.VM_COUNTERS),
|
||||
null,
|
||||
)) {
|
||||
.SUCCESS => child.resource_usage_statistics.rusage = vmc,
|
||||
else => child.resource_usage_statistics.rusage = null,
|
||||
}
|
||||
}
|
||||
|
||||
windows.CloseHandle(handle);
|
||||
child.id = null;
|
||||
|
|
|
|||
|
|
@ -2906,275 +2906,6 @@ pub fn GetCurrentDirectory(buffer: []u8) GetCurrentDirectoryError![]u8 {
|
|||
return buffer[0..end_index];
|
||||
}
|
||||
|
||||
pub const DeleteFileError = error{
|
||||
FileNotFound,
|
||||
AccessDenied,
|
||||
NameTooLong,
|
||||
/// Also known as sharing violation.
|
||||
FileBusy,
|
||||
Unexpected,
|
||||
NotDir,
|
||||
IsDir,
|
||||
DirNotEmpty,
|
||||
NetworkNotFound,
|
||||
};
|
||||
|
||||
pub const DeleteFileOptions = struct {
|
||||
dir: ?HANDLE,
|
||||
remove_dir: bool = false,
|
||||
};
|
||||
|
||||
pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void {
|
||||
const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2));
|
||||
var nt_name: UNICODE_STRING = .{
|
||||
.Length = path_len_bytes,
|
||||
.MaximumLength = path_len_bytes,
|
||||
// The Windows API makes this mutable, but it will not mutate here.
|
||||
.Buffer = @constCast(sub_path_w.ptr),
|
||||
};
|
||||
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
|
||||
// Windows does not recognize this, but it does work with empty string.
|
||||
nt_name.Length = 0;
|
||||
}
|
||||
if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) {
|
||||
// Can't remove the parent directory with an open handle.
|
||||
return error.FileBusy;
|
||||
}
|
||||
|
||||
var io: IO_STATUS_BLOCK = undefined;
|
||||
var tmp_handle: HANDLE = undefined;
|
||||
var rc = ntdll.NtCreateFile(
|
||||
&tmp_handle,
|
||||
.{ .STANDARD = .{
|
||||
.RIGHTS = .{ .DELETE = true },
|
||||
.SYNCHRONIZE = true,
|
||||
} },
|
||||
&.{
|
||||
.Length = @sizeOf(OBJECT_ATTRIBUTES),
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
|
||||
.Attributes = .{},
|
||||
.ObjectName = &nt_name,
|
||||
.SecurityDescriptor = null,
|
||||
.SecurityQualityOfService = null,
|
||||
},
|
||||
&io,
|
||||
null,
|
||||
.{},
|
||||
.VALID_FLAGS,
|
||||
.OPEN,
|
||||
.{
|
||||
.DIRECTORY_FILE = options.remove_dir,
|
||||
.NON_DIRECTORY_FILE = !options.remove_dir,
|
||||
.OPEN_REPARSE_POINT = true, // would we ever want to delete the target instead?
|
||||
},
|
||||
null,
|
||||
0,
|
||||
);
|
||||
switch (rc) {
|
||||
.SUCCESS => {},
|
||||
.OBJECT_NAME_INVALID => unreachable,
|
||||
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found
|
||||
.BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.FILE_IS_A_DIRECTORY => return error.IsDir,
|
||||
.NOT_A_DIRECTORY => return error.NotDir,
|
||||
.SHARING_VIOLATION => return error.FileBusy,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.DELETE_PENDING => return,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
defer CloseHandle(tmp_handle);
|
||||
|
||||
// FileDispositionInformationEx has varying levels of support:
|
||||
// - FILE_DISPOSITION_INFORMATION_EX requires >= win10_rs1
|
||||
// (INVALID_INFO_CLASS is returned if not supported)
|
||||
// - Requires the NTFS filesystem
|
||||
// (on filesystems like FAT32, INVALID_PARAMETER is returned)
|
||||
// - FILE_DISPOSITION_POSIX_SEMANTICS requires >= win10_rs1
|
||||
// - FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5
|
||||
// (NOT_SUPPORTED is returned if a flag is unsupported)
|
||||
//
|
||||
// The strategy here is just to try using FileDispositionInformationEx and fall back to
|
||||
// FileDispositionInformation if the return value lets us know that some aspect of it is not supported.
|
||||
const need_fallback = need_fallback: {
|
||||
// Deletion with posix semantics if the filesystem supports it.
|
||||
var info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
|
||||
.DELETE = true,
|
||||
.POSIX_SEMANTICS = true,
|
||||
.IGNORE_READONLY_ATTRIBUTE = true,
|
||||
} };
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
tmp_handle,
|
||||
&io,
|
||||
&info,
|
||||
@sizeOf(FILE.DISPOSITION.INFORMATION.EX),
|
||||
.DispositionEx,
|
||||
);
|
||||
switch (rc) {
|
||||
.SUCCESS => return,
|
||||
// The filesystem does not support FileDispositionInformationEx
|
||||
.INVALID_PARAMETER,
|
||||
// The operating system does not support FileDispositionInformationEx
|
||||
.INVALID_INFO_CLASS,
|
||||
// The operating system does not support one of the flags
|
||||
.NOT_SUPPORTED,
|
||||
=> break :need_fallback true,
|
||||
// For all other statuses, fall down to the switch below to handle them.
|
||||
else => break :need_fallback false,
|
||||
}
|
||||
};
|
||||
|
||||
if (need_fallback) {
|
||||
// Deletion with file pending semantics, which requires waiting or moving
|
||||
// files to get them removed (from here).
|
||||
var file_dispo: FILE.DISPOSITION.INFORMATION = .{
|
||||
.DeleteFile = TRUE,
|
||||
};
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
tmp_handle,
|
||||
&io,
|
||||
&file_dispo,
|
||||
@sizeOf(FILE.DISPOSITION.INFORMATION),
|
||||
.Disposition,
|
||||
);
|
||||
}
|
||||
switch (rc) {
|
||||
.SUCCESS => {},
|
||||
.DIRECTORY_NOT_EMPTY => return error.DirNotEmpty,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.CANNOT_DELETE => return error.AccessDenied,
|
||||
.MEDIA_WRITE_PROTECTED => return error.AccessDenied,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
pub const RenameError = error{
|
||||
IsDir,
|
||||
NotDir,
|
||||
FileNotFound,
|
||||
NoDevice,
|
||||
AccessDenied,
|
||||
PipeBusy,
|
||||
PathAlreadyExists,
|
||||
Unexpected,
|
||||
NameTooLong,
|
||||
NetworkNotFound,
|
||||
AntivirusInterference,
|
||||
BadPathName,
|
||||
CrossDevice,
|
||||
} || UnexpectedError;
|
||||
|
||||
pub fn RenameFile(
|
||||
/// May only be `null` if `old_path_w` is a fully-qualified absolute path.
|
||||
old_dir_fd: ?HANDLE,
|
||||
old_path_w: []const u16,
|
||||
/// May only be `null` if `new_path_w` is a fully-qualified absolute path,
|
||||
/// or if the file is not being moved to a different directory.
|
||||
new_dir_fd: ?HANDLE,
|
||||
new_path_w: []const u16,
|
||||
replace_if_exists: bool,
|
||||
) RenameError!void {
|
||||
const src_fd = OpenFile(old_path_w, .{
|
||||
.dir = old_dir_fd,
|
||||
.access_mask = .{
|
||||
.STANDARD = .{
|
||||
.RIGHTS = .{ .DELETE = true },
|
||||
.SYNCHRONIZE = true,
|
||||
},
|
||||
.GENERIC = .{ .WRITE = true },
|
||||
},
|
||||
.creation = .OPEN,
|
||||
.filter = .any, // This function is supposed to rename both files and directories.
|
||||
.follow_symlinks = false,
|
||||
}) catch |err| switch (err) {
|
||||
error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
|
||||
else => |e| return e,
|
||||
};
|
||||
defer CloseHandle(src_fd);
|
||||
|
||||
var rc: NTSTATUS = undefined;
|
||||
// FileRenameInformationEx has varying levels of support:
|
||||
// - FILE_RENAME_INFORMATION_EX requires >= win10_rs1
|
||||
// (INVALID_INFO_CLASS is returned if not supported)
|
||||
// - Requires the NTFS filesystem
|
||||
// (on filesystems like FAT32, INVALID_PARAMETER is returned)
|
||||
// - FILE_RENAME_POSIX_SEMANTICS requires >= win10_rs1
|
||||
// - FILE_RENAME_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5
|
||||
// (NOT_SUPPORTED is returned if a flag is unsupported)
|
||||
//
|
||||
// The strategy here is just to try using FileRenameInformationEx and fall back to
|
||||
// FileRenameInformation if the return value lets us know that some aspect of it is not supported.
|
||||
const need_fallback = need_fallback: {
|
||||
var rename_info: FILE.RENAME_INFORMATION = .init(.{
|
||||
.Flags = .{
|
||||
.REPLACE_IF_EXISTS = replace_if_exists,
|
||||
.POSIX_SEMANTICS = true,
|
||||
.IGNORE_READONLY_ATTRIBUTE = true,
|
||||
},
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
|
||||
.FileName = new_path_w,
|
||||
});
|
||||
var io_status_block: IO_STATUS_BLOCK = undefined;
|
||||
const rename_info_buf = rename_info.toBuffer();
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
src_fd,
|
||||
&io_status_block,
|
||||
rename_info_buf.ptr,
|
||||
@intCast(rename_info_buf.len), // already checked for error.NameTooLong
|
||||
.RenameEx,
|
||||
);
|
||||
switch (rc) {
|
||||
.SUCCESS => return,
|
||||
// The filesystem does not support FileDispositionInformationEx
|
||||
.INVALID_PARAMETER,
|
||||
// The operating system does not support FileDispositionInformationEx
|
||||
.INVALID_INFO_CLASS,
|
||||
// The operating system does not support one of the flags
|
||||
.NOT_SUPPORTED,
|
||||
=> break :need_fallback true,
|
||||
// For all other statuses, fall down to the switch below to handle them.
|
||||
else => break :need_fallback false,
|
||||
}
|
||||
};
|
||||
|
||||
if (need_fallback) {
|
||||
var rename_info: FILE.RENAME_INFORMATION = .init(.{
|
||||
.Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists },
|
||||
.RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
|
||||
.FileName = new_path_w,
|
||||
});
|
||||
var io_status_block: IO_STATUS_BLOCK = undefined;
|
||||
const rename_info_buf = rename_info.toBuffer();
|
||||
rc = ntdll.NtSetInformationFile(
|
||||
src_fd,
|
||||
&io_status_block,
|
||||
rename_info_buf.ptr,
|
||||
@intCast(rename_info_buf.len), // already checked for error.NameTooLong
|
||||
.Rename,
|
||||
);
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
.SUCCESS => {},
|
||||
.INVALID_HANDLE => unreachable,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.OBJECT_PATH_SYNTAX_BAD => unreachable,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
|
||||
.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.NOT_SAME_DEVICE => return error.CrossDevice,
|
||||
.OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
|
||||
.DIRECTORY_NOT_EMPTY => return error.PathAlreadyExists,
|
||||
.FILE_IS_A_DIRECTORY => return error.IsDir,
|
||||
.NOT_A_DIRECTORY => return error.NotDir,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
pub const GetStdHandleError = error{
|
||||
NoStandardHandleAttached,
|
||||
Unexpected,
|
||||
|
|
@ -3508,18 +3239,6 @@ test GetFinalPathNameByHandle {
|
|||
_ = try GetFinalPathNameByHandle(handle, .{ .volume_name = .Dos }, buffer[0..required_len_in_u16]);
|
||||
}
|
||||
|
||||
pub const GetFileSizeError = error{Unexpected};
|
||||
|
||||
pub fn GetFileSizeEx(hFile: HANDLE) GetFileSizeError!u64 {
|
||||
var file_size: LARGE_INTEGER = undefined;
|
||||
if (kernel32.GetFileSizeEx(hFile, &file_size) == 0) {
|
||||
switch (GetLastError()) {
|
||||
else => |err| return unexpectedError(err),
|
||||
}
|
||||
}
|
||||
return @as(u64, @bitCast(file_size));
|
||||
}
|
||||
|
||||
pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {
|
||||
return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
|
||||
}
|
||||
|
|
@ -3714,69 +3433,6 @@ pub const CreateProcessFlags = packed struct(u32) {
|
|||
create_ignore_system_default: bool = false,
|
||||
};
|
||||
|
||||
pub fn CreateProcessW(
|
||||
lpApplicationName: ?LPCWSTR,
|
||||
lpCommandLine: ?LPWSTR,
|
||||
lpProcessAttributes: ?*SECURITY_ATTRIBUTES,
|
||||
lpThreadAttributes: ?*SECURITY_ATTRIBUTES,
|
||||
bInheritHandles: BOOL,
|
||||
dwCreationFlags: CreateProcessFlags,
|
||||
lpEnvironment: ?[*:0]u16,
|
||||
lpCurrentDirectory: ?LPCWSTR,
|
||||
lpStartupInfo: *STARTUPINFOW,
|
||||
lpProcessInformation: *PROCESS_INFORMATION,
|
||||
) CreateProcessError!void {
|
||||
if (kernel32.CreateProcessW(
|
||||
lpApplicationName,
|
||||
lpCommandLine,
|
||||
lpProcessAttributes,
|
||||
lpThreadAttributes,
|
||||
bInheritHandles,
|
||||
dwCreationFlags,
|
||||
lpEnvironment,
|
||||
lpCurrentDirectory,
|
||||
lpStartupInfo,
|
||||
lpProcessInformation,
|
||||
) == 0) {
|
||||
switch (GetLastError()) {
|
||||
.FILE_NOT_FOUND => return error.FileNotFound,
|
||||
.PATH_NOT_FOUND => return error.FileNotFound,
|
||||
.DIRECTORY => return error.FileNotFound,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
.INVALID_NAME => return error.InvalidName,
|
||||
.FILENAME_EXCED_RANGE => return error.NameTooLong,
|
||||
.SHARING_VIOLATION => return error.FileBusy,
|
||||
// These are all the system errors that are mapped to ENOEXEC by
|
||||
// the undocumented _dosmaperr (old CRT) or __acrt_errno_map_os_error
|
||||
// (newer CRT) functions. Their code can be found in crt/src/dosmap.c (old SDK)
|
||||
// or urt/misc/errno.cpp (newer SDK) in the Windows SDK.
|
||||
.BAD_FORMAT,
|
||||
.INVALID_STARTING_CODESEG, // MIN_EXEC_ERROR in errno.cpp
|
||||
.INVALID_STACKSEG,
|
||||
.INVALID_MODULETYPE,
|
||||
.INVALID_EXE_SIGNATURE,
|
||||
.EXE_MARKED_INVALID,
|
||||
.BAD_EXE_FORMAT,
|
||||
.ITERATED_DATA_EXCEEDS_64k,
|
||||
.INVALID_MINALLOCSIZE,
|
||||
.DYNLINK_FROM_INVALID_RING,
|
||||
.IOPL_NOT_ENABLED,
|
||||
.INVALID_SEGDPL,
|
||||
.AUTODATASEG_EXCEEDS_64k,
|
||||
.RING2SEG_MUST_BE_MOVABLE,
|
||||
.RELOC_CHAIN_XEEDS_SEGLIM,
|
||||
.INFLOOP_IN_RELOC_CHAIN, // MAX_EXEC_ERROR in errno.cpp
|
||||
// This one is not mapped to ENOEXEC but it is possible, for example
|
||||
// when calling CreateProcessW on a plain text file with a .exe extension
|
||||
.EXE_MACHINE_TYPE_MISMATCH,
|
||||
=> return error.InvalidExe,
|
||||
.COMMITMENT_LIMIT => return error.SystemResources,
|
||||
else => |err| return unexpectedError(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const LoadLibraryError = error{
|
||||
FileNotFound,
|
||||
Unexpected,
|
||||
|
|
@ -3843,10 +3499,6 @@ pub fn QueryPerformanceCounter() u64 {
|
|||
return @as(u64, @bitCast(result));
|
||||
}
|
||||
|
||||
pub fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*anyopaque, Context: ?*anyopaque) void {
|
||||
assert(kernel32.InitOnceExecuteOnce(InitOnce, InitFn, Parameter, Context) != 0);
|
||||
}
|
||||
|
||||
/// This is a workaround for the C backend until zig has the ability to put
|
||||
/// C code in inline assembly.
|
||||
extern fn zig_thumb_windows_teb() callconv(.c) *anyopaque;
|
||||
|
|
@ -6072,24 +5724,6 @@ pub const PROCESS_MEMORY_COUNTERS_EX = extern struct {
|
|||
PrivateUsage: SIZE_T,
|
||||
};
|
||||
|
||||
pub const GetProcessMemoryInfoError = error{
|
||||
AccessDenied,
|
||||
InvalidHandle,
|
||||
Unexpected,
|
||||
};
|
||||
|
||||
pub fn GetProcessMemoryInfo(hProcess: HANDLE) GetProcessMemoryInfoError!VM_COUNTERS {
|
||||
var vmc: VM_COUNTERS = undefined;
|
||||
const rc = ntdll.NtQueryInformationProcess(hProcess, .VmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
|
||||
switch (rc) {
|
||||
.SUCCESS => return vmc,
|
||||
.ACCESS_DENIED => return error.AccessDenied,
|
||||
.INVALID_HANDLE => return error.InvalidHandle,
|
||||
.INVALID_PARAMETER => unreachable,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
||||
pub const PERFORMANCE_INFORMATION = extern struct {
|
||||
cb: DWORD,
|
||||
CommitTotal: SIZE_T,
|
||||
|
|
@ -6623,7 +6257,11 @@ pub fn WriteProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []const u8) Wri
|
|||
}
|
||||
}
|
||||
|
||||
pub const ProcessBaseAddressError = GetProcessMemoryInfoError || ReadMemoryError;
|
||||
pub const ProcessBaseAddressError = error{
|
||||
AccessDenied,
|
||||
InvalidHandle,
|
||||
Unexpected,
|
||||
} || ReadMemoryError;
|
||||
|
||||
/// Returns the base address of the process loaded into memory.
|
||||
pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE {
|
||||
|
|
|
|||
|
|
@ -117,12 +117,6 @@ pub extern "kernel32" fn WriteFile(
|
|||
in_out_lpOverlapped: ?*OVERLAPPED,
|
||||
) callconv(.winapi) BOOL;
|
||||
|
||||
// TODO: wrapper for NtQueryInformationFile + `FILE_STANDARD_INFORMATION`
|
||||
pub extern "kernel32" fn GetFileSizeEx(
|
||||
hFile: HANDLE,
|
||||
lpFileSize: *LARGE_INTEGER,
|
||||
) callconv(.winapi) BOOL;
|
||||
|
||||
// TODO: Wrapper around GetStdHandle + NtFlushBuffersFile.
|
||||
pub extern "kernel32" fn FlushFileBuffers(
|
||||
hFile: HANDLE,
|
||||
|
|
@ -283,12 +277,6 @@ pub extern "kernel32" fn GetExitCodeProcess(
|
|||
lpExitCode: *DWORD,
|
||||
) callconv(.winapi) BOOL;
|
||||
|
||||
// TODO: Wrapper around RtlSetEnvironmentVar.
|
||||
pub extern "kernel32" fn SetEnvironmentVariableW(
|
||||
lpName: LPCWSTR,
|
||||
lpValue: ?LPCWSTR,
|
||||
) callconv(.winapi) BOOL;
|
||||
|
||||
pub extern "kernel32" fn CreateToolhelp32Snapshot(
|
||||
dwFlags: DWORD,
|
||||
th32ProcessID: DWORD,
|
||||
|
|
@ -311,13 +299,6 @@ pub extern "kernel32" fn CreateThread(
|
|||
|
||||
// Locks, critical sections, initializers
|
||||
|
||||
pub extern "kernel32" fn InitOnceExecuteOnce(
|
||||
InitOnce: *INIT_ONCE,
|
||||
InitFn: INIT_ONCE_FN,
|
||||
Parameter: ?*anyopaque,
|
||||
Context: ?*anyopaque,
|
||||
) callconv(.winapi) BOOL;
|
||||
|
||||
// TODO:
|
||||
// - dwMilliseconds -> LARGE_INTEGER.
|
||||
// - RtlSleepConditionVariableSRW
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO
|
|||
};
|
||||
var proc_info: windows.PROCESS_INFORMATION = undefined;
|
||||
|
||||
try windows.CreateProcessW(
|
||||
if (windows.kernel32.CreateProcessW(
|
||||
@constCast(verify_path.ptr),
|
||||
@constCast(cmd_line.ptr),
|
||||
null,
|
||||
|
|
@ -140,7 +140,10 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO
|
|||
null,
|
||||
&startup_info,
|
||||
&proc_info,
|
||||
);
|
||||
) == 0) {
|
||||
std.process.fatal("kernel32 CreateProcessW failed with {t}", .{windows.kernel32.GetLastError()});
|
||||
}
|
||||
|
||||
windows.CloseHandle(proc_info.hThread);
|
||||
|
||||
break :spawn proc_info.hProcess;
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@ pub fn main(init: std.process.Init) !void {
|
|||
defer gpa.free(tmp_relative_path);
|
||||
|
||||
// Clear PATH
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
null,
|
||||
) == windows.TRUE);
|
||||
|
||||
// Set PATHEXT to something predictable
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATHEXT"),
|
||||
utf16Literal(".COM;.EXE;.BAT;.CMD;.JS"),
|
||||
) == windows.TRUE);
|
||||
|
|
@ -48,7 +48,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
// make sure we don't get error.BadPath traversing out of cwd with a relative path
|
||||
try testExecError(error.FileNotFound, gpa, io, "..\\.\\.\\.\\\\..\\more_missing");
|
||||
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
tmp_absolute_path_w,
|
||||
) == windows.TRUE);
|
||||
|
|
@ -131,7 +131,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
const something_subdir_abs_path = try std.mem.concatWithSentinel(gpa, u16, &.{ tmp_absolute_path_w, utf16Literal("\\something") }, 0);
|
||||
defer gpa.free(something_subdir_abs_path);
|
||||
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
something_subdir_abs_path,
|
||||
) == windows.TRUE);
|
||||
|
|
@ -171,7 +171,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
defer gpa.free(denormed_something_subdir_wtf8);
|
||||
|
||||
// clear the path to ensure that the match comes from the cwd
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
null,
|
||||
) == windows.TRUE);
|
||||
|
|
@ -179,7 +179,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
try testExecWithCwd(gpa, io, "goodbye", denormed_something_subdir_wtf8, "hello from exe\n");
|
||||
|
||||
// normalization should also work if the non-normalized path is found in the PATH var.
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
denormed_something_subdir_abs_path,
|
||||
) == windows.TRUE);
|
||||
|
|
@ -193,7 +193,7 @@ pub fn main(init: std.process.Init) !void {
|
|||
try std.process.setCurrentDir(io, subdir_cwd);
|
||||
|
||||
// clear the PATH again
|
||||
std.debug.assert(windows.kernel32.SetEnvironmentVariableW(
|
||||
std.debug.assert(SetEnvironmentVariableW(
|
||||
utf16Literal("PATH"),
|
||||
null,
|
||||
) == windows.TRUE);
|
||||
|
|
@ -235,3 +235,8 @@ fn renameExe(dir: Io.Dir, io: Io, old_sub_path: []const u8, new_sub_path: []cons
|
|||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
pub extern "kernel32" fn SetEnvironmentVariableW(
|
||||
lpName: windows.LPCWSTR,
|
||||
lpValue: ?windows.LPCWSTR,
|
||||
) callconv(.winapi) windows.BOOL;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue