diff options
| author | Lee Cannon <leecannon@leecannon.xyz> | 2020-11-07 11:55:55 +0000 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2020-11-18 15:37:44 +0100 |
| commit | 32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d (patch) | |
| tree | a62ddbdf336b426f0bf72764b918461faebe4b25 /lib/std | |
| parent | 80b1e82b1b8706b7654560013751dd4a6fc8ae2a (diff) | |
| download | zig-32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d.tar.gz zig-32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d.zip | |
Switch to RtlSetCurrentDirectory_U
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/os.zig | 8 | ||||
| -rw-r--r-- | lib/std/os/windows.zig | 43 | ||||
| -rw-r--r-- | lib/std/os/windows/kernel32.zig | 1 | ||||
| -rw-r--r-- | lib/std/os/windows/ntdll.zig | 4 |
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; |
