| ... | @@ -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 { |
| 708 | | 709 | |
| 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 | //} |
| 761 | | 779 | |
| 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 | }, |