aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorLee Cannon <leecannon@leecannon.xyz>2020-11-07 11:55:55 +0000
committerJakub Konka <kubkon@jakubkonka.com>2020-11-18 15:37:44 +0100
commit32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d (patch)
treea62ddbdf336b426f0bf72764b918461faebe4b25 /lib/std
parent80b1e82b1b8706b7654560013751dd4a6fc8ae2a (diff)
downloadzig-32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d.tar.gz
zig-32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d.zip
Switch to RtlSetCurrentDirectory_U
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/os.zig8
-rw-r--r--lib/std/os/windows.zig43
-rw-r--r--lib/std/os/windows/kernel32.zig1
-rw-r--r--lib/std/os/windows/ntdll.zig4
4 files changed, 39 insertions, 17 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index edb53ec6a3..cfa9c99643 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -2297,6 +2297,9 @@ pub const ChangeCurDirError = error{
FileNotFound,
SystemResources,
NotDir,
+
+ /// On Windows, file paths must be valid Unicode.
+ InvalidUtf8,
} || UnexpectedError;
/// Changes the current working directory of the calling process.
@@ -2306,9 +2309,12 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
@compileError("chdir is not supported in WASI");
} else if (builtin.os.tag == .windows) {
windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
- error.PathNotFound, error.InvalidName, error.InvalidUtf8 => return error.FileNotFound,
+ error.InvalidUtf8 => return error.InvalidUtf8,
error.NameTooLong => return error.NameTooLong,
+ error.FileNotFound => return error.FileNotFound,
error.NotDir => return error.NotDir,
+ error.NoDevice => return error.FileSystem,
+ error.AccessDenied => return error.AccessDenied,
error.Unexpected => return error.Unexpected,
};
} else {
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index 6bdc858fc2..b382dccf2e 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -556,29 +556,42 @@ pub fn WriteFile(
}
pub const SetCurrentDirectoryError = error{
- PathNotFound,
- InvalidName,
- InvalidUtf8,
NameTooLong,
+ InvalidUtf8,
+ FileNotFound,
NotDir,
+ AccessDenied,
+ NoDevice,
Unexpected,
};
pub fn SetCurrentDirectory(path_name: []const u8) SetCurrentDirectoryError!void {
- // PATH_MAX_WIDE - 1 as we need to ensure there is space for the null terminator
- if (path_name.len >= PATH_MAX_WIDE - 1) return error.NameTooLong;
+ var path_space: PathSpace = undefined;
+ path_space.len = try std.unicode.utf8ToUtf16Le(path_space.data[0..], path_name);
+ if (path_space.len > path_space.data.len) return error.NameTooLong;
- var utf16le_buf: [PATH_MAX_WIDE]u16 = undefined;
- const end = try std.unicode.utf8ToUtf16Le(utf16le_buf[0..], path_name);
- utf16le_buf[end] = 0;
+ const path_len_bytes = math.cast(u16, path_space.len * 2) catch |err| switch (err) {
+ error.Overflow => return error.NameTooLong,
+ };
- if (kernel32.SetCurrentDirectoryW(@ptrCast([*:0]const u16, &utf16le_buf)) == 0) {
- switch (kernel32.GetLastError()) {
- .PATH_NOT_FOUND, .FILE_NOT_FOUND => return error.PathNotFound,
- .DIRECTORY => return error.NotDir,
- .INVALID_NAME => return error.InvalidName,
- else => |err| return unexpectedError(err),
- }
+ var nt_name = UNICODE_STRING{
+ .Length = path_len_bytes,
+ .MaximumLength = path_len_bytes,
+ .Buffer = @intToPtr([*]u16, @ptrToInt(&path_space.data)),
+ };
+
+ const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
+ switch (rc) {
+ .SUCCESS => {},
+ .OBJECT_NAME_INVALID => unreachable,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NO_MEDIA_IN_DEVICE => return error.NoDevice,
+ .INVALID_PARAMETER => unreachable,
+ .ACCESS_DENIED => return error.AccessDenied,
+ .OBJECT_PATH_SYNTAX_BAD => unreachable,
+ .NOT_A_DIRECTORY => return error.NotDir,
+ else => return unexpectedStatus(rc),
}
}
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 9a79f0e728..5d0b5bb227 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -93,7 +93,6 @@ pub extern "kernel32" fn FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCh
pub extern "kernel32" fn FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfAttrsWritten: LPDWORD) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) callconv(.Stdcall) BOOL;
-pub extern "kernel32" fn SetCurrentDirectoryW(lpPathName: [*:0]const u16) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;
pub extern "kernel32" fn GetCurrentThread() callconv(.Stdcall) HANDLE;
diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig
index c11098b6bc..c077eae594 100644
--- a/lib/std/os/windows/ntdll.zig
+++ b/lib/std/os/windows/ntdll.zig
@@ -111,3 +111,7 @@ pub extern "NtDll" fn NtWaitForKeyedEvent(
Alertable: BOOLEAN,
Timeout: ?*LARGE_INTEGER,
) callconv(.Stdcall) NTSTATUS;
+
+pub extern "NtDll" fn RtlSetCurrentDirectory_U(
+ PathName: *UNICODE_STRING
+) callconv(.Stdcall) NTSTATUS;