aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/heap.zig2
-rw-r--r--lib/std/os.zig15
-rw-r--r--lib/std/os/windows.zig220
-rw-r--r--lib/std/os/windows/kernel32.zig62
-rw-r--r--lib/std/posix.zig111
5 files changed, 132 insertions, 278 deletions
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
index c35e6f6684..445b5da455 100644
--- a/lib/std/heap.zig
+++ b/lib/std/heap.zig
@@ -46,7 +46,7 @@ pub var next_mmap_addr_hint: ?[*]align(page_size_min) u8 = null;
/// comptime-known minimum page size of the target.
///
-/// All pointers from `mmap` or `VirtualAlloc` are aligned to at least
+/// All pointers from `mmap` or `NtAllocateVirtualMemory` are aligned to at least
/// `page_size_min`, but their actual alignment may be bigger.
///
/// This value can be overridden via `std.options.page_size_min`.
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 5efca5899c..110c92da2b 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -56,21 +56,6 @@ pub var argv: [][*:0]u8 = if (builtin.link_libc) undefined else switch (native_o
else => undefined,
};
-/// Call from Windows-specific code if you already have a WTF-16LE encoded, null terminated string.
-/// Otherwise use `access`.
-pub fn accessW(path: [*:0]const u16) windows.GetFileAttributesError!void {
- const ret = try windows.GetFileAttributesW(path);
- if (ret != windows.INVALID_FILE_ATTRIBUTES) {
- return;
- }
- switch (windows.GetLastError()) {
- .FILE_NOT_FOUND => return error.FileNotFound,
- .PATH_NOT_FOUND => return error.FileNotFound,
- .ACCESS_DENIED => return error.AccessDenied,
- else => |err| return windows.unexpectedError(err),
- }
-}
-
pub fn isGetFdPathSupportedOnTarget(os: std.Target.Os) bool {
return switch (os.tag) {
.windows,
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index a855a58d4f..86655051fd 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -306,22 +306,6 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
wr.* = write;
}
-pub fn CreateEventEx(attributes: ?*SECURITY_ATTRIBUTES, name: []const u8, flags: DWORD, desired_access: DWORD) !HANDLE {
- const nameW = try sliceToPrefixedFileW(null, name);
- return CreateEventExW(attributes, nameW.span().ptr, flags, desired_access);
-}
-
-pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: ?LPCWSTR, flags: DWORD, desired_access: DWORD) !HANDLE {
- const handle = kernel32.CreateEventExW(attributes, nameW, flags, desired_access);
- if (handle) |h| {
- return h;
- } else {
- switch (GetLastError()) {
- else => |err| return unexpectedError(err),
- }
- }
-}
-
pub const DeviceIoControlError = error{
AccessDenied,
/// The volume does not contain a recognized file system. File system
@@ -598,10 +582,6 @@ pub fn CloseHandle(hObject: HANDLE) void {
assert(ntdll.NtClose(hObject) == .SUCCESS);
}
-pub fn FindClose(hFindFile: HANDLE) void {
- assert(kernel32.FindClose(hFindFile) != 0);
-}
-
pub const ReadFileError = error{
BrokenPipe,
/// The specified network name is no longer available.
@@ -1104,21 +1084,135 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
}
}
-pub const MoveFileError = error{ FileNotFound, AccessDenied, Unexpected };
+pub const RenameError = error{
+ IsDir,
+ NotDir,
+ FileNotFound,
+ NoDevice,
+ AccessDenied,
+ PipeBusy,
+ PathAlreadyExists,
+ Unexpected,
+ NameTooLong,
+ NetworkNotFound,
+ AntivirusInterference,
+ BadPathName,
+ RenameAcrossMountPoints,
+} || UnexpectedError;
-pub fn MoveFileEx(old_path: []const u8, new_path: []const u8, flags: DWORD) (MoveFileError || Wtf8ToPrefixedFileWError)!void {
- const old_path_w = try sliceToPrefixedFileW(null, old_path);
- const new_path_w = try sliceToPrefixedFileW(null, new_path);
- return MoveFileExW(old_path_w.span().ptr, new_path_w.span().ptr, flags);
-}
+pub fn RenameFile(
+ /// May only be `null` if `old_path_w` is a fully-qualified absolute path.
+ old_dir_fd: ?HANDLE,
+ old_path_w: []const u16,
+ /// May only be `null` if `new_path_w` is a fully-qualified absolute path,
+ /// or if the file is not being moved to a different directory.
+ new_dir_fd: ?HANDLE,
+ new_path_w: []const u16,
+ replace_if_exists: bool,
+) RenameError!void {
+ const src_fd = OpenFile(old_path_w, .{
+ .dir = old_dir_fd,
+ .access_mask = SYNCHRONIZE | GENERIC_WRITE | DELETE,
+ .creation = FILE_OPEN,
+ .filter = .any, // This function is supposed to rename both files and directories.
+ .follow_symlinks = false,
+ }) catch |err| switch (err) {
+ error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
+ else => |e| return e,
+ };
+ defer CloseHandle(src_fd);
-pub fn MoveFileExW(old_path: [*:0]const u16, new_path: [*:0]const u16, flags: DWORD) MoveFileError!void {
- if (kernel32.MoveFileExW(old_path, new_path, flags) == 0) {
- switch (GetLastError()) {
- .FILE_NOT_FOUND => return error.FileNotFound,
- .ACCESS_DENIED => return error.AccessDenied,
- else => |err| return unexpectedError(err),
+ var rc: NTSTATUS = undefined;
+ // FileRenameInformationEx has varying levels of support:
+ // - FILE_RENAME_INFORMATION_EX requires >= win10_rs1
+ // (INVALID_INFO_CLASS is returned if not supported)
+ // - Requires the NTFS filesystem
+ // (on filesystems like FAT32, INVALID_PARAMETER is returned)
+ // - FILE_RENAME_POSIX_SEMANTICS requires >= win10_rs1
+ // - FILE_RENAME_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5
+ // (NOT_SUPPORTED is returned if a flag is unsupported)
+ //
+ // The strategy here is just to try using FileRenameInformationEx and fall back to
+ // FileRenameInformation if the return value lets us know that some aspect of it is not supported.
+ const need_fallback = need_fallback: {
+ const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + (PATH_MAX_WIDE * 2);
+ var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION_EX)) = undefined;
+ const struct_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + new_path_w.len * 2;
+ if (struct_len > struct_buf_len) return error.NameTooLong;
+
+ const rename_info: *FILE_RENAME_INFORMATION_EX = @ptrCast(&rename_info_buf);
+ var io_status_block: IO_STATUS_BLOCK = undefined;
+
+ var flags: ULONG = FILE_RENAME_POSIX_SEMANTICS | FILE_RENAME_IGNORE_READONLY_ATTRIBUTE;
+ if (replace_if_exists) flags |= FILE_RENAME_REPLACE_IF_EXISTS;
+ rename_info.* = .{
+ .Flags = flags,
+ .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
+ .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
+ .FileName = undefined,
+ };
+ @memcpy((&rename_info.FileName).ptr, new_path_w);
+ rc = ntdll.NtSetInformationFile(
+ src_fd,
+ &io_status_block,
+ rename_info,
+ @intCast(struct_len), // already checked for error.NameTooLong
+ .FileRenameInformationEx,
+ );
+ switch (rc) {
+ .SUCCESS => return,
+ // The filesystem does not support FileDispositionInformationEx
+ .INVALID_PARAMETER,
+ // The operating system does not support FileDispositionInformationEx
+ .INVALID_INFO_CLASS,
+ // The operating system does not support one of the flags
+ .NOT_SUPPORTED,
+ => break :need_fallback true,
+ // For all other statuses, fall down to the switch below to handle them.
+ else => break :need_fallback false,
}
+ };
+
+ if (need_fallback) {
+ const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION) + (PATH_MAX_WIDE * 2);
+ var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION)) = undefined;
+ const struct_len = @sizeOf(FILE_RENAME_INFORMATION) + new_path_w.len * 2;
+ if (struct_len > struct_buf_len) return error.NameTooLong;
+
+ const rename_info: *FILE_RENAME_INFORMATION = @ptrCast(&rename_info_buf);
+ var io_status_block: IO_STATUS_BLOCK = undefined;
+
+ rename_info.* = .{
+ .Flags = @intFromBool(replace_if_exists),
+ .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
+ .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
+ .FileName = undefined,
+ };
+ @memcpy((&rename_info.FileName).ptr, new_path_w);
+
+ rc = ntdll.NtSetInformationFile(
+ src_fd,
+ &io_status_block,
+ rename_info,
+ @intCast(struct_len), // already checked for error.NameTooLong
+ .FileRenameInformation,
+ );
+ }
+
+ switch (rc) {
+ .SUCCESS => {},
+ .INVALID_HANDLE => unreachable,
+ .INVALID_PARAMETER => unreachable,
+ .OBJECT_PATH_SYNTAX_BAD => unreachable,
+ .ACCESS_DENIED => return error.AccessDenied,
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
+ .NOT_SAME_DEVICE => return error.RenameAcrossMountPoints,
+ .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
+ .DIRECTORY_NOT_EMPTY => return error.PathAlreadyExists,
+ .FILE_IS_A_DIRECTORY => return error.IsDir,
+ .NOT_A_DIRECTORY => return error.NotDir,
+ else => return unexpectedStatus(rc),
}
}
@@ -1515,30 +1609,6 @@ pub fn GetFileSizeEx(hFile: HANDLE) GetFileSizeError!u64 {
return @as(u64, @bitCast(file_size));
}
-pub const GetFileAttributesError = error{
- FileNotFound,
- AccessDenied,
- Unexpected,
-};
-
-pub fn GetFileAttributes(filename: []const u8) (GetFileAttributesError || Wtf8ToPrefixedFileWError)!DWORD {
- const filename_w = try sliceToPrefixedFileW(null, filename);
- return GetFileAttributesW(filename_w.span().ptr);
-}
-
-pub fn GetFileAttributesW(lpFileName: [*:0]const u16) GetFileAttributesError!DWORD {
- const rc = kernel32.GetFileAttributesW(lpFileName);
- if (rc == INVALID_FILE_ATTRIBUTES) {
- switch (GetLastError()) {
- .FILE_NOT_FOUND => return error.FileNotFound,
- .PATH_NOT_FOUND => return error.FileNotFound,
- .ACCESS_DENIED => return error.AccessDenied,
- else => |err| return unexpectedError(err),
- }
- }
- return rc;
-}
-
pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {
return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
}
@@ -1657,6 +1727,7 @@ pub const NtFreeVirtualMemoryError = error{
};
pub fn NtFreeVirtualMemory(hProcess: HANDLE, addr: ?*PVOID, size: *SIZE_T, free_type: ULONG) NtFreeVirtualMemoryError!void {
+ // TODO: If the return value is .INVALID_PAGE_PROTECTION, call RtlFlushSecureMemoryCache and try again.
return switch (ntdll.NtFreeVirtualMemory(hProcess, addr, size, free_type)) {
.SUCCESS => return,
.ACCESS_DENIED => NtFreeVirtualMemoryError.AccessDenied,
@@ -1665,20 +1736,6 @@ pub fn NtFreeVirtualMemory(hProcess: HANDLE, addr: ?*PVOID, size: *SIZE_T, free_
};
}
-pub const VirtualAllocError = error{Unexpected};
-
-pub fn VirtualAlloc(addr: ?LPVOID, size: usize, alloc_type: DWORD, flProtect: DWORD) VirtualAllocError!LPVOID {
- return kernel32.VirtualAlloc(addr, size, alloc_type, flProtect) orelse {
- switch (GetLastError()) {
- else => |err| return unexpectedError(err),
- }
- };
-}
-
-pub fn VirtualFree(lpAddress: ?LPVOID, dwSize: usize, dwFreeType: DWORD) void {
- assert(kernel32.VirtualFree(lpAddress, dwSize, dwFreeType) != 0);
-}
-
pub const VirtualProtectError = error{
InvalidAddress,
Unexpected,
@@ -1713,19 +1770,6 @@ pub fn VirtualProtectEx(handle: HANDLE, addr: ?LPVOID, size: SIZE_T, new_prot: D
}
}
-pub const VirtualQueryError = error{Unexpected};
-
-pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T {
- const rc = kernel32.VirtualQuery(lpAddress, lpBuffer, dwLength);
- if (rc == 0) {
- switch (GetLastError()) {
- else => |err| return unexpectedError(err),
- }
- }
-
- return rc;
-}
-
pub const SetConsoleTextAttributeError = error{Unexpected};
pub fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) SetConsoleTextAttributeError!void {
@@ -2628,16 +2672,6 @@ test ntToWin32Namespace {
try std.testing.expectError(error.NameTooLong, ntToWin32Namespace(L("\\??\\C:\\test"), &too_small_buf));
}
-fn getFullPathNameW(path: [*:0]const u16, out: []u16) !usize {
- const result = kernel32.GetFullPathNameW(path, @as(u32, @intCast(out.len)), out.ptr, null);
- if (result == 0) {
- switch (GetLastError()) {
- else => |err| return unexpectedError(err),
- }
- }
- return result;
-}
-
inline fn MAKELANGID(p: c_ushort, s: c_ushort) LANGID {
return (s << 10) | p;
}
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 98d72a04e1..7f746057a9 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -86,34 +86,11 @@ pub extern "kernel32" fn CreateNamedPipeW(
lpSecurityAttributes: ?*const SECURITY_ATTRIBUTES,
) callconv(.winapi) HANDLE;
-pub extern "kernel32" fn FindFirstFileW(
- lpFileName: LPCWSTR,
- lpFindFileData: *WIN32_FIND_DATAW,
-) callconv(.winapi) HANDLE;
-
-pub extern "kernel32" fn FindClose(
- hFindFile: HANDLE,
-) callconv(.winapi) BOOL;
-
-// TODO: Wrapper around RtlGetFullPathName_UEx
-pub extern "kernel32" fn GetFullPathNameW(
- lpFileName: LPCWSTR,
- nBufferLength: DWORD,
- lpBuffer: LPWSTR,
- lpFilePart: ?*?LPWSTR,
-) callconv(.winapi) DWORD;
-
// TODO: Matches `STD_*_HANDLE` to peb().ProcessParameters.Standard*
pub extern "kernel32" fn GetStdHandle(
nStdHandle: DWORD,
) callconv(.winapi) ?HANDLE;
-pub extern "kernel32" fn MoveFileExW(
- lpExistingFileName: LPCWSTR,
- lpNewFileName: LPCWSTR,
- dwFlags: DWORD,
-) callconv(.winapi) BOOL;
-
// TODO: Wrapper around NtSetInformationFile + `FILE_POSITION_INFORMATION`.
// `FILE_STANDARD_INFORMATION` is also used if dwMoveMethod is `FILE_END`
pub extern "kernel32" fn SetFilePointerEx(
@@ -162,11 +139,6 @@ pub extern "kernel32" fn GetCurrentDirectoryW(
lpBuffer: ?[*]WCHAR,
) callconv(.winapi) DWORD;
-// TODO: RtlDosPathNameToNtPathNameU_WithStatus + NtQueryAttributesFile.
-pub extern "kernel32" fn GetFileAttributesW(
- lpFileName: LPCWSTR,
-) callconv(.winapi) DWORD;
-
pub extern "kernel32" fn ReadFile(
hFile: HANDLE,
lpBuffer: LPVOID,
@@ -182,14 +154,6 @@ pub extern "kernel32" fn GetSystemDirectoryW(
// I/O - Kernel Objects
-// TODO: Wrapper around NtCreateEvent.
-pub extern "kernel32" fn CreateEventExW(
- lpEventAttributes: ?*SECURITY_ATTRIBUTES,
- lpName: ?LPCWSTR,
- dwFlags: DWORD,
- dwDesiredAccess: DWORD,
-) callconv(.winapi) ?HANDLE;
-
// TODO: Wrapper around GetStdHandle + NtDuplicateObject.
pub extern "kernel32" fn DuplicateHandle(
hSourceProcessHandle: HANDLE,
@@ -318,9 +282,6 @@ pub extern "kernel32" fn GetExitCodeProcess(
lpExitCode: *DWORD,
) callconv(.winapi) BOOL;
-// TODO: Already a wrapper for this, see `windows.GetCurrentProcess`.
-pub extern "kernel32" fn GetCurrentProcess() callconv(.winapi) HANDLE;
-
// TODO: Wrapper around RtlSetEnvironmentVar.
pub extern "kernel32" fn SetEnvironmentVariableW(
lpName: LPCWSTR,
@@ -465,29 +426,6 @@ pub extern "kernel32" fn HeapValidate(
lpMem: ?*const anyopaque,
) callconv(.winapi) BOOL;
-// TODO: Wrapper around NtAllocateVirtualMemory.
-pub extern "kernel32" fn VirtualAlloc(
- lpAddress: ?LPVOID,
- dwSize: SIZE_T,
- flAllocationType: DWORD,
- flProtect: DWORD,
-) callconv(.winapi) ?LPVOID;
-
-// TODO: Wrapper around NtFreeVirtualMemory.
-// If the return value is .INVALID_PAGE_PROTECTION, calls RtlFlushSecureMemoryCache and try again.
-pub extern "kernel32" fn VirtualFree(
- lpAddress: ?LPVOID,
- dwSize: SIZE_T,
- dwFreeType: DWORD,
-) callconv(.winapi) BOOL;
-
-// TODO: Wrapper around NtQueryVirtualMemory.
-pub extern "kernel32" fn VirtualQuery(
- lpAddress: ?LPVOID,
- lpBuffer: PMEMORY_BASIC_INFORMATION,
- dwLength: SIZE_T,
-) callconv(.winapi) SIZE_T;
-
// TODO: Getter for peb.ProcessHeap
pub extern "kernel32" fn GetProcessHeap() callconv(.winapi) ?HANDLE;
diff --git a/lib/std/posix.zig b/lib/std/posix.zig
index 13d16ea324..3e80466cd3 100644
--- a/lib/std/posix.zig
+++ b/lib/std/posix.zig
@@ -2470,8 +2470,8 @@ pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!voi
/// Same as `rename` except the parameters are null-terminated and WTF16LE encoded.
/// Assumes target is Windows.
pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!void {
- const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
- return windows.MoveFileExW(old_path, new_path, flags);
+ const cwd_handle = std.fs.cwd().fd;
+ return windows.RenameFile(cwd_handle, mem.span(old_path), cwd_handle, mem.span(new_path), true);
}
/// Change the name or location of a file based on an open directory handle.
@@ -2588,110 +2588,7 @@ pub fn renameatW(
new_path_w: []const u16,
ReplaceIfExists: windows.BOOLEAN,
) RenameError!void {
- const src_fd = windows.OpenFile(old_path_w, .{
- .dir = old_dir_fd,
- .access_mask = windows.SYNCHRONIZE | windows.GENERIC_WRITE | windows.DELETE,
- .creation = windows.FILE_OPEN,
- .filter = .any, // This function is supposed to rename both files and directories.
- .follow_symlinks = false,
- }) catch |err| switch (err) {
- error.WouldBlock => unreachable, // Not possible without `.share_access_nonblocking = true`.
- else => |e| return e,
- };
- defer windows.CloseHandle(src_fd);
-
- var rc: windows.NTSTATUS = undefined;
- // FileRenameInformationEx has varying levels of support:
- // - FILE_RENAME_INFORMATION_EX requires >= win10_rs1
- // (INVALID_INFO_CLASS is returned if not supported)
- // - Requires the NTFS filesystem
- // (on filesystems like FAT32, INVALID_PARAMETER is returned)
- // - FILE_RENAME_POSIX_SEMANTICS requires >= win10_rs1
- // - FILE_RENAME_IGNORE_READONLY_ATTRIBUTE requires >= win10_rs5
- // (NOT_SUPPORTED is returned if a flag is unsupported)
- //
- // The strategy here is just to try using FileRenameInformationEx and fall back to
- // FileRenameInformation if the return value lets us know that some aspect of it is not supported.
- const need_fallback = need_fallback: {
- const struct_buf_len = @sizeOf(windows.FILE_RENAME_INFORMATION_EX) + (max_path_bytes - 1);
- var rename_info_buf: [struct_buf_len]u8 align(@alignOf(windows.FILE_RENAME_INFORMATION_EX)) = undefined;
- const struct_len = @sizeOf(windows.FILE_RENAME_INFORMATION_EX) - 1 + new_path_w.len * 2;
- if (struct_len > struct_buf_len) return error.NameTooLong;
-
- const rename_info: *windows.FILE_RENAME_INFORMATION_EX = @ptrCast(&rename_info_buf);
- var io_status_block: windows.IO_STATUS_BLOCK = undefined;
-
- var flags: windows.ULONG = windows.FILE_RENAME_POSIX_SEMANTICS | windows.FILE_RENAME_IGNORE_READONLY_ATTRIBUTE;
- if (ReplaceIfExists == windows.TRUE) flags |= windows.FILE_RENAME_REPLACE_IF_EXISTS;
- rename_info.* = .{
- .Flags = flags,
- .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
- .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
- .FileName = undefined,
- };
- @memcpy((&rename_info.FileName).ptr, new_path_w);
- rc = windows.ntdll.NtSetInformationFile(
- src_fd,
- &io_status_block,
- rename_info,
- @intCast(struct_len), // already checked for error.NameTooLong
- .FileRenameInformationEx,
- );
- switch (rc) {
- .SUCCESS => return,
- // The filesystem does not support FileDispositionInformationEx
- .INVALID_PARAMETER,
- // The operating system does not support FileDispositionInformationEx
- .INVALID_INFO_CLASS,
- // The operating system does not support one of the flags
- .NOT_SUPPORTED,
- => break :need_fallback true,
- // For all other statuses, fall down to the switch below to handle them.
- else => break :need_fallback false,
- }
- };
-
- if (need_fallback) {
- const struct_buf_len = @sizeOf(windows.FILE_RENAME_INFORMATION) + (max_path_bytes - 1);
- var rename_info_buf: [struct_buf_len]u8 align(@alignOf(windows.FILE_RENAME_INFORMATION)) = undefined;
- const struct_len = @sizeOf(windows.FILE_RENAME_INFORMATION) - 1 + new_path_w.len * 2;
- if (struct_len > struct_buf_len) return error.NameTooLong;
-
- const rename_info: *windows.FILE_RENAME_INFORMATION = @ptrCast(&rename_info_buf);
- var io_status_block: windows.IO_STATUS_BLOCK = undefined;
-
- rename_info.* = .{
- .Flags = ReplaceIfExists,
- .RootDirectory = if (fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
- .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
- .FileName = undefined,
- };
- @memcpy((&rename_info.FileName).ptr, new_path_w);
-
- rc = windows.ntdll.NtSetInformationFile(
- src_fd,
- &io_status_block,
- rename_info,
- @intCast(struct_len), // already checked for error.NameTooLong
- .FileRenameInformation,
- );
- }
-
- switch (rc) {
- .SUCCESS => {},
- .INVALID_HANDLE => unreachable,
- .INVALID_PARAMETER => unreachable,
- .OBJECT_PATH_SYNTAX_BAD => unreachable,
- .ACCESS_DENIED => return error.AccessDenied,
- .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
- .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
- .NOT_SAME_DEVICE => return error.RenameAcrossMountPoints,
- .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
- .DIRECTORY_NOT_EMPTY => return error.PathAlreadyExists,
- .FILE_IS_A_DIRECTORY => return error.IsDir,
- .NOT_A_DIRECTORY => return error.NotDir,
- else => return windows.unexpectedStatus(rc),
- }
+ return windows.RenameFile(old_dir_fd, old_path_w, new_dir_fd, new_path_w, ReplaceIfExists != 0);
}
/// On Windows, `sub_dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
@@ -4409,7 +4306,7 @@ pub fn mmap(
/// Note that while POSIX allows unmapping a region in the middle of an existing mapping,
/// Zig's munmap function does not, for two reasons:
/// * It violates the Zig principle that resource deallocation must succeed.
-/// * The Windows function, VirtualFree, has this restriction.
+/// * The Windows function, NtFreeVirtualMemory, has this restriction.
pub fn munmap(memory: []align(page_size_min) const u8) void {
switch (errno(system.munmap(memory.ptr, memory.len))) {
.SUCCESS => return,