diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a34d034d..cd1ba9d3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -630,5 +630,8 @@ set_target_properties(zig PROPERTIES LINK_FLAGS ${EXE_LDFLAGS} ) target_link_libraries(zig compiler "${LIBUSERLAND}") +if(MSVC) + target_link_libraries(zig ntdll.lib) +endif() add_dependencies(zig zig_build_libuserland) install(TARGETS zig DESTINATION bin) diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 51623d305..8f9f8c17d 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -590,6 +590,7 @@ pub const Dir = struct { self.end_index = io.Information; switch (rc) { w.STATUS.SUCCESS => {}, + w.STATUS.ACCESS_DENIED => return error.AccessDenied, else => return w.unexpectedStatus(rc), } } @@ -708,7 +709,7 @@ pub const Dir = struct { /// Call `close` on the result when done. pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir { - std.debug.warn("openDir {}\n", sub_path); + // std.debug.warn("openDir {}\n", sub_path); if (os.windows.is_the_target) { const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path); return self.openDirW(&sub_path_w); @@ -740,9 +741,26 @@ pub const Dir = struct { /// This function is Windows-only. pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir { const w = os.windows; + var result = Dir{ .fd = undefined, }; + + const desired_access = w.GENERIC_READ | w.SYNCHRONIZE; + + // if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + // // Windows gives me STATUS_OBJECT_NAME_INVALID with "." as the object name. + + // if (w.kernel32.DuplicateHandle(w.self_process_handle, self.fd, w.self_process_handle, &result.fd, desired_access, w.TRUE, 0) == 0) { + // switch (w.kernel32.GetLastError()) { + // else => |err| return w.unexpectedError(err), + // } + + // @panic("handle DuplicateHandle error"); + // } + // return result; + // } + //var mask: ?[*]const u16 = undefined; //var nt_name: w.UNICODE_STRING = undefined; //if (w.ntdll.RtlDosPathNameToNtPathName_U(sub_path_w, &nt_name, null, null) == 0) { @@ -760,7 +778,7 @@ pub const Dir = struct { //} const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2); - std.debug.warn("path_len_bytes = {}\n", path_len_bytes); + // std.debug.warn("path_len_bytes = {}\n", path_len_bytes); var nt_name = w.UNICODE_STRING{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, @@ -774,7 +792,11 @@ pub const Dir = struct { .SecurityDescriptor = null, .SecurityQualityOfService = null, }; - std.debug.warn("RootDirectory = {}\n", attr.RootDirectory); + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + // Windows does not recognize this, but it does work with empty string. + nt_name.Length = 0; + } + // std.debug.warn("RootDirectory = {}\n", attr.RootDirectory); var io: w.IO_STATUS_BLOCK = undefined; const wide_slice = nt_name.Buffer[0 .. nt_name.Length / 2]; //const wide_slice2 = std.mem.toSliceConst(u16, mask.?); @@ -782,11 +804,11 @@ pub const Dir = struct { //var buf2: [200]u8 = undefined; const len = std.unicode.utf16leToUtf8(&buf, wide_slice) catch unreachable; //const len2 = std.unicode.utf16leToUtf8(&buf2, wide_slice2) catch unreachable; - std.debug.warn("path: {}\n", buf[0..len]); + // std.debug.warn("path: {}\n", buf[0..len]); //std.debug.warn("path: {}\nmask: {}\n", buf[0..len], buf2[0..len2]); const rc = w.ntdll.NtCreateFile( &result.fd, - w.GENERIC_READ | w.SYNCHRONIZE, + desired_access, &attr, &io, null, @@ -797,11 +819,12 @@ pub const Dir = struct { null, 0, ); - std.debug.warn("result.fd = {}\n", result.fd); + // std.debug.warn("result.fd = {}\n", result.fd); switch (rc) { w.STATUS.SUCCESS => return result, w.STATUS.OBJECT_NAME_INVALID => @panic("openDirW invalid object name"), w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound, w.STATUS.INVALID_PARAMETER => { @panic("invalid parameter"); }, diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 6a5d03b52..93a5a65a9 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -20,6 +20,8 @@ pub const shell32 = @import("windows/shell32.zig"); pub usingnamespace @import("windows/bits.zig"); +pub const self_process_handle = @intToPtr(HANDLE, maxInt(usize)); + /// `builtin` is missing `subsystem` when the subsystem is automatically detected, /// so Zig standard library has the subsystem detection logic here. This should generally be /// used rather than `builtin.subsystem`. @@ -898,7 +900,7 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError { /// and you get an unexpected status. pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError { if (std.os.unexpected_error_tracing) { - std.debug.warn("error.Unexpected NTSTATUS={}\n", status); + std.debug.warn("error.Unexpected NTSTATUS=0x{x}\n", status); std.debug.dumpCurrentStackTrace(null); } return error.Unexpected; diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index 68d5ab6b8..214f75186 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -872,3 +872,5 @@ pub const CURDIR = extern struct { DosPath: UNICODE_STRING, Handle: HANDLE, }; + +pub const DUPLICATE_SAME_ACCESS = 2; \ No newline at end of file diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig index 2ae73ad45..736d81ae5 100644 --- a/lib/std/os/windows/kernel32.zig +++ b/lib/std/os/windows/kernel32.zig @@ -47,6 +47,8 @@ pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_ pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL; +pub extern "kernel32" stdcallcc fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) BOOL; + pub extern "kernel32" stdcallcc fn ExitProcess(exit_code: UINT) noreturn; pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFindFileData: *WIN32_FIND_DATAW) HANDLE; diff --git a/lib/std/os/windows/status.zig b/lib/std/os/windows/status.zig index d381e3b2e..424cae5e2 100644 --- a/lib/std/os/windows/status.zig +++ b/lib/std/os/windows/status.zig @@ -8,4 +8,5 @@ pub const INVALID_PARAMETER = 0xC000000D; pub const ACCESS_DENIED = 0xC0000022; pub const OBJECT_NAME_INVALID = 0xC0000033; pub const OBJECT_NAME_NOT_FOUND = 0xC0000034; +pub const OBJECT_PATH_NOT_FOUND = 0xC000003A; pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B;