authorgravatar for leecannon@leecannon.xyzLee Cannon <leecannon@leecannon.xyz> 2020-11-07 11:55:55+00:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-11-18 15:37:44+01:00
log32c998e03c38fabfb3f26ad7f88817ec8a8e5f6d
treea62ddbdf336b426f0bf72764b918461faebe4b25
parent80b1e82b1b8706b7654560013751dd4a6fc8ae2a

Switch to RtlSetCurrentDirectory_U


4 files changed, 39 insertions(+), 17 deletions(-)

lib/std/os.zig+7-1
...@@ -2297,6 +2297,9 @@ pub const ChangeCurDirError = error{...@@ -2297,6 +2297,9 @@ pub const ChangeCurDirError = error{
2297 FileNotFound,2297 FileNotFound,
2298 SystemResources,2298 SystemResources,
2299 NotDir,2299 NotDir,
2300
2301 /// On Windows, file paths must be valid Unicode.
2302 InvalidUtf8,
2300} || UnexpectedError;2303} || UnexpectedError;
23012304
2302/// Changes the current working directory of the calling process.2305/// Changes the current working directory of the calling process.
...@@ -2306,9 +2309,12 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {...@@ -2306,9 +2309,12 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
2306 @compileError("chdir is not supported in WASI");2309 @compileError("chdir is not supported in WASI");
2307 } else if (builtin.os.tag == .windows) {2310 } else if (builtin.os.tag == .windows) {
2308 windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {2311 windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
2309 error.PathNotFound, error.InvalidName, error.InvalidUtf8 => return error.FileNotFound,2312 error.InvalidUtf8 => return error.InvalidUtf8,
2310 error.NameTooLong => return error.NameTooLong,2313 error.NameTooLong => return error.NameTooLong,
2314 error.FileNotFound => return error.FileNotFound,
2311 error.NotDir => return error.NotDir,2315 error.NotDir => return error.NotDir,
2316 error.NoDevice => return error.FileSystem,
2317 error.AccessDenied => return error.AccessDenied,
2312 error.Unexpected => return error.Unexpected,2318 error.Unexpected => return error.Unexpected,
2313 };2319 };
2314 } else {2320 } else {
lib/std/os/windows.zig+28-15
...@@ -556,29 +556,42 @@ pub fn WriteFile(...@@ -556,29 +556,42 @@ pub fn WriteFile(
556}556}
557557
558pub const SetCurrentDirectoryError = error{558pub const SetCurrentDirectoryError = error{
559 PathNotFound,
560 InvalidName,
561 InvalidUtf8,
562 NameTooLong,559 NameTooLong,
560 InvalidUtf8,
561 FileNotFound,
563 NotDir,562 NotDir,
563 AccessDenied,
564 NoDevice,
564 Unexpected,565 Unexpected,
565};566};
566567
567pub fn SetCurrentDirectory(path_name: []const u8) SetCurrentDirectoryError!void {568pub fn SetCurrentDirectory(path_name: []const u8) SetCurrentDirectoryError!void {
568 // PATH_MAX_WIDE - 1 as we need to ensure there is space for the null terminator569 var path_space: PathSpace = undefined;
569 if (path_name.len >= PATH_MAX_WIDE - 1) return error.NameTooLong;570 path_space.len = try std.unicode.utf8ToUtf16Le(path_space.data[0..], path_name);
571 if (path_space.len > path_space.data.len) return error.NameTooLong;
570 572
571 var utf16le_buf: [PATH_MAX_WIDE]u16 = undefined;573 const path_len_bytes = math.cast(u16, path_space.len * 2) catch |err| switch (err) {
572 const end = try std.unicode.utf8ToUtf16Le(utf16le_buf[0..], path_name);574 error.Overflow => return error.NameTooLong,
573 utf16le_buf[end] = 0;575 };
574 576
575 if (kernel32.SetCurrentDirectoryW(@ptrCast([*:0]const u16, &utf16le_buf)) == 0) {577 var nt_name = UNICODE_STRING{
576 switch (kernel32.GetLastError()) {578 .Length = path_len_bytes,
577 .PATH_NOT_FOUND, .FILE_NOT_FOUND => return error.PathNotFound,579 .MaximumLength = path_len_bytes,
578 .DIRECTORY => return error.NotDir,580 .Buffer = @intToPtr([*]u16, @ptrToInt(&path_space.data)),
579 .INVALID_NAME => return error.InvalidName,581 };
580 else => |err| return unexpectedError(err),582
581 }583 const rc = ntdll.RtlSetCurrentDirectory_U(&nt_name);
584 switch (rc) {
585 .SUCCESS => {},
586 .OBJECT_NAME_INVALID => unreachable,
587 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
588 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
589 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
590 .INVALID_PARAMETER => unreachable,
591 .ACCESS_DENIED => return error.AccessDenied,
592 .OBJECT_PATH_SYNTAX_BAD => unreachable,
593 .NOT_A_DIRECTORY => return error.NotDir,
594 else => return unexpectedStatus(rc),
582 }595 }
583}596}
584597
lib/std/os/windows/kernel32.zig-1
...@@ -93,7 +93,6 @@ pub extern "kernel32" fn FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCh...@@ -93,7 +93,6 @@ pub extern "kernel32" fn FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCh
93pub extern "kernel32" fn FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfAttrsWritten: LPDWORD) callconv(.Stdcall) BOOL;93pub extern "kernel32" fn FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfAttrsWritten: LPDWORD) callconv(.Stdcall) BOOL;
94pub extern "kernel32" fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) callconv(.Stdcall) BOOL;94pub extern "kernel32" fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) callconv(.Stdcall) BOOL;
9595
96pub extern "kernel32" fn SetCurrentDirectoryW(lpPathName: [*:0]const u16) callconv(.Stdcall) BOOL;
97pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;96pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;
9897
99pub extern "kernel32" fn GetCurrentThread() callconv(.Stdcall) HANDLE;98pub extern "kernel32" fn GetCurrentThread() callconv(.Stdcall) HANDLE;
lib/std/os/windows/ntdll.zig+4
...@@ -111,3 +111,7 @@ pub extern "NtDll" fn NtWaitForKeyedEvent(...@@ -111,3 +111,7 @@ pub extern "NtDll" fn NtWaitForKeyedEvent(
111 Alertable: BOOLEAN,111 Alertable: BOOLEAN,
112 Timeout: ?*LARGE_INTEGER,112 Timeout: ?*LARGE_INTEGER,
113) callconv(.Stdcall) NTSTATUS;113) callconv(.Stdcall) NTSTATUS;
114
115pub extern "NtDll" fn RtlSetCurrentDirectory_U(
116 PathName: *UNICODE_STRING
117) callconv(.Stdcall) NTSTATUS;