diff --git a/lib/std/fs.zig b/lib/std/fs.zig index fbc76f702f..bc2c921d1e 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1243,9 +1243,9 @@ pub fn openSelfExe() OpenSelfExeError!File { return File.openReadC(c"/proc/self/exe"); } if (builtin.os == .windows) { - var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined; - const wide_slice = try selfExePathW(&buf); - return File.openReadW(wide_slice.ptr); + const wide_slice = selfExePathW(); + const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice); + return Dir.cwd().openReadW(&prefixed_path_w); } var buf: [MAX_PATH_BYTES]u8 = undefined; const self_exe_path = try selfExePath(&buf); @@ -1296,8 +1296,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 { return mem.toSlice(u8, out_buffer); }, .windows => { - var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined; - const utf16le_slice = try selfExePathW(&utf16le_buf); + const utf16le_slice = selfExePathW(); // Trust that Windows gives us valid UTF-16LE. const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable; return out_buffer[0..end_index]; @@ -1306,9 +1305,10 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 { } } -/// Same as `selfExePath` except the result is UTF16LE-encoded. -pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) SelfExePathError![]u16 { - return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len); +/// The result is UTF16LE-encoded. +pub fn selfExePathW() []const u16 { + const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName; + return mem.toSliceConst(u16, image_path_name.Buffer); } /// `selfExeDirPath` except allocates the result on the heap. diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 06da223d5c..a04e351799 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -927,6 +927,24 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 { return sliceToPrefixedSuffixedFileW(s, [_]u16{0}); } +/// Assumes an absolute path. +pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 { + // TODO https://github.com/ziglang/zig/issues/2765 + var result: [PATH_MAX_WIDE + 1]u16 = undefined; + + const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: { + const prefix = [_]u16{ '\\', '?', '?', '\\' }; + mem.copy(u16, result[0..], prefix); + break :blk prefix.len; + }; + const end_index = start_index + s.len; + if (end_index + 1 > result.len) return error.NameTooLong; + mem.copy(u16, result[start_index..], s); + result[end_index] = 0; + return result; + +} + pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 { // TODO https://github.com/ziglang/zig/issues/2765 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined; @@ -948,7 +966,6 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) break :blk prefix.len; }; const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s); - assert(end_index <= result.len); if (end_index + suffix.len > result.len) return error.NameTooLong; mem.copy(u16, result[end_index..], suffix); return result;