zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit c13857e504f5893cabf182dde1e826131f2acf24 (tree)
parent 27e5047a888fbfd6c9db6a8374e070eb0deb5d0a
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date:   Tue,  9 Dec 2025 13:59:59 -0500

windows: type safety improvements and more ntdll functions

Diffstat:
Mlib/std/Build/Watch.zig | 33+++++++++++++++++++++------------
Mlib/std/Io/Threaded.zig | 170++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mlib/std/Thread.zig | 27++++++++++++---------------
Mlib/std/debug/SelfInfo/Windows.zig | 22++++++++++++++--------
Mlib/std/enums.zig | 4+++-
Mlib/std/fs/Dir.zig | 19+++++++++----------
Mlib/std/fs/File.zig | 14+++++++-------
Mlib/std/fs/test.zig | 40++++++++++++++++++++++++++--------------
Mlib/std/heap/PageAllocator.zig | 19++++++++++---------
Mlib/std/os/windows.zig | 3374++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlib/std/os/windows/kernel32.zig | 36+++---------------------------------
Mlib/std/os/windows/ntdll.zig | 651+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mlib/std/posix.zig | 15++++++++-------
Mlib/std/process/Child.zig | 16+++++++++-------
Mlib/std/zig/WindowsSdk.zig | 13+++++++++----
Msrc/link/MappedFile.zig | 21++++++++++++++-------
16 files changed, 3131 insertions(+), 1343 deletions(-)

diff --git a/lib/std/Build/Watch.zig b/lib/std/Build/Watch.zig @@ -366,7 +366,7 @@ const Os = switch (builtin.os.tag) { var attr = windows.OBJECT_ATTRIBUTES{ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else root_fd, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .Attributes = .{}, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, @@ -375,14 +375,23 @@ const Os = switch (builtin.os.tag) { switch (windows.ntdll.NtCreateFile( &dir_handle, - windows.SYNCHRONIZE | windows.GENERIC_READ | windows.FILE_LIST_DIRECTORY, + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, &attr, &io, null, - 0, - windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, - windows.FILE_OPEN, - windows.FILE_DIRECTORY_FILE | windows.FILE_OPEN_FOR_BACKUP_INTENT, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = true, + .OPEN_FOR_BACKUP_INTENT = true, + }, null, 0, )) { @@ -437,13 +446,13 @@ const Os = switch (builtin.os.tag) { fn getFileId(handle: windows.HANDLE) !FileId { var file_id: FileId = undefined; var io_status: windows.IO_STATUS_BLOCK = undefined; - var volume_info: windows.FILE_FS_VOLUME_INFORMATION = undefined; + var volume_info: windows.FILE.FS_VOLUME_INFORMATION = undefined; switch (windows.ntdll.NtQueryVolumeInformationFile( handle, &io_status, &volume_info, - @sizeOf(windows.FILE_FS_VOLUME_INFORMATION), - .FileFsVolumeInformation, + @sizeOf(windows.FILE.FS_VOLUME_INFORMATION), + .Volume, )) { .SUCCESS => {}, // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer @@ -453,13 +462,13 @@ const Os = switch (builtin.os.tag) { else => |rc| return windows.unexpectedStatus(rc), } file_id.volumeSerialNumber = volume_info.VolumeSerialNumber; - var internal_info: windows.FILE_INTERNAL_INFORMATION = undefined; + var internal_info: windows.FILE.INTERNAL_INFORMATION = undefined; switch (windows.ntdll.NtQueryInformationFile( handle, &io_status, &internal_info, - @sizeOf(windows.FILE_INTERNAL_INFORMATION), - .FileInternalInformation, + @sizeOf(windows.FILE.INTERNAL_INFORMATION), + .Internal, )) { .SUCCESS => {}, else => |rc| return windows.unexpectedStatus(rc), diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig @@ -1301,8 +1301,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode _ = mode; const sub_dir_handle = windows.OpenFile(sub_path_w.span(), .{ .dir = dir.handle, - .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, - .creation = windows.FILE_CREATE, + .access_mask = .{ + .GENERIC = .{ .READ = true }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, + .creation = .CREATE, .filter = .dir_only, }) catch |err| switch (err) { error.IsDir => return error.Unexpected, @@ -1370,9 +1373,6 @@ fn dirMakeOpenPathWindows( const t: *Threaded = @ptrCast(@alignCast(userdata)); const current_thread = Thread.getCurrent(t); const w = windows; - const access_mask = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | - w.SYNCHRONIZE | w.FILE_TRAVERSE | - (if (options.iterate) w.FILE_LIST_DIRECTORY else @as(u32, 0)); var it = std.fs.path.componentIterator(sub_path); // If there are no components in the path, then create a dummy component with the full path. @@ -1387,7 +1387,7 @@ fn dirMakeOpenPathWindows( const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, component.path); const sub_path_w = sub_path_w_array.span(); const is_last = it.peekNext() == null; - const create_disposition: u32 = if (is_last) w.FILE_OPEN_IF else w.FILE_CREATE; + const create_disposition: w.FILE.CREATE_DISPOSITION = if (is_last) .OPEN_IF else .CREATE; var result: Io.Dir = .{ .handle = undefined }; @@ -1397,26 +1397,40 @@ fn dirMakeOpenPathWindows( .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; - var attr: w.OBJECT_ATTRIBUTES = .{ - .Length = @sizeOf(w.OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0; var io_status_block: w.IO_STATUS_BLOCK = undefined; const rc = w.ntdll.NtCreateFile( &result.handle, - access_mask, - &attr, + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = options.iterate, + .READ_EA = true, + .READ_ATTRIBUTES = true, + .TRAVERSE = true, + } }, + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + }, + &.{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, &io_status_block, null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE, + .{ .NORMAL = true }, + .VALID_FLAGS, create_disposition, - w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point, + .{ + .DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_FOR_BACKUP_INTENT = true, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, null, 0, ); @@ -1749,8 +1763,8 @@ fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.Fi try current_thread.checkCancel(); var io_status_block: windows.IO_STATUS_BLOCK = undefined; - var info: windows.FILE_ALL_INFORMATION = undefined; - const rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation); + var info: windows.FILE.ALL_INFORMATION = undefined; + const rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &info, @sizeOf(windows.FILE.ALL_INFORMATION), .All); switch (rc) { .SUCCESS => {}, // Buffer overflow here indicates that there is more information available than was able to be stored in the buffer @@ -1765,9 +1779,9 @@ fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.Fi .inode = info.InternalInformation.IndexNumber, .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), .mode = 0, - .kind = if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) reparse_point: { - var tag_info: windows.FILE_ATTRIBUTE_TAG_INFO = undefined; - const tag_rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE_ATTRIBUTE_TAG_INFO), .FileAttributeTagInformation); + .kind = if (info.BasicInformation.FileAttributes.REPARSE_POINT) reparse_point: { + var tag_info: windows.FILE.ATTRIBUTE_TAG_INFO = undefined; + const tag_rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE.ATTRIBUTE_TAG_INFO), .AttributeTag); switch (tag_rc) { .SUCCESS => {}, // INFO_LENGTH_MISMATCH and ACCESS_DENIED are the only documented possible errors @@ -1776,12 +1790,10 @@ fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.Fi .ACCESS_DENIED => return error.AccessDenied, else => return windows.unexpectedStatus(rc), } - if (tag_info.ReparseTag & windows.reparse_tag_name_surrogate_bit != 0) { - break :reparse_point .sym_link; - } + if (tag_info.ReparseTag.IsSurrogate) break :reparse_point .sym_link; // Unknown reparse point break :reparse_point .unknown; - } else if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) + } else if (info.BasicInformation.FileAttributes.DIRECTORY) .directory else .file, @@ -1983,15 +1995,15 @@ fn dirAccessWindows( .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; - var attr = windows.OBJECT_ATTRIBUTES{ + var attr: windows.OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .Attributes = .{}, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; - var basic_info: windows.FILE_BASIC_INFORMATION = undefined; + var basic_info: windows.FILE.BASIC_INFORMATION = undefined; switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) { .SUCCESS => return, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, @@ -2187,16 +2199,21 @@ fn dirCreateFileWindows( const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path); const sub_path_w = sub_path_w_array.span(); - const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0; const handle = try w.OpenFile(sub_path_w, .{ .dir = dir.handle, - .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ + .WRITE = true, + .READ = flags.read, + }, + }, .creation = if (flags.exclusive) - @as(u32, w.FILE_CREATE) + .CREATE else if (flags.truncate) - @as(u32, w.FILE_OVERWRITE_IF) + .OVERWRITE_IF else - @as(u32, w.FILE_OPEN_IF), + .OPEN_IF, }); errdefer w.CloseHandle(handle); var io_status_block: w.IO_STATUS_BLOCK = undefined; @@ -2511,18 +2528,12 @@ pub fn dirOpenFileWtf16( var attr: w.OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(w.OBJECT_ATTRIBUTES), .RootDirectory = dir_handle, - .Attributes = 0, + .Attributes = .{}, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; var io_status_block: w.IO_STATUS_BLOCK = undefined; - const blocking_flag: w.ULONG = w.FILE_SYNCHRONOUS_IO_NONALERT; - const file_or_dir_flag: w.ULONG = w.FILE_NON_DIRECTORY_FILE; - // If we're not following symlinks, we need to ensure we don't pass in any - // synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. - const create_file_flags: w.ULONG = file_or_dir_flag | - if (flags.follow_symlinks) blocking_flag else w.FILE_OPEN_REPARSE_POINT; // There are multiple kernel bugs being worked around with retries. const max_attempts = 13; @@ -2534,16 +2545,24 @@ pub fn dirOpenFileWtf16( var result: w.HANDLE = undefined; const rc = w.ntdll.NtCreateFile( &result, - w.SYNCHRONIZE | - (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) | - (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0), + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ + .READ = flags.isRead(), + .WRITE = flags.isWrite(), + }, + }, &attr, &io_status_block, null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE, - w.FILE_OPEN, - create_file_flags, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .NON_DIRECTORY_FILE = true, + .OPEN_REPARSE_POINT = !flags.follow_symlinks, + }, null, 0, ); @@ -2835,10 +2854,6 @@ pub fn dirOpenDirWindows( ) Io.Dir.OpenError!Io.Dir { const current_thread = Thread.getCurrent(t); const w = windows; - // TODO remove some of these flags if options.access_sub_paths is false - const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA | - w.SYNCHRONIZE | w.FILE_TRAVERSE; - const access_mask: u32 = if (options.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags; const path_len_bytes: u16 = @intCast(sub_path_w.len * 2); var nt_name: w.UNICODE_STRING = .{ @@ -2846,28 +2861,43 @@ pub fn dirOpenDirWindows( .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; - var attr: w.OBJECT_ATTRIBUTES = .{ - .Length = @sizeOf(w.OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; - const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0; var io_status_block: w.IO_STATUS_BLOCK = undefined; var result: Io.Dir = .{ .handle = undefined }; try current_thread.checkCancel(); const rc = w.ntdll.NtCreateFile( &result.handle, - access_mask, - &attr, + // TODO remove some of these flags if options.access_sub_paths is false + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .LIST = options.iterate, + .READ_EA = true, + .TRAVERSE = true, + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + }, + &.{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, &io_status_block, null, - w.FILE_ATTRIBUTE_NORMAL, - w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE, - w.FILE_OPEN, - w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_FOR_BACKUP_INTENT = true, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, null, 0, ); diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig @@ -226,7 +226,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void { switch (windows.ntdll.NtSetInformationThread( self.getHandle(), - .ThreadNameInformation, + .NameInformation, &unicode_string, @sizeOf(windows.UNICODE_STRING), )) { @@ -338,7 +338,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co switch (windows.ntdll.NtQueryInformationThread( self.getHandle(), - .ThreadNameInformation, + .NameInformation, &buf, buf_capacity, null, @@ -521,12 +521,10 @@ pub const YieldError = error{ /// Yields the current thread potentially allowing other threads to run. pub fn yield() YieldError!void { - if (native_os == .windows) { - // The return value has to do with how many other threads there are; it is not - // an error condition on Windows. - _ = windows.kernel32.SwitchToThread(); - return; - } + if (native_os == .windows) switch (windows.ntdll.NtYieldExecution()) { + .SUCCESS, .NO_YIELD_PERFORMED => return, + else => return error.SystemCannotYield, + }; switch (posix.errno(posix.system.sched_yield())) { .SUCCESS => return, .NOSYS => return error.SystemCannotYield, @@ -647,11 +645,11 @@ const WindowsThreadImpl = struct { const ThreadCompletion = struct { completion: Completion, heap_ptr: windows.PVOID, - heap_handle: windows.HANDLE, + heap_handle: *windows.HEAP, thread_handle: windows.HANDLE = undefined, fn free(self: ThreadCompletion) void { - const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr); + const status = windows.ntdll.RtlFreeHeap(self.heap_handle, .{}, self.heap_ptr); assert(status != 0); } }; @@ -673,10 +671,10 @@ const WindowsThreadImpl = struct { } }; - const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory; + const heap_handle = windows.GetProcessHeap() orelse return error.OutOfMemory; const alloc_bytes = @alignOf(Instance) + @sizeOf(Instance); - const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory; - errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0); + const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, .{}, alloc_bytes) orelse return error.OutOfMemory; + errdefer assert(windows.ntdll.RtlFreeHeap(heap_handle, .{}, alloc_ptr) != 0); const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes]; var fba = std.heap.FixedBufferAllocator.init(instance_bytes); @@ -693,8 +691,7 @@ const WindowsThreadImpl = struct { // Windows appears to only support SYSTEM_INFO.dwAllocationGranularity minimum stack size. // Going lower makes it default to that specified in the executable (~1mb). // Its also fine if the limit here is incorrect as stack size is only a hint. - var stack_size = std.math.cast(u32, config.stack_size) orelse std.math.maxInt(u32); - stack_size = @max(64 * 1024, stack_size); + const stack_size = @max(64 * 1024, std.math.lossyCast(u32, config.stack_size)); instance.thread.thread_handle = windows.kernel32.CreateThread( null, diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig @@ -154,10 +154,10 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error _ = gpa; const current_regs = context.cur.getRegs(); - var image_base: windows.DWORD64 = undefined; + var image_base: usize = undefined; if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &context.history_table)) |runtime_function| { var handler_data: ?*anyopaque = null; - var establisher_frame: u64 = undefined; + var establisher_frame: usize = undefined; _ = windows.ntdll.RtlVirtualUnwind( windows.UNW_FLAG_NHANDLER, image_base, @@ -351,13 +351,19 @@ const Module = struct { var section_handle: windows.HANDLE = undefined; const create_section_rc = windows.ntdll.NtCreateSection( &section_handle, - windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | windows.SECTION_MAP_READ, + .{ + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_READ = true, + } }, + .STANDARD = .{ .RIGHTS = .REQUIRED }, + }, null, null, - windows.PAGE_READONLY, + .{ .READONLY = true }, // The documentation states that if no AllocationAttribute is specified, then SEC_COMMIT is the default. // In practice, this isn't the case and specifying 0 will result in INVALID_PARAMETER_6. - windows.SEC_COMMIT, + .{ .COMMIT = true }, coff_file.handle, ); if (create_section_rc != .SUCCESS) return error.MissingDebugInfo; @@ -372,9 +378,9 @@ const Module = struct { 0, null, &coff_len, - .ViewUnmap, - 0, - windows.PAGE_READONLY, + .Unmap, + .{}, + .{ .READONLY = true }, ); if (map_section_rc != .SUCCESS) return error.MissingDebugInfo; errdefer assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(section_view_ptr.?)) == .SUCCESS); diff --git a/lib/std/enums.zig b/lib/std/enums.zig @@ -61,7 +61,9 @@ pub fn values(comptime E: type) []const E { /// panic when `e` has no tagged value. /// Returns the tag name for `e` or null if no tag exists. pub fn tagName(comptime E: type, e: E) ?[:0]const u8 { - return inline for (@typeInfo(E).@"enum".fields) |f| { + const fields = @typeInfo(E).@"enum".fields; + @setEvalBranchQuota(fields.len); + return inline for (fields) |f| { if (@intFromEnum(e) == f.value) break f.name; } else null; } diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig @@ -453,10 +453,10 @@ pub const Iterator = switch (native_os) { &io, &self.buf, self.buf.len, - .FileBothDirectoryInformation, + .BothDirectory, w.FALSE, null, - if (self.first_iter) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE), + @intFromBool(self.first_iter), ); self.first_iter = false; if (io.Information == 0) return null; @@ -487,8 +487,8 @@ pub const Iterator = switch (native_os) { const name_wtf8 = self.name_data[0..name_wtf8_len]; const kind: Entry.Kind = blk: { const attrs = dir_info.FileAttributes; - if (attrs & w.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk .directory; - if (attrs & w.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk .sym_link; + if (attrs.DIRECTORY) break :blk .directory; + if (attrs.REPARSE_POINT) break :blk .sym_link; break :blk .file; }; return Entry{ @@ -1013,15 +1013,14 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 { const w = windows; - const access_mask = w.GENERIC_READ | w.SYNCHRONIZE; - const share_access = w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE; - const creation = w.FILE_OPEN; const h_file = blk: { const res = w.OpenFile(pathname, .{ .dir = self.fd, - .access_mask = access_mask, - .share_access = share_access, - .creation = creation, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, + .creation = .OPEN, .filter = .any, }) catch |err| switch (err) { error.WouldBlock => unreachable, diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig @@ -146,13 +146,13 @@ pub fn isCygwinPty(file: File) bool { // for handles that aren't named pipes. { var io_status: windows.IO_STATUS_BLOCK = undefined; - var device_info: windows.FILE_FS_DEVICE_INFORMATION = undefined; - const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE_FS_DEVICE_INFORMATION), .FileFsDeviceInformation); + var device_info: windows.FILE.FS_DEVICE_INFORMATION = undefined; + const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE.FS_DEVICE_INFORMATION), .Device); switch (rc) { .SUCCESS => {}, else => return false, } - if (device_info.DeviceType != windows.FILE_DEVICE_NAMED_PIPE) return false; + if (device_info.DeviceType.FileDevice != .NAMED_PIPE) return false; } const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName"); @@ -166,7 +166,7 @@ pub fn isCygwinPty(file: File) bool { var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes); var io_status_block: windows.IO_STATUS_BLOCK = undefined; - const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(name_info_bytes.len), .FileNameInformation); + const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(name_info_bytes.len), .Name); switch (rc) { .SUCCESS => {}, .INVALID_PARAMETER => unreachable, @@ -485,7 +485,7 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError! &io_status_block, &info, @sizeOf(windows.FILE_BASIC_INFORMATION), - .FileBasicInformation, + .Basic, ); switch (rc) { .SUCCESS => return, @@ -1324,7 +1324,7 @@ pub fn unlock(file: File) void { &io_status_block, &range_off, &range_len, - null, + 0, ) catch |err| switch (err) { error.RangeNotLocked => unreachable, // Function assumes unlocked. error.Unexpected => unreachable, // Resource deallocation must succeed. @@ -1415,7 +1415,7 @@ pub fn downgradeLock(file: File) LockError!void { &io_status_block, &range_off, &range_len, - null, + 0, ) catch |err| switch (err) { error.RangeNotLocked => unreachable, // File was not locked. error.Unexpected => unreachable, // Resource deallocation must succeed. diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig @@ -256,13 +256,11 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { try setupSymlink(ctx.dir, dir_target_path, "symlink", .{ .is_directory = true }); - var symlink = switch (builtin.target.os.tag) { + var symlink: Dir = switch (builtin.target.os.tag) { .windows => windows_symlink: { const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.fd, "symlink"); - var result = Dir{ - .fd = undefined, - }; + var handle: windows.HANDLE = undefined; const path_len_bytes = @as(u16, @intCast(sub_path_w.span().len * 2)); var nt_name = windows.UNICODE_STRING{ @@ -270,32 +268,46 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { .MaximumLength = path_len_bytes, .Buffer = @constCast(&sub_path_w.data), }; - var attr = windows.OBJECT_ATTRIBUTES{ + var attr: windows.OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES), .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.fd, - .Attributes = 0, + .Attributes = .{}, .ObjectName = &nt_name, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; var io: windows.IO_STATUS_BLOCK = undefined; const rc = windows.ntdll.NtCreateFile( - &result.fd, - windows.STANDARD_RIGHTS_READ | windows.FILE_READ_ATTRIBUTES | windows.FILE_READ_EA | windows.SYNCHRONIZE | windows.FILE_TRAVERSE, + &handle, + .{ + .SPECIFIC = .{ .FILE_DIRECTORY = .{ + .READ_EA = true, + .TRAVERSE = true, + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + }, &attr, &io, null, - windows.FILE_ATTRIBUTE_NORMAL, - windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, - windows.FILE_OPEN, - // FILE_OPEN_REPARSE_POINT is the important thing here - windows.FILE_OPEN_REPARSE_POINT | windows.FILE_DIRECTORY_FILE | windows.FILE_SYNCHRONOUS_IO_NONALERT | windows.FILE_OPEN_FOR_BACKUP_INTENT, + .{ .NORMAL = true }, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = true, + .IO = .SYNCHRONOUS_NONALERT, + .OPEN_FOR_BACKUP_INTENT = true, + .OPEN_REPARSE_POINT = true, // the important thing here + }, null, 0, ); switch (rc) { - .SUCCESS => break :windows_symlink result, + .SUCCESS => break :windows_symlink .{ .fd = handle }, else => return windows.unexpectedStatus(rc), } }, diff --git a/lib/std/heap/PageAllocator.zig b/lib/std/heap/PageAllocator.zig @@ -30,7 +30,8 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { var base_addr: ?*anyopaque = null; var size: windows.SIZE_T = n; - var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE); + const current_process = windows.GetCurrentProcess(); + var status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true, .RESERVE = true }, .{ .READWRITE = true }); if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) { return @ptrCast(base_addr); @@ -38,7 +39,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (status == SUCCESS) { var region_size: windows.SIZE_T = 0; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &region_size, .{ .RELEASE = true }); } const overalloc_len = n + alignment_bytes - page_size; @@ -47,7 +48,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { base_addr = null; size = overalloc_len; - status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS); + status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .RESERVE = true, .RESERVE_PLACEHOLDER = true }, .{ .NOACCESS = true }); if (status != SUCCESS) return null; @@ -58,7 +59,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (prefix_size > 0) { var prefix_base = base_addr; var prefix_size_param: windows.SIZE_T = prefix_size; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&prefix_base), &prefix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&prefix_base), &prefix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true }); } const suffix_start = aligned_addr + aligned_len; @@ -66,13 +67,13 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { if (suffix_size > 0) { var suffix_base = @as(?*anyopaque, @ptrFromInt(suffix_start)); var suffix_size_param: windows.SIZE_T = suffix_size; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&suffix_base), &suffix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&suffix_base), &suffix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true }); } base_addr = @ptrFromInt(aligned_addr); size = aligned_len; - status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | MEM_PRESERVE_PLACEHOLDER, windows.PAGE_READWRITE); + status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true }, .{ .READWRITE = true }); if (status == SUCCESS) { return @ptrCast(base_addr); @@ -80,7 +81,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 { base_addr = @as(?*anyopaque, @ptrFromInt(aligned_addr)); size = aligned_len; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &size, .{ .RELEASE = true }); return null; } @@ -145,7 +146,7 @@ pub fn unmap(memory: []align(page_size_min) u8) void { if (native_os == .windows) { var base_addr: ?*anyopaque = memory.ptr; var region_size: windows.SIZE_T = 0; - _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, windows.MEM_RELEASE); + _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, .{ .RELEASE = true }); } else { const page_aligned_len = mem.alignForward(usize, memory.len, std.heap.pageSize()); posix.munmap(memory.ptr[0..page_aligned_len]); @@ -166,7 +167,7 @@ pub fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 { var decommit_addr: ?*anyopaque = @ptrFromInt(new_addr_end); var decommit_size: windows.SIZE_T = old_addr_end - new_addr_end; - _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, windows.MEM_RESET, windows.PAGE_NOACCESS); + _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, .{ .RESET = true }, .{ .NOACCESS = true }); } return memory.ptr; } diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig @@ -28,9 +28,2265 @@ pub const ws2_32 = @import("windows/ws2_32.zig"); pub const crypt32 = @import("windows/crypt32.zig"); pub const nls = @import("windows/nls.zig"); -pub const self_process_handle = @as(HANDLE, @ptrFromInt(maxInt(usize))); +pub const FILE = struct { + // ref: km/ntddk.h -const Self = @This(); + pub const END_OF_FILE_INFORMATION = extern struct { + EndOfFile: LARGE_INTEGER, + }; + + pub const ALIGNMENT_INFORMATION = extern struct { + AlignmentRequirement: ULONG, + }; + + pub const NAME_INFORMATION = extern struct { + FileNameLength: ULONG, + FileName: [1]WCHAR, + }; + + pub const DISPOSITION = packed struct(ULONG) { + DELETE: bool = false, + POSIX_SEMANTICS: bool = false, + FORCE_IMAGE_SECTION_CHECK: bool = false, + ON_CLOSE: bool = false, + IGNORE_READONLY_ATTRIBUTE: bool = false, + Reserved5: u27 = 0, + + pub const DO_NOT_DELETE: DISPOSITION = .{}; + + pub const INFORMATION = extern struct { + DeleteFile: BOOLEAN, + + pub const EX = extern struct { + Flags: DISPOSITION, + }; + }; + }; + + pub const FS_VOLUME_INFORMATION = extern struct { + VolumeCreationTime: LARGE_INTEGER, + VolumeSerialNumber: ULONG, + VolumeLabelLength: ULONG, + SupportsObjects: BOOLEAN, + VolumeLabel: [0]WCHAR, + + pub fn getVolumeLabel(fvi: *const FS_VOLUME_INFORMATION) []const WCHAR { + return (&fvi).ptr[0..@divExact(fvi.VolumeLabelLength, @sizeOf(WCHAR))]; + } + }; + + // ref: km/ntifs.h + + pub const PIPE = struct { + /// Define the `NamedPipeType` flags for `NtCreateNamedPipeFile` + pub const TYPE = packed struct(ULONG) { + TYPE: enum(u1) { + BYTE_STREAM = 0b0, + MESSAGE = 0b1, + } = .BYTE_STREAM, + REMOTE_CLIENTS: enum(u1) { + ACCEPT = 0b0, + REJECT = 0b1, + } = .ACCEPT, + Reserved2: u30 = 0, + + pub const VALID_MASK: TYPE = .{ + .TYPE = .MESSAGE, + .REMOTE_CLIENTS = .REJECT, + }; + }; + + /// Define the `CompletionMode` flags for `NtCreateNamedPipeFile` + pub const COMPLETION_MODE = packed struct(ULONG) { + OPERATION: enum(u1) { + QUEUE = 0b0, + COMPLETE = 0b1, + } = .QUEUE, + Reserved1: u31 = 0, + }; + + /// Define the `ReadMode` flags for `NtCreateNamedPipeFile` + pub const READ_MODE = packed struct(ULONG) { + MODE: enum(u1) { + BYTE_STREAM = 0b0, + MESSAGE = 0b1, + }, + Reserved1: u31 = 0, + }; + + /// Define the `NamedPipeConfiguration` flags for `NtQueryInformationFile` + pub const CONFIGURATION = enum(ULONG) { + INBOUND = 0x00000000, + OUTBOUND = 0x00000001, + FULL_DUPLEX = 0x00000002, + }; + + /// Define the `NamedPipeState` flags for `NtQueryInformationFile` + pub const STATE = enum(ULONG) { + DISCONNECTED = 0x00000001, + LISTENING = 0x00000002, + CONNECTED = 0x00000003, + CLOSING = 0x00000004, + }; + + /// Define the `NamedPipeEnd` flags for `NtQueryInformationFile` + pub const END = enum(ULONG) { + CLIENT = 0x00000000, + SERVER = 0x00000001, + }; + + pub const INFORMATION = extern struct { + ReadMode: READ_MODE, + CompletionMode: COMPLETION_MODE, + }; + + pub const LOCAL_INFORMATION = extern struct { + NamedPipeType: TYPE, + NamedPipeConfiguration: CONFIGURATION, + MaximumInstances: ULONG, + CurrentInstances: ULONG, + InboundQuota: ULONG, + ReadDataAvailable: ULONG, + OutboundQuota: ULONG, + WriteQuotaAvailable: ULONG, + NamedPipeState: STATE, + NamedPipeEnd: END, + }; + + pub const REMOTE_INFORMATION = extern struct { + CollectDataTime: LARGE_INTEGER, + MaximumCollectionCount: ULONG, + }; + + pub const WAIT_FOR_BUFFER = extern struct { + Timeout: LARGE_INTEGER, + NameLength: ULONG, + TimeoutSpecified: BOOLEAN, + Name: [PATH_MAX_WIDE]WCHAR, + + pub const WAIT_FOREVER: LARGE_INTEGER = std.math.minInt(LARGE_INTEGER); + + pub fn init(opts: struct { + Timeout: ?LARGE_INTEGER = null, + Name: []const WCHAR, + }) WAIT_FOR_BUFFER { + var fpwfb: WAIT_FOR_BUFFER = .{ + .Timeout = opts.Timeout orelse undefined, + .NameLength = @intCast(@sizeOf(WCHAR) * opts.Name.len), + .TimeoutSpecified = @intFromBool(opts.Timeout != null), + .Name = undefined, + }; + @memcpy(fpwfb.Name[0..opts.Name.len], opts.Name); + return fpwfb; + } + + pub fn getName(fpwfb: *const WAIT_FOR_BUFFER) []const WCHAR { + return fpwfb.Name[0..@divExact(fpwfb.NameLength, @sizeOf(WCHAR))]; + } + + pub fn toBuffer(fpwfb: *const WAIT_FOR_BUFFER) []const u8 { + const start: [*]const u8 = @ptrCast(fpwfb); + return start[0 .. @offsetOf(WAIT_FOR_BUFFER, "Name") + fpwfb.NameLength]; + } + }; + }; + + pub const ALL_INFORMATION = extern struct { + BasicInformation: BASIC_INFORMATION, + StandardInformation: STANDARD_INFORMATION, + InternalInformation: INTERNAL_INFORMATION, + EaInformation: EA_INFORMATION, + AccessInformation: ACCESS_INFORMATION, + PositionInformation: POSITION_INFORMATION, + ModeInformation: MODE.INFORMATION, + AlignmentInformation: ALIGNMENT_INFORMATION, + NameInformation: NAME_INFORMATION, + }; + + pub const INTERNAL_INFORMATION = extern struct { + IndexNumber: LARGE_INTEGER, + }; + + pub const EA_INFORMATION = extern struct { + EaSize: ULONG, + }; + + pub const ACCESS_INFORMATION = extern struct { + AccessFlags: ACCESS_MASK, + }; + + pub const RENAME_INFORMATION = extern struct { + Flags: FLAGS, + RootDirectory: ?HANDLE, + FileNameLength: ULONG, + FileName: [PATH_MAX_WIDE]WCHAR, + + pub fn init(opts: struct { + Flags: FLAGS = .{}, + RootDirectory: ?HANDLE = null, + FileName: []const WCHAR, + }) RENAME_INFORMATION { + var fri: RENAME_INFORMATION = .{ + .Flags = opts.Flags, + .RootDirectory = opts.RootDirectory, + .FileNameLength = @intCast(@sizeOf(WCHAR) * opts.FileName.len), + .FileName = undefined, + }; + @memcpy(fri.FileName[0..opts.FileName.len], opts.FileName); + return fri; + } + + pub const FLAGS = packed struct(ULONG) { + REPLACE_IF_EXISTS: bool = false, + POSIX_SEMANTICS: bool = false, + SUPPRESS_PIN_STATE_INHERITANCE: bool = false, + SUPPRESS_STORAGE_RESERVE_INHERITANCE: bool = false, + AVAILABLE_SPACE: enum(u2) { + NO_PRESERVE = 0b00, + NO_INCREASE = 0b01, + NO_DECREASE = 0b10, + PRESERVE = 0b11, + } = .NO_PRESERVE, + IGNORE_READONLY_ATTRIBUTE: bool = false, + RESIZE_SR: enum(u2) { + NO_FORCE = 0b00, + FORCE_TARGET = 0b01, + FORCE_SOURCE = 0b10, + FORCE = 0b11, + } = .NO_FORCE, + Reserved9: u23 = 0, + }; + + pub fn getFileName(ri: *const RENAME_INFORMATION) []const WCHAR { + return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))]; + } + + pub fn toBuffer(fri: *const RENAME_INFORMATION) []const u8 { + const start: [*]const u8 = @ptrCast(fri); + return start[0 .. @offsetOf(RENAME_INFORMATION, "FileName") + fri.FileNameLength]; + } + }; + + // ref: km/wdm.h + + pub const INFORMATION_CLASS = enum(c_int) { + Directory = 1, + FullDirectory = 2, + BothDirectory = 3, + Basic = 4, + Standard = 5, + Internal = 6, + Ea = 7, + Access = 8, + Name = 9, + Rename = 10, + Link = 11, + Names = 12, + Disposition = 13, + Position = 14, + FullEa = 15, + Mode = 16, + Alignment = 17, + All = 18, + Allocation = 19, + EndOfFile = 20, + AlternateName = 21, + Stream = 22, + Pipe = 23, + PipeLocal = 24, + PipeRemote = 25, + MailslotQuery = 26, + MailslotSet = 27, + Compression = 28, + ObjectId = 29, + Completion = 30, + MoveCluster = 31, + Quota = 32, + ReparsePoint = 33, + NetworkOpen = 34, + AttributeTag = 35, + Tracking = 36, + IdBothDirectory = 37, + IdFullDirectory = 38, + ValidDataLength = 39, + ShortName = 40, + IoCompletionNotification = 41, + IoStatusBlockRange = 42, + IoPriorityHint = 43, + SfioReserve = 44, + SfioVolume = 45, + HardLink = 46, + ProcessIdsUsingFile = 47, + NormalizedName = 48, + NetworkPhysicalName = 49, + IdGlobalTxDirectory = 50, + IsRemoteDevice = 51, + Unused = 52, + NumaNode = 53, + StandardLink = 54, + RemoteProtocol = 55, + RenameBypassAccessCheck = 56, + LinkBypassAccessCheck = 57, + VolumeName = 58, + Id = 59, + IdExtdDirectory = 60, + ReplaceCompletion = 61, + HardLinkFullId = 62, + IdExtdBothDirectory = 63, + DispositionEx = 64, + RenameEx = 65, + RenameExBypassAccessCheck = 66, + DesiredStorageClass = 67, + Stat = 68, + MemoryPartition = 69, + StatLx = 70, + CaseSensitive = 71, + LinkEx = 72, + LinkExBypassAccessCheck = 73, + StorageReserveId = 74, + CaseSensitiveForceAccessCheck = 75, + KnownFolder = 76, + StatBasic = 77, + Id64ExtdDirectory = 78, + Id64ExtdBothDirectory = 79, + IdAllExtdDirectory = 80, + IdAllExtdBothDirectory = 81, + StreamReservation = 82, + MupProvider = 83, + + pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len; + }; + + pub const BASIC_INFORMATION = extern struct { + CreationTime: LARGE_INTEGER, + LastAccessTime: LARGE_INTEGER, + LastWriteTime: LARGE_INTEGER, + ChangeTime: LARGE_INTEGER, + FileAttributes: ATTRIBUTE, + }; + + pub const STANDARD_INFORMATION = extern struct { + AllocationSize: LARGE_INTEGER, + EndOfFile: LARGE_INTEGER, + NumberOfLinks: ULONG, + DeletePending: BOOLEAN, + Directory: BOOLEAN, + }; + + pub const POSITION_INFORMATION = extern struct { + CurrentByteOffset: LARGE_INTEGER, + }; + + pub const FS_DEVICE_INFORMATION = extern struct { + DeviceType: DEVICE_TYPE, + Characteristics: ULONG, + }; + + // ref: um/WinBase.h + + pub const ATTRIBUTE_TAG_INFO = extern struct { + FileAttributes: DWORD, + ReparseTag: IO_REPARSE_TAG, + }; + + // ref: um/winnt.h + + pub const SHARE = packed struct(ULONG) { + /// The file can be opened for read access by other threads. + READ: bool = false, + /// The file can be opened for write access by other threads. + WRITE: bool = false, + /// The file can be opened for delete access by other threads. + DELETE: bool = false, + Reserved3: u29 = 0, + + pub const VALID_FLAGS: SHARE = .{ + .READ = true, + .WRITE = true, + .DELETE = true, + }; + }; + + pub const ATTRIBUTE = packed struct(ULONG) { + /// The file is read only. Applications can read the file, but cannot write to or delete it. + READONLY: bool = false, + /// The file is hidden. Do not include it in an ordinary directory listing. + HIDDEN: bool = false, + /// The file is part of or used exclusively by an operating system. + SYSTEM: bool = false, + Reserved3: u1 = 0, + DIRECTORY: bool = false, + /// The file should be archived. Applications use this attribute to mark files for backup or removal. + ARCHIVE: bool = false, + DEVICE: bool = false, + /// The file does not have other attributes set. This attribute is valid only if used alone. + NORMAL: bool = false, + /// The file is being used for temporary storage. + TEMPORARY: bool = false, + SPARSE_FILE: bool = false, + REPARSE_POINT: bool = false, + COMPRESSED: bool = false, + /// The data of a file is not immediately available. This attribute indicates that file data is physically moved to offline storage. + /// This attribute is used by Remote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute. + OFFLINE: bool = false, + NOT_CONTENT_INDEXED: bool = false, + /// The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is + /// the default for newly created files and subdirectories. For more information, see File Encryption. + /// + /// This flag has no effect if `SYSTEM` is also specified. + /// + /// This flag is not supported on Home, Home Premium, Starter, or ARM editions of Windows. + ENCRYPTED: bool = false, + INTEGRITY_STREAM: bool = false, + VIRTUAL: bool = false, + NO_SCRUB_DATA: bool = false, + EA_or_RECALL_ON_OPEN: bool = false, + PINNED: bool = false, + UNPINNED: bool = false, + Reserved21: u1 = 0, + RECALL_ON_DATA_ACCESS: bool = false, + Reserved23: u6 = 0, + STRICTLY_SEQUENTIAL: bool = false, + Reserved30: u2 = 0, + }; + + // ref: um/winternl.h + + /// Define the create disposition values + pub const CREATE_DISPOSITION = enum(ULONG) { + /// If the file already exists, replace it with the given file. If it does not, create the given file. + SUPERSEDE = 0x00000000, + /// If the file already exists, open it instead of creating a new file. If it does not, fail the request and do not create a new file. + OPEN = 0x00000001, + /// If the file already exists, fail the request and do not create or open the given file. If it does not, create the given file. + CREATE = 0x00000002, + /// If the file already exists, open it. If it does not, create the given file. + OPEN_IF = 0x00000003, + /// If the file already exists, open it and overwrite it. If it does not, fail the request. + OVERWRITE = 0x00000004, + /// If the file already exists, open it and overwrite it. If it does not, create the given file. + OVERWRITE_IF = 0x00000005, + + pub const MAXIMUM_DISPOSITION: CREATE_DISPOSITION = .OVERWRITE_IF; + }; + + /// Define the create/open option flags + pub const MODE = packed struct(ULONG) { + /// The file being created or opened is a directory file. With this flag, the CreateDisposition parameter must be set to `.CREATE`, `.FILE_OPEN`, or `.OPEN_IF`. + /// With this flag, other compatible CreateOptions flags include only the following: `SYNCHRONOUS_IO`, `WRITE_THROUGH`, `OPEN_FOR_BACKUP_INTENT`, and `OPEN_BY_FILE_ID`. + DIRECTORY_FILE: bool = false, + /// Applications that write data to the file must actually transfer the data into the file before any requested write operation is considered complete. + /// This flag is automatically set if the CreateOptions flag `NO_INTERMEDIATE_BUFFERING` is set. + WRITE_THROUGH: bool = false, + /// All accesses to the file are sequential. + SEQUENTIAL_ONLY: bool = false, + /// The file cannot be cached or buffered in a driver's internal buffers. This flag is incompatible with the DesiredAccess `FILE_APPEND_DATA` flag. + NO_INTERMEDIATE_BUFFERING: bool = false, + IO: enum(u2) { + /// All operations on the file are performed asynchronously. + ASYNCHRONOUS = 0b00, + /// All operations on the file are performed synchronously. Any wait on behalf of the caller is subject to premature termination from alerts. + /// This flag also causes the I/O system to maintain the file position context. If this flag is set, the DesiredAccess `SYNCHRONIZE` flag also must be set. + SYNCHRONOUS_ALERT = 0b01, + /// All operations on the file are performed synchronously. Waits in the system to synchronize I/O queuing and completion are not subject to alerts. + /// This flag also causes the I/O system to maintain the file position context. If this flag is set, the DesiredAccess `SYNCHRONIZE` flag also must be set. + SYNCHRONOUS_NONALERT = 0b10, + _, + + pub const VALID_FLAGS: @This() = @enumFromInt(0b11); + } = .ASYNCHRONOUS, + /// The file being opened must not be a directory file or this call fails. The file object being opened can represent a data file, a logical, virtual, or physical + /// device, or a volume. + NON_DIRECTORY_FILE: bool = false, + /// Create a tree connection for this file in order to open it over the network. This flag is not used by device and intermediate drivers. + CREATE_TREE_CONNECTION: bool = false, + /// Complete this operation immediately with an alternate success code of `STATUS_OPLOCK_BREAK_IN_PROGRESS` if the target file is oplocked, rather than blocking + /// the caller's thread. If the file is oplocked, another caller already has access to the file. This flag is not used by device and intermediate drivers. + COMPLETE_IF_OPLOCKED: bool = false, + /// If the extended attributes on an existing file being opened indicate that the caller must understand EAs to properly interpret the file, fail this request + /// because the caller does not understand how to deal with EAs. This flag is irrelevant for device and intermediate drivers. + NO_EA_KNOWLEDGE: bool = false, + OPEN_REMOTE_INSTANCE: bool = false, + /// Accesses to the file can be random, so no sequential read-ahead operations should be performed on the file by FSDs or the system. + RANDOM_ACCESS: bool = false, + /// Delete the file when the last handle to it is passed to `NtClose`. If this flag is set, the `DELETE` flag must be set in the DesiredAccess parameter. + DELETE_ON_CLOSE: bool = false, + /// The file name that is specified by the `ObjectAttributes` parameter includes the 8-byte file reference number for the file. This number is assigned by and + /// specific to the particular file system. If the file is a reparse point, the file name will also include the name of a device. Note that the FAT file system + /// does not support this flag. This flag is not used by device and intermediate drivers. + OPEN_BY_FILE_ID: bool = false, + /// The file is being opened for backup intent. Therefore, the system should check for certain access rights and grant the caller the appropriate access to the + /// file before checking the DesiredAccess parameter against the file's security descriptor. This flag not used by device and intermediate drivers. + OPEN_FOR_BACKUP_INTENT: bool = false, + /// Suppress inheritance of `FILE_ATTRIBUTE.COMPRESSED` from the parent directory. This allows creation of a non-compressed file in a directory that is marked + /// compressed. + NO_COMPRESSION: bool = false, + /// The file is being opened and an opportunistic lock on the file is being requested as a single atomic operation. The file system checks for oplocks before it + /// performs the create operation and will fail the create with a return code of STATUS_CANNOT_BREAK_OPLOCK if the result would be to break an existing oplock. + /// For more information, see the Remarks section. + /// + /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This flag is not supported. + /// + /// This flag is supported on the following file systems: NTFS, FAT, and exFAT. + OPEN_REQUIRING_OPLOCK: bool = false, + Reserved17: u3 = 0, + /// This flag allows an application to request a filter opportunistic lock to prevent other applications from getting share violations. If there are already open + /// handles, the create request will fail with STATUS_OPLOCK_NOT_GRANTED. For more information, see the Remarks section. + RESERVE_OPFILTER: bool = false, + /// Open a file with a reparse point and bypass normal reparse point processing for the file. For more information, see the Remarks section. + OPEN_REPARSE_POINT: bool = false, + /// Instructs any filters that perform offline storage or virtualization to not recall the contents of the file as a result of this open. + OPEN_NO_RECALL: bool = false, + /// This flag instructs the file system to capture the user associated with the calling thread. Any subsequent calls to `FltQueryVolumeInformation` or + /// `ZwQueryVolumeInformationFile` using the returned handle will assume the captured user, rather than the calling user at the time, for purposes of computing + /// the free space available to the caller. This applies to the following FsInformationClass values: `FileFsSizeInformation`, `FileFsFullSizeInformation`, and + /// `FileFsFullSizeInformationEx`. + OPEN_FOR_FREE_SPACE_QUERY: bool = false, + Reserved24: u8 = 0, + + pub const VALID_OPTION_FLAGS: MODE = .{ + .DIRECTORY_FILE = true, + .WRITE_THROUGH = true, + .SEQUENTIAL_ONLY = true, + .NO_INTERMEDIATE_BUFFERING = true, + .IO = .VALID_FLAGS, + .NON_DIRECTORY_FILE = true, + .CREATE_TREE_CONNECTION = true, + .COMPLETE_IF_OPLOCKED = true, + .NO_EA_KNOWLEDGE = true, + .OPEN_REMOTE_INSTANCE = true, + .RANDOM_ACCESS = true, + .DELETE_ON_CLOSE = true, + .OPEN_BY_FILE_ID = true, + .OPEN_FOR_BACKUP_INTENT = true, + .NO_COMPRESSION = true, + .OPEN_REQUIRING_OPLOCK = true, + .Reserved17 = 0b111, + .RESERVE_OPFILTER = true, + .OPEN_REPARSE_POINT = true, + .OPEN_NO_RECALL = true, + .OPEN_FOR_FREE_SPACE_QUERY = true, + }; + + pub const VALID_PIPE_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .IO = .VALID_FLAGS, + }; + + pub const VALID_MAILSLOT_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .IO = .VALID_FLAGS, + }; + + pub const VALID_SET_OPTION_FLAGS: MODE = .{ + .WRITE_THROUGH = true, + .SEQUENTIAL_ONLY = true, + .IO = .VALID_FLAGS, + }; + + // ref: km/ntifs.h + + pub const INFORMATION = extern struct { + /// The set of flags that specify the mode in which the file can be accessed. These flags are a subset of `MODE`. + Mode: MODE, + }; + }; +}; + +// ref: km/ntddk.h + +pub const PROCESSINFOCLASS = enum(c_int) { + BasicInformation = 0, + QuotaLimits = 1, + IoCounters = 2, + VmCounters = 3, + Times = 4, + BasePriority = 5, + RaisePriority = 6, + DebugPort = 7, + ExceptionPort = 8, + AccessToken = 9, + LdtInformation = 10, + LdtSize = 11, + DefaultHardErrorMode = 12, + IoPortHandlers = 13, + PooledUsageAndLimits = 14, + WorkingSetWatch = 15, + UserModeIOPL = 16, + EnableAlignmentFaultFixup = 17, + PriorityClass = 18, + Wx86Information = 19, + HandleCount = 20, + AffinityMask = 21, + PriorityBoost = 22, + DeviceMap = 23, + SessionInformation = 24, + ForegroundInformation = 25, + Wow64Information = 26, + ImageFileName = 27, + LUIDDeviceMapsEnabled = 28, + BreakOnTermination = 29, + DebugObjectHandle = 30, + DebugFlags = 31, + HandleTracing = 32, + IoPriority = 33, + ExecuteFlags = 34, + TlsInformation = 35, + Cookie = 36, + ImageInformation = 37, + CycleTime = 38, + PagePriority = 39, + InstrumentationCallback = 40, + ThreadStackAllocation = 41, + WorkingSetWatchEx = 42, + ImageFileNameWin32 = 43, + ImageFileMapping = 44, + AffinityUpdateMode = 45, + MemoryAllocationMode = 46, + GroupInformation = 47, + TokenVirtualizationEnabled = 48, + OwnerInformation = 49, + WindowInformation = 50, + HandleInformation = 51, + MitigationPolicy = 52, + DynamicFunctionTableInformation = 53, + HandleCheckingMode = 54, + KeepAliveCount = 55, + RevokeFileHandles = 56, + WorkingSetControl = 57, + HandleTable = 58, + CheckStackExtentsMode = 59, + CommandLineInformation = 60, + ProtectionInformation = 61, + MemoryExhaustion = 62, + FaultInformation = 63, + TelemetryIdInformation = 64, + CommitReleaseInformation = 65, + Reserved1Information = 66, + Reserved2Information = 67, + SubsystemProcess = 68, + InPrivate = 70, + RaiseUMExceptionOnInvalidHandleClose = 71, + SubsystemInformation = 75, + Win32kSyscallFilterInformation = 79, + EnergyTrackingState = 82, + NetworkIoCounters = 114, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = 117; +}; + +pub const THREADINFOCLASS = enum(c_int) { + BasicInformation = 0, + Times = 1, + Priority = 2, + BasePriority = 3, + AffinityMask = 4, + ImpersonationToken = 5, + DescriptorTableEntry = 6, + EnableAlignmentFaultFixup = 7, + EventPair_Reusable = 8, + QuerySetWin32StartAddress = 9, + ZeroTlsCell = 10, + PerformanceCount = 11, + AmILastThread = 12, + IdealProcessor = 13, + PriorityBoost = 14, + SetTlsArrayAddress = 15, + IsIoPending = 16, + // Windows 2000+ from here + HideFromDebugger = 17, + // Windows XP+ from here + BreakOnTermination = 18, + SwitchLegacyState = 19, + IsTerminated = 20, + // Windows Vista+ from here + LastSystemCall = 21, + IoPriority = 22, + CycleTime = 23, + PagePriority = 24, + ActualBasePriority = 25, + TebInformation = 26, + CSwitchMon = 27, + // Windows 7+ from here + CSwitchPmu = 28, + Wow64Context = 29, + GroupInformation = 30, + UmsInformation = 31, + CounterProfiling = 32, + IdealProcessorEx = 33, + // Windows 8+ from here + CpuAccountingInformation = 34, + // Windows 8.1+ from here + SuspendCount = 35, + // Windows 10+ from here + HeterogeneousCpuPolicy = 36, + ContainerId = 37, + NameInformation = 38, + SelectedCpuSets = 39, + SystemThreadInformation = 40, + ActualGroupAffinity = 41, + DynamicCodePolicyInfo = 42, + SubsystemInformation = 45, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = 60; +}; + +// ref: km/ntifs.h + +pub const HEAP = opaque { + pub const FLAGS = packed struct(u8) { + /// Serialized access is not used when the heap functions access this heap. This option + /// applies to all subsequent heap function calls. Alternatively, you can specify this + /// option on individual heap function calls. + /// + /// The low-fragmentation heap (LFH) cannot be enabled for a heap created with this option. + /// + /// A heap created with this option cannot be locked. + NO_SERIALIZE: bool = false, + /// Specifies that the heap is growable. Must be specified if `HeapBase` is `NULL`. + GROWABLE: bool = false, + /// The system raises an exception to indicate failure (for example, an out-of-memory + /// condition) for calls to `HeapAlloc` and `HeapReAlloc` instead of returning `NULL`. + /// + /// To ensure that exceptions are generated for all calls to an allocation function, specify + /// `GENERATE_EXCEPTIONS` in the call to `HeapCreate`. In this case, it is not necessary to + /// additionally specify `GENERATE_EXCEPTIONS` in the allocation function calls. + GENERATE_EXCEPTIONS: bool = false, + /// The allocated memory will be initialized to zero. Otherwise, the memory is not + /// initialized to zero. + ZERO_MEMORY: bool = false, + REALLOC_IN_PLACE_ONLY: bool = false, + TAIL_CHECKING_ENABLED: bool = false, + FREE_CHECKING_ENABLED: bool = false, + DISABLE_COALESCE_ON_FREE: bool = false, + + pub const CLASS = enum(u4) { + /// process heap + PROCESS, + /// private heap + PRIVATE, + /// Kernel Heap + KERNEL, + /// GDI heap + GDI, + /// User heap + USER, + /// Console heap + CONSOLE, + /// User Desktop heap + USER_DESKTOP, + /// Csrss Shared heap + CSRSS_SHARED, + /// Csr Port heap + CSR_PORT, + _, + + pub const MASK: CLASS = @enumFromInt(maxInt(@typeInfo(CLASS).@"enum".tag_type)); + }; + + pub const CREATE = packed struct(ULONG) { + COMMON: FLAGS = .{}, + SEGMENT_HEAP: bool = false, + /// Only applies to segment heap. Applies pointer obfuscation which is + /// generally excessive and unnecessary but is necessary for certain insecure + /// heaps in win32k. + /// + /// Specifying HEAP_CREATE_HARDENED prevents the heap from using locks as + /// pointers would potentially be exposed in heap metadata lock variables. + /// Callers are therefore responsible for synchronizing access to hardened heaps. + HARDENED: bool = false, + Reserved10: u2 = 0, + CLASS: CLASS = @enumFromInt(0), + /// Create heap with 16 byte alignment (obsolete) + ALIGN_16: bool = false, + /// Create heap call tracing enabled (obsolete) + ENABLE_TRACING: bool = false, + /// Create heap with executable pages + /// + /// All memory blocks that are allocated from this heap allow code execution, if the + /// hardware enforces data execution prevention. Use this flag heap in applications that + /// run code from the heap. If `ENABLE_EXECUTE` is not specified and an application + /// attempts to run code from a protected page, the application receives an exception + /// with the status code `STATUS_ACCESS_VIOLATION`. + ENABLE_EXECUTE: bool = false, + Reserved19: u13 = 0, + + pub const VALID_MASK: CREATE = .{ + .COMMON = .{ + .NO_SERIALIZE = true, + .GROWABLE = true, + .GENERATE_EXCEPTIONS = true, + .ZERO_MEMORY = true, + .REALLOC_IN_PLACE_ONLY = true, + .TAIL_CHECKING_ENABLED = true, + .FREE_CHECKING_ENABLED = true, + .DISABLE_COALESCE_ON_FREE = true, + }, + .CLASS = .MASK, + .ALIGN_16 = true, + .ENABLE_TRACING = true, + .ENABLE_EXECUTE = true, + .SEGMENT_HEAP = true, + .HARDENED = true, + }; + }; + + pub const ALLOCATION = packed struct(ULONG) { + COMMON: FLAGS = .{}, + SETTABLE_USER: packed struct(u4) { + VALUE: u1 = 0, + FLAGS: packed struct(u3) { + FLAG1: bool = false, + FLAG2: bool = false, + FLAG3: bool = false, + } = .{}, + } = .{}, + CLASS: CLASS = @enumFromInt(0), + Reserved16: u2 = 0, + TAG: u12 = 0, + Reserved30: u2 = 0, + }; + }; + + pub const RTL_PARAMETERS = extern struct { + Length: ULONG, + SegmentReserve: SIZE_T, + SegmentCommit: SIZE_T, + DeCommitFreeBlockThreshold: SIZE_T, + DeCommitTotalFreeThreshold: SIZE_T, + MaximumAllocationSize: SIZE_T, + VirtualMemoryThreshold: SIZE_T, + InitialCommit: SIZE_T, + InitialReserve: SIZE_T, + CommitRoutine: *const COMMIT_ROUTINE, + Reserved: [2]SIZE_T = @splat(0), + + pub const COMMIT_ROUTINE = fn ( + Base: PVOID, + CommitAddress: *PVOID, + CommitSize: *SIZE_T, + ) callconv(.winapi) NTSTATUS; + + pub const SEGMENT = extern struct { + Version: VERSION, + Size: USHORT, + Flags: FLG, + MemorySource: MEMORY_SOURCE, + Reserved: [4]SIZE_T, + + pub const VERSION = enum(USHORT) { + CURRENT = 3, + _, + }; + + pub const FLG = packed struct(ULONG) { + USE_PAGE_HEAP: bool = false, + NO_LFH: bool = false, + Reserved2: u30 = 0, + + pub const VALID_FLAGS: FLG = .{ + .USE_PAGE_HEAP = true, + .NO_LFH = true, + }; + }; + + pub const MEMORY_SOURCE = extern struct { + Flags: ULONG, + MemoryTypeMask: TYPE, + NumaNode: ULONG, + u: extern union { + PartitionHandle: HANDLE, + Callbacks: *const VA_CALLBACKS, + }, + Reserved: [2]SIZE_T = @splat(0), + + pub const TYPE = enum(ULONG) { + Paged, + NonPaged, + @"64KPage", + LargePage, + HugePage, + Custom, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len; + }; + + pub const VA_CALLBACKS = extern struct { + CallbackContext: HANDLE, + AllocateVirtualMemory: *const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK, + FreeVirtualMemory: *const FREE_VIRTUAL_MEMORY_EX_CALLBACK, + QueryVirtualMemory: *const QUERY_VIRTUAL_MEMORY_CALLBACK, + + pub const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK = fn ( + CallbackContext: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + AllocationType: ULONG, + PageProtection: ULONG, + ExtendedParameters: ?[*]MEM.EXTENDED_PARAMETER, + ExtendedParameterCount: ULONG, + ) callconv(.c) NTSTATUS; + + pub const FREE_VIRTUAL_MEMORY_EX_CALLBACK = fn ( + CallbackContext: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + FreeType: ULONG, + ) callconv(.c) NTSTATUS; + + pub const QUERY_VIRTUAL_MEMORY_CALLBACK = fn ( + CallbackContext: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + MemoryInformationClass: MEMORY_INFO_CLASS, + MemoryInformation: PVOID, + MemoryInformationLength: SIZE_T, + ReturnLength: ?*SIZE_T, + ) callconv(.c) NTSTATUS; + + pub const MEMORY_INFO_CLASS = enum(c_int) { + Basic, + _, + }; + }; + }; + }; + }; +}; + +pub const CTL_CODE = packed struct(ULONG) { + Method: METHOD, + Function: u12, + Access: FILE_ACCESS, + DeviceType: FILE_DEVICE, + + pub const METHOD = enum(u2) { + BUFFERED = 0, + IN_DIRECT = 1, + OUT_DIRECT = 2, + NEITHER = 3, + }; + + pub const FILE_ACCESS = packed struct(u2) { + READ: bool = false, + WRITE: bool = false, + + pub const ANY: FILE_ACCESS = .{ .READ = false, .WRITE = false }; + pub const SPECIAL = ANY; + }; + + pub const FILE_DEVICE = enum(u16) { + BEEP = 0x00000001, + CD_ROM = 0x00000002, + CD_ROM_FILE_SYSTEM = 0x00000003, + CONTROLLER = 0x00000004, + DATALINK = 0x00000005, + DFS = 0x00000006, + DISK = 0x00000007, + DISK_FILE_SYSTEM = 0x00000008, + FILE_SYSTEM = 0x00000009, + INPORT_PORT = 0x0000000a, + KEYBOARD = 0x0000000b, + MAILSLOT = 0x0000000c, + MIDI_IN = 0x0000000d, + MIDI_OUT = 0x0000000e, + MOUSE = 0x0000000f, + MULTI_UNC_PROVIDER = 0x00000010, + NAMED_PIPE = 0x00000011, + NETWORK = 0x00000012, + NETWORK_BROWSER = 0x00000013, + NETWORK_FILE_SYSTEM = 0x00000014, + NULL = 0x00000015, + PARALLEL_PORT = 0x00000016, + PHYSICAL_NETCARD = 0x00000017, + PRINTER = 0x00000018, + SCANNER = 0x00000019, + SERIAL_MOUSE_PORT = 0x0000001a, + SERIAL_PORT = 0x0000001b, + SCREEN = 0x0000001c, + SOUND = 0x0000001d, + STREAMS = 0x0000001e, + TAPE = 0x0000001f, + TAPE_FILE_SYSTEM = 0x00000020, + TRANSPORT = 0x00000021, + UNKNOWN = 0x00000022, + VIDEO = 0x00000023, + VIRTUAL_DISK = 0x00000024, + WAVE_IN = 0x00000025, + WAVE_OUT = 0x00000026, + @"8042_PORT" = 0x00000027, + NETWORK_REDIRECTOR = 0x00000028, + BATTERY = 0x00000029, + BUS_EXTENDER = 0x0000002a, + MODEM = 0x0000002b, + VDM = 0x0000002c, + MASS_STORAGE = 0x0000002d, + SMB = 0x0000002e, + KS = 0x0000002f, + CHANGER = 0x00000030, + SMARTCARD = 0x00000031, + ACPI = 0x00000032, + DVD = 0x00000033, + FULLSCREEN_VIDEO = 0x00000034, + DFS_FILE_SYSTEM = 0x00000035, + DFS_VOLUME = 0x00000036, + SERENUM = 0x00000037, + TERMSRV = 0x00000038, + KSEC = 0x00000039, + FIPS = 0x0000003A, + INFINIBAND = 0x0000003B, + VMBUS = 0x0000003E, + CRYPT_PROVIDER = 0x0000003F, + WPD = 0x00000040, + BLUETOOTH = 0x00000041, + MT_COMPOSITE = 0x00000042, + MT_TRANSPORT = 0x00000043, + BIOMETRIC = 0x00000044, + PMI = 0x00000045, + EHSTOR = 0x00000046, + DEVAPI = 0x00000047, + GPIO = 0x00000048, + USBEX = 0x00000049, + CONSOLE = 0x00000050, + NFP = 0x00000051, + SYSENV = 0x00000052, + VIRTUAL_BLOCK = 0x00000053, + POINT_OF_SERVICE = 0x00000054, + STORAGE_REPLICATION = 0x00000055, + TRUST_ENV = 0x00000056, + UCM = 0x00000057, + UCMTCPCI = 0x00000058, + PERSISTENT_MEMORY = 0x00000059, + NVDIMM = 0x0000005a, + HOLOGRAPHIC = 0x0000005b, + SDFXHCI = 0x0000005c, + UCMUCSI = 0x0000005d, + PRM = 0x0000005e, + EVENT_COLLECTOR = 0x0000005f, + USB4 = 0x00000060, + SOUNDWIRE = 0x00000061, + + MOUNTMGRCONTROLTYPE = 'm', + + _, + }; +}; + +pub const IOCTL = struct { + pub const MOUNTMGR = struct { + pub const QUERY_POINTS: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY }; + pub const QUERY_DOS_VOLUME_PATH: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY }; + }; +}; + +pub const FSCTL = struct { + pub const SET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 41, .Method = .BUFFERED, .Access = .SPECIAL }; + pub const GET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 42, .Method = .BUFFERED, .Access = .ANY }; + + pub const PIPE = struct { + pub const ASSIGN_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 0, .Method = .BUFFERED, .Access = .ANY }; + pub const DISCONNECT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 1, .Method = .BUFFERED, .Access = .ANY }; + pub const LISTEN: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY }; + pub const PEEK: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 3, .Method = .BUFFERED, .Access = .{ .READ = true } }; + pub const QUERY_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 4, .Method = .BUFFERED, .Access = .ANY }; + pub const TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 5, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } }; + pub const WAIT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 6, .Method = .BUFFERED, .Access = .ANY }; + pub const IMPERSONATE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 7, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 8, .Method = .BUFFERED, .Access = .ANY }; + pub const QUERY_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 9, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 10, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 11, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 13, .Method = .BUFFERED, .Access = .ANY }; + pub const GET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 14, .Method = .BUFFERED, .Access = .ANY }; + pub const SET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 15, .Method = .BUFFERED, .Access = .ANY }; + pub const FLUSH: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 16, .Method = .BUFFERED, .Access = .{ .WRITE = true } }; + + pub const INTERNAL_READ: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2045, .Method = .BUFFERED, .Access = .{ .READ = true } }; + pub const INTERNAL_WRITE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2046, .Method = .BUFFERED, .Access = .{ .WRITE = true } }; + pub const INTERNAL_TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2047, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } }; + pub const INTERNAL_READ_OVFLOW: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2048, .Method = .BUFFERED, .Access = .{ .READ = true } }; + }; +}; + +pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024; + +pub const IO_REPARSE_TAG = packed struct(ULONG) { + Value: u12, + Index: u4 = 0, + ReservedBits: u12 = 0, + /// Can have children if a directory. + IsDirectory: bool = false, + /// Represents another named entity in the system. + IsSurrogate: bool = false, + /// Must be `false` for non-Microsoft tags. + IsReserved: bool = false, + /// Owned by Microsoft. + IsMicrosoft: bool = false, + + pub const RESERVED_INVALID: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Index = 0x8, .Value = 0x000 }; + pub const MOUNT_POINT: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x003 }; + pub const HSM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x004 }; + pub const DRIVE_EXTENDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x005 }; + pub const HSM2: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x006 }; + pub const SIS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x007 }; + pub const WIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x008 }; + pub const CSV: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x009 }; + pub const DFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00A }; + pub const FILTER_MANAGER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00B }; + pub const SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x00C }; + pub const IIS_CACHE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x010 }; + pub const DFSR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x012 }; + pub const DEDUP: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x013 }; + pub const APPXSTRM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x014 }; + pub const NFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x014 }; + pub const FILE_PLACEHOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x015 }; + pub const DFM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x016 }; + pub const WOF: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x017 }; + pub inline fn WCI(index: u1) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsDirectory = index == 0x1, .Index = index, .Value = 0x018 }; + } + pub const GLOBAL_REPARSE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x0019 }; + pub inline fn CLOUD(index: u4) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsDirectory = true, .Index = index, .Value = 0x01A }; + } + pub const APPEXECLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01B }; + pub const PROJFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x01C }; + pub const LX_SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01D }; + pub const STORAGE_SYNC: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01E }; + pub const WCI_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01F }; + pub const UNHANDLED: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x020 }; + pub const ONEDRIVE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x021 }; + pub const PROJFS_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x022 }; + pub const AF_UNIX: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x023 }; + pub const LX_FIFO: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x024 }; + pub const LX_CHR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x025 }; + pub const LX_BLK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x026 }; + pub const LX_STORAGE_SYNC_FOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x027 }; + pub inline fn WCI_LINK(index: u1) IO_REPARSE_TAG { + return .{ .IsMicrosoft = true, .IsSurrogate = true, .Index = index, .Value = 0x027 }; + } + pub const DATALESS_CIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x28 }; +}; + +// ref: km/wdm.h + +pub const ACCESS_MASK = packed struct(DWORD) { + SPECIFIC: Specific = .{ .bits = 0 }, + STANDARD: Standard = .{}, + Reserved21: u3 = 0, + ACCESS_SYSTEM_SECURITY: bool = false, + MAXIMUM_ALLOWED: bool = false, + Reserved26: u2 = 0, + GENERIC: Generic = .{}, + + pub const Specific = packed union { + bits: u16, + + // ref: km/wdm.h + + /// Define access rights to files and directories + FILE: File, + FILE_DIRECTORY: File.Directory, + FILE_PIPE: File.Pipe, + /// Registry Specific Access Rights. + KEY: Key, + /// Object Manager Object Type Specific Access Rights. + OBJECT_TYPE: ObjectType, + /// Object Manager Directory Specific Access Rights. + DIRECTORY: Directory, + /// Object Manager Symbolic Link Specific Access Rights. + SYMBOLIC_LINK: SymbolicLink, + /// Section Access Rights. + SECTION: Section, + /// Session Specific Access Rights. + SESSION: Session, + /// Process Specific Access Rights. + PROCESS: Process, + /// Thread Specific Access Rights. + THREAD: Thread, + /// Partition Specific Access Rights. + MEMORY_PARTITION: MemoryPartition, + /// Generic mappings for transaction manager rights. + TRANSACTIONMANAGER: TransactionManager, + /// Generic mappings for transaction rights. + TRANSACTION: Transaction, + /// Generic mappings for resource manager rights. + RESOURCEMANAGER: ResourceManager, + /// Generic mappings for enlistment rights. + ENLISTMENT: Enlistment, + /// Event Specific Access Rights. + EVENT: Event, + /// Semaphore Specific Access Rights. + SEMAPHORE: Semaphore, + + // ref: km/ntifs.h + + /// Token Specific Access Rights. + TOKEN: Token, + + // um/winnt.h + + /// Job Object Specific Access Rights. + JOB_OBJECT: JobObject, + /// Mutant Specific Access Rights. + MUTANT: Mutant, + /// Timer Specific Access Rights. + TIMER: Timer, + /// I/O Completion Specific Access Rights. + IO_COMPLETION: IoCompletion, + + pub const File = packed struct(u16) { + READ_DATA: bool = false, + WRITE_DATA: bool = false, + APPEND_DATA: bool = false, + READ_EA: bool = false, + WRITE_EA: bool = false, + EXECUTE: bool = false, + Reserved6: u1 = 0, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_DATA = true, + .WRITE_DATA = true, + .APPEND_DATA = true, + .READ_EA = true, + .WRITE_EA = true, + .EXECUTE = true, + .Reserved6 = maxInt(@FieldType(File, "Reserved6")), + .READ_ATTRIBUTES = true, + .WRITE_ATTRIBUTES = true, + } }, + }; + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_DATA = true, + .READ_ATTRIBUTES = true, + .READ_EA = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .WRITE_DATA = true, + .WRITE_ATTRIBUTES = true, + .WRITE_EA = true, + .APPEND_DATA = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .FILE = .{ + .READ_ATTRIBUTES = true, + .EXECUTE = true, + } }, + }; + + pub const Directory = packed struct(u16) { + LIST: bool = false, + ADD_FILE: bool = false, + ADD_SUBDIRECTORY: bool = false, + READ_EA: bool = false, + WRITE_EA: bool = false, + TRAVERSE: bool = false, + DELETE_CHILD: bool = false, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + }; + + pub const Pipe = packed struct(u16) { + READ_DATA: bool = false, + WRITE_DATA: bool = false, + CREATE_PIPE_INSTANCE: bool = false, + Reserved3: u4 = 0, + READ_ATTRIBUTES: bool = false, + WRITE_ATTRIBUTES: bool = false, + Reserved9: u7 = 0, + }; + }; + + pub const Key = packed struct(u16) { + /// Required to query the values of a registry key. + QUERY_VALUE: bool = false, + /// Required to create, delete, or set a registry value. + SET_VALUE: bool = false, + /// Required to create a subkey of a registry key. + CREATE_SUB_KEY: bool = false, + /// Required to enumerate the subkeys of a registry key. + ENUMERATE_SUB_KEYS: bool = false, + /// Required to request change notifications for a registry key or for subkeys of a registry key. + NOTIFY: bool = false, + /// Reserved for system use. + CREATE_LINK: bool = false, + Reserved6: u2 = 0, + /// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. + /// This flag is ignored by 32-bit Windows. + WOW64_64KEY: bool = false, + /// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. + /// This flag is ignored by 32-bit Windows. + WOW64_32KEY: bool = false, + Reserved10: u6 = 0, + + pub const WOW64_RES: ACCESS_MASK = .{ + .SPECIFIC = .{ .KEY = .{ + .WOW64_32KEY = true, + .WOW64_64KEY = true, + } }, + }; + + /// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. + pub const READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + .NOTIFY = true, + } }, + }; + + /// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. + pub const WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .SET_VALUE = true, + .CREATE_SUB_KEY = true, + } }, + }; + + /// Equivalent to KEY_READ. + pub const EXECUTE = READ; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .ALL, + .SYNCHRONIZE = false, + }, + .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .SET_VALUE = true, + .CREATE_SUB_KEY = true, + .ENUMERATE_SUB_KEYS = true, + .NOTIFY = true, + .CREATE_LINK = true, + } }, + }; + }; + + pub const ObjectType = packed struct(u16) { + CREATE: bool = false, + Reserved1: u15 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .OBJECT_TYPE = .{ + .CREATE = true, + } }, + }; + }; + + pub const Directory = packed struct(u16) { + QUERY: bool = false, + TRAVERSE: bool = false, + CREATE_OBJECT: bool = false, + CREATE_SUBDIRECTORY: bool = false, + Reserved3: u12 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .DIRECTORY = .{ + .QUERY = true, + .TRAVERSE = true, + .CREATE_OBJECT = true, + .CREATE_SUBDIRECTORY = true, + } }, + }; + }; + + pub const SymbolicLink = packed struct(u16) { + QUERY: bool = false, + SET: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SYMBOLIC_LINK = .{ + .QUERY = true, + } }, + }; + + pub const ALL_ACCESS_EX: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SYMBOLIC_LINK = .{ + .QUERY = true, + .SET = true, + .Reserved2 = maxInt(@FieldType(SymbolicLink, "Reserved2")), + } }, + }; + }; + + pub const Section = packed struct(u16) { + QUERY: bool = false, + MAP_WRITE: bool = false, + MAP_READ: bool = false, + MAP_EXECUTE: bool = false, + EXTEND_SIZE: bool = false, + /// not included in `ALL_ACCESS` + MAP_EXECUTE_EXPLICIT: bool = false, + Reserved6: u10 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_WRITE = true, + .MAP_READ = true, + .MAP_EXECUTE = true, + .EXTEND_SIZE = true, + } }, + }; + }; + + pub const Session = packed struct(u16) { + QUERY_ACCESS: bool = false, + MODIFY_ACCESS: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .SESSION = .{ + .QUERY_ACCESS = true, + .MODIFY_ACCESS = true, + } }, + }; + }; + + pub const Process = packed struct(u16) { + TERMINATE: bool = false, + CREATE_THREAD: bool = false, + SET_SESSIONID: bool = false, + VM_OPERATION: bool = false, + VM_READ: bool = false, + VM_WRITE: bool = false, + DUP_HANDLE: bool = false, + CREATE_PROCESS: bool = false, + SET_QUOTA: bool = false, + SET_INFORMATION: bool = false, + QUERY_INFORMATION: bool = false, + SUSPEND_RESUME: bool = false, + QUERY_LIMITED_INFORMATION: bool = false, + SET_LIMITED_INFORMATION: bool = false, + Reserved14: u2 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .PROCESS = .{ + .TERMINATE = true, + .CREATE_THREAD = true, + .SET_SESSIONID = true, + .VM_OPERATION = true, + .VM_READ = true, + .VM_WRITE = true, + .DUP_HANDLE = true, + .CREATE_PROCESS = true, + .SET_QUOTA = true, + .SET_INFORMATION = true, + .QUERY_INFORMATION = true, + .SUSPEND_RESUME = true, + .QUERY_LIMITED_INFORMATION = true, + .SET_LIMITED_INFORMATION = true, + .Reserved14 = maxInt(@FieldType(Process, "Reserved14")), + } }, + }; + }; + + pub const Thread = packed struct(u16) { + TERMINATE: bool = false, + SUSPEND_RESUME: bool = false, + ALERT: bool = false, + GET_CONTEXT: bool = false, + SET_CONTEXT: bool = false, + SET_INFORMATION: bool = false, + QUERY_INFORMATION: bool = false, + SET_THREAD_TOKEN: bool = false, + IMPERSONATE: bool = false, + DIRECT_IMPERSONATION: bool = false, + SET_LIMITED_INFORMATION: bool = false, + QUERY_LIMITED_INFORMATION: bool = false, + RESUME: bool = false, + Reserved13: u3 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .THREAD = .{ + .TERMINATE = true, + .SUSPEND_RESUME = true, + .ALERT = true, + .GET_CONTEXT = true, + .SET_CONTEXT = true, + .SET_INFORMATION = true, + .QUERY_INFORMATION = true, + .SET_THREAD_TOKEN = true, + .IMPERSONATE = true, + .DIRECT_IMPERSONATION = true, + .SET_LIMITED_INFORMATION = true, + .QUERY_LIMITED_INFORMATION = true, + .RESUME = true, + .Reserved13 = maxInt(@FieldType(Thread, "Reserved13")), + } }, + }; + }; + + pub const MemoryPartition = packed struct(u16) { + QUERY_ACCESS: bool = false, + MODIFY_ACCESS: bool = false, + Required2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .MEMORY_PARTITION = .{ + .QUERY_ACCESS = true, + .MODIFY_ACCESS = true, + } }, + }; + }; + + pub const TransactionManager = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + RENAME: bool = false, + CREATE_RM: bool = false, + /// The following right is intended for DTC's use only; it will be deprecated, and no one else should take a dependency on it. + BIND_TRANSACTION: bool = false, + Reserved6: u10 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .RENAME = true, + .CREATE_RM = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{} }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TRANSACTIONMANAGER = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .RENAME = true, + .CREATE_RM = true, + .BIND_TRANSACTION = true, + } }, + }; + }; + + pub const Transaction = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + ENLIST: bool = false, + COMMIT: bool = false, + ROLLBACK: bool = false, + PROPAGATE: bool = false, + RIGHT_RESERVED1: bool = false, + Reserved7: u9 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .SET_INFORMATION = true, + .COMMIT = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .COMMIT = true, + .ROLLBACK = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .COMMIT = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + + pub const RESOURCE_MANAGER_RIGHTS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .{ + .READ_CONTROL = true, + }, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TRANSACTION = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .ENLIST = true, + .ROLLBACK = true, + .PROPAGATE = true, + } }, + }; + }; + + pub const ResourceManager = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + ENLIST: bool = false, + GET_NOTIFICATION: bool = false, + REGISTER_PROTOCOL: bool = false, + COMPLETE_PROPAGATION: bool = false, + Reserved7: u9 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .READ, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .WRITE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .REGISTER_PROTOCOL = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .EXECUTE, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .RESOURCEMANAGER = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .ENLIST = true, + .GET_NOTIFICATION = true, + .REGISTER_PROTOCOL = true, + .COMPLETE_PROPAGATION = true, + } }, + }; + }; + + pub const Enlistment = packed struct(u16) { + QUERY_INFORMATION: bool = false, + SET_INFORMATION: bool = false, + RECOVER: bool = false, + SUBORDINATE_RIGHTS: bool = false, + SUPERIOR_RIGHTS: bool = false, + Reserved5: u11 = 0, + + pub const GENERIC_READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .QUERY_INFORMATION = true, + } }, + }; + + pub const GENERIC_WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .SET_INFORMATION = true, + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + + pub const GENERIC_EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .ENLISTMENT = .{ + .QUERY_INFORMATION = true, + .SET_INFORMATION = true, + .RECOVER = true, + .SUBORDINATE_RIGHTS = true, + .SUPERIOR_RIGHTS = true, + } }, + }; + }; + + pub const Event = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .EVENT = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const Semaphore = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .SEMAPHORE = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const Token = packed struct(u16) { + ASSIGN_PRIMARY: bool = false, + DUPLICATE: bool = false, + IMPERSONATE: bool = false, + QUERY: bool = false, + QUERY_SOURCE: bool = false, + ADJUST_PRIVILEGES: bool = false, + ADJUST_GROUPS: bool = false, + ADJUST_DEFAULT: bool = false, + ADJUST_SESSIONID: bool = false, + Reserved9: u7 = 0, + + pub const ALL_ACCESS_P: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TOKEN = .{ + .ASSIGN_PRIMARY = true, + .DUPLICATE = true, + .IMPERSONATE = true, + .QUERY = true, + .QUERY_SOURCE = true, + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + } }, + }; + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED }, + .SPECIFIC = .{ .TOKEN = .{ + .ASSIGN_PRIMARY = true, + .DUPLICATE = true, + .IMPERSONATE = true, + .QUERY = true, + .QUERY_SOURCE = true, + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + .ADJUST_SESSIONID = true, + } }, + }; + + pub const READ: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + } }, + }; + + pub const WRITE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .WRITE }, + .SPECIFIC = .{ .TOKEN = .{ + .ADJUST_PRIVILEGES = true, + .ADJUST_GROUPS = true, + .ADJUST_DEFAULT = true, + } }, + }; + + pub const EXECUTE: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .EXECUTE }, + .SPECIFIC = .{ .TOKEN = .{} }, + }; + + pub const TRUST_CONSTRAINT_MASK: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + .QUERY_SOURCE = true, + } }, + }; + + pub const TRUST_ALLOWED_MASK: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .READ }, + .SPECIFIC = .{ .TOKEN = .{ + .QUERY = true, + .QUERY_SOURCE = true, + .DUPLICATE = true, + .IMPERSONATE = true, + } }, + }; + }; + + pub const JobObject = packed struct(u16) { + ASSIGN_PROCESS: bool = false, + SET_ATTRIBUTES: bool = false, + QUERY: bool = false, + TERMINATE: bool = false, + SET_SECURITY_ATTRIBUTES: bool = false, + IMPERSONATE: bool = false, + Reserved6: u10 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .JOB_OBJECT = .{ + .ASSIGN_PROCESS = true, + .SET_ATTRIBUTES = true, + .QUERY = true, + .TERMINATE = true, + .SET_SECURITY_ATTRIBUTES = true, + .IMPERSONATE = true, + } }, + }; + }; + + pub const Mutant = packed struct(u16) { + QUERY_STATE: bool = false, + Reserved1: u15 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .MUTANT = .{ + .QUERY_STATE = true, + } }, + }; + }; + + pub const Timer = packed struct(u16) { + QUERY_STATE: bool = false, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ + .RIGHTS = .REQUIRED, + .SYNCHRONIZE = true, + }, + .SPECIFIC = .{ .TIMER = .{ + .QUERY_STATE = true, + .MODIFY_STATE = true, + } }, + }; + }; + + pub const IoCompletion = packed struct(u16) { + Reserved0: u1 = 0, + MODIFY_STATE: bool = false, + Reserved2: u14 = 0, + + pub const ALL_ACCESS: ACCESS_MASK = .{ + .STANDARD = .{ .RIGHTS = .REQUIRED, .SYNCHRONIZE = true }, + .SPECIFIC = .{ .IO_COMPLETION = .{ + .Reserved0 = maxInt(@FieldType(IoCompletion, "Reserved0")), + .MODIFY_STATE = true, + } }, + }; + }; + + pub const RIGHTS_ALL: Specific = .{ .bits = maxInt(@FieldType(Specific, "bits")) }; + }; + + pub const Standard = packed struct(u5) { + RIGHTS: Rights = .{}, + SYNCHRONIZE: bool = false, + + pub const RIGHTS_ALL: Standard = .{ + .RIGHTS = .ALL, + .SYNCHRONIZE = true, + }; + + pub const Rights = packed struct(u4) { + DELETE: bool = false, + READ_CONTROL: bool = false, + WRITE_DAC: bool = false, + WRITE_OWNER: bool = false, + + pub const REQUIRED: Rights = .{ + .DELETE = true, + .READ_CONTROL = true, + .WRITE_DAC = true, + .WRITE_OWNER = true, + }; + + pub const READ: Rights = .{ + .READ_CONTROL = true, + }; + pub const WRITE: Rights = .{ + .READ_CONTROL = true, + }; + pub const EXECUTE: Rights = .{ + .READ_CONTROL = true, + }; + + pub const ALL = REQUIRED; + }; + }; + + pub const Generic = packed struct(u4) { + ALL: bool = false, + EXECUTE: bool = false, + WRITE: bool = false, + READ: bool = false, + }; +}; + +pub const DEVICE_TYPE = packed struct(ULONG) { + FileDevice: CTL_CODE.FILE_DEVICE, + Reserved16: u16 = 0, +}; + +pub const FS_INFORMATION_CLASS = enum(c_int) { + Volume = 1, + Label = 2, + Size = 3, + Device = 4, + Attribute = 5, + Control = 6, + FullSize = 7, + ObjectId = 8, + DriverPath = 9, + VolumeFlags = 10, + SectorSize = 11, + DataCopy = 12, + MetadataSize = 13, + FullSizeEx = 14, + Guid = 15, + _, + + pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len; +}; + +pub const SECTION_INHERIT = enum(c_int) { + Share = 1, + Unmap = 2, +}; + +pub const PAGE = packed struct(ULONG) { + NOACCESS: bool = false, + READONLY: bool = false, + READWRITE: bool = false, + WRITECOPY: bool = false, + + EXECUTE: bool = false, + EXECUTE_READ: bool = false, + EXECUTE_READWRITE: bool = false, + EXECUTE_WRITECOPY: bool = false, + + GUARD: bool = false, + NOCACHE: bool = false, + WRITECOMBINE: bool = false, + + GRAPHICS_NOACCESS: bool = false, + GRAPHICS_READONLY: bool = false, + GRAPHICS_READWRITE: bool = false, + GRAPHICS_EXECUTE: bool = false, + GRAPHICS_EXECUTE_READ: bool = false, + GRAPHICS_EXECUTE_READWRITE: bool = false, + GRAPHICS_COHERENT: bool = false, + GRAPHICS_NOCACHE: bool = false, + + Reserved19: u12 = 0, + + REVERT_TO_FILE_MAP: bool = false, +}; + +pub const MEM = struct { + pub const ALLOCATE = packed struct(ULONG) { + Reserved0: u12 = 0, + COMMIT: bool = false, + RESERVE: bool = false, + REPLACE_PLACEHOLDER: bool = false, + Reserved15: u3 = 0, + RESERVE_PLACEHOLDER: bool = false, + RESET: bool = false, + TOP_DOWN: bool = false, + WRITE_WATCH: bool = false, + PHYSICAL: bool = false, + Reserved23: u1 = 0, + RESET_UNDO: bool = false, + Reserved25: u4 = 0, + LARGE_PAGES: bool = false, + Reserved30: u1 = 0, + @"4MB_PAGES": bool = false, + + pub const @"64K_PAGES": ALLOCATE = .{ + .LARGE_PAGES = true, + .PHYSICAL = true, + }; + }; + + pub const FREE = packed struct(ULONG) { + COALESCE_PLACEHOLDERS: bool = false, + PRESERVE_PLACEHOLDER: bool = false, + Reserved2: u12 = 0, + DECOMMIT: bool = false, + RELEASE: bool = false, + FREE: bool = false, + Reserved17: u15 = 0, + }; + + pub const MAP = packed struct(ULONG) { + Reserved0: u13 = 0, + RESERVE: bool = false, + REPLACE_PLACEHOLDER: bool = false, + Reserved15: u14 = 0, + LARGE_PAGES: bool = false, + Reserved30: u2 = 0, + }; + + pub const UNMAP = packed struct(ULONG) { + WITH_TRANSIENT_BOOST: bool = false, + PRESERVE_PLACEHOLDER: bool = false, + Reserved2: u30 = 0, + }; + + pub const EXTENDED_PARAMETER = extern struct { + s: packed struct(ULONG64) { + Type: TYPE, + Reserved: u56, + }, + u: extern union { + ULong64: ULONG64, + Pointer: PVOID, + Size: SIZE_T, + Handle: HANDLE, + ULong: ULONG, + }, + + pub const TYPE = enum(u8) { + InvalidType = 0, + AddressRequirements, + NumaNode, + PartitionHandle, + UserPhysicalHandle, + AttributeFlags, + ImageMachine, + _, + + pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len; + }; + }; +}; + +pub const SEC = packed struct(ULONG) { + Reserved0: u17 = 0, + HUGE_PAGES: bool = false, + PARTITION_OWNER_HANDLE: bool = false, + @"64K_PAGES": bool = false, + Reserved19: u3 = 0, + FILE: bool = false, + IMAGE: bool = false, + PROTECTED_IMAGE: bool = false, + RESERVE: bool = false, + COMMIT: bool = false, + NOCACHE: bool = false, + Reserved29: u1 = 0, + WRITECOMBINE: bool = false, + LARGE_PAGES: bool = false, + + pub const IMAGE_NO_EXECUTE: SEC = .{ + .IMAGE = true, + .NOCACHE = true, + }; +}; + +pub const ERESOURCE = opaque {}; + +// ref: shared/ntdef.h + +pub const EVENT_TYPE = enum(c_int) { + Notification, + Synchronization, +}; + +pub const TIMER_TYPE = enum(c_int) { + Notification, + Synchronization, +}; + +pub const WAIT_TYPE = enum(c_int) { + All, + Any, +}; + +pub const LOGICAL = ULONG; + +pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; + +// ref: um/heapapi.h + +pub fn GetProcessHeap() ?*HEAP { + return peb().ProcessHeap; +} + +// ref: um/winternl.h + +pub const OBJECT_ATTRIBUTES = extern struct { + Length: ULONG, + RootDirectory: ?HANDLE, + ObjectName: *UNICODE_STRING, + Attributes: ATTRIBUTES, + SecurityDescriptor: ?*anyopaque, + SecurityQualityOfService: ?*anyopaque, + + // Valid values for the Attributes field + pub const ATTRIBUTES = packed struct(ULONG) { + Reserved0: u1 = 0, + INHERIT: bool = false, + Reserved2: u2 = 0, + PERMANENT: bool = false, + EXCLUSIVE: bool = false, + /// If name-lookup code should ignore the case of the ObjectName member rather than performing an exact-match search. + CASE_INSENSITIVE: bool = true, + OPENIF: bool = false, + OPENLINK: bool = false, + KERNEL_HANDLE: bool = false, + FORCE_ACCESS_CHECK: bool = false, + IGNORE_IMPERSONATED_DEVICEMAP: bool = false, + DONT_REPARSE: bool = false, + Reserved13: u19 = 0, + + pub const VALID_ATTRIBUTES: ATTRIBUTES = .{ + .INHERIT = true, + .PERMANENT = true, + .EXCLUSIVE = true, + .CASE_INSENSITIVE = true, + .OPENIF = true, + .OPENLINK = true, + .KERNEL_HANDLE = true, + .FORCE_ACCESS_CHECK = true, + .IGNORE_IMPERSONATED_DEVICEMAP = true, + .DONT_REPARSE = true, + }; + }; +}; + +// ref none pub const OpenError = error{ IsDir, @@ -52,8 +2308,8 @@ pub const OpenFileOptions = struct { access_mask: ACCESS_MASK, dir: ?HANDLE = null, sa: ?*SECURITY_ATTRIBUTES = null, - share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, - creation: ULONG, + share_access: FILE.SHARE = .VALID_FLAGS, + creation: FILE.CREATE_DISPOSITION, /// If true, tries to open path as a directory. /// Defaults to false. filter: Filter = .file_only, @@ -82,32 +2338,22 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN var result: HANDLE = undefined; const path_len_bytes = math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong; - var nt_name = UNICODE_STRING{ + var nt_name: UNICODE_STRING = .{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, .Buffer = @constCast(sub_path_w.ptr), }; - var attr = OBJECT_ATTRIBUTES{ + const attr: OBJECT_ATTRIBUTES = .{ .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, - .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here. - const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0; - break :blk inherit; - } else 0, + .Attributes = .{ + .INHERIT = if (options.sa) |sa| sa.bInheritHandle != FALSE else false, + }, .ObjectName = &nt_name, .SecurityDescriptor = if (options.sa) |ptr| ptr.lpSecurityDescriptor else null, .SecurityQualityOfService = null, }; var io: IO_STATUS_BLOCK = undefined; - const blocking_flag: ULONG = FILE_SYNCHRONOUS_IO_NONALERT; - const file_or_dir_flag: ULONG = switch (options.filter) { - .file_only => FILE_NON_DIRECTORY_FILE, - .dir_only => FILE_DIRECTORY_FILE, - .any => 0, - }; - // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT. - const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT; - while (true) { const rc = ntdll.NtCreateFile( &result, @@ -115,10 +2361,15 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN &attr, &io, null, - FILE_ATTRIBUTE_NORMAL, + .{ .NORMAL = true }, options.share_access, options.creation, - flags, + .{ + .DIRECTORY_FILE = options.filter == .dir_only, + .NON_DIRECTORY_FILE = options.filter == .file_only, + .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, + .OPEN_REPARSE_POINT = !options.follow_symlinks, + }, null, 0, ); @@ -201,16 +2452,16 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C const dev_handle = opt_dev_handle orelse blk: { const str = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\NamedPipe\\"); const len: u16 = @truncate(str.len * @sizeOf(u16)); - const name = UNICODE_STRING{ + const name: UNICODE_STRING = .{ .Length = len, .MaximumLength = len, .Buffer = @ptrCast(@constCast(str)), }; - const attrs = OBJECT_ATTRIBUTES{ + const attrs: OBJECT_ATTRIBUTES = .{ .ObjectName = @constCast(&name), .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = null, - .Attributes = 0, + .Attributes = .{}, .SecurityDescriptor = null, .SecurityQualityOfService = null, }; @@ -219,14 +2470,17 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var handle: HANDLE = undefined; switch (ntdll.NtCreateFile( &handle, - GENERIC_READ | SYNCHRONIZE, + .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, @constCast(&attrs), &iosb, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT, + .{}, + .VALID_FLAGS, + .OPEN, + .{ .IO = .SYNCHRONOUS_NONALERT }, null, 0, )) { @@ -242,16 +2496,15 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C } else break :blk handle; }; - const name = UNICODE_STRING{ .Buffer = null, .Length = 0, .MaximumLength = 0 }; - var attrs = OBJECT_ATTRIBUTES{ + const name: UNICODE_STRING = .{ .Buffer = null, .Length = 0, .MaximumLength = 0 }; + var attrs: OBJECT_ATTRIBUTES = .{ .ObjectName = @constCast(&name), .Length = @sizeOf(OBJECT_ATTRIBUTES), .RootDirectory = dev_handle, - .Attributes = OBJ_CASE_INSENSITIVE, + .Attributes = .{ .INHERIT = sattr.bInheritHandle != FALSE }, .SecurityDescriptor = sattr.lpSecurityDescriptor, .SecurityQualityOfService = null, }; - if (sattr.bInheritHandle != 0) attrs.Attributes |= OBJ_INHERIT; // 120 second relative timeout in 100ns units. const default_timeout: LARGE_INTEGER = (-120 * std.time.ns_per_s) / 100; @@ -259,15 +2512,21 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var read: HANDLE = undefined; switch (ntdll.NtCreateNamedPipeFile( &read, - GENERIC_READ | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + .{ + .SPECIFIC = .{ .FILE_PIPE = .{ + .WRITE_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, &attrs, &iosb, - FILE_SHARE_READ | FILE_SHARE_WRITE, - FILE_CREATE, - FILE_SYNCHRONOUS_IO_NONALERT, - FILE_PIPE_BYTE_STREAM_TYPE, - FILE_PIPE_BYTE_STREAM_MODE, - FILE_PIPE_QUEUE_OPERATION, + .{ .READ = true, .WRITE = true }, + .CREATE, + .{ .IO = .SYNCHRONOUS_NONALERT }, + .{ .TYPE = .BYTE_STREAM }, + .{ .MODE = .BYTE_STREAM }, + .{ .OPERATION = .QUEUE }, 1, 4096, 4096, @@ -285,14 +2544,23 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C var write: HANDLE = undefined; switch (ntdll.NtCreateFile( &write, - GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES, + .{ + .SPECIFIC = .{ .FILE_PIPE = .{ + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true }, + }, &attrs, &iosb, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .IO = .SYNCHRONOUS_NONALERT, + .NON_DIRECTORY_FILE = true, + }, null, 0, )) { @@ -311,6 +2579,15 @@ pub const DeviceIoControlError = error{ /// The volume does not contain a recognized file system. File system /// drivers might not be loaded, or the volume may be corrupt. UnrecognizedVolume, + Pending, + /// Attempted to connect a named pipe in the "closing" state, meaning a previous client has + /// has closed their handle but we have not yet disconnected the pipe. + PipeClosing, + /// Attempted to connect a named pipe in the "connected" state, meaning a client has already + /// opened the pipe; there is a good connection between client and server. + PipeAlreadyConnected, + /// Attempted to connect a non-blocking named pipe which is already listening for connections. + PipeAlreadyListening, Unexpected, }; @@ -319,56 +2596,55 @@ pub const DeviceIoControlError = error{ /// as a direct substitute for that call. /// TODO work out if we need to expose other arguments to the underlying syscalls. pub fn DeviceIoControl( - h: HANDLE, - ioControlCode: ULONG, - in: ?[]const u8, - out: ?[]u8, + device: HANDLE, + io_control_code: CTL_CODE, + opts: struct { + event: ?HANDLE = null, + apc_routine: ?*const IO_APC_ROUTINE = null, + apc_context: ?*anyopaque = null, + io_status_block: ?*IO_STATUS_BLOCK = null, + in: []const u8 = &.{}, + out: []u8 = &.{}, + }, ) DeviceIoControlError!void { - // Logic from: https://doxygen.reactos.org/d3/d74/deviceio_8c.html - const is_fsctl = (ioControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM; - - var io: IO_STATUS_BLOCK = undefined; - const in_ptr = if (in) |i| i.ptr else null; - const in_len = if (in) |i| @as(ULONG, @intCast(i.len)) else 0; - const out_ptr = if (out) |o| o.ptr else null; - const out_len = if (out) |o| @as(ULONG, @intCast(o.len)) else 0; - - const rc = blk: { - if (is_fsctl) { - break :blk ntdll.NtFsControlFile( - h, - null, - null, - null, - &io, - ioControlCode, - in_ptr, - in_len, - out_ptr, - out_len, - ); - } else { - break :blk ntdll.NtDeviceIoControlFile( - h, - null, - null, - null, - &io, - ioControlCode, - in_ptr, - in_len, - out_ptr, - out_len, - ); - } + var io_status_block: IO_STATUS_BLOCK = undefined; + const rc = switch (io_control_code.DeviceType) { + .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile( + device, + opts.event, + opts.apc_routine, + opts.apc_context, + opts.io_status_block orelse &io_status_block, + io_control_code, + if (opts.in.len > 0) opts.in.ptr else null, + @intCast(opts.in.len), + if (opts.out.len > 0) opts.out.ptr else null, + @intCast(opts.out.len), + ), + else => ntdll.NtDeviceIoControlFile( + device, + opts.event, + opts.apc_routine, + opts.apc_context, + opts.io_status_block orelse &io_status_block, + io_control_code, + if (opts.in.len > 0) opts.in.ptr else null, + @intCast(opts.in.len), + if (opts.out.len > 0) opts.out.ptr else null, + @intCast(opts.out.len), + ), }; switch (rc) { .SUCCESS => {}, + .PIPE_CLOSING => return error.PipeClosing, + .PIPE_CONNECTED => return error.PipeAlreadyConnected, + .PIPE_LISTENING => return error.PipeAlreadyListening, .PRIVILEGE_NOT_HELD => return error.AccessDenied, .ACCESS_DENIED => return error.AccessDenied, .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem .INVALID_PARAMETER => unreachable, .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume, + .PENDING => return error.Pending, else => return unexpectedStatus(rc), } } @@ -704,7 +2980,7 @@ pub const SetCurrentDirectoryError = error{ pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void { const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong; - var nt_name = UNICODE_STRING{ + var nt_name: UNICODE_STRING = .{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, .Buffer = @constCast(path_name.ptr), @@ -780,7 +3056,7 @@ pub fn CreateSymbolicLink( is_directory: bool, ) CreateSymbolicLinkError!void { const SYMLINK_DATA = extern struct { - ReparseTag: ULONG, + ReparseTag: IO_REPARSE_TAG, ReparseDataLength: USHORT, Reserved: USHORT, SubstituteNameOffset: USHORT, @@ -791,9 +3067,12 @@ pub fn CreateSymbolicLink( }; const symlink_handle = OpenFile(sym_link_path, .{ - .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true, .READ = true }, + }, .dir = dir, - .creation = FILE_CREATE, + .creation = .CREATE, .filter = if (is_directory) .dir_only else .file_only, }) catch |err| switch (err) { error.IsDir => return error.PathAlreadyExists, @@ -845,8 +3124,8 @@ pub fn CreateSymbolicLink( const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4; const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2; const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path); - const symlink_data = SYMLINK_DATA{ - .ReparseTag = IO_REPARSE_TAG_SYMLINK, + const symlink_data: SYMLINK_DATA = .{ + .ReparseTag = .SYMLINK, .ReparseDataLength = @intCast(buf_len - header_len), .Reserved = 0, .SubstituteNameOffset = @intCast(final_target_path.len * 2), @@ -860,7 +3139,13 @@ pub fn CreateSymbolicLink( @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2; @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path))); - _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null); + _ = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }) catch |err| switch (err) { + error.PipeClosing => unreachable, + error.PipeAlreadyConnected => unreachable, + error.PipeAlreadyListening => unreachable, + error.Pending => unreachable, + else => |e| return e, + }; } pub const ReadLinkError = error{ @@ -878,9 +3163,14 @@ pub const ReadLinkError = error{ /// is safe to reuse a single buffer for both. pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLinkError![]u16 { const result_handle = OpenFile(sub_path_w, .{ - .access_mask = FILE_READ_ATTRIBUTES | SYNCHRONIZE, + .access_mask = .{ + .SPECIFIC = .{ .FILE = .{ + .READ_ATTRIBUTES = true, + } }, + .STANDARD = .{ .SYNCHRONIZE = true }, + }, .dir = dir, - .creation = FILE_OPEN, + .creation = .OPEN, .follow_symlinks = false, .filter = .any, }) catch |err| switch (err) { @@ -894,15 +3184,20 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi defer CloseHandle(result_handle); var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined; - _ = DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]) catch |err| switch (err) { + _ = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }) catch |err| switch (err) { + error.PipeClosing => unreachable, + error.PipeAlreadyConnected => unreachable, + error.PipeAlreadyListening => unreachable, error.AccessDenied => return error.Unexpected, error.UnrecognizedVolume => return error.Unexpected, + error.Pending => unreachable, else => |e| return e, }; const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0])); - switch (reparse_struct.ReparseTag) { - IO_REPARSE_TAG_SYMLINK => { + const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?; + switch (@as(IoReparseTagInt, @bitCast(reparse_struct.ReparseTag))) { + @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.SYMLINK)) => { const buf: *const SYMBOLIC_LINK_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0])); const offset = buf.SubstituteNameOffset >> 1; const len = buf.SubstituteNameLength >> 1; @@ -910,16 +3205,14 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi const is_relative = buf.Flags & SYMLINK_FLAG_RELATIVE != 0; return parseReadLinkPath(path_buf[offset..][0..len], is_relative, out_buffer); }, - IO_REPARSE_TAG_MOUNT_POINT => { + @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.MOUNT_POINT)) => { const buf: *const MOUNT_POINT_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0])); const offset = buf.SubstituteNameOffset >> 1; const len = buf.SubstituteNameLength >> 1; const path_buf = @as([*]const u16, &buf.PathBuffer); return parseReadLinkPath(path_buf[offset..][0..len], false, out_buffer); }, - else => { - return error.UnsupportedReparsePointType; - }, + else => return error.UnsupportedReparsePointType, } } @@ -956,13 +3249,8 @@ pub const DeleteFileOptions = struct { }; pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void { - const create_options_flags: ULONG = if (options.remove_dir) - FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT - else - FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead? - const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2)); - var nt_name = UNICODE_STRING{ + var nt_name: UNICODE_STRING = .{ .Length = path_len_bytes, .MaximumLength = path_len_bytes, // The Windows API makes this mutable, but it will not mutate here. @@ -978,26 +3266,32 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil return error.FileBusy; } - var attr = OBJECT_ATTRIBUTES{ - .Length = @sizeOf(OBJECT_ATTRIBUTES), - .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, - .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. - .ObjectName = &nt_name, - .SecurityDescriptor = null, - .SecurityQualityOfService = null, - }; var io: IO_STATUS_BLOCK = undefined; var tmp_handle: HANDLE = undefined; var rc = ntdll.NtCreateFile( &tmp_handle, - SYNCHRONIZE | DELETE, - &attr, + .{ .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + } }, + &.{ + .Length = @sizeOf(OBJECT_ATTRIBUTES), + .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir, + .Attributes = .{}, + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }, &io, null, - 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, - create_options_flags, + .{}, + .VALID_FLAGS, + .OPEN, + .{ + .DIRECTORY_FILE = options.remove_dir, + .NON_DIRECTORY_FILE = !options.remove_dir, + .OPEN_REPARSE_POINT = true, // would we ever want to delete the target instead? + }, null, 0, ); @@ -1031,18 +3325,17 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil // FileDispositionInformation if the return value lets us know that some aspect of it is not supported. const need_fallback = need_fallback: { // Deletion with posix semantics if the filesystem supports it. - var info = FILE_DISPOSITION_INFORMATION_EX{ - .Flags = FILE_DISPOSITION_DELETE | - FILE_DISPOSITION_POSIX_SEMANTICS | - FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE, - }; - + const info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{ + .DELETE = true, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, + } }; rc = ntdll.NtSetInformationFile( tmp_handle, &io, &info, - @sizeOf(FILE_DISPOSITION_INFORMATION_EX), - .FileDispositionInformationEx, + @sizeOf(FILE.DISPOSITION.INFORMATION.EX), + .DispositionEx, ); switch (rc) { .SUCCESS => return, @@ -1061,16 +3354,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil if (need_fallback) { // Deletion with file pending semantics, which requires waiting or moving // files to get them removed (from here). - var file_dispo = FILE_DISPOSITION_INFORMATION{ + const file_dispo: FILE.DISPOSITION.INFORMATION = .{ .DeleteFile = TRUE, }; - rc = ntdll.NtSetInformationFile( tmp_handle, &io, &file_dispo, - @sizeOf(FILE_DISPOSITION_INFORMATION), - .FileDispositionInformation, + @sizeOf(FILE.DISPOSITION.INFORMATION), + .Disposition, ); } switch (rc) { @@ -1112,8 +3404,14 @@ pub fn RenameFile( ) RenameError!void { const src_fd = OpenFile(old_path_w, .{ .dir = old_dir_fd, - .access_mask = SYNCHRONIZE | GENERIC_WRITE | DELETE, - .creation = FILE_OPEN, + .access_mask = .{ + .STANDARD = .{ + .RIGHTS = .{ .DELETE = true }, + .SYNCHRONIZE = true, + }, + .GENERIC = .{ .WRITE = true }, + }, + .creation = .OPEN, .filter = .any, // This function is supposed to rename both files and directories. .follow_symlinks = false, }) catch |err| switch (err) { @@ -1135,29 +3433,23 @@ pub fn RenameFile( // 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, + const rename_info: FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ + .REPLACE_IF_EXISTS = replace_if_exists, + .POSIX_SEMANTICS = true, + .IGNORE_READONLY_ATTRIBUTE = true, + }, .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); + .FileName = new_path_w, + }); + var io_status_block: IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); rc = ntdll.NtSetInformationFile( src_fd, &io_status_block, - rename_info, - @intCast(struct_len), // already checked for error.NameTooLong - .FileRenameInformationEx, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), // already checked for error.NameTooLong + .RenameEx, ); switch (rc) { .SUCCESS => return, @@ -1174,28 +3466,19 @@ pub fn RenameFile( }; 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), + const rename_info: FILE.RENAME_INFORMATION = .init(.{ + .Flags = .{ .REPLACE_IF_EXISTS = 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); - + .FileName = new_path_w, + }); + var io_status_block: IO_STATUS_BLOCK = undefined; + const rename_info_buf = rename_info.toBuffer(); rc = ntdll.NtSetInformationFile( src_fd, &io_status_block, - rename_info, - @intCast(struct_len), // already checked for error.NameTooLong - .FileRenameInformation, + rename_info_buf.ptr, + @intCast(rename_info_buf.len), // already checked for error.NameTooLong + .Rename, ); } @@ -1308,7 +3591,7 @@ pub fn QueryObjectName(handle: HANDLE, out_buffer: []u16) QueryObjectNameError![ const info = @as(*OBJECT_NAME_INFORMATION, @ptrCast(out_buffer_aligned)); // buffer size is specified in bytes - const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse std.math.maxInt(ULONG); + const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse maxInt(ULONG); // last argument would return the length required for full_buffer, not exposed here return switch (ntdll.NtQueryObject(handle, .ObjectNameInformation, info, out_buffer_len, null)) { .SUCCESS => blk: { @@ -1440,9 +3723,8 @@ pub fn GetFinalPathNameByHandle( // This is the NT namespaced version of \\.\MountPointManager const mgmt_path_u16 = std.unicode.utf8ToUtf16LeStringLiteral("\\??\\MountPointManager"); const mgmt_handle = OpenFile(mgmt_path_u16, .{ - .access_mask = SYNCHRONIZE, - .share_access = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - .creation = FILE_OPEN, + .access_mask = .{ .STANDARD = .{ .SYNCHRONIZE = true } }, + .creation = .OPEN, }) catch |err| switch (err) { error.IsDir => return error.Unexpected, error.NotDir => return error.Unexpected, @@ -1462,8 +3744,12 @@ pub fn GetFinalPathNameByHandle( input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2); @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr))); - DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_POINTS, &input_buf, &output_buf) catch |err| switch (err) { + DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }) catch |err| switch (err) { + error.PipeClosing => unreachable, + error.PipeAlreadyConnected => unreachable, + error.PipeAlreadyListening => unreachable, error.AccessDenied => return error.Unexpected, + error.Pending => unreachable, else => |e| return e, }; const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]); @@ -1517,8 +3803,12 @@ pub fn GetFinalPathNameByHandle( vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2); @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink); - DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, &vol_input_buf, &vol_output_buf) catch |err| switch (err) { + DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }) catch |err| switch (err) { + error.PipeClosing => unreachable, + error.PipeAlreadyConnected => unreachable, + error.PipeAlreadyListening => unreachable, error.AccessDenied => return error.Unexpected, + error.Pending => unreachable, else => |e| return e, }; const volume_paths_struct: *const MOUNTMGR_VOLUME_PATHS = @ptrCast(&vol_output_buf[0]); @@ -1758,7 +4048,7 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l // ntdll takes an extra level of indirection here var addr = lpAddress; var size = dwSize; - switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) { + switch (ntdll.NtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, flNewProtect, lpflOldProtect)) { .SUCCESS => {}, .INVALID_ADDRESS => return error.InvalidAddress, else => |st| return unexpectedStatus(st), @@ -2018,7 +4308,7 @@ pub const LockFileError = error{ pub fn LockFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?*IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, ByteOffset: *const LARGE_INTEGER, @@ -2057,7 +4347,7 @@ pub fn UnlockFile( IoStatusBlock: *IO_STATUS_BLOCK, ByteOffset: *const LARGE_INTEGER, Length: *const LARGE_INTEGER, - Key: ?*ULONG, + Key: ULONG, ) !void { const rc = ntdll.NtUnlockFile(FileHandle, IoStatusBlock, ByteOffset, Length, Key); switch (rc) { @@ -2168,13 +4458,13 @@ pub fn eqlIgnoreCaseWtf16(a: []const u16, b: []const u16) bool { // Use RtlEqualUnicodeString on Windows when not in comptime to avoid including a // redundant copy of the uppercase data. const a_bytes = @as(u16, @intCast(a.len * 2)); - const a_string = UNICODE_STRING{ + const a_string: UNICODE_STRING = .{ .Length = a_bytes, .MaximumLength = a_bytes, .Buffer = @constCast(a.ptr), }; const b_bytes = @as(u16, @intCast(b.len * 2)); - const b_string = UNICODE_STRING{ + const b_string: UNICODE_STRING = .{ .Length = b_bytes, .MaximumLength = b_bytes, .Buffer = @constCast(b.ptr), @@ -2206,7 +4496,7 @@ pub fn eqlIgnoreCaseWtf8(a: []const u8, b: []const u8) bool { const a_cp = a_wtf8_it.nextCodepoint() orelse break; const b_cp = b_wtf8_it.nextCodepoint() orelse return false; - if (a_cp <= std.math.maxInt(u16) and b_cp <= std.math.maxInt(u16)) { + if (a_cp <= maxInt(u16) and b_cp <= maxInt(u16)) { if (a_cp != b_cp and upcaseImpl(@intCast(a_cp)) != upcaseImpl(@intCast(b_cp))) { return false; } @@ -2783,7 +5073,10 @@ pub fn unexpectedWSAError(err: ws2_32.WinsockError) UnexpectedError { /// and you get an unexpected status. pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { if (std.posix.unexpected_error_tracing) { - std.debug.print("error.Unexpected NTSTATUS=0x{x}\n", .{@intFromEnum(status)}); + std.debug.print("error.Unexpected NTSTATUS=0x{x} ({s})\n", .{ + @intFromEnum(status), + std.enums.tagName(NTSTATUS, status) orelse "<unnamed>", + }); std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() }); } return error.Unexpected; @@ -2791,20 +5084,25 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError { pub fn statusBug(status: NTSTATUS) UnexpectedError { switch (builtin.mode) { - .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}), + .Debug => std.debug.panic("programmer bug caused syscall status: 0x{x} ({s})", .{ + @intFromEnum(status), + std.enums.tagName(NTSTATUS, status) orelse "<unnamed>", + }), else => return error.Unexpected, } } pub fn errorBug(err: Win32Error) UnexpectedError { switch (builtin.mode) { - .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{err}), + .Debug => std.debug.panic("programmer bug caused syscall error: 0x{x} ({s})", .{ + @intFromEnum(err), + std.enums.tagName(Win32Error, err) orelse "<unnamed>", + }), else => return error.Unexpected, } } pub const Win32Error = @import("windows/win32error.zig").Win32Error; -pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS; pub const LANG = @import("windows/lang.zig"); pub const SUBLANG = @import("windows/sublang.zig"); @@ -2885,217 +5183,9 @@ pub const PCTSTR = @compileError("Deprecated: choose between `PCSTR` or `PCWSTR` pub const TRUE = 1; pub const FALSE = 0; -pub const DEVICE_TYPE = ULONG; -pub const FILE_DEVICE_BEEP: DEVICE_TYPE = 0x0001; -pub const FILE_DEVICE_CD_ROM: DEVICE_TYPE = 0x0002; -pub const FILE_DEVICE_CD_ROM_FILE_SYSTEM: DEVICE_TYPE = 0x0003; -pub const FILE_DEVICE_CONTROLLER: DEVICE_TYPE = 0x0004; -pub const FILE_DEVICE_DATALINK: DEVICE_TYPE = 0x0005; -pub const FILE_DEVICE_DFS: DEVICE_TYPE = 0x0006; -pub const FILE_DEVICE_DISK: DEVICE_TYPE = 0x0007; -pub const FILE_DEVICE_DISK_FILE_SYSTEM: DEVICE_TYPE = 0x0008; -pub const FILE_DEVICE_FILE_SYSTEM: DEVICE_TYPE = 0x0009; -pub const FILE_DEVICE_INPORT_PORT: DEVICE_TYPE = 0x000a; -pub const FILE_DEVICE_KEYBOARD: DEVICE_TYPE = 0x000b; -pub const FILE_DEVICE_MAILSLOT: DEVICE_TYPE = 0x000c; -pub const FILE_DEVICE_MIDI_IN: DEVICE_TYPE = 0x000d; -pub const FILE_DEVICE_MIDI_OUT: DEVICE_TYPE = 0x000e; -pub const FILE_DEVICE_MOUSE: DEVICE_TYPE = 0x000f; -pub const FILE_DEVICE_MULTI_UNC_PROVIDER: DEVICE_TYPE = 0x0010; -pub const FILE_DEVICE_NAMED_PIPE: DEVICE_TYPE = 0x0011; -pub const FILE_DEVICE_NETWORK: DEVICE_TYPE = 0x0012; -pub const FILE_DEVICE_NETWORK_BROWSER: DEVICE_TYPE = 0x0013; -pub const FILE_DEVICE_NETWORK_FILE_SYSTEM: DEVICE_TYPE = 0x0014; -pub const FILE_DEVICE_NULL: DEVICE_TYPE = 0x0015; -pub const FILE_DEVICE_PARALLEL_PORT: DEVICE_TYPE = 0x0016; -pub const FILE_DEVICE_PHYSICAL_NETCARD: DEVICE_TYPE = 0x0017; -pub const FILE_DEVICE_PRINTER: DEVICE_TYPE = 0x0018; -pub const FILE_DEVICE_SCANNER: DEVICE_TYPE = 0x0019; -pub const FILE_DEVICE_SERIAL_MOUSE_PORT: DEVICE_TYPE = 0x001a; -pub const FILE_DEVICE_SERIAL_PORT: DEVICE_TYPE = 0x001b; -pub const FILE_DEVICE_SCREEN: DEVICE_TYPE = 0x001c; -pub const FILE_DEVICE_SOUND: DEVICE_TYPE = 0x001d; -pub const FILE_DEVICE_STREAMS: DEVICE_TYPE = 0x001e; -pub const FILE_DEVICE_TAPE: DEVICE_TYPE = 0x001f; -pub const FILE_DEVICE_TAPE_FILE_SYSTEM: DEVICE_TYPE = 0x0020; -pub const FILE_DEVICE_TRANSPORT: DEVICE_TYPE = 0x0021; -pub const FILE_DEVICE_UNKNOWN: DEVICE_TYPE = 0x0022; -pub const FILE_DEVICE_VIDEO: DEVICE_TYPE = 0x0023; -pub const FILE_DEVICE_VIRTUAL_DISK: DEVICE_TYPE = 0x0024; -pub const FILE_DEVICE_WAVE_IN: DEVICE_TYPE = 0x0025; -pub const FILE_DEVICE_WAVE_OUT: DEVICE_TYPE = 0x0026; -pub const FILE_DEVICE_8042_PORT: DEVICE_TYPE = 0x0027; -pub const FILE_DEVICE_NETWORK_REDIRECTOR: DEVICE_TYPE = 0x0028; -pub const FILE_DEVICE_BATTERY: DEVICE_TYPE = 0x0029; -pub const FILE_DEVICE_BUS_EXTENDER: DEVICE_TYPE = 0x002a; -pub const FILE_DEVICE_MODEM: DEVICE_TYPE = 0x002b; -pub const FILE_DEVICE_VDM: DEVICE_TYPE = 0x002c; -pub const FILE_DEVICE_MASS_STORAGE: DEVICE_TYPE = 0x002d; -pub const FILE_DEVICE_SMB: DEVICE_TYPE = 0x002e; -pub const FILE_DEVICE_KS: DEVICE_TYPE = 0x002f; -pub const FILE_DEVICE_CHANGER: DEVICE_TYPE = 0x0030; -pub const FILE_DEVICE_SMARTCARD: DEVICE_TYPE = 0x0031; -pub const FILE_DEVICE_ACPI: DEVICE_TYPE = 0x0032; -pub const FILE_DEVICE_DVD: DEVICE_TYPE = 0x0033; -pub const FILE_DEVICE_FULLSCREEN_VIDEO: DEVICE_TYPE = 0x0034; -pub const FILE_DEVICE_DFS_FILE_SYSTEM: DEVICE_TYPE = 0x0035; -pub const FILE_DEVICE_DFS_VOLUME: DEVICE_TYPE = 0x0036; -pub const FILE_DEVICE_SERENUM: DEVICE_TYPE = 0x0037; -pub const FILE_DEVICE_TERMSRV: DEVICE_TYPE = 0x0038; -pub const FILE_DEVICE_KSEC: DEVICE_TYPE = 0x0039; -pub const FILE_DEVICE_FIPS: DEVICE_TYPE = 0x003a; -pub const FILE_DEVICE_INFINIBAND: DEVICE_TYPE = 0x003b; -// TODO: missing values? -pub const FILE_DEVICE_VMBUS: DEVICE_TYPE = 0x003e; -pub const FILE_DEVICE_CRYPT_PROVIDER: DEVICE_TYPE = 0x003f; -pub const FILE_DEVICE_WPD: DEVICE_TYPE = 0x0040; -pub const FILE_DEVICE_BLUETOOTH: DEVICE_TYPE = 0x0041; -pub const FILE_DEVICE_MT_COMPOSITE: DEVICE_TYPE = 0x0042; -pub const FILE_DEVICE_MT_TRANSPORT: DEVICE_TYPE = 0x0043; -pub const FILE_DEVICE_BIOMETRIC: DEVICE_TYPE = 0x0044; -pub const FILE_DEVICE_PMI: DEVICE_TYPE = 0x0045; -pub const FILE_DEVICE_EHSTOR: DEVICE_TYPE = 0x0046; -pub const FILE_DEVICE_DEVAPI: DEVICE_TYPE = 0x0047; -pub const FILE_DEVICE_GPIO: DEVICE_TYPE = 0x0048; -pub const FILE_DEVICE_USBEX: DEVICE_TYPE = 0x0049; -pub const FILE_DEVICE_CONSOLE: DEVICE_TYPE = 0x0050; -pub const FILE_DEVICE_NFP: DEVICE_TYPE = 0x0051; -pub const FILE_DEVICE_SYSENV: DEVICE_TYPE = 0x0052; -pub const FILE_DEVICE_VIRTUAL_BLOCK: DEVICE_TYPE = 0x0053; -pub const FILE_DEVICE_POINT_OF_SERVICE: DEVICE_TYPE = 0x0054; -pub const FILE_DEVICE_STORAGE_REPLICATION: DEVICE_TYPE = 0x0055; -pub const FILE_DEVICE_TRUST_ENV: DEVICE_TYPE = 0x0056; -pub const FILE_DEVICE_UCM: DEVICE_TYPE = 0x0057; -pub const FILE_DEVICE_UCMTCPCI: DEVICE_TYPE = 0x0058; -pub const FILE_DEVICE_PERSISTENT_MEMORY: DEVICE_TYPE = 0x0059; -pub const FILE_DEVICE_NVDIMM: DEVICE_TYPE = 0x005a; -pub const FILE_DEVICE_HOLOGRAPHIC: DEVICE_TYPE = 0x005b; -pub const FILE_DEVICE_SDFXHCI: DEVICE_TYPE = 0x005c; - -/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/buffer-descriptions-for-i-o-control-codes -pub const TransferType = enum(u2) { - METHOD_BUFFERED = 0, - METHOD_IN_DIRECT = 1, - METHOD_OUT_DIRECT = 2, - METHOD_NEITHER = 3, -}; - -pub const FILE_ANY_ACCESS = 0; -pub const FILE_READ_ACCESS = 1; -pub const FILE_WRITE_ACCESS = 2; - -/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes -pub fn CTL_CODE(deviceType: u16, function: u12, method: TransferType, access: u2) DWORD { - return (@as(DWORD, deviceType) << 16) | - (@as(DWORD, access) << 14) | - (@as(DWORD, function) << 2) | - @intFromEnum(method); -} - -pub const INVALID_HANDLE_VALUE = @as(HANDLE, @ptrFromInt(maxInt(usize))); - -pub const INVALID_FILE_ATTRIBUTES = @as(DWORD, maxInt(DWORD)); - -pub const FILE_ALL_INFORMATION = extern struct { - BasicInformation: FILE_BASIC_INFORMATION, - StandardInformation: FILE_STANDARD_INFORMATION, - InternalInformation: FILE_INTERNAL_INFORMATION, - EaInformation: FILE_EA_INFORMATION, - AccessInformation: FILE_ACCESS_INFORMATION, - PositionInformation: FILE_POSITION_INFORMATION, - ModeInformation: FILE_MODE_INFORMATION, - AlignmentInformation: FILE_ALIGNMENT_INFORMATION, - NameInformation: FILE_NAME_INFORMATION, -}; - -pub const FILE_BASIC_INFORMATION = extern struct { - CreationTime: LARGE_INTEGER, - LastAccessTime: LARGE_INTEGER, - LastWriteTime: LARGE_INTEGER, - ChangeTime: LARGE_INTEGER, - FileAttributes: ULONG, -}; - -pub const FILE_STANDARD_INFORMATION = extern struct { - AllocationSize: LARGE_INTEGER, - EndOfFile: LARGE_INTEGER, - NumberOfLinks: ULONG, - DeletePending: BOOLEAN, - Directory: BOOLEAN, -}; - -pub const FILE_INTERNAL_INFORMATION = extern struct { - IndexNumber: LARGE_INTEGER, -}; - -pub const FILE_EA_INFORMATION = extern struct { - EaSize: ULONG, -}; - -pub const FILE_ACCESS_INFORMATION = extern struct { - AccessFlags: ACCESS_MASK, -}; - -pub const FILE_POSITION_INFORMATION = extern struct { - CurrentByteOffset: LARGE_INTEGER, -}; - -pub const FILE_END_OF_FILE_INFORMATION = extern struct { - EndOfFile: LARGE_INTEGER, -}; - -pub const FILE_MODE_INFORMATION = extern struct { - Mode: ULONG, -}; - -pub const FILE_ALIGNMENT_INFORMATION = extern struct { - AlignmentRequirement: ULONG, -}; - -pub const FILE_NAME_INFORMATION = extern struct { - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; - -pub const FILE_DISPOSITION_INFORMATION_EX = extern struct { - /// combination of FILE_DISPOSITION_* flags - Flags: ULONG, -}; - -pub const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000; -pub const FILE_DISPOSITION_DELETE: ULONG = 0x00000001; -pub const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002; -pub const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004; -pub const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008; -pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010; - -// FILE_RENAME_INFORMATION.Flags -pub const FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001; -pub const FILE_RENAME_POSIX_SEMANTICS = 0x00000002; -pub const FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004; -pub const FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008; -pub const FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010; -pub const FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020; -pub const FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030; -pub const FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040; -pub const FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080; -pub const FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100; -pub const FILE_RENAME_FORCE_RESIZE_SR = 0x00000180; - -pub const FILE_RENAME_INFORMATION = extern struct { - Flags: BOOLEAN, - RootDirectory: ?HANDLE, - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; +pub const INVALID_HANDLE_VALUE: HANDLE = @ptrFromInt(maxInt(usize)); -// FileRenameInformationEx (since .win10_rs1) -pub const FILE_RENAME_INFORMATION_EX = extern struct { - Flags: ULONG, - RootDirectory: ?HANDLE, - FileNameLength: ULONG, - FileName: [1]WCHAR, -}; +pub const INVALID_FILE_ATTRIBUTES: DWORD = maxInt(DWORD); pub const IO_STATUS_BLOCK = extern struct { // "DUMMYUNIONNAME" expands to "u" @@ -3106,130 +5196,6 @@ pub const IO_STATUS_BLOCK = extern struct { Information: ULONG_PTR, }; -pub const FILE_INFORMATION_CLASS = enum(c_int) { - FileDirectoryInformation = 1, - FileFullDirectoryInformation, - FileBothDirectoryInformation, - FileBasicInformation, - FileStandardInformation, - FileInternalInformation, - FileEaInformation, - FileAccessInformation, - FileNameInformation, - FileRenameInformation, - FileLinkInformation, - FileNamesInformation, - FileDispositionInformation, - FilePositionInformation, - FileFullEaInformation, - FileModeInformation, - FileAlignmentInformation, - FileAllInformation, - FileAllocationInformation, - FileEndOfFileInformation, - FileAlternateNameInformation, - FileStreamInformation, - FilePipeInformation, - FilePipeLocalInformation, - FilePipeRemoteInformation, - FileMailslotQueryInformation, - FileMailslotSetInformation, - FileCompressionInformation, - FileObjectIdInformation, - FileCompletionInformation, - FileMoveClusterInformation, - FileQuotaInformation, - FileReparsePointInformation, - FileNetworkOpenInformation, - FileAttributeTagInformation, - FileTrackingInformation, - FileIdBothDirectoryInformation, - FileIdFullDirectoryInformation, - FileValidDataLengthInformation, - FileShortNameInformation, - FileIoCompletionNotificationInformation, - FileIoStatusBlockRangeInformation, - FileIoPriorityHintInformation, - FileSfioReserveInformation, - FileSfioVolumeInformation, - FileHardLinkInformation, - FileProcessIdsUsingFileInformation, - FileNormalizedNameInformation, - FileNetworkPhysicalNameInformation, - FileIdGlobalTxDirectoryInformation, - FileIsRemoteDeviceInformation, - FileUnusedInformation, - FileNumaNodeInformation, - FileStandardLinkInformation, - FileRemoteProtocolInformation, - FileRenameInformationBypassAccessCheck, - FileLinkInformationBypassAccessCheck, - FileVolumeNameInformation, - FileIdInformation, - FileIdExtdDirectoryInformation, - FileReplaceCompletionInformation, - FileHardLinkFullIdInformation, - FileIdExtdBothDirectoryInformation, - FileDispositionInformationEx, - FileRenameInformationEx, - FileRenameInformationExBypassAccessCheck, - FileDesiredStorageClassInformation, - FileStatInformation, - FileMemoryPartitionInformation, - FileStatLxInformation, - FileCaseSensitiveInformation, - FileLinkInformationEx, - FileLinkInformationExBypassAccessCheck, - FileStorageReserveIdInformation, - FileCaseSensitiveInformationForceAccessCheck, - FileMaximumInformation, -}; - -pub const FILE_ATTRIBUTE_TAG_INFO = extern struct { - FileAttributes: DWORD, - ReparseTag: DWORD, -}; - -/// "If this bit is set, the file or directory represents another named entity in the system." -/// https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags -pub const reparse_tag_name_surrogate_bit = 0x20000000; - -pub const FILE_DISPOSITION_INFORMATION = extern struct { - DeleteFile: BOOLEAN, -}; - -pub const FILE_FS_DEVICE_INFORMATION = extern struct { - DeviceType: DEVICE_TYPE, - Characteristics: ULONG, -}; - -pub const FILE_FS_VOLUME_INFORMATION = extern struct { - VolumeCreationTime: LARGE_INTEGER, - VolumeSerialNumber: ULONG, - VolumeLabelLength: ULONG, - SupportsObjects: BOOLEAN, - // Flexible array member - VolumeLabel: [1]WCHAR, -}; - -pub const FS_INFORMATION_CLASS = enum(c_int) { - FileFsVolumeInformation = 1, - FileFsLabelInformation, - FileFsSizeInformation, - FileFsDeviceInformation, - FileFsAttributeInformation, - FileFsControlInformation, - FileFsFullSizeInformation, - FileFsObjectIdInformation, - FileFsDriverPathInformation, - FileFsVolumeFlagsInformation, - FileFsSectorSizeInformation, - FileFsDataCopyInformation, - FileFsMetadataSizeInformation, - FileFsFullSizeInformationEx, - FileFsMaximumInformation, -}; - pub const OVERLAPPED = extern struct { Internal: ULONG_PTR, InternalHigh: ULONG_PTR, @@ -3331,129 +5297,16 @@ pub const PIPE_READMODE_MESSAGE = 0x00000002; pub const PIPE_WAIT = 0x00000000; pub const PIPE_NOWAIT = 0x00000001; -pub const GENERIC_READ = 0x80000000; -pub const GENERIC_WRITE = 0x40000000; -pub const GENERIC_EXECUTE = 0x20000000; -pub const GENERIC_ALL = 0x10000000; - -pub const FILE_SHARE_DELETE = 0x00000004; -pub const FILE_SHARE_READ = 0x00000001; -pub const FILE_SHARE_WRITE = 0x00000002; - -pub const DELETE = 0x00010000; -pub const READ_CONTROL = 0x00020000; -pub const WRITE_DAC = 0x00040000; -pub const WRITE_OWNER = 0x00080000; -pub const SYNCHRONIZE = 0x00100000; -pub const STANDARD_RIGHTS_READ = READ_CONTROL; -pub const STANDARD_RIGHTS_WRITE = READ_CONTROL; -pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL; -pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER; -pub const MAXIMUM_ALLOWED = 0x02000000; - -// disposition for NtCreateFile -pub const FILE_SUPERSEDE = 0; -pub const FILE_OPEN = 1; -pub const FILE_CREATE = 2; -pub const FILE_OPEN_IF = 3; -pub const FILE_OVERWRITE = 4; -pub const FILE_OVERWRITE_IF = 5; -pub const FILE_MAXIMUM_DISPOSITION = 5; - -// flags for NtCreateFile and NtOpenFile -pub const FILE_READ_DATA = 0x00000001; -pub const FILE_LIST_DIRECTORY = 0x00000001; -pub const FILE_WRITE_DATA = 0x00000002; -pub const FILE_ADD_FILE = 0x00000002; -pub const FILE_APPEND_DATA = 0x00000004; -pub const FILE_ADD_SUBDIRECTORY = 0x00000004; -pub const FILE_CREATE_PIPE_INSTANCE = 0x00000004; -pub const FILE_READ_EA = 0x00000008; -pub const FILE_WRITE_EA = 0x00000010; -pub const FILE_EXECUTE = 0x00000020; -pub const FILE_TRAVERSE = 0x00000020; -pub const FILE_DELETE_CHILD = 0x00000040; -pub const FILE_READ_ATTRIBUTES = 0x00000080; -pub const FILE_WRITE_ATTRIBUTES = 0x00000100; - -pub const FILE_DIRECTORY_FILE = 0x00000001; -pub const FILE_WRITE_THROUGH = 0x00000002; -pub const FILE_SEQUENTIAL_ONLY = 0x00000004; -pub const FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008; -pub const FILE_SYNCHRONOUS_IO_ALERT = 0x00000010; -pub const FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020; -pub const FILE_NON_DIRECTORY_FILE = 0x00000040; -pub const FILE_CREATE_TREE_CONNECTION = 0x00000080; -pub const FILE_COMPLETE_IF_OPLOCKED = 0x00000100; -pub const FILE_NO_EA_KNOWLEDGE = 0x00000200; -pub const FILE_OPEN_FOR_RECOVERY = 0x00000400; -pub const FILE_RANDOM_ACCESS = 0x00000800; -pub const FILE_DELETE_ON_CLOSE = 0x00001000; -pub const FILE_OPEN_BY_FILE_ID = 0x00002000; -pub const FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000; -pub const FILE_NO_COMPRESSION = 0x00008000; -pub const FILE_RESERVE_OPFILTER = 0x00100000; -pub const FILE_OPEN_REPARSE_POINT = 0x00200000; -pub const FILE_OPEN_OFFLINE_FILE = 0x00400000; -pub const FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000; - pub const CREATE_ALWAYS = 2; pub const CREATE_NEW = 1; pub const OPEN_ALWAYS = 4; pub const OPEN_EXISTING = 3; pub const TRUNCATE_EXISTING = 5; -pub const FILE_ATTRIBUTE_ARCHIVE = 0x20; -pub const FILE_ATTRIBUTE_COMPRESSED = 0x800; -pub const FILE_ATTRIBUTE_DEVICE = 0x40; -pub const FILE_ATTRIBUTE_DIRECTORY = 0x10; -pub const FILE_ATTRIBUTE_ENCRYPTED = 0x4000; -pub const FILE_ATTRIBUTE_HIDDEN = 0x2; -pub const FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x8000; -pub const FILE_ATTRIBUTE_NORMAL = 0x80; -pub const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000; -pub const FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x20000; -pub const FILE_ATTRIBUTE_OFFLINE = 0x1000; -pub const FILE_ATTRIBUTE_READONLY = 0x1; -pub const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x400000; -pub const FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x40000; -pub const FILE_ATTRIBUTE_REPARSE_POINT = 0x400; -pub const FILE_ATTRIBUTE_SPARSE_FILE = 0x200; -pub const FILE_ATTRIBUTE_SYSTEM = 0x4; -pub const FILE_ATTRIBUTE_TEMPORARY = 0x100; -pub const FILE_ATTRIBUTE_VIRTUAL = 0x10000; - -pub const FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1ff; -pub const FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE; -pub const FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE; -pub const FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE; - -// Flags for NtCreateNamedPipeFile -// NamedPipeType -pub const FILE_PIPE_BYTE_STREAM_TYPE = 0x0; -pub const FILE_PIPE_MESSAGE_TYPE = 0x1; -pub const FILE_PIPE_ACCEPT_REMOTE_CLIENTS = 0x0; -pub const FILE_PIPE_REJECT_REMOTE_CLIENTS = 0x2; -pub const FILE_PIPE_TYPE_VALID_MASK = 0x3; -// CompletionMode -pub const FILE_PIPE_QUEUE_OPERATION = 0x0; -pub const FILE_PIPE_COMPLETE_OPERATION = 0x1; -// ReadMode -pub const FILE_PIPE_BYTE_STREAM_MODE = 0x0; -pub const FILE_PIPE_MESSAGE_MODE = 0x1; - // flags for CreateEvent pub const CREATE_EVENT_INITIAL_SET = 0x00000002; pub const CREATE_EVENT_MANUAL_RESET = 0x00000001; -pub const EVENT_ALL_ACCESS = 0x1F0003; -pub const EVENT_MODIFY_STATE = 0x0002; - -// MEMORY_BASIC_INFORMATION.Type flags for VirtualQuery -pub const MEM_IMAGE = 0x1000000; -pub const MEM_MAPPED = 0x40000; -pub const MEM_PRIVATE = 0x20000; - pub const PROCESS_INFORMATION = extern struct { hProcess: HANDLE, hThread: HANDLE, @@ -3521,45 +5374,6 @@ pub const FILE_BEGIN = 0; pub const FILE_CURRENT = 1; pub const FILE_END = 2; -pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000; -pub const HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010; -pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004; -pub const HEAP_NO_SERIALIZE = 0x00000001; - -// AllocationType values -pub const MEM_COMMIT = 0x1000; -pub const MEM_RESERVE = 0x2000; -pub const MEM_FREE = 0x10000; -pub const MEM_RESET = 0x80000; -pub const MEM_RESET_UNDO = 0x1000000; -pub const MEM_LARGE_PAGES = 0x20000000; -pub const MEM_PHYSICAL = 0x400000; -pub const MEM_TOP_DOWN = 0x100000; -pub const MEM_WRITE_WATCH = 0x200000; -pub const MEM_RESERVE_PLACEHOLDER = 0x00040000; -pub const MEM_PRESERVE_PLACEHOLDER = 0x00000400; - -// Protect values -pub const PAGE_EXECUTE = 0x10; -pub const PAGE_EXECUTE_READ = 0x20; -pub const PAGE_EXECUTE_READWRITE = 0x40; -pub const PAGE_EXECUTE_WRITECOPY = 0x80; -pub const PAGE_NOACCESS = 0x01; -pub const PAGE_READONLY = 0x02; -pub const PAGE_READWRITE = 0x04; -pub const PAGE_WRITECOPY = 0x08; -pub const PAGE_TARGETS_INVALID = 0x40000000; -pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID -pub const PAGE_GUARD = 0x100; -pub const PAGE_NOCACHE = 0x200; -pub const PAGE_WRITECOMBINE = 0x400; - -// FreeType values -pub const MEM_COALESCE_PLACEHOLDERS = 0x1; -pub const MEM_RESERVE_PLACEHOLDERS = 0x2; -pub const MEM_DECOMMIT = 0x4000; -pub const MEM_RELEASE = 0x8000; - pub const PTHREAD_START_ROUTINE = *const fn (LPVOID) callconv(.winapi) DWORD; pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE; @@ -3743,38 +5557,8 @@ pub const PIMAGE_TLS_CALLBACK = ?*const fn (PVOID, DWORD, PVOID) callconv(.winap pub const PROV_RSA_FULL = 1; pub const REGSAM = ACCESS_MASK; -pub const ACCESS_MASK = DWORD; pub const LSTATUS = LONG; -pub const SECTION_INHERIT = enum(c_int) { - ViewShare = 0, - ViewUnmap = 1, -}; - -pub const SECTION_QUERY = 0x0001; -pub const SECTION_MAP_WRITE = 0x0002; -pub const SECTION_MAP_READ = 0x0004; -pub const SECTION_MAP_EXECUTE = 0x0008; -pub const SECTION_EXTEND_SIZE = 0x0010; -pub const SECTION_ALL_ACCESS = - STANDARD_RIGHTS_REQUIRED | - SECTION_QUERY | - SECTION_MAP_WRITE | - SECTION_MAP_READ | - SECTION_MAP_EXECUTE | - SECTION_EXTEND_SIZE; - -pub const SEC_64K_PAGES = 0x80000; -pub const SEC_FILE = 0x800000; -pub const SEC_IMAGE = 0x1000000; -pub const SEC_PROTECTED_IMAGE = 0x2000000; -pub const SEC_RESERVE = 0x4000000; -pub const SEC_COMMIT = 0x8000000; -pub const SEC_IMAGE_NO_EXECUTE = SEC_IMAGE | SEC_NOCACHE; -pub const SEC_NOCACHE = 0x10000000; -pub const SEC_WRITECOMBINE = 0x40000000; -pub const SEC_LARGE_PAGES = 0x80000000; - pub const HKEY = *opaque {}; pub const HKEY_CLASSES_ROOT: HKEY = @ptrFromInt(0x80000000); @@ -3788,34 +5572,6 @@ pub const HKEY_CURRENT_CONFIG: HKEY = @ptrFromInt(0x80000005); pub const HKEY_DYN_DATA: HKEY = @ptrFromInt(0x80000006); pub const HKEY_CURRENT_USER_LOCAL_SETTINGS: HKEY = @ptrFromInt(0x80000007); -/// Combines the STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY, -/// KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK access rights. -pub const KEY_ALL_ACCESS = 0xF003F; -/// Reserved for system use. -pub const KEY_CREATE_LINK = 0x0020; -/// Required to create a subkey of a registry key. -pub const KEY_CREATE_SUB_KEY = 0x0004; -/// Required to enumerate the subkeys of a registry key. -pub const KEY_ENUMERATE_SUB_KEYS = 0x0008; -/// Equivalent to KEY_READ. -pub const KEY_EXECUTE = 0x20019; -/// Required to request change notifications for a registry key or for subkeys of a registry key. -pub const KEY_NOTIFY = 0x0010; -/// Required to query the values of a registry key. -pub const KEY_QUERY_VALUE = 0x0001; -/// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values. -pub const KEY_READ = 0x20019; -/// Required to create, delete, or set a registry value. -pub const KEY_SET_VALUE = 0x0002; -/// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. -/// This flag is ignored by 32-bit Windows. -pub const KEY_WOW64_32KEY = 0x0200; -/// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. -/// This flag is ignored by 32-bit Windows. -pub const KEY_WOW64_64KEY = 0x0100; -/// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights. -pub const KEY_WRITE = 0x20006; - /// Open symbolic link. pub const REG_OPTION_OPEN_LINK: DWORD = 0x8; @@ -4466,14 +6222,14 @@ pub const EXCEPTION_DISPOSITION = i32; pub const EXCEPTION_ROUTINE = *const fn ( ExceptionRecord: ?*EXCEPTION_RECORD, EstablisherFrame: PVOID, - ContextRecord: *(Self.CONTEXT), + ContextRecord: *CONTEXT, DispatcherContext: PVOID, ) callconv(.winapi) EXCEPTION_DISPOSITION; pub const UNWIND_HISTORY_TABLE_SIZE = 12; pub const UNWIND_HISTORY_TABLE_ENTRY = extern struct { ImageBase: ULONG64, - FunctionEntry: *Self.RUNTIME_FUNCTION, + FunctionEntry: *RUNTIME_FUNCTION, }; pub const UNWIND_HISTORY_TABLE = extern struct { @@ -4492,24 +6248,6 @@ pub const UNW_FLAG_EHANDLER = 0x1; pub const UNW_FLAG_UHANDLER = 0x2; pub const UNW_FLAG_CHAININFO = 0x4; -pub const OBJECT_ATTRIBUTES = extern struct { - Length: ULONG, - RootDirectory: ?HANDLE, - ObjectName: *UNICODE_STRING, - Attributes: ULONG, - SecurityDescriptor: ?*anyopaque, - SecurityQualityOfService: ?*anyopaque, -}; - -pub const OBJ_INHERIT = 0x00000002; -pub const OBJ_PERMANENT = 0x00000010; -pub const OBJ_EXCLUSIVE = 0x00000020; -pub const OBJ_CASE_INSENSITIVE = 0x00000040; -pub const OBJ_OPENIF = 0x00000080; -pub const OBJ_OPENLINK = 0x00000100; -pub const OBJ_KERNEL_HANDLE = 0x00000200; -pub const OBJ_VALID_ATTRIBUTES = 0x000003F2; - pub const UNICODE_STRING = extern struct { Length: c_ushort, MaximumLength: c_ushort, @@ -4617,7 +6355,7 @@ pub const PEB = extern struct { Ldr: *PEB_LDR_DATA, ProcessParameters: *RTL_USER_PROCESS_PARAMETERS, SubSystemData: PVOID, - ProcessHeap: HANDLE, + ProcessHeap: ?*HEAP, // Versions: 5.1+ FastPebLock: *RTL_CRITICAL_SECTION, @@ -4862,7 +6600,7 @@ pub const FILE_DIRECTORY_INFORMATION = extern struct { ChangeTime: LARGE_INTEGER, EndOfFile: LARGE_INTEGER, AllocationSize: LARGE_INTEGER, - FileAttributes: ULONG, + FileAttributes: FILE.ATTRIBUTE, FileNameLength: ULONG, FileName: [1]WCHAR, }; @@ -4876,7 +6614,7 @@ pub const FILE_BOTH_DIR_INFORMATION = extern struct { ChangeTime: LARGE_INTEGER, EndOfFile: LARGE_INTEGER, AllocationSize: LARGE_INTEGER, - FileAttributes: ULONG, + FileAttributes: FILE.ATTRIBUTE, FileNameLength: ULONG, EaSize: ULONG, ShortNameLength: CHAR, @@ -4905,7 +6643,7 @@ pub fn FileInformationIterator(comptime FileInformationType: type) type { }; } -pub const IO_APC_ROUTINE = *const fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void; +pub const IO_APC_ROUTINE = fn (?*anyopaque, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void; pub const CURDIR = extern struct { DosPath: UNICODE_STRING, @@ -4974,7 +6712,7 @@ pub const GetProcessMemoryInfoError = error{ pub fn GetProcessMemoryInfo(hProcess: HANDLE) GetProcessMemoryInfoError!VM_COUNTERS { var vmc: VM_COUNTERS = undefined; - const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null); + const rc = ntdll.NtQueryInformationProcess(hProcess, .VmCounters, &vmc, @sizeOf(VM_COUNTERS), null); switch (rc) { .SUCCESS => return vmc, .ACCESS_DENIED => return error.AccessDenied, @@ -5029,7 +6767,7 @@ pub const OSVERSIONINFOW = extern struct { pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW; pub const REPARSE_DATA_BUFFER = extern struct { - ReparseTag: ULONG, + ReparseTag: IO_REPARSE_TAG, ReparseDataLength: USHORT, Reserved: USHORT, DataBuffer: [1]UCHAR, @@ -5049,18 +6787,11 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct { PrintNameLength: USHORT, PathBuffer: [1]WCHAR, }; -pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024; -pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4; -pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; -pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c; -pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003; pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x1; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1; pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2; -pub const MOUNTMGRCONTROLTYPE = 0x0000006D; - pub const MOUNTMGR_MOUNT_POINT = extern struct { SymbolicLinkNameOffset: ULONG, SymbolicLinkNameLength: USHORT, @@ -5077,7 +6808,6 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct { NumberOfMountPoints: ULONG, MountPoints: [1]MOUNTMGR_MOUNT_POINT, }; -pub const IOCTL_MOUNTMGR_QUERY_POINTS = CTL_CODE(MOUNTMGRCONTROLTYPE, 2, .METHOD_BUFFERED, FILE_ANY_ACCESS); pub const MOUNTMGR_TARGET_NAME = extern struct { DeviceNameLength: USHORT, @@ -5087,7 +6817,6 @@ pub const MOUNTMGR_VOLUME_PATHS = extern struct { MultiSzLength: ULONG, MultiSz: [1]WCHAR, }; -pub const IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH = CTL_CODE(MOUNTMGRCONTROLTYPE, 12, .METHOD_BUFFERED, FILE_ANY_ACCESS); pub const OBJECT_INFORMATION_CLASS = enum(c_int) { ObjectBasicInformation = 0, @@ -5479,113 +7208,6 @@ pub const SYSTEM_BASIC_INFORMATION = extern struct { NumberOfProcessors: UCHAR, }; -pub const THREADINFOCLASS = enum(c_int) { - ThreadBasicInformation, - ThreadTimes, - ThreadPriority, - ThreadBasePriority, - ThreadAffinityMask, - ThreadImpersonationToken, - ThreadDescriptorTableEntry, - ThreadEnableAlignmentFaultFixup, - ThreadEventPair_Reusable, - ThreadQuerySetWin32StartAddress, - ThreadZeroTlsCell, - ThreadPerformanceCount, - ThreadAmILastThread, - ThreadIdealProcessor, - ThreadPriorityBoost, - ThreadSetTlsArrayAddress, - ThreadIsIoPending, - // Windows 2000+ from here - ThreadHideFromDebugger, - // Windows XP+ from here - ThreadBreakOnTermination, - ThreadSwitchLegacyState, - ThreadIsTerminated, - // Windows Vista+ from here - ThreadLastSystemCall, - ThreadIoPriority, - ThreadCycleTime, - ThreadPagePriority, - ThreadActualBasePriority, - ThreadTebInformation, - ThreadCSwitchMon, - // Windows 7+ from here - ThreadCSwitchPmu, - ThreadWow64Context, - ThreadGroupInformation, - ThreadUmsInformation, - ThreadCounterProfiling, - ThreadIdealProcessorEx, - // Windows 8+ from here - ThreadCpuAccountingInformation, - // Windows 8.1+ from here - ThreadSuspendCount, - // Windows 10+ from here - ThreadHeterogeneousCpuPolicy, - ThreadContainerId, - ThreadNameInformation, - ThreadSelectedCpuSets, - ThreadSystemThreadInformation, - ThreadActualGroupAffinity, -}; - -pub const PROCESSINFOCLASS = enum(c_int) { - ProcessBasicInformation, - ProcessQuotaLimits, - ProcessIoCounters, - ProcessVmCounters, - ProcessTimes, - ProcessBasePriority, - ProcessRaisePriority, - ProcessDebugPort, - ProcessExceptionPort, - ProcessAccessToken, - ProcessLdtInformation, - ProcessLdtSize, - ProcessDefaultHardErrorMode, - ProcessIoPortHandlers, - ProcessPooledUsageAndLimits, - ProcessWorkingSetWatch, - ProcessUserModeIOPL, - ProcessEnableAlignmentFaultFixup, - ProcessPriorityClass, - ProcessWx86Information, - ProcessHandleCount, - ProcessAffinityMask, - ProcessPriorityBoost, - ProcessDeviceMap, - ProcessSessionInformation, - ProcessForegroundInformation, - ProcessWow64Information, - ProcessImageFileName, - ProcessLUIDDeviceMapsEnabled, - ProcessBreakOnTermination, - ProcessDebugObjectHandle, - ProcessDebugFlags, - ProcessHandleTracing, - ProcessIoPriority, - ProcessExecuteFlags, - ProcessTlsInformation, - ProcessCookie, - ProcessImageInformation, - ProcessCycleTime, - ProcessPagePriority, - ProcessInstrumentationCallback, - ProcessThreadStackAllocation, - ProcessWorkingSetWatchEx, - ProcessImageFileNameWin32, - ProcessImageFileMapping, - ProcessAffinityUpdateMode, - ProcessMemoryAllocationMode, - ProcessGroupInformation, - ProcessTokenVirtualizationEnabled, - ProcessConsoleHostProcess, - ProcessWindowInformation, - MaxProcessInfoClass, -}; - pub const PROCESS_BASIC_INFORMATION = extern struct { ExitStatus: NTSTATUS, PebBaseAddress: *PEB, @@ -5641,7 +7263,7 @@ pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE { var nread: DWORD = 0; const rc = ntdll.NtQueryInformationProcess( handle, - .ProcessBasicInformation, + .BasicInformation, &info, @sizeOf(PROCESS_BASIC_INFORMATION), &nread, diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig @@ -1,6 +1,7 @@ const std = @import("../../std.zig"); const windows = std.os.windows; +const ACCESS_MASK = windows.ACCESS_MASK; const BOOL = windows.BOOL; const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO; @@ -66,7 +67,7 @@ pub extern "kernel32" fn CancelIoEx( pub extern "kernel32" fn CreateFileW( lpFileName: LPCWSTR, - dwDesiredAccess: DWORD, + dwDesiredAccess: ACCESS_MASK, dwShareMode: DWORD, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, @@ -160,7 +161,7 @@ pub extern "kernel32" fn DuplicateHandle( hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, - dwDesiredAccess: DWORD, + dwDesiredAccess: ACCESS_MASK, bInheritHandle: BOOL, dwOptions: DWORD, ) callconv(.winapi) BOOL; @@ -308,9 +309,6 @@ pub extern "kernel32" fn CreateThread( lpThreadId: ?*DWORD, ) callconv(.winapi) ?HANDLE; -// TODO: Wrapper around RtlDelayExecution. -pub extern "kernel32" fn SwitchToThread() callconv(.winapi) BOOL; - // Locks, critical sections, initializers pub extern "kernel32" fn InitOnceExecuteOnce( @@ -401,34 +399,6 @@ pub extern "kernel32" fn ReadConsoleOutputCharacterW( lpNumberOfCharsRead: *DWORD, ) callconv(.winapi) BOOL; -// Memory Mapping/Allocation - -// TODO: Wrapper around RtlCreateHeap. -pub extern "kernel32" fn HeapCreate( - flOptions: DWORD, - dwInitialSize: SIZE_T, - dwMaximumSize: SIZE_T, -) callconv(.winapi) ?HANDLE; - -// TODO: Fowrarder to RtlFreeHeap before win11_zn. -// Since win11_zn this function points to unexported symbol RtlFreeHeapFast. -// See https://github.com/ziglang/zig/pull/25766#discussion_r2479727640 -pub extern "kernel32" fn HeapFree( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: LPVOID, -) callconv(.winapi) BOOL; - -// TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL) -pub extern "kernel32" fn HeapValidate( - hHeap: HANDLE, - dwFlags: DWORD, - lpMem: ?*const anyopaque, -) callconv(.winapi) BOOL; - -// TODO: Getter for peb.ProcessHeap -pub extern "kernel32" fn GetProcessHeap() callconv(.winapi) ?HANDLE; - // Code Libraries/Modules // TODO: Wrapper around LdrGetDllFullName. diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig @@ -1,277 +1,279 @@ const std = @import("../../std.zig"); const windows = std.os.windows; +const ACCESS_MASK = windows.ACCESS_MASK; const BOOL = windows.BOOL; +const BOOLEAN = windows.BOOLEAN; +const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; +const CONTEXT = windows.CONTEXT; +const CRITICAL_SECTION = windows.CRITICAL_SECTION; +const CTL_CODE = windows.CTL_CODE; +const CURDIR = windows.CURDIR; const DWORD = windows.DWORD; const DWORD64 = windows.DWORD64; -const ULONG = windows.ULONG; -const ULONG_PTR = windows.ULONG_PTR; -const NTSTATUS = windows.NTSTATUS; -const WORD = windows.WORD; +const ERESOURCE = windows.ERESOURCE; +const EVENT_TYPE = windows.EVENT_TYPE; +const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; +const FILE = windows.FILE; +const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS; const HANDLE = windows.HANDLE; -const ACCESS_MASK = windows.ACCESS_MASK; +const HEAP = windows.HEAP; const IO_APC_ROUTINE = windows.IO_APC_ROUTINE; -const BOOLEAN = windows.BOOLEAN; -const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; -const PVOID = windows.PVOID; const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK; +const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; const LARGE_INTEGER = windows.LARGE_INTEGER; +const LOGICAL = windows.LOGICAL; +const LONG = windows.LONG; +const LPCVOID = windows.LPCVOID; +const LPVOID = windows.LPVOID; +const MEM = windows.MEM; +const NTSTATUS = windows.NTSTATUS; +const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES; const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS; -const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS; -const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS; -const UNICODE_STRING = windows.UNICODE_STRING; -const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; -const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION; -const SIZE_T = windows.SIZE_T; -const CURDIR = windows.CURDIR; +const PAGE = windows.PAGE; const PCWSTR = windows.PCWSTR; +const PROCESSINFOCLASS = windows.PROCESSINFOCLASS; +const PVOID = windows.PVOID; +const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW; const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE; -const CONTEXT = windows.CONTEXT; -const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION; -const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS; -const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE; +const SEC = windows.SEC; +const SECTION_INHERIT = windows.SECTION_INHERIT; +const SIZE_T = windows.SIZE_T; +const SRWLOCK = windows.SRWLOCK; const SYSTEM_INFORMATION_CLASS = windows.SYSTEM_INFORMATION_CLASS; const THREADINFOCLASS = windows.THREADINFOCLASS; -const PROCESSINFOCLASS = windows.PROCESSINFOCLASS; -const LPVOID = windows.LPVOID; -const LPCVOID = windows.LPCVOID; -const SECTION_INHERIT = windows.SECTION_INHERIT; +const ULONG = windows.ULONG; +const ULONG_PTR = windows.ULONG_PTR; +const UNICODE_STRING = windows.UNICODE_STRING; +const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE; +const USHORT = windows.USHORT; const VECTORED_EXCEPTION_HANDLER = windows.VECTORED_EXCEPTION_HANDLER; -const CRITICAL_SECTION = windows.CRITICAL_SECTION; -const SRWLOCK = windows.SRWLOCK; -const CONDITION_VARIABLE = windows.CONDITION_VARIABLE; +const WORD = windows.WORD; -pub extern "ntdll" fn NtQueryInformationProcess( - ProcessHandle: HANDLE, - ProcessInformationClass: PROCESSINFOCLASS, - ProcessInformation: *anyopaque, - ProcessInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +// ref: km/ntifs.h -pub extern "ntdll" fn NtQueryInformationThread( - ThreadHandle: HANDLE, - ThreadInformationClass: THREADINFOCLASS, - ThreadInformation: *anyopaque, - ThreadInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlCreateHeap( + Flags: HEAP.FLAGS.CREATE, + HeapBase: ?PVOID, + ReserveSize: SIZE_T, + CommitSize: SIZE_T, + Lock: ?*ERESOURCE, + Parameters: ?*const HEAP.RTL_PARAMETERS, +) callconv(.winapi) ?*HEAP; -pub extern "ntdll" fn NtQuerySystemInformation( - SystemInformationClass: SYSTEM_INFORMATION_CLASS, - SystemInformation: PVOID, - SystemInformationLength: ULONG, - ReturnLength: ?*ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlDestroyHeap( + HeapHandle: *HEAP, +) callconv(.winapi) ?*HEAP; -pub extern "ntdll" fn NtSetInformationThread( - ThreadHandle: HANDLE, - ThreadInformationClass: THREADINFOCLASS, - ThreadInformation: *const anyopaque, - ThreadInformationLength: ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlAllocateHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; + +pub extern "ntdll" fn RtlFreeHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + BaseAddress: ?PVOID, +) callconv(.winapi) LOGICAL; -pub extern "ntdll" fn RtlGetVersion( - lpVersionInformation: *RTL_OSVERSIONINFOW, -) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlCaptureStackBackTrace( - FramesToSkip: DWORD, - FramesToCapture: DWORD, + FramesToSkip: ULONG, + FramesToCapture: ULONG, BackTrace: **anyopaque, - BackTraceHash: ?*DWORD, -) callconv(.winapi) WORD; -pub extern "ntdll" fn RtlCaptureContext(ContextRecord: *CONTEXT) callconv(.winapi) void; -pub extern "ntdll" fn RtlLookupFunctionEntry( - ControlPc: DWORD64, - ImageBase: *DWORD64, - HistoryTable: *UNWIND_HISTORY_TABLE, -) callconv(.winapi) ?*RUNTIME_FUNCTION; -pub extern "ntdll" fn RtlVirtualUnwind( - HandlerType: DWORD, - ImageBase: DWORD64, - ControlPc: DWORD64, - FunctionEntry: *RUNTIME_FUNCTION, - ContextRecord: *CONTEXT, - HandlerData: *?PVOID, - EstablisherFrame: *DWORD64, - ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, -) callconv(.winapi) *EXCEPTION_ROUTINE; -pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER; -pub extern "ntdll" fn NtQueryInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FileInformation: *anyopaque, - Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtSetInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FileInformation: PVOID, - Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, -) callconv(.winapi) NTSTATUS; + BackTraceHash: ?*ULONG, +) callconv(.winapi) USHORT; -pub extern "ntdll" fn NtQueryAttributesFile( - ObjectAttributes: *OBJECT_ATTRIBUTES, - FileAttributes: *FILE_BASIC_INFORMATION, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlCaptureContext( + ContextRecord: *CONTEXT, +) callconv(.winapi) void; -pub extern "ntdll" fn RtlQueryPerformanceCounter(PerformanceCounter: *LARGE_INTEGER) callconv(.winapi) BOOL; -pub extern "ntdll" fn RtlQueryPerformanceFrequency(PerformanceFrequency: *LARGE_INTEGER) callconv(.winapi) BOOL; -pub extern "ntdll" fn NtQueryPerformanceCounter( - PerformanceCounter: *LARGE_INTEGER, - PerformanceFrequency: ?*LARGE_INTEGER, +pub extern "ntdll" fn NtSetInformationThread( + ThreadHandle: HANDLE, + ThreadInformationClass: THREADINFOCLASS, + ThreadInformation: *const anyopaque, + ThreadInformationLength: ULONG, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtCreateFile( FileHandle: *HANDLE, DesiredAccess: ACCESS_MASK, - ObjectAttributes: *OBJECT_ATTRIBUTES, + ObjectAttributes: *const OBJECT_ATTRIBUTES, IoStatusBlock: *IO_STATUS_BLOCK, - AllocationSize: ?*LARGE_INTEGER, - FileAttributes: ULONG, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, + AllocationSize: ?*const LARGE_INTEGER, + FileAttributes: FILE.ATTRIBUTE, + ShareAccess: FILE.SHARE, + CreateDisposition: FILE.CREATE_DISPOSITION, + CreateOptions: FILE.MODE, EaBuffer: ?*anyopaque, EaLength: ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtCreateSection( - SectionHandle: *HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: ?*OBJECT_ATTRIBUTES, - MaximumSize: ?*LARGE_INTEGER, - SectionPageProtection: ULONG, - AllocationAttributes: ULONG, - FileHandle: ?HANDLE, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtMapViewOfSection( - SectionHandle: HANDLE, - ProcessHandle: HANDLE, - BaseAddress: *PVOID, - ZeroBits: ?*ULONG, - CommitSize: SIZE_T, - SectionOffset: ?*LARGE_INTEGER, - ViewSize: *SIZE_T, - InheritDispostion: SECTION_INHERIT, - AllocationType: ULONG, - Win32Protect: ULONG, -) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtUnmapViewOfSection( - ProcessHandle: HANDLE, - BaseAddress: PVOID, -) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn NtDeviceIoControlFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, - IoControlCode: ULONG, + IoControlCode: CTL_CODE, InputBuffer: ?*const anyopaque, InputBufferLength: ULONG, OutputBuffer: ?PVOID, OutputBufferLength: ULONG, ) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn NtFsControlFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, - FsControlCode: ULONG, + FsControlCode: CTL_CODE, InputBuffer: ?*const anyopaque, InputBufferLength: ULONG, OutputBuffer: ?PVOID, OutputBufferLength: ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtClose(Handle: HANDLE) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlDosPathNameToNtPathName_U( - DosPathName: [*:0]const u16, - NtPathName: *UNICODE_STRING, - NtFileNamePart: ?*?[*:0]const u16, - DirectoryInfo: ?*CURDIR, -) callconv(.winapi) BOOL; -pub extern "ntdll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(.winapi) void; -/// Returns the number of bytes written to `Buffer`. -/// If the returned count is larger than `BufferByteLength`, the buffer was too small. -/// If the returned count is zero, an error occurred. -pub extern "ntdll" fn RtlGetFullPathName_U( - FileName: [*:0]const u16, - BufferByteLength: ULONG, - Buffer: [*]u16, - ShortName: ?*[*:0]const u16, -) callconv(.winapi) windows.ULONG; +pub extern "ntdll" fn NtLockFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + ByteOffset: *const LARGE_INTEGER, + Length: *const LARGE_INTEGER, + Key: ?*const ULONG, + FailImmediately: BOOLEAN, + ExclusiveLock: BOOLEAN, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtOpenFile( + FileHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, + IoStatusBlock: *IO_STATUS_BLOCK, + ShareAccess: FILE.SHARE, + OpenOptions: FILE.MODE, +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtQueryDirectoryFile( FileHandle: HANDLE, Event: ?HANDLE, - ApcRoutine: ?IO_APC_ROUTINE, + ApcRoutine: ?*const IO_APC_ROUTINE, ApcContext: ?*anyopaque, IoStatusBlock: *IO_STATUS_BLOCK, FileInformation: *anyopaque, Length: ULONG, - FileInformationClass: FILE_INFORMATION_CLASS, + FileInformationClass: FILE.INFORMATION_CLASS, ReturnSingleEntry: BOOLEAN, - FileName: ?*UNICODE_STRING, + FileName: ?*const UNICODE_STRING, RestartScan: BOOLEAN, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtCreateKeyedEvent( - KeyedEventHandle: *HANDLE, - DesiredAccess: ACCESS_MASK, - ObjectAttributes: ?PVOID, - Flags: ULONG, +pub extern "ntdll" fn NtQueryInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FileInformation: *anyopaque, + Length: ULONG, + FileInformationClass: FILE.INFORMATION_CLASS, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtReleaseKeyedEvent( - EventHandle: ?HANDLE, - Key: ?*const anyopaque, - Alertable: BOOLEAN, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtQueryVolumeInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FsInformation: *anyopaque, + Length: ULONG, + FsInformationClass: FS_INFORMATION_CLASS, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtWaitForKeyedEvent( - EventHandle: ?HANDLE, - Key: ?*const anyopaque, - Alertable: BOOLEAN, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtReadFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + Buffer: *anyopaque, + Length: ULONG, + ByteOffset: ?*const LARGE_INTEGER, + Key: ?*const ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtSetInformationFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + FileInformation: *const anyopaque, + Length: ULONG, + FileInformationClass: FILE.INFORMATION_CLASS, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtWriteFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*const IO_APC_ROUTINE, + ApcContext: ?*anyopaque, + IoStatusBlock: *IO_STATUS_BLOCK, + Buffer: *const anyopaque, + Length: ULONG, + ByteOffset: ?*const LARGE_INTEGER, + Key: ?*const ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnlockFile( + FileHandle: HANDLE, + IoStatusBlock: *IO_STATUS_BLOCK, + ByteOffset: *const LARGE_INTEGER, + Length: *const LARGE_INTEGER, + Key: ULONG, +) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtQueryObject( Handle: HANDLE, ObjectInformationClass: OBJECT_INFORMATION_CLASS, - ObjectInformation: PVOID, + ObjectInformation: ?PVOID, ObjectInformationLength: ULONG, ReturnLength: ?*ULONG, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtQueryVolumeInformationFile( - FileHandle: HANDLE, - IoStatusBlock: *IO_STATUS_BLOCK, - FsInformation: *anyopaque, - Length: ULONG, - FsInformationClass: FS_INFORMATION_CLASS, +pub extern "ntdll" fn NtClose( + Handle: HANDLE, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWakeAddressAll( - Address: ?*const anyopaque, -) callconv(.winapi) void; +pub extern "ntdll" fn NtCreateSection( + SectionHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + MaximumSize: ?*const LARGE_INTEGER, + SectionPageProtection: PAGE, + AllocationAttributes: SEC, + FileHandle: ?HANDLE, +) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWakeAddressSingle( - Address: ?*const anyopaque, -) callconv(.winapi) void; +pub extern "ntdll" fn NtAllocateVirtualMemory( + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + ZeroBits: ULONG_PTR, + RegionSize: *SIZE_T, + AllocationType: MEM.ALLOCATE, + Protect: PAGE, +) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlWaitOnAddress( - Address: ?*const anyopaque, - CompareAddress: ?*const anyopaque, - AddressSize: SIZE_T, - Timeout: ?*const LARGE_INTEGER, +pub extern "ntdll" fn NtFreeVirtualMemory( + ProcessHandle: HANDLE, + BaseAddress: *PVOID, + RegionSize: *SIZE_T, + FreeType: MEM.FREE, +) callconv(.winapi) NTSTATUS; + +// ref: km/wdm.h + +pub extern "ntdll" fn RtlQueryRegistryValues( + RelativeTo: ULONG, + Path: PCWSTR, + QueryTable: [*]RTL_QUERY_REGISTRY_TABLE, + Context: ?*const anyopaque, + Environment: ?*const anyopaque, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlEqualUnicodeString( @@ -284,39 +286,153 @@ pub extern "ntdll" fn RtlUpcaseUnicodeChar( SourceCharacter: u16, ) callconv(.winapi) u16; -pub extern "ntdll" fn NtLockFile( - FileHandle: HANDLE, - Event: ?HANDLE, - ApcRoutine: ?*IO_APC_ROUTINE, - ApcContext: ?*anyopaque, - IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, - FailImmediately: BOOLEAN, - ExclusiveLock: BOOLEAN, +pub extern "ntdll" fn RtlFreeUnicodeString( + UnicodeString: *UNICODE_STRING, +) callconv(.winapi) void; + +pub extern "ntdll" fn RtlGetVersion( + lpVersionInformation: *RTL_OSVERSIONINFOW, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn NtUnlockFile( - FileHandle: HANDLE, +// ref: um/winnt.h + +pub extern "ntdll" fn RtlLookupFunctionEntry( + ControlPc: usize, + ImageBase: *usize, + HistoryTable: *UNWIND_HISTORY_TABLE, +) callconv(.winapi) ?*RUNTIME_FUNCTION; + +pub extern "ntdll" fn RtlVirtualUnwind( + HandlerType: DWORD, + ImageBase: usize, + ControlPc: usize, + FunctionEntry: *RUNTIME_FUNCTION, + ContextRecord: *CONTEXT, + HandlerData: *?PVOID, + EstablisherFrame: *usize, + ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS, +) callconv(.winapi) *EXCEPTION_ROUTINE; + +// ref: um/winternl.h + +pub extern "ntdll" fn NtWaitForSingleObject( + Handle: HANDLE, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQueryInformationProcess( + ProcessHandle: HANDLE, + ProcessInformationClass: PROCESSINFOCLASS, + ProcessInformation: *anyopaque, + ProcessInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQueryInformationThread( + ThreadHandle: HANDLE, + ThreadInformationClass: THREADINFOCLASS, + ThreadInformation: *anyopaque, + ThreadInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtQuerySystemInformation( + SystemInformationClass: SYSTEM_INFORMATION_CLASS, + SystemInformation: PVOID, + SystemInformationLength: ULONG, + ReturnLength: ?*ULONG, +) callconv(.winapi) NTSTATUS; + +// ref none + +pub extern "ntdll" fn NtQueryAttributesFile( + ObjectAttributes: *const OBJECT_ATTRIBUTES, + FileAttributes: *FILE.BASIC_INFORMATION, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateEvent( + EventHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + EventType: EVENT_TYPE, + InitialState: BOOLEAN, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtSetEvent( + EventHandle: HANDLE, + PreviousState: ?*LONG, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateKeyedEvent( + KeyedEventHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?*const OBJECT_ATTRIBUTES, + Flags: ULONG, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtReleaseKeyedEvent( + EventHandle: ?HANDLE, + Key: ?*const anyopaque, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtWaitForKeyedEvent( + EventHandle: ?HANDLE, + Key: ?*const anyopaque, + Alertable: BOOLEAN, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtCreateNamedPipeFile( + FileHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: *const OBJECT_ATTRIBUTES, IoStatusBlock: *IO_STATUS_BLOCK, - ByteOffset: *const LARGE_INTEGER, - Length: *const LARGE_INTEGER, - Key: ?*ULONG, + ShareAccess: FILE.SHARE, + CreateDisposition: FILE.CREATE_DISPOSITION, + CreateOptions: FILE.MODE, + NamedPipeType: FILE.PIPE.TYPE, + ReadMode: FILE.PIPE.READ_MODE, + CompletionMode: FILE.PIPE.COMPLETION_MODE, + MaximumInstances: ULONG, + InboundQuota: ULONG, + OutboundQuota: ULONG, + DefaultTimeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn NtMapViewOfSection( + SectionHandle: HANDLE, + ProcessHandle: HANDLE, + BaseAddress: ?*PVOID, + ZeroBits: ?*const ULONG, + CommitSize: SIZE_T, + SectionOffset: ?*LARGE_INTEGER, + ViewSize: *SIZE_T, + InheritDispostion: SECTION_INHERIT, + AllocationType: MEM.MAP, + PageProtection: PAGE, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnmapViewOfSection( + ProcessHandle: HANDLE, + BaseAddress: PVOID, +) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtUnmapViewOfSectionEx( + ProcessHandle: HANDLE, + BaseAddress: PVOID, + UnmapFlags: MEM.UNMAP, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtOpenKey( KeyHandle: *HANDLE, DesiredAccess: ACCESS_MASK, - ObjectAttributes: OBJECT_ATTRIBUTES, + ObjectAttributes: *const OBJECT_ATTRIBUTES, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlQueryRegistryValues( - RelativeTo: ULONG, - Path: PCWSTR, - QueryTable: [*]RTL_QUERY_REGISTRY_TABLE, - Context: ?*anyopaque, - Environment: ?*anyopaque, +pub extern "ntdll" fn NtQueueApcThread( + ThreadHandle: HANDLE, + ApcRoutine: *const IO_APC_ROUTINE, + ApcArgument1: ?*anyopaque, + ApcArgument2: ?*anyopaque, + ApcArgument3: ?*anyopaque, ) callconv(.winapi) NTSTATUS; pub extern "ntdll" fn NtReadVirtualMemory( @@ -326,7 +442,6 @@ pub extern "ntdll" fn NtReadVirtualMemory( NumberOfBytesToRead: SIZE_T, NumberOfBytesRead: ?*SIZE_T, ) callconv(.winapi) NTSTATUS; - pub extern "ntdll" fn NtWriteVirtualMemory( ProcessHandle: HANDLE, BaseAddress: ?PVOID, @@ -334,51 +449,15 @@ pub extern "ntdll" fn NtWriteVirtualMemory( NumberOfBytesToWrite: SIZE_T, NumberOfBytesWritten: ?*SIZE_T, ) callconv(.winapi) NTSTATUS; - pub extern "ntdll" fn NtProtectVirtualMemory( ProcessHandle: HANDLE, BaseAddress: *?PVOID, NumberOfBytesToProtect: *SIZE_T, - NewAccessProtection: ULONG, - OldAccessProtection: *ULONG, + NewAccessProtection: PAGE, + OldAccessProtection: *PAGE, ) callconv(.winapi) NTSTATUS; -pub extern "ntdll" fn RtlExitUserProcess( - ExitStatus: u32, -) callconv(.winapi) noreturn; - -pub extern "ntdll" fn NtCreateNamedPipeFile( - FileHandle: *HANDLE, - DesiredAccess: ULONG, - ObjectAttributes: *OBJECT_ATTRIBUTES, - IoStatusBlock: *IO_STATUS_BLOCK, - ShareAccess: ULONG, - CreateDisposition: ULONG, - CreateOptions: ULONG, - NamedPipeType: ULONG, - ReadMode: ULONG, - CompletionMode: ULONG, - MaximumInstances: ULONG, - InboundQuota: ULONG, - OutboundQuota: ULONG, - DefaultTimeout: *LARGE_INTEGER, -) callconv(.winapi) NTSTATUS; - -pub extern "ntdll" fn NtAllocateVirtualMemory( - ProcessHandle: HANDLE, - BaseAddress: ?*PVOID, - ZeroBits: ULONG_PTR, - RegionSize: ?*SIZE_T, - AllocationType: ULONG, - PageProtection: ULONG, -) callconv(.winapi) NTSTATUS; - -pub extern "ntdll" fn NtFreeVirtualMemory( - ProcessHandle: HANDLE, - BaseAddress: ?*PVOID, - RegionSize: *SIZE_T, - FreeType: ULONG, -) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn NtYieldExecution() callconv(.winapi) NTSTATUS; pub extern "ntdll" fn RtlAddVectoredExceptionHandler( First: ULONG, @@ -388,6 +467,29 @@ pub extern "ntdll" fn RtlRemoveVectoredExceptionHandler( Handle: HANDLE, ) callconv(.winapi) ULONG; +pub extern "ntdll" fn RtlDosPathNameToNtPathName_U( + DosPathName: [*:0]const u16, + NtPathName: *UNICODE_STRING, + NtFileNamePart: ?*?[*:0]const u16, + DirectoryInfo: ?*CURDIR, +) callconv(.winapi) BOOL; + +pub extern "ntdll" fn RtlExitUserProcess( + ExitStatus: u32, +) callconv(.winapi) noreturn; + +/// Returns the number of bytes written to `Buffer`. +/// If the returned count is larger than `BufferByteLength`, the buffer was too small. +/// If the returned count is zero, an error occurred. +pub extern "ntdll" fn RtlGetFullPathName_U( + FileName: [*:0]const u16, + BufferByteLength: ULONG, + Buffer: [*]u16, + ShortName: ?*[*:0]const u16, +) callconv(.winapi) ULONG; + +pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER; + pub extern "ntdll" fn RtlInitializeCriticalSection( lpCriticalSection: *CRITICAL_SECTION, ) callconv(.winapi) NTSTATUS; @@ -401,6 +503,28 @@ pub extern "ntdll" fn RtlDeleteCriticalSection( lpCriticalSection: *CRITICAL_SECTION, ) callconv(.winapi) NTSTATUS; +pub extern "ntdll" fn RtlQueryPerformanceCounter( + PerformanceCounter: *LARGE_INTEGER, +) callconv(.winapi) BOOL; +pub extern "ntdll" fn RtlQueryPerformanceFrequency( + PerformanceFrequency: *LARGE_INTEGER, +) callconv(.winapi) BOOL; +pub extern "ntdll" fn NtQueryPerformanceCounter( + PerformanceCounter: *LARGE_INTEGER, + PerformanceFrequency: ?*LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + +pub extern "ntdll" fn RtlReAllocateHeap( + HeapHandle: *HEAP, + Flags: HEAP.FLAGS.ALLOCATION, + BaseAddress: ?PVOID, + Size: SIZE_T, +) callconv(.winapi) ?PVOID; + +pub extern "ntdll" fn RtlSetCurrentDirectory_U( + PathName: *UNICODE_STRING, +) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn RtlTryAcquireSRWLockExclusive( SRWLock: *SRWLOCK, ) callconv(.winapi) BOOLEAN; @@ -411,21 +535,22 @@ pub extern "ntdll" fn RtlReleaseSRWLockExclusive( SRWLock: *SRWLOCK, ) callconv(.winapi) void; +pub extern "ntdll" fn RtlWakeAddressAll( + Address: ?*const anyopaque, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlWakeAddressSingle( + Address: ?*const anyopaque, +) callconv(.winapi) void; +pub extern "ntdll" fn RtlWaitOnAddress( + Address: ?*const anyopaque, + CompareAddress: ?*const anyopaque, + AddressSize: SIZE_T, + Timeout: ?*const LARGE_INTEGER, +) callconv(.winapi) NTSTATUS; + pub extern "ntdll" fn RtlWakeConditionVariable( ConditionVariable: *CONDITION_VARIABLE, ) callconv(.winapi) void; pub extern "ntdll" fn RtlWakeAllConditionVariable( ConditionVariable: *CONDITION_VARIABLE, ) callconv(.winapi) void; - -pub extern "ntdll" fn RtlReAllocateHeap( - HeapHandle: HANDLE, - Flags: ULONG, - BaseAddress: PVOID, - Size: SIZE_T, -) callconv(.winapi) ?PVOID; -pub extern "ntdll" fn RtlAllocateHeap( - HeapHandle: HANDLE, - Flags: ULONG, - Size: SIZE_T, -) callconv(.winapi) ?PVOID; diff --git a/lib/std/posix.zig b/lib/std/posix.zig @@ -1041,18 +1041,16 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void { if (native_os == .windows) { var io_status_block: windows.IO_STATUS_BLOCK = undefined; - var eof_info = windows.FILE_END_OF_FILE_INFORMATION{ + const eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{ .EndOfFile = signed_len, }; - const rc = windows.ntdll.NtSetInformationFile( fd, &io_status_block, &eof_info, - @sizeOf(windows.FILE_END_OF_FILE_INFORMATION), - .FileEndOfFileInformation, + @sizeOf(windows.FILE.END_OF_FILE_INFORMATION), + .EndOfFile, ); - switch (rc) { .SUCCESS => return, .INVALID_HANDLE => unreachable, // Handle not open for writing @@ -2691,8 +2689,11 @@ pub fn mkdirW(dir_path_w: []const u16, mode: mode_t) MakeDirError!void { _ = mode; const sub_dir_handle = windows.OpenFile(dir_path_w, .{ .dir = fs.cwd().fd, - .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE, - .creation = windows.FILE_CREATE, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .READ = true }, + }, + .creation = .CREATE, .filter = .dir_only, }) catch |err| switch (err) { error.IsDir => return error.Unexpected, diff --git a/lib/std/process/Child.zig b/lib/std/process/Child.zig @@ -762,10 +762,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void { const nul_handle = if (any_ignore) // "\Device\Null" or "\??\NUL" windows.OpenFile(&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }, .{ - .access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE | windows.SYNCHRONIZE, - .share_access = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE, + .access_mask = .{ + .STANDARD = .{ .SYNCHRONIZE = true }, + .GENERIC = .{ .WRITE = true, .READ = true }, + }, .sa = &saAttr, - .creation = windows.OPEN_EXISTING, + .creation = .OPEN, }) catch |err| switch (err) { error.PathAlreadyExists => return error.Unexpected, // not possible for "NUL" error.PipeBusy => return error.Unexpected, // not possible for "NUL" @@ -1174,7 +1176,7 @@ fn windowsCreateProcessPathExt( &io_status, &file_information_buf, file_information_buf.len, - .FileDirectoryInformation, + .Directory, windows.FALSE, // single result &app_name_unicode_string, windows.FALSE, // restart iteration @@ -1198,7 +1200,7 @@ fn windowsCreateProcessPathExt( var it = windows.FileInformationIterator(windows.FILE_DIRECTORY_INFORMATION){ .buf = &file_information_buf }; while (it.next()) |info| { // Skip directories - if (info.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) continue; + if (info.FileAttributes.DIRECTORY) continue; const filename = @as([*]u16, @ptrCast(&info.FileName))[0 .. info.FileNameLength / 2]; // Because all results start with the app_name since we're using the wildcard `app_name*`, // if the length is equal to app_name then this is an exact match @@ -1415,11 +1417,11 @@ fn windowsMakeAsyncPipe(rd: *?windows.HANDLE, wr: *?windows.HANDLE, sattr: *cons var sattr_copy = sattr.*; const write_handle = windows.kernel32.CreateFileW( pipe_path.ptr, - windows.GENERIC_WRITE, + .{ .GENERIC = .{ .WRITE = true } }, 0, &sattr_copy, windows.OPEN_EXISTING, - windows.FILE_ATTRIBUTE_NORMAL, + @bitCast(windows.FILE.ATTRIBUTE{ .NORMAL = true }), null, ); if (write_handle == windows.INVALID_HANDLE_VALUE) { diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig @@ -250,13 +250,15 @@ const RegistryWtf16Le = struct { /// After finishing work, call `closeKey`. fn openKey(hkey: windows.HKEY, key_wtf16le: [:0]const u16, options: OpenOptions) error{KeyNotFound}!RegistryWtf16Le { var key: windows.HKEY = undefined; - var access: windows.REGSAM = windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS; - if (options.wow64_32) access |= windows.KEY_WOW64_32KEY; const return_code_int: windows.HRESULT = windows.advapi32.RegOpenKeyExW( hkey, key_wtf16le, 0, - access, + .{ .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + .WOW64_32KEY = options.wow64_32, + } } }, &key, ); const return_code: windows.Win32Error = @enumFromInt(return_code_int); @@ -389,7 +391,10 @@ const RegistryWtf16Le = struct { const return_code_int: windows.HRESULT = std.os.windows.advapi32.RegLoadAppKeyW( absolute_path_as_wtf16le, &key, - windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS, + .{ .SPECIFIC = .{ .KEY = .{ + .QUERY_VALUE = true, + .ENUMERATE_SUB_KEYS = true, + } } }, 0, 0, ); diff --git a/src/link/MappedFile.zig b/src/link/MappedFile.zig @@ -953,12 +953,19 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void { if (is_windows) { if (mf.section == windows.INVALID_HANDLE_VALUE) switch (windows.ntdll.NtCreateSection( &mf.section, - windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | - windows.SECTION_MAP_WRITE | windows.SECTION_MAP_READ | windows.SECTION_EXTEND_SIZE, + .{ + .SPECIFIC = .{ .SECTION = .{ + .QUERY = true, + .MAP_WRITE = true, + .MAP_READ = true, + .EXTEND_SIZE = true, + } }, + .STANDARD = .{ .RIGHTS = .REQUIRED }, + }, null, @constCast(&@as(i64, @intCast(aligned_capacity))), - windows.PAGE_READWRITE, - windows.SEC_COMMIT, + .{ .READWRITE = true }, + .{ .COMMIT = true }, mf.file.handle, )) { .SUCCESS => {}, @@ -974,9 +981,9 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void { 0, null, &contents_len, - .ViewUnmap, - 0, - windows.PAGE_READWRITE, + .Unmap, + .{}, + .{ .READWRITE = true }, )) { .SUCCESS => mf.contents = contents_ptr.?[0..contents_len], else => return error.MemoryMappingNotSupported,