diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 563b24cf83c3..eaac89bf24d1 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1886,13 +1886,48 @@ pub const CreateProcessError = error{ Unexpected, }; +pub const CreateProcessFlags = packed struct(u32) { + debug_process: bool = false, + debug_only_this_process: bool = false, + create_suspended: bool = false, + detached_process: bool = false, + create_new_console: bool = false, + normal_priority_class: bool = false, + idle_priority_class: bool = false, + high_priority_class: bool = false, + realtime_priority_class: bool = false, + create_new_process_group: bool = false, + create_unicode_environment: bool = false, + create_separate_wow_vdm: bool = false, + create_shared_wow_vdm: bool = false, + create_forcedos: bool = false, + below_normal_priority_class: bool = false, + above_normal_priority_class: bool = false, + inherit_parent_affinity: bool = false, + inherit_caller_priority: bool = false, + create_protected_process: bool = false, + extended_startupinfo_present: bool = false, + process_mode_background_begin: bool = false, + process_mode_background_end: bool = false, + create_secure_process: bool = false, + _reserved: bool = false, + create_breakaway_from_job: bool = false, + create_preserve_code_authz_level: bool = false, + create_default_error_mode: bool = false, + create_no_window: bool = false, + profile_user: bool = false, + profile_kernel: bool = false, + profile_server: bool = false, + create_ignore_system_default: bool = false, +}; + pub fn CreateProcessW( lpApplicationName: ?LPCWSTR, lpCommandLine: ?LPWSTR, lpProcessAttributes: ?*SECURITY_ATTRIBUTES, lpThreadAttributes: ?*SECURITY_ATTRIBUTES, bInheritHandles: BOOL, - dwCreationFlags: DWORD, + dwCreationFlags: CreateProcessFlags, lpEnvironment: ?*anyopaque, lpCurrentDirectory: ?LPCWSTR, lpStartupInfo: *STARTUPINFOW, diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index ce151279796a..d23fd6b32683 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -314,7 +314,7 @@ pub extern "kernel32" fn CreateProcessW( lpProcessAttributes: ?*SECURITY_ATTRIBUTES, lpThreadAttributes: ?*SECURITY_ATTRIBUTES, bInheritHandles: BOOL, - dwCreationFlags: DWORD, + dwCreationFlags: windows.CreateProcessFlags, lpEnvironment: ?LPVOID, lpCurrentDirectory: ?LPCWSTR, lpStartupInfo: *STARTUPINFOW, diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig index 8a4cab5e83e7..27b5c6b7c958 100644 --- a/lib/std/process/Child.zig +++ b/lib/std/process/Child.zig @@ -80,9 +80,13 @@ expand_arg0: Arg0Expand, /// Darwin-only. Disable ASLR for the child process. disable_aslr: bool = false, -/// Darwin-only. Start child process in suspended state as if SIGSTOP was sent. +/// Darwin and Windows only. Start child process in suspended state. For Darwin it's started +/// as if SIGSTOP was sent. start_suspended: bool = false, +/// Windows-only. Sets the CREATE_NO_WINDOW flag in CreateProcess. +create_no_window: bool = false, + /// Set to true to obtain rusage information for the child process. /// Depending on the target platform and implementation status, the /// requested statistics may or may not be available. If they are @@ -854,6 +858,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { const app_name_w = try unicode.wtf8ToWtf16LeAllocZ(self.allocator, app_basename_wtf8); defer self.allocator.free(app_name_w); + const flags: windows.CreateProcessFlags = .{ + .create_suspended = self.start_suspended, + .create_unicode_environment = true, + .create_no_window = self.create_no_window, + }; + run: { const PATH: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATH")) orelse &[_:0]u16{}; const PATHEXT: [:0]const u16 = process.getenvW(unicode.utf8ToUtf16LeStringLiteral("PATHEXT")) orelse &[_:0]u16{}; @@ -889,7 +899,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { dir_buf.shrinkRetainingCapacity(normalized_len); } - windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| { + windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo) catch |no_path_err| { const original_err = switch (no_path_err) { // argv[0] contains unsupported characters that will never resolve to a valid exe. error.InvalidArg0 => return error.FileNotFound, @@ -917,7 +927,7 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { const normalized_len = windows.normalizePath(u16, dir_buf.items) catch continue; dir_buf.shrinkRetainingCapacity(normalized_len); - if (windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) { + if (windowsCreateProcessPathExt(self.allocator, &dir_buf, &app_buf, PATHEXT, &cmd_line_cache, envp_ptr, cwd_w_ptr, flags, &siStartInfo, &piProcInfo)) { break :run; } else |err| switch (err) { // argv[0] contains unsupported characters that will never resolve to a valid exe. @@ -1016,6 +1026,7 @@ fn windowsCreateProcessPathExt( cmd_line_cache: *WindowsCommandLineCache, envp_ptr: ?[*]u16, cwd_ptr: ?[*:0]u16, + flags: windows.CreateProcessFlags, lpStartupInfo: *windows.STARTUPINFOW, lpProcessInformation: *windows.PROCESS_INFORMATION, ) !void { @@ -1166,7 +1177,7 @@ fn windowsCreateProcessPathExt( else full_app_name; - if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, lpStartupInfo, lpProcessInformation)) |_| { + if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { return; } else |err| switch (err) { error.FileNotFound, @@ -1221,7 +1232,7 @@ fn windowsCreateProcessPathExt( else full_app_name; - if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, lpStartupInfo, lpProcessInformation)) |_| { + if (windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_ptr, flags, lpStartupInfo, lpProcessInformation)) |_| { return; } else |err| switch (err) { error.FileNotFound => continue, @@ -1247,6 +1258,7 @@ fn windowsCreateProcess( cmd_line: [*:0]u16, envp_ptr: ?[*]u16, cwd_ptr: ?[*:0]u16, + flags: windows.CreateProcessFlags, lpStartupInfo: *windows.STARTUPINFOW, lpProcessInformation: *windows.PROCESS_INFORMATION, ) !void { @@ -1273,7 +1285,7 @@ fn windowsCreateProcess( null, null, windows.TRUE, - windows.CREATE_UNICODE_ENVIRONMENT, + flags, @as(?*anyopaque, @ptrCast(envp_ptr)), cwd_ptr, lpStartupInfo, diff --git a/test/standalone/windows_argv/fuzz.zig b/test/standalone/windows_argv/fuzz.zig index 4accccb3bad7..6d08c1bf8423 100644 --- a/test/standalone/windows_argv/fuzz.zig +++ b/test/standalone/windows_argv/fuzz.zig @@ -138,7 +138,7 @@ fn spawnVerify(verify_path: [:0]const u16, cmd_line: [:0]const u16) !windows.DWO null, null, windows.TRUE, - 0, + .{}, null, null, &startup_info,