authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-21 19:17:33-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-21 19:19:49-04:00
log87f632b08a04f4a03facfa220df1cbc466a5de39
tree9a6b7deaad57b5f0dbd36308c6fae9dfd632c067
parentef67c497856fb97f7d2854991a72237ad4332810

fs.Dir.openDir: use empty object name for "." on Windows


6 files changed, 40 insertions(+), 7 deletions(-)

CMakeLists.txt+3
...@@ -630,5 +630,8 @@ set_target_properties(zig PROPERTIES...@@ -630,5 +630,8 @@ set_target_properties(zig PROPERTIES
630 LINK_FLAGS ${EXE_LDFLAGS}630 LINK_FLAGS ${EXE_LDFLAGS}
631)631)
632target_link_libraries(zig compiler "${LIBUSERLAND}")632target_link_libraries(zig compiler "${LIBUSERLAND}")
633if(MSVC)
634 target_link_libraries(zig ntdll.lib)
635endif()
633add_dependencies(zig zig_build_libuserland)636add_dependencies(zig zig_build_libuserland)
634install(TARGETS zig DESTINATION bin)637install(TARGETS zig DESTINATION bin)
lib/std/fs.zig+29-6
...@@ -590,6 +590,7 @@ pub const Dir = struct {...@@ -590,6 +590,7 @@ pub const Dir = struct {
590 self.end_index = io.Information;590 self.end_index = io.Information;
591 switch (rc) {591 switch (rc) {
592 w.STATUS.SUCCESS => {},592 w.STATUS.SUCCESS => {},
593 w.STATUS.ACCESS_DENIED => return error.AccessDenied,
593 else => return w.unexpectedStatus(rc),594 else => return w.unexpectedStatus(rc),
594 }595 }
595 }596 }
...@@ -708,7 +709,7 @@ pub const Dir = struct {...@@ -708,7 +709,7 @@ pub const Dir = struct {
708709
709 /// Call `close` on the result when done.710 /// Call `close` on the result when done.
710 pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {711 pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir {
711 std.debug.warn("openDir {}\n", sub_path);712 // std.debug.warn("openDir {}\n", sub_path);
712 if (os.windows.is_the_target) {713 if (os.windows.is_the_target) {
713 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);714 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
714 return self.openDirW(&sub_path_w);715 return self.openDirW(&sub_path_w);
...@@ -740,9 +741,26 @@ pub const Dir = struct {...@@ -740,9 +741,26 @@ pub const Dir = struct {
740 /// This function is Windows-only.741 /// This function is Windows-only.
741 pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir {742 pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir {
742 const w = os.windows;743 const w = os.windows;
744
743 var result = Dir{745 var result = Dir{
744 .fd = undefined,746 .fd = undefined,
745 };747 };
748
749 const desired_access = w.GENERIC_READ | w.SYNCHRONIZE;
750
751 // if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
752 // // Windows gives me STATUS_OBJECT_NAME_INVALID with "." as the object name.
753
754 // if (w.kernel32.DuplicateHandle(w.self_process_handle, self.fd, w.self_process_handle, &result.fd, desired_access, w.TRUE, 0) == 0) {
755 // switch (w.kernel32.GetLastError()) {
756 // else => |err| return w.unexpectedError(err),
757 // }
758
759 // @panic("handle DuplicateHandle error");
760 // }
761 // return result;
762 // }
763
746 //var mask: ?[*]const u16 = undefined;764 //var mask: ?[*]const u16 = undefined;
747 //var nt_name: w.UNICODE_STRING = undefined;765 //var nt_name: w.UNICODE_STRING = undefined;
748 //if (w.ntdll.RtlDosPathNameToNtPathName_U(sub_path_w, &nt_name, null, null) == 0) {766 //if (w.ntdll.RtlDosPathNameToNtPathName_U(sub_path_w, &nt_name, null, null) == 0) {
...@@ -760,7 +778,7 @@ pub const Dir = struct {...@@ -760,7 +778,7 @@ pub const Dir = struct {
760 //}778 //}
761779
762 const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2);780 const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2);
763 std.debug.warn("path_len_bytes = {}\n", path_len_bytes);781 // std.debug.warn("path_len_bytes = {}\n", path_len_bytes);
764 var nt_name = w.UNICODE_STRING{782 var nt_name = w.UNICODE_STRING{
765 .Length = path_len_bytes,783 .Length = path_len_bytes,
766 .MaximumLength = path_len_bytes,784 .MaximumLength = path_len_bytes,
...@@ -774,7 +792,11 @@ pub const Dir = struct {...@@ -774,7 +792,11 @@ pub const Dir = struct {
774 .SecurityDescriptor = null,792 .SecurityDescriptor = null,
775 .SecurityQualityOfService = null,793 .SecurityQualityOfService = null,
776 };794 };
777 std.debug.warn("RootDirectory = {}\n", attr.RootDirectory);795 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
796 // Windows does not recognize this, but it does work with empty string.
797 nt_name.Length = 0;
798 }
799 // std.debug.warn("RootDirectory = {}\n", attr.RootDirectory);
778 var io: w.IO_STATUS_BLOCK = undefined;800 var io: w.IO_STATUS_BLOCK = undefined;
779 const wide_slice = nt_name.Buffer[0 .. nt_name.Length / 2];801 const wide_slice = nt_name.Buffer[0 .. nt_name.Length / 2];
780 //const wide_slice2 = std.mem.toSliceConst(u16, mask.?);802 //const wide_slice2 = std.mem.toSliceConst(u16, mask.?);
...@@ -782,11 +804,11 @@ pub const Dir = struct {...@@ -782,11 +804,11 @@ pub const Dir = struct {
782 //var buf2: [200]u8 = undefined;804 //var buf2: [200]u8 = undefined;
783 const len = std.unicode.utf16leToUtf8(&buf, wide_slice) catch unreachable;805 const len = std.unicode.utf16leToUtf8(&buf, wide_slice) catch unreachable;
784 //const len2 = std.unicode.utf16leToUtf8(&buf2, wide_slice2) catch unreachable;806 //const len2 = std.unicode.utf16leToUtf8(&buf2, wide_slice2) catch unreachable;
785 std.debug.warn("path: {}\n", buf[0..len]);807 // std.debug.warn("path: {}\n", buf[0..len]);
786 //std.debug.warn("path: {}\nmask: {}\n", buf[0..len], buf2[0..len2]);808 //std.debug.warn("path: {}\nmask: {}\n", buf[0..len], buf2[0..len2]);
787 const rc = w.ntdll.NtCreateFile(809 const rc = w.ntdll.NtCreateFile(
788 &result.fd,810 &result.fd,
789 w.GENERIC_READ | w.SYNCHRONIZE,811 desired_access,
790 &attr,812 &attr,
791 &io,813 &io,
792 null,814 null,
...@@ -797,11 +819,12 @@ pub const Dir = struct {...@@ -797,11 +819,12 @@ pub const Dir = struct {
797 null,819 null,
798 0,820 0,
799 );821 );
800 std.debug.warn("result.fd = {}\n", result.fd);822 // std.debug.warn("result.fd = {}\n", result.fd);
801 switch (rc) {823 switch (rc) {
802 w.STATUS.SUCCESS => return result,824 w.STATUS.SUCCESS => return result,
803 w.STATUS.OBJECT_NAME_INVALID => @panic("openDirW invalid object name"),825 w.STATUS.OBJECT_NAME_INVALID => @panic("openDirW invalid object name"),
804 w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,826 w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
827 w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
805 w.STATUS.INVALID_PARAMETER => {828 w.STATUS.INVALID_PARAMETER => {
806 @panic("invalid parameter");829 @panic("invalid parameter");
807 },830 },
lib/std/os/windows.zig+3-1
...@@ -20,6 +20,8 @@ pub const shell32 = @import("windows/shell32.zig");...@@ -20,6 +20,8 @@ pub const shell32 = @import("windows/shell32.zig");
2020
21pub usingnamespace @import("windows/bits.zig");21pub usingnamespace @import("windows/bits.zig");
2222
23pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize));
24
23/// `builtin` is missing `subsystem` when the subsystem is automatically detected,25/// `builtin` is missing `subsystem` when the subsystem is automatically detected,
24/// so Zig standard library has the subsystem detection logic here. This should generally be26/// so Zig standard library has the subsystem detection logic here. This should generally be
25/// used rather than `builtin.subsystem`.27/// used rather than `builtin.subsystem`.
...@@ -898,7 +900,7 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError {...@@ -898,7 +900,7 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError {
898/// and you get an unexpected status.900/// and you get an unexpected status.
899pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {901pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError {
900 if (std.os.unexpected_error_tracing) {902 if (std.os.unexpected_error_tracing) {
901 std.debug.warn("error.Unexpected NTSTATUS={}\n", status);903 std.debug.warn("error.Unexpected NTSTATUS=0x{x}\n", status);
902 std.debug.dumpCurrentStackTrace(null);904 std.debug.dumpCurrentStackTrace(null);
903 }905 }
904 return error.Unexpected;906 return error.Unexpected;
lib/std/os/windows/bits.zig+2
...@@ -872,3 +872,5 @@ pub const CURDIR = extern struct {...@@ -872,3 +872,5 @@ pub const CURDIR = extern struct {
872 DosPath: UNICODE_STRING,872 DosPath: UNICODE_STRING,
873 Handle: HANDLE,873 Handle: HANDLE,
874};874};
875
876pub const DUPLICATE_SAME_ACCESS = 2;
\ No newline at end of file
lib/std/os/windows/kernel32.zig+2
...@@ -47,6 +47,8 @@ pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_...@@ -47,6 +47,8 @@ pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_
4747
48pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;48pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL;
4949
50pub extern "kernel32" stdcallcc fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) BOOL;
51
50pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;52pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn;
5153
52pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;54pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE;
lib/std/os/windows/status.zig+1
...@@ -8,4 +8,5 @@ pub const INVALID_PARAMETER = 0xC000000D;...@@ -8,4 +8,5 @@ pub const INVALID_PARAMETER = 0xC000000D;
8pub const ACCESS_DENIED = 0xC0000022;8pub const ACCESS_DENIED = 0xC0000022;
9pub const OBJECT_NAME_INVALID = 0xC0000033;9pub const OBJECT_NAME_INVALID = 0xC0000033;
10pub const OBJECT_NAME_NOT_FOUND = 0xC0000034;10pub const OBJECT_NAME_NOT_FOUND = 0xC0000034;
11pub const OBJECT_PATH_NOT_FOUND = 0xC000003A;
11pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B;12pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B;