authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-12-09 13:59:59-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-12-12 01:58:21-05:00
logc13857e504f5893cabf182dde1e826131f2acf24
tree23d77542db837bb1f7f4277e9e8b83948852fbac
parent27e5047a888fbfd6c9db6a8374e070eb0deb5d0a

windows: type safety improvements and more ntdll functions


16 files changed, 3131 insertions(+), 1343 deletions(-)

lib/std/Build/Watch.zig+21-12
......@@ -366,7 +366,7 @@ const Os = switch (builtin.os.tag) {
366366 var attr = windows.OBJECT_ATTRIBUTES{
367367 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
368368 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else root_fd,
369 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
369 .Attributes = .{},
370370 .ObjectName = &nt_name,
371371 .SecurityDescriptor = null,
372372 .SecurityQualityOfService = null,
......@@ -375,14 +375,23 @@ const Os = switch (builtin.os.tag) {
375375
376376 switch (windows.ntdll.NtCreateFile(
377377 &dir_handle,
378 windows.SYNCHRONIZE | windows.GENERIC_READ | windows.FILE_LIST_DIRECTORY,
378 .{
379 .SPECIFIC = .{ .FILE_DIRECTORY = .{
380 .LIST = true,
381 } },
382 .STANDARD = .{ .SYNCHRONIZE = true },
383 .GENERIC = .{ .READ = true },
384 },
379385 &attr,
380386 &io,
381387 null,
382 0,
383 windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE,
384 windows.FILE_OPEN,
385 windows.FILE_DIRECTORY_FILE | windows.FILE_OPEN_FOR_BACKUP_INTENT,
388 .{},
389 .VALID_FLAGS,
390 .OPEN,
391 .{
392 .DIRECTORY_FILE = true,
393 .OPEN_FOR_BACKUP_INTENT = true,
394 },
386395 null,
387396 0,
388397 )) {
......@@ -437,13 +446,13 @@ const Os = switch (builtin.os.tag) {
437446 fn getFileId(handle: windows.HANDLE) !FileId {
438447 var file_id: FileId = undefined;
439448 var io_status: windows.IO_STATUS_BLOCK = undefined;
440 var volume_info: windows.FILE_FS_VOLUME_INFORMATION = undefined;
449 var volume_info: windows.FILE.FS_VOLUME_INFORMATION = undefined;
441450 switch (windows.ntdll.NtQueryVolumeInformationFile(
442451 handle,
443452 &io_status,
444453 &volume_info,
445 @sizeOf(windows.FILE_FS_VOLUME_INFORMATION),
446 .FileFsVolumeInformation,
454 @sizeOf(windows.FILE.FS_VOLUME_INFORMATION),
455 .Volume,
447456 )) {
448457 .SUCCESS => {},
449458 // 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) {
453462 else => |rc| return windows.unexpectedStatus(rc),
454463 }
455464 file_id.volumeSerialNumber = volume_info.VolumeSerialNumber;
456 var internal_info: windows.FILE_INTERNAL_INFORMATION = undefined;
465 var internal_info: windows.FILE.INTERNAL_INFORMATION = undefined;
457466 switch (windows.ntdll.NtQueryInformationFile(
458467 handle,
459468 &io_status,
460469 &internal_info,
461 @sizeOf(windows.FILE_INTERNAL_INFORMATION),
462 .FileInternalInformation,
470 @sizeOf(windows.FILE.INTERNAL_INFORMATION),
471 .Internal,
463472 )) {
464473 .SUCCESS => {},
465474 else => |rc| return windows.unexpectedStatus(rc),
lib/std/Io/Threaded.zig+100-70
......@@ -1301,8 +1301,11 @@ fn dirMakeWindows(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode
13011301 _ = mode;
13021302 const sub_dir_handle = windows.OpenFile(sub_path_w.span(), .{
13031303 .dir = dir.handle,
1304 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
1305 .creation = windows.FILE_CREATE,
1304 .access_mask = .{
1305 .GENERIC = .{ .READ = true },
1306 .STANDARD = .{ .SYNCHRONIZE = true },
1307 },
1308 .creation = .CREATE,
13061309 .filter = .dir_only,
13071310 }) catch |err| switch (err) {
13081311 error.IsDir => return error.Unexpected,
......@@ -1370,9 +1373,6 @@ fn dirMakeOpenPathWindows(
13701373 const t: *Threaded = @ptrCast(@alignCast(userdata));
13711374 const current_thread = Thread.getCurrent(t);
13721375 const w = windows;
1373 const access_mask = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
1374 w.SYNCHRONIZE | w.FILE_TRAVERSE |
1375 (if (options.iterate) w.FILE_LIST_DIRECTORY else @as(u32, 0));
13761376
13771377 var it = std.fs.path.componentIterator(sub_path);
13781378 // If there are no components in the path, then create a dummy component with the full path.
......@@ -1387,7 +1387,7 @@ fn dirMakeOpenPathWindows(
13871387 const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, component.path);
13881388 const sub_path_w = sub_path_w_array.span();
13891389 const is_last = it.peekNext() == null;
1390 const create_disposition: u32 = if (is_last) w.FILE_OPEN_IF else w.FILE_CREATE;
1390 const create_disposition: w.FILE.CREATE_DISPOSITION = if (is_last) .OPEN_IF else .CREATE;
13911391
13921392 var result: Io.Dir = .{ .handle = undefined };
13931393
......@@ -1397,26 +1397,40 @@ fn dirMakeOpenPathWindows(
13971397 .MaximumLength = path_len_bytes,
13981398 .Buffer = @constCast(sub_path_w.ptr),
13991399 };
1400 var attr: w.OBJECT_ATTRIBUTES = .{
1401 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
1402 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
1403 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
1404 .ObjectName = &nt_name,
1405 .SecurityDescriptor = null,
1406 .SecurityQualityOfService = null,
1407 };
1408 const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0;
14091400 var io_status_block: w.IO_STATUS_BLOCK = undefined;
14101401 const rc = w.ntdll.NtCreateFile(
14111402 &result.handle,
1412 access_mask,
1413 &attr,
1403 .{
1404 .SPECIFIC = .{ .FILE_DIRECTORY = .{
1405 .LIST = options.iterate,
1406 .READ_EA = true,
1407 .READ_ATTRIBUTES = true,
1408 .TRAVERSE = true,
1409 } },
1410 .STANDARD = .{
1411 .RIGHTS = .READ,
1412 .SYNCHRONIZE = true,
1413 },
1414 },
1415 &.{
1416 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
1417 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
1418 .Attributes = .{},
1419 .ObjectName = &nt_name,
1420 .SecurityDescriptor = null,
1421 .SecurityQualityOfService = null,
1422 },
14141423 &io_status_block,
14151424 null,
1416 w.FILE_ATTRIBUTE_NORMAL,
1417 w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE,
1425 .{ .NORMAL = true },
1426 .VALID_FLAGS,
14181427 create_disposition,
1419 w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point,
1428 .{
1429 .DIRECTORY_FILE = true,
1430 .IO = .SYNCHRONOUS_NONALERT,
1431 .OPEN_FOR_BACKUP_INTENT = true,
1432 .OPEN_REPARSE_POINT = !options.follow_symlinks,
1433 },
14201434 null,
14211435 0,
14221436 );
......@@ -1749,8 +1763,8 @@ fn fileStatWindows(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.Fi
17491763 try current_thread.checkCancel();
17501764
17511765 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
1752 var info: windows.FILE_ALL_INFORMATION = undefined;
1753 const rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
1766 var info: windows.FILE.ALL_INFORMATION = undefined;
1767 const rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &info, @sizeOf(windows.FILE.ALL_INFORMATION), .All);
17541768 switch (rc) {
17551769 .SUCCESS => {},
17561770 // 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
17651779 .inode = info.InternalInformation.IndexNumber,
17661780 .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)),
17671781 .mode = 0,
1768 .kind = if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_REPARSE_POINT != 0) reparse_point: {
1769 var tag_info: windows.FILE_ATTRIBUTE_TAG_INFO = undefined;
1770 const tag_rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE_ATTRIBUTE_TAG_INFO), .FileAttributeTagInformation);
1782 .kind = if (info.BasicInformation.FileAttributes.REPARSE_POINT) reparse_point: {
1783 var tag_info: windows.FILE.ATTRIBUTE_TAG_INFO = undefined;
1784 const tag_rc = windows.ntdll.NtQueryInformationFile(file.handle, &io_status_block, &tag_info, @sizeOf(windows.FILE.ATTRIBUTE_TAG_INFO), .AttributeTag);
17711785 switch (tag_rc) {
17721786 .SUCCESS => {},
17731787 // 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
17761790 .ACCESS_DENIED => return error.AccessDenied,
17771791 else => return windows.unexpectedStatus(rc),
17781792 }
1779 if (tag_info.ReparseTag & windows.reparse_tag_name_surrogate_bit != 0) {
1780 break :reparse_point .sym_link;
1781 }
1793 if (tag_info.ReparseTag.IsSurrogate) break :reparse_point .sym_link;
17821794 // Unknown reparse point
17831795 break :reparse_point .unknown;
1784 } else if (info.BasicInformation.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0)
1796 } else if (info.BasicInformation.FileAttributes.DIRECTORY)
17851797 .directory
17861798 else
17871799 .file,
......@@ -1983,15 +1995,15 @@ fn dirAccessWindows(
19831995 .MaximumLength = path_len_bytes,
19841996 .Buffer = @constCast(sub_path_w.ptr),
19851997 };
1986 var attr = windows.OBJECT_ATTRIBUTES{
1998 var attr: windows.OBJECT_ATTRIBUTES = .{
19871999 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
19882000 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
1989 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
2001 .Attributes = .{},
19902002 .ObjectName = &nt_name,
19912003 .SecurityDescriptor = null,
19922004 .SecurityQualityOfService = null,
19932005 };
1994 var basic_info: windows.FILE_BASIC_INFORMATION = undefined;
2006 var basic_info: windows.FILE.BASIC_INFORMATION = undefined;
19952007 switch (windows.ntdll.NtQueryAttributesFile(&attr, &basic_info)) {
19962008 .SUCCESS => return,
19972009 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
......@@ -2187,16 +2199,21 @@ fn dirCreateFileWindows(
21872199 const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path);
21882200 const sub_path_w = sub_path_w_array.span();
21892201
2190 const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0;
21912202 const handle = try w.OpenFile(sub_path_w, .{
21922203 .dir = dir.handle,
2193 .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag,
2204 .access_mask = .{
2205 .STANDARD = .{ .SYNCHRONIZE = true },
2206 .GENERIC = .{
2207 .WRITE = true,
2208 .READ = flags.read,
2209 },
2210 },
21942211 .creation = if (flags.exclusive)
2195 @as(u32, w.FILE_CREATE)
2212 .CREATE
21962213 else if (flags.truncate)
2197 @as(u32, w.FILE_OVERWRITE_IF)
2214 .OVERWRITE_IF
21982215 else
2199 @as(u32, w.FILE_OPEN_IF),
2216 .OPEN_IF,
22002217 });
22012218 errdefer w.CloseHandle(handle);
22022219 var io_status_block: w.IO_STATUS_BLOCK = undefined;
......@@ -2511,18 +2528,12 @@ pub fn dirOpenFileWtf16(
25112528 var attr: w.OBJECT_ATTRIBUTES = .{
25122529 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
25132530 .RootDirectory = dir_handle,
2514 .Attributes = 0,
2531 .Attributes = .{},
25152532 .ObjectName = &nt_name,
25162533 .SecurityDescriptor = null,
25172534 .SecurityQualityOfService = null,
25182535 };
25192536 var io_status_block: w.IO_STATUS_BLOCK = undefined;
2520 const blocking_flag: w.ULONG = w.FILE_SYNCHRONOUS_IO_NONALERT;
2521 const file_or_dir_flag: w.ULONG = w.FILE_NON_DIRECTORY_FILE;
2522 // If we're not following symlinks, we need to ensure we don't pass in any
2523 // synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
2524 const create_file_flags: w.ULONG = file_or_dir_flag |
2525 if (flags.follow_symlinks) blocking_flag else w.FILE_OPEN_REPARSE_POINT;
25262537
25272538 // There are multiple kernel bugs being worked around with retries.
25282539 const max_attempts = 13;
......@@ -2534,16 +2545,24 @@ pub fn dirOpenFileWtf16(
25342545 var result: w.HANDLE = undefined;
25352546 const rc = w.ntdll.NtCreateFile(
25362547 &result,
2537 w.SYNCHRONIZE |
2538 (if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |
2539 (if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),
2548 .{
2549 .STANDARD = .{ .SYNCHRONIZE = true },
2550 .GENERIC = .{
2551 .READ = flags.isRead(),
2552 .WRITE = flags.isWrite(),
2553 },
2554 },
25402555 &attr,
25412556 &io_status_block,
25422557 null,
2543 w.FILE_ATTRIBUTE_NORMAL,
2544 w.FILE_SHARE_WRITE | w.FILE_SHARE_READ | w.FILE_SHARE_DELETE,
2545 w.FILE_OPEN,
2546 create_file_flags,
2558 .{ .NORMAL = true },
2559 .VALID_FLAGS,
2560 .OPEN,
2561 .{
2562 .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,
2563 .NON_DIRECTORY_FILE = true,
2564 .OPEN_REPARSE_POINT = !flags.follow_symlinks,
2565 },
25472566 null,
25482567 0,
25492568 );
......@@ -2835,10 +2854,6 @@ pub fn dirOpenDirWindows(
28352854) Io.Dir.OpenError!Io.Dir {
28362855 const current_thread = Thread.getCurrent(t);
28372856 const w = windows;
2838 // TODO remove some of these flags if options.access_sub_paths is false
2839 const base_flags = w.STANDARD_RIGHTS_READ | w.FILE_READ_ATTRIBUTES | w.FILE_READ_EA |
2840 w.SYNCHRONIZE | w.FILE_TRAVERSE;
2841 const access_mask: u32 = if (options.iterate) base_flags | w.FILE_LIST_DIRECTORY else base_flags;
28422857
28432858 const path_len_bytes: u16 = @intCast(sub_path_w.len * 2);
28442859 var nt_name: w.UNICODE_STRING = .{
......@@ -2846,28 +2861,43 @@ pub fn dirOpenDirWindows(
28462861 .MaximumLength = path_len_bytes,
28472862 .Buffer = @constCast(sub_path_w.ptr),
28482863 };
2849 var attr: w.OBJECT_ATTRIBUTES = .{
2850 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
2851 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
2852 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
2853 .ObjectName = &nt_name,
2854 .SecurityDescriptor = null,
2855 .SecurityQualityOfService = null,
2856 };
2857 const open_reparse_point: w.DWORD = if (!options.follow_symlinks) w.FILE_OPEN_REPARSE_POINT else 0x0;
28582864 var io_status_block: w.IO_STATUS_BLOCK = undefined;
28592865 var result: Io.Dir = .{ .handle = undefined };
28602866 try current_thread.checkCancel();
28612867 const rc = w.ntdll.NtCreateFile(
28622868 &result.handle,
2863 access_mask,
2864 &attr,
2869 // TODO remove some of these flags if options.access_sub_paths is false
2870 .{
2871 .SPECIFIC = .{ .FILE_DIRECTORY = .{
2872 .LIST = options.iterate,
2873 .READ_EA = true,
2874 .TRAVERSE = true,
2875 .READ_ATTRIBUTES = true,
2876 } },
2877 .STANDARD = .{
2878 .RIGHTS = .READ,
2879 .SYNCHRONIZE = true,
2880 },
2881 },
2882 &.{
2883 .Length = @sizeOf(w.OBJECT_ATTRIBUTES),
2884 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else dir.handle,
2885 .Attributes = .{},
2886 .ObjectName = &nt_name,
2887 .SecurityDescriptor = null,
2888 .SecurityQualityOfService = null,
2889 },
28652890 &io_status_block,
28662891 null,
2867 w.FILE_ATTRIBUTE_NORMAL,
2868 w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE,
2869 w.FILE_OPEN,
2870 w.FILE_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT | w.FILE_OPEN_FOR_BACKUP_INTENT | open_reparse_point,
2892 .{ .NORMAL = true },
2893 .VALID_FLAGS,
2894 .OPEN,
2895 .{
2896 .DIRECTORY_FILE = true,
2897 .IO = .SYNCHRONOUS_NONALERT,
2898 .OPEN_FOR_BACKUP_INTENT = true,
2899 .OPEN_REPARSE_POINT = !options.follow_symlinks,
2900 },
28712901 null,
28722902 0,
28732903 );
lib/std/Thread.zig+12-15
......@@ -226,7 +226,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
226226
227227 switch (windows.ntdll.NtSetInformationThread(
228228 self.getHandle(),
229 .ThreadNameInformation,
229 .NameInformation,
230230 &unicode_string,
231231 @sizeOf(windows.UNICODE_STRING),
232232 )) {
......@@ -338,7 +338,7 @@ pub fn getName(self: Thread, buffer_ptr: *[max_name_len:0]u8) GetNameError!?[]co
338338
339339 switch (windows.ntdll.NtQueryInformationThread(
340340 self.getHandle(),
341 .ThreadNameInformation,
341 .NameInformation,
342342 &buf,
343343 buf_capacity,
344344 null,
......@@ -521,12 +521,10 @@ pub const YieldError = error{
521521
522522/// Yields the current thread potentially allowing other threads to run.
523523pub fn yield() YieldError!void {
524 if (native_os == .windows) {
525 // The return value has to do with how many other threads there are; it is not
526 // an error condition on Windows.
527 _ = windows.kernel32.SwitchToThread();
528 return;
529 }
524 if (native_os == .windows) switch (windows.ntdll.NtYieldExecution()) {
525 .SUCCESS, .NO_YIELD_PERFORMED => return,
526 else => return error.SystemCannotYield,
527 };
530528 switch (posix.errno(posix.system.sched_yield())) {
531529 .SUCCESS => return,
532530 .NOSYS => return error.SystemCannotYield,
......@@ -647,11 +645,11 @@ const WindowsThreadImpl = struct {
647645 const ThreadCompletion = struct {
648646 completion: Completion,
649647 heap_ptr: windows.PVOID,
650 heap_handle: windows.HANDLE,
648 heap_handle: *windows.HEAP,
651649 thread_handle: windows.HANDLE = undefined,
652650
653651 fn free(self: ThreadCompletion) void {
654 const status = windows.kernel32.HeapFree(self.heap_handle, 0, self.heap_ptr);
652 const status = windows.ntdll.RtlFreeHeap(self.heap_handle, .{}, self.heap_ptr);
655653 assert(status != 0);
656654 }
657655 };
......@@ -673,10 +671,10 @@ const WindowsThreadImpl = struct {
673671 }
674672 };
675673
676 const heap_handle = windows.kernel32.GetProcessHeap() orelse return error.OutOfMemory;
674 const heap_handle = windows.GetProcessHeap() orelse return error.OutOfMemory;
677675 const alloc_bytes = @alignOf(Instance) + @sizeOf(Instance);
678 const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, 0, alloc_bytes) orelse return error.OutOfMemory;
679 errdefer assert(windows.kernel32.HeapFree(heap_handle, 0, alloc_ptr) != 0);
676 const alloc_ptr = windows.ntdll.RtlAllocateHeap(heap_handle, .{}, alloc_bytes) orelse return error.OutOfMemory;
677 errdefer assert(windows.ntdll.RtlFreeHeap(heap_handle, .{}, alloc_ptr) != 0);
680678
681679 const instance_bytes = @as([*]u8, @ptrCast(alloc_ptr))[0..alloc_bytes];
682680 var fba = std.heap.FixedBufferAllocator.init(instance_bytes);
......@@ -693,8 +691,7 @@ const WindowsThreadImpl = struct {
693691 // Windows appears to only support SYSTEM_INFO.dwAllocationGranularity minimum stack size.
694692 // Going lower makes it default to that specified in the executable (~1mb).
695693 // Its also fine if the limit here is incorrect as stack size is only a hint.
696 var stack_size = std.math.cast(u32, config.stack_size) orelse std.math.maxInt(u32);
697 stack_size = @max(64 * 1024, stack_size);
694 const stack_size = @max(64 * 1024, std.math.lossyCast(u32, config.stack_size));
698695
699696 instance.thread.thread_handle = windows.kernel32.CreateThread(
700697 null,
lib/std/debug/SelfInfo/Windows.zig+14-8
......@@ -154,10 +154,10 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error
154154 _ = gpa;
155155
156156 const current_regs = context.cur.getRegs();
157 var image_base: windows.DWORD64 = undefined;
157 var image_base: usize = undefined;
158158 if (windows.ntdll.RtlLookupFunctionEntry(current_regs.ip, &image_base, &context.history_table)) |runtime_function| {
159159 var handler_data: ?*anyopaque = null;
160 var establisher_frame: u64 = undefined;
160 var establisher_frame: usize = undefined;
161161 _ = windows.ntdll.RtlVirtualUnwind(
162162 windows.UNW_FLAG_NHANDLER,
163163 image_base,
......@@ -351,13 +351,19 @@ const Module = struct {
351351 var section_handle: windows.HANDLE = undefined;
352352 const create_section_rc = windows.ntdll.NtCreateSection(
353353 &section_handle,
354 windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY | windows.SECTION_MAP_READ,
354 .{
355 .SPECIFIC = .{ .SECTION = .{
356 .QUERY = true,
357 .MAP_READ = true,
358 } },
359 .STANDARD = .{ .RIGHTS = .REQUIRED },
360 },
355361 null,
356362 null,
357 windows.PAGE_READONLY,
363 .{ .READONLY = true },
358364 // The documentation states that if no AllocationAttribute is specified, then SEC_COMMIT is the default.
359365 // In practice, this isn't the case and specifying 0 will result in INVALID_PARAMETER_6.
360 windows.SEC_COMMIT,
366 .{ .COMMIT = true },
361367 coff_file.handle,
362368 );
363369 if (create_section_rc != .SUCCESS) return error.MissingDebugInfo;
......@@ -372,9 +378,9 @@ const Module = struct {
372378 0,
373379 null,
374380 &coff_len,
375 .ViewUnmap,
376 0,
377 windows.PAGE_READONLY,
381 .Unmap,
382 .{},
383 .{ .READONLY = true },
378384 );
379385 if (map_section_rc != .SUCCESS) return error.MissingDebugInfo;
380386 errdefer assert(windows.ntdll.NtUnmapViewOfSection(process_handle, @constCast(section_view_ptr.?)) == .SUCCESS);
lib/std/enums.zig+3-1
......@@ -61,7 +61,9 @@ pub fn values(comptime E: type) []const E {
6161/// panic when `e` has no tagged value.
6262/// Returns the tag name for `e` or null if no tag exists.
6363pub fn tagName(comptime E: type, e: E) ?[:0]const u8 {
64 return inline for (@typeInfo(E).@"enum".fields) |f| {
64 const fields = @typeInfo(E).@"enum".fields;
65 @setEvalBranchQuota(fields.len);
66 return inline for (fields) |f| {
6567 if (@intFromEnum(e) == f.value) break f.name;
6668 } else null;
6769}
lib/std/fs/Dir.zig+9-10
......@@ -453,10 +453,10 @@ pub const Iterator = switch (native_os) {
453453 &io,
454454 &self.buf,
455455 self.buf.len,
456 .FileBothDirectoryInformation,
456 .BothDirectory,
457457 w.FALSE,
458458 null,
459 if (self.first_iter) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE),
459 @intFromBool(self.first_iter),
460460 );
461461 self.first_iter = false;
462462 if (io.Information == 0) return null;
......@@ -487,8 +487,8 @@ pub const Iterator = switch (native_os) {
487487 const name_wtf8 = self.name_data[0..name_wtf8_len];
488488 const kind: Entry.Kind = blk: {
489489 const attrs = dir_info.FileAttributes;
490 if (attrs & w.FILE_ATTRIBUTE_DIRECTORY != 0) break :blk .directory;
491 if (attrs & w.FILE_ATTRIBUTE_REPARSE_POINT != 0) break :blk .sym_link;
490 if (attrs.DIRECTORY) break :blk .directory;
491 if (attrs.REPARSE_POINT) break :blk .sym_link;
492492 break :blk .file;
493493 };
494494 return Entry{
......@@ -1013,15 +1013,14 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathErr
10131013pub fn realpathW2(self: Dir, pathname: []const u16, out_buffer: []u16) RealPathError![]u16 {
10141014 const w = windows;
10151015
1016 const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
1017 const share_access = w.FILE_SHARE_READ | w.FILE_SHARE_WRITE | w.FILE_SHARE_DELETE;
1018 const creation = w.FILE_OPEN;
10191016 const h_file = blk: {
10201017 const res = w.OpenFile(pathname, .{
10211018 .dir = self.fd,
1022 .access_mask = access_mask,
1023 .share_access = share_access,
1024 .creation = creation,
1019 .access_mask = .{
1020 .STANDARD = .{ .SYNCHRONIZE = true },
1021 .GENERIC = .{ .READ = true },
1022 },
1023 .creation = .OPEN,
10251024 .filter = .any,
10261025 }) catch |err| switch (err) {
10271026 error.WouldBlock => unreachable,
lib/std/fs/File.zig+7-7
......@@ -146,13 +146,13 @@ pub fn isCygwinPty(file: File) bool {
146146 // for handles that aren't named pipes.
147147 {
148148 var io_status: windows.IO_STATUS_BLOCK = undefined;
149 var device_info: windows.FILE_FS_DEVICE_INFORMATION = undefined;
150 const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE_FS_DEVICE_INFORMATION), .FileFsDeviceInformation);
149 var device_info: windows.FILE.FS_DEVICE_INFORMATION = undefined;
150 const rc = windows.ntdll.NtQueryVolumeInformationFile(handle, &io_status, &device_info, @sizeOf(windows.FILE.FS_DEVICE_INFORMATION), .Device);
151151 switch (rc) {
152152 .SUCCESS => {},
153153 else => return false,
154154 }
155 if (device_info.DeviceType != windows.FILE_DEVICE_NAMED_PIPE) return false;
155 if (device_info.DeviceType.FileDevice != .NAMED_PIPE) return false;
156156 }
157157
158158 const name_bytes_offset = @offsetOf(windows.FILE_NAME_INFO, "FileName");
......@@ -166,7 +166,7 @@ pub fn isCygwinPty(file: File) bool {
166166 var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (name_bytes_offset + num_name_bytes);
167167
168168 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
169 const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(name_info_bytes.len), .FileNameInformation);
169 const rc = windows.ntdll.NtQueryInformationFile(handle, &io_status_block, &name_info_bytes, @intCast(name_info_bytes.len), .Name);
170170 switch (rc) {
171171 .SUCCESS => {},
172172 .INVALID_PARAMETER => unreachable,
......@@ -485,7 +485,7 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError!
485485 &io_status_block,
486486 &info,
487487 @sizeOf(windows.FILE_BASIC_INFORMATION),
488 .FileBasicInformation,
488 .Basic,
489489 );
490490 switch (rc) {
491491 .SUCCESS => return,
......@@ -1324,7 +1324,7 @@ pub fn unlock(file: File) void {
13241324 &io_status_block,
13251325 &range_off,
13261326 &range_len,
1327 null,
1327 0,
13281328 ) catch |err| switch (err) {
13291329 error.RangeNotLocked => unreachable, // Function assumes unlocked.
13301330 error.Unexpected => unreachable, // Resource deallocation must succeed.
......@@ -1415,7 +1415,7 @@ pub fn downgradeLock(file: File) LockError!void {
14151415 &io_status_block,
14161416 &range_off,
14171417 &range_len,
1418 null,
1418 0,
14191419 ) catch |err| switch (err) {
14201420 error.RangeNotLocked => unreachable, // File was not locked.
14211421 error.Unexpected => unreachable, // Resource deallocation must succeed.
lib/std/fs/test.zig+26-14
......@@ -256,13 +256,11 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" {
256256
257257 try setupSymlink(ctx.dir, dir_target_path, "symlink", .{ .is_directory = true });
258258
259 var symlink = switch (builtin.target.os.tag) {
259 var symlink: Dir = switch (builtin.target.os.tag) {
260260 .windows => windows_symlink: {
261261 const sub_path_w = try windows.cStrToPrefixedFileW(ctx.dir.fd, "symlink");
262262
263 var result = Dir{
264 .fd = undefined,
265 };
263 var handle: windows.HANDLE = undefined;
266264
267265 const path_len_bytes = @as(u16, @intCast(sub_path_w.span().len * 2));
268266 var nt_name = windows.UNICODE_STRING{
......@@ -270,32 +268,46 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" {
270268 .MaximumLength = path_len_bytes,
271269 .Buffer = @constCast(&sub_path_w.data),
272270 };
273 var attr = windows.OBJECT_ATTRIBUTES{
271 var attr: windows.OBJECT_ATTRIBUTES = .{
274272 .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
275273 .RootDirectory = if (fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else ctx.dir.fd,
276 .Attributes = 0,
274 .Attributes = .{},
277275 .ObjectName = &nt_name,
278276 .SecurityDescriptor = null,
279277 .SecurityQualityOfService = null,
280278 };
281279 var io: windows.IO_STATUS_BLOCK = undefined;
282280 const rc = windows.ntdll.NtCreateFile(
283 &result.fd,
284 windows.STANDARD_RIGHTS_READ | windows.FILE_READ_ATTRIBUTES | windows.FILE_READ_EA | windows.SYNCHRONIZE | windows.FILE_TRAVERSE,
281 &handle,
282 .{
283 .SPECIFIC = .{ .FILE_DIRECTORY = .{
284 .READ_EA = true,
285 .TRAVERSE = true,
286 .READ_ATTRIBUTES = true,
287 } },
288 .STANDARD = .{
289 .RIGHTS = .READ,
290 .SYNCHRONIZE = true,
291 },
292 },
285293 &attr,
286294 &io,
287295 null,
288 windows.FILE_ATTRIBUTE_NORMAL,
289 windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE,
290 windows.FILE_OPEN,
291 // FILE_OPEN_REPARSE_POINT is the important thing here
292 windows.FILE_OPEN_REPARSE_POINT | windows.FILE_DIRECTORY_FILE | windows.FILE_SYNCHRONOUS_IO_NONALERT | windows.FILE_OPEN_FOR_BACKUP_INTENT,
296 .{ .NORMAL = true },
297 .VALID_FLAGS,
298 .OPEN,
299 .{
300 .DIRECTORY_FILE = true,
301 .IO = .SYNCHRONOUS_NONALERT,
302 .OPEN_FOR_BACKUP_INTENT = true,
303 .OPEN_REPARSE_POINT = true, // the important thing here
304 },
293305 null,
294306 0,
295307 );
296308
297309 switch (rc) {
298 .SUCCESS => break :windows_symlink result,
310 .SUCCESS => break :windows_symlink .{ .fd = handle },
299311 else => return windows.unexpectedStatus(rc),
300312 }
301313 },
lib/std/heap/PageAllocator.zig+10-9
......@@ -30,7 +30,8 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
3030 var base_addr: ?*anyopaque = null;
3131 var size: windows.SIZE_T = n;
3232
33 var status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | windows.MEM_RESERVE, windows.PAGE_READWRITE);
33 const current_process = windows.GetCurrentProcess();
34 var status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true, .RESERVE = true }, .{ .READWRITE = true });
3435
3536 if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) {
3637 return @ptrCast(base_addr);
......@@ -38,7 +39,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
3839
3940 if (status == SUCCESS) {
4041 var region_size: windows.SIZE_T = 0;
41 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, windows.MEM_RELEASE);
42 _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &region_size, .{ .RELEASE = true });
4243 }
4344
4445 const overalloc_len = n + alignment_bytes - page_size;
......@@ -47,7 +48,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
4748 base_addr = null;
4849 size = overalloc_len;
4950
50 status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, windows.PAGE_NOACCESS);
51 status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .RESERVE = true, .RESERVE_PLACEHOLDER = true }, .{ .NOACCESS = true });
5152
5253 if (status != SUCCESS) return null;
5354
......@@ -58,7 +59,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
5859 if (prefix_size > 0) {
5960 var prefix_base = base_addr;
6061 var prefix_size_param: windows.SIZE_T = prefix_size;
61 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&prefix_base), &prefix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
62 _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&prefix_base), &prefix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true });
6263 }
6364
6465 const suffix_start = aligned_addr + aligned_len;
......@@ -66,13 +67,13 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
6667 if (suffix_size > 0) {
6768 var suffix_base = @as(?*anyopaque, @ptrFromInt(suffix_start));
6869 var suffix_size_param: windows.SIZE_T = suffix_size;
69 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&suffix_base), &suffix_size_param, windows.MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
70 _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&suffix_base), &suffix_size_param, .{ .RELEASE = true, .PRESERVE_PLACEHOLDER = true });
7071 }
7172
7273 base_addr = @ptrFromInt(aligned_addr);
7374 size = aligned_len;
7475
75 status = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), 0, &size, windows.MEM_COMMIT | MEM_PRESERVE_PLACEHOLDER, windows.PAGE_READWRITE);
76 status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true }, .{ .READWRITE = true });
7677
7778 if (status == SUCCESS) {
7879 return @ptrCast(base_addr);
......@@ -80,7 +81,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
8081
8182 base_addr = @as(?*anyopaque, @ptrFromInt(aligned_addr));
8283 size = aligned_len;
83 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &size, windows.MEM_RELEASE);
84 _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &size, .{ .RELEASE = true });
8485
8586 return null;
8687 }
......@@ -145,7 +146,7 @@ pub fn unmap(memory: []align(page_size_min) u8) void {
145146 if (native_os == .windows) {
146147 var base_addr: ?*anyopaque = memory.ptr;
147148 var region_size: windows.SIZE_T = 0;
148 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, windows.MEM_RELEASE);
149 _ = ntdll.NtFreeVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&base_addr), &region_size, .{ .RELEASE = true });
149150 } else {
150151 const page_aligned_len = mem.alignForward(usize, memory.len, std.heap.pageSize());
151152 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 {
166167 var decommit_addr: ?*anyopaque = @ptrFromInt(new_addr_end);
167168 var decommit_size: windows.SIZE_T = old_addr_end - new_addr_end;
168169
169 _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, windows.MEM_RESET, windows.PAGE_NOACCESS);
170 _ = ntdll.NtAllocateVirtualMemory(windows.GetCurrentProcess(), @ptrCast(&decommit_addr), 0, &decommit_size, .{ .RESET = true }, .{ .NOACCESS = true });
170171 }
171172 return memory.ptr;
172173 }
lib/std/os/windows.zig+2498-876
......@@ -28,9 +28,2265 @@ pub const ws2_32 = @import("windows/ws2_32.zig");
2828pub const crypt32 = @import("windows/crypt32.zig");
2929pub const nls = @import("windows/nls.zig");
3030
31pub const self_process_handle = @as(HANDLE, @ptrFromInt(maxInt(usize)));
31pub const FILE = struct {
32 // ref: km/ntddk.h
3233
33const Self = @This();
34 pub const END_OF_FILE_INFORMATION = extern struct {
35 EndOfFile: LARGE_INTEGER,
36 };
37
38 pub const ALIGNMENT_INFORMATION = extern struct {
39 AlignmentRequirement: ULONG,
40 };
41
42 pub const NAME_INFORMATION = extern struct {
43 FileNameLength: ULONG,
44 FileName: [1]WCHAR,
45 };
46
47 pub const DISPOSITION = packed struct(ULONG) {
48 DELETE: bool = false,
49 POSIX_SEMANTICS: bool = false,
50 FORCE_IMAGE_SECTION_CHECK: bool = false,
51 ON_CLOSE: bool = false,
52 IGNORE_READONLY_ATTRIBUTE: bool = false,
53 Reserved5: u27 = 0,
54
55 pub const DO_NOT_DELETE: DISPOSITION = .{};
56
57 pub const INFORMATION = extern struct {
58 DeleteFile: BOOLEAN,
59
60 pub const EX = extern struct {
61 Flags: DISPOSITION,
62 };
63 };
64 };
65
66 pub const FS_VOLUME_INFORMATION = extern struct {
67 VolumeCreationTime: LARGE_INTEGER,
68 VolumeSerialNumber: ULONG,
69 VolumeLabelLength: ULONG,
70 SupportsObjects: BOOLEAN,
71 VolumeLabel: [0]WCHAR,
72
73 pub fn getVolumeLabel(fvi: *const FS_VOLUME_INFORMATION) []const WCHAR {
74 return (&fvi).ptr[0..@divExact(fvi.VolumeLabelLength, @sizeOf(WCHAR))];
75 }
76 };
77
78 // ref: km/ntifs.h
79
80 pub const PIPE = struct {
81 /// Define the `NamedPipeType` flags for `NtCreateNamedPipeFile`
82 pub const TYPE = packed struct(ULONG) {
83 TYPE: enum(u1) {
84 BYTE_STREAM = 0b0,
85 MESSAGE = 0b1,
86 } = .BYTE_STREAM,
87 REMOTE_CLIENTS: enum(u1) {
88 ACCEPT = 0b0,
89 REJECT = 0b1,
90 } = .ACCEPT,
91 Reserved2: u30 = 0,
92
93 pub const VALID_MASK: TYPE = .{
94 .TYPE = .MESSAGE,
95 .REMOTE_CLIENTS = .REJECT,
96 };
97 };
98
99 /// Define the `CompletionMode` flags for `NtCreateNamedPipeFile`
100 pub const COMPLETION_MODE = packed struct(ULONG) {
101 OPERATION: enum(u1) {
102 QUEUE = 0b0,
103 COMPLETE = 0b1,
104 } = .QUEUE,
105 Reserved1: u31 = 0,
106 };
107
108 /// Define the `ReadMode` flags for `NtCreateNamedPipeFile`
109 pub const READ_MODE = packed struct(ULONG) {
110 MODE: enum(u1) {
111 BYTE_STREAM = 0b0,
112 MESSAGE = 0b1,
113 },
114 Reserved1: u31 = 0,
115 };
116
117 /// Define the `NamedPipeConfiguration` flags for `NtQueryInformationFile`
118 pub const CONFIGURATION = enum(ULONG) {
119 INBOUND = 0x00000000,
120 OUTBOUND = 0x00000001,
121 FULL_DUPLEX = 0x00000002,
122 };
123
124 /// Define the `NamedPipeState` flags for `NtQueryInformationFile`
125 pub const STATE = enum(ULONG) {
126 DISCONNECTED = 0x00000001,
127 LISTENING = 0x00000002,
128 CONNECTED = 0x00000003,
129 CLOSING = 0x00000004,
130 };
131
132 /// Define the `NamedPipeEnd` flags for `NtQueryInformationFile`
133 pub const END = enum(ULONG) {
134 CLIENT = 0x00000000,
135 SERVER = 0x00000001,
136 };
137
138 pub const INFORMATION = extern struct {
139 ReadMode: READ_MODE,
140 CompletionMode: COMPLETION_MODE,
141 };
142
143 pub const LOCAL_INFORMATION = extern struct {
144 NamedPipeType: TYPE,
145 NamedPipeConfiguration: CONFIGURATION,
146 MaximumInstances: ULONG,
147 CurrentInstances: ULONG,
148 InboundQuota: ULONG,
149 ReadDataAvailable: ULONG,
150 OutboundQuota: ULONG,
151 WriteQuotaAvailable: ULONG,
152 NamedPipeState: STATE,
153 NamedPipeEnd: END,
154 };
155
156 pub const REMOTE_INFORMATION = extern struct {
157 CollectDataTime: LARGE_INTEGER,
158 MaximumCollectionCount: ULONG,
159 };
160
161 pub const WAIT_FOR_BUFFER = extern struct {
162 Timeout: LARGE_INTEGER,
163 NameLength: ULONG,
164 TimeoutSpecified: BOOLEAN,
165 Name: [PATH_MAX_WIDE]WCHAR,
166
167 pub const WAIT_FOREVER: LARGE_INTEGER = std.math.minInt(LARGE_INTEGER);
168
169 pub fn init(opts: struct {
170 Timeout: ?LARGE_INTEGER = null,
171 Name: []const WCHAR,
172 }) WAIT_FOR_BUFFER {
173 var fpwfb: WAIT_FOR_BUFFER = .{
174 .Timeout = opts.Timeout orelse undefined,
175 .NameLength = @intCast(@sizeOf(WCHAR) * opts.Name.len),
176 .TimeoutSpecified = @intFromBool(opts.Timeout != null),
177 .Name = undefined,
178 };
179 @memcpy(fpwfb.Name[0..opts.Name.len], opts.Name);
180 return fpwfb;
181 }
182
183 pub fn getName(fpwfb: *const WAIT_FOR_BUFFER) []const WCHAR {
184 return fpwfb.Name[0..@divExact(fpwfb.NameLength, @sizeOf(WCHAR))];
185 }
186
187 pub fn toBuffer(fpwfb: *const WAIT_FOR_BUFFER) []const u8 {
188 const start: [*]const u8 = @ptrCast(fpwfb);
189 return start[0 .. @offsetOf(WAIT_FOR_BUFFER, "Name") + fpwfb.NameLength];
190 }
191 };
192 };
193
194 pub const ALL_INFORMATION = extern struct {
195 BasicInformation: BASIC_INFORMATION,
196 StandardInformation: STANDARD_INFORMATION,
197 InternalInformation: INTERNAL_INFORMATION,
198 EaInformation: EA_INFORMATION,
199 AccessInformation: ACCESS_INFORMATION,
200 PositionInformation: POSITION_INFORMATION,
201 ModeInformation: MODE.INFORMATION,
202 AlignmentInformation: ALIGNMENT_INFORMATION,
203 NameInformation: NAME_INFORMATION,
204 };
205
206 pub const INTERNAL_INFORMATION = extern struct {
207 IndexNumber: LARGE_INTEGER,
208 };
209
210 pub const EA_INFORMATION = extern struct {
211 EaSize: ULONG,
212 };
213
214 pub const ACCESS_INFORMATION = extern struct {
215 AccessFlags: ACCESS_MASK,
216 };
217
218 pub const RENAME_INFORMATION = extern struct {
219 Flags: FLAGS,
220 RootDirectory: ?HANDLE,
221 FileNameLength: ULONG,
222 FileName: [PATH_MAX_WIDE]WCHAR,
223
224 pub fn init(opts: struct {
225 Flags: FLAGS = .{},
226 RootDirectory: ?HANDLE = null,
227 FileName: []const WCHAR,
228 }) RENAME_INFORMATION {
229 var fri: RENAME_INFORMATION = .{
230 .Flags = opts.Flags,
231 .RootDirectory = opts.RootDirectory,
232 .FileNameLength = @intCast(@sizeOf(WCHAR) * opts.FileName.len),
233 .FileName = undefined,
234 };
235 @memcpy(fri.FileName[0..opts.FileName.len], opts.FileName);
236 return fri;
237 }
238
239 pub const FLAGS = packed struct(ULONG) {
240 REPLACE_IF_EXISTS: bool = false,
241 POSIX_SEMANTICS: bool = false,
242 SUPPRESS_PIN_STATE_INHERITANCE: bool = false,
243 SUPPRESS_STORAGE_RESERVE_INHERITANCE: bool = false,
244 AVAILABLE_SPACE: enum(u2) {
245 NO_PRESERVE = 0b00,
246 NO_INCREASE = 0b01,
247 NO_DECREASE = 0b10,
248 PRESERVE = 0b11,
249 } = .NO_PRESERVE,
250 IGNORE_READONLY_ATTRIBUTE: bool = false,
251 RESIZE_SR: enum(u2) {
252 NO_FORCE = 0b00,
253 FORCE_TARGET = 0b01,
254 FORCE_SOURCE = 0b10,
255 FORCE = 0b11,
256 } = .NO_FORCE,
257 Reserved9: u23 = 0,
258 };
259
260 pub fn getFileName(ri: *const RENAME_INFORMATION) []const WCHAR {
261 return ri.FileName[0..@divExact(ri.FileNameLength, @sizeOf(WCHAR))];
262 }
263
264 pub fn toBuffer(fri: *const RENAME_INFORMATION) []const u8 {
265 const start: [*]const u8 = @ptrCast(fri);
266 return start[0 .. @offsetOf(RENAME_INFORMATION, "FileName") + fri.FileNameLength];
267 }
268 };
269
270 // ref: km/wdm.h
271
272 pub const INFORMATION_CLASS = enum(c_int) {
273 Directory = 1,
274 FullDirectory = 2,
275 BothDirectory = 3,
276 Basic = 4,
277 Standard = 5,
278 Internal = 6,
279 Ea = 7,
280 Access = 8,
281 Name = 9,
282 Rename = 10,
283 Link = 11,
284 Names = 12,
285 Disposition = 13,
286 Position = 14,
287 FullEa = 15,
288 Mode = 16,
289 Alignment = 17,
290 All = 18,
291 Allocation = 19,
292 EndOfFile = 20,
293 AlternateName = 21,
294 Stream = 22,
295 Pipe = 23,
296 PipeLocal = 24,
297 PipeRemote = 25,
298 MailslotQuery = 26,
299 MailslotSet = 27,
300 Compression = 28,
301 ObjectId = 29,
302 Completion = 30,
303 MoveCluster = 31,
304 Quota = 32,
305 ReparsePoint = 33,
306 NetworkOpen = 34,
307 AttributeTag = 35,
308 Tracking = 36,
309 IdBothDirectory = 37,
310 IdFullDirectory = 38,
311 ValidDataLength = 39,
312 ShortName = 40,
313 IoCompletionNotification = 41,
314 IoStatusBlockRange = 42,
315 IoPriorityHint = 43,
316 SfioReserve = 44,
317 SfioVolume = 45,
318 HardLink = 46,
319 ProcessIdsUsingFile = 47,
320 NormalizedName = 48,
321 NetworkPhysicalName = 49,
322 IdGlobalTxDirectory = 50,
323 IsRemoteDevice = 51,
324 Unused = 52,
325 NumaNode = 53,
326 StandardLink = 54,
327 RemoteProtocol = 55,
328 RenameBypassAccessCheck = 56,
329 LinkBypassAccessCheck = 57,
330 VolumeName = 58,
331 Id = 59,
332 IdExtdDirectory = 60,
333 ReplaceCompletion = 61,
334 HardLinkFullId = 62,
335 IdExtdBothDirectory = 63,
336 DispositionEx = 64,
337 RenameEx = 65,
338 RenameExBypassAccessCheck = 66,
339 DesiredStorageClass = 67,
340 Stat = 68,
341 MemoryPartition = 69,
342 StatLx = 70,
343 CaseSensitive = 71,
344 LinkEx = 72,
345 LinkExBypassAccessCheck = 73,
346 StorageReserveId = 74,
347 CaseSensitiveForceAccessCheck = 75,
348 KnownFolder = 76,
349 StatBasic = 77,
350 Id64ExtdDirectory = 78,
351 Id64ExtdBothDirectory = 79,
352 IdAllExtdDirectory = 80,
353 IdAllExtdBothDirectory = 81,
354 StreamReservation = 82,
355 MupProvider = 83,
356
357 pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len;
358 };
359
360 pub const BASIC_INFORMATION = extern struct {
361 CreationTime: LARGE_INTEGER,
362 LastAccessTime: LARGE_INTEGER,
363 LastWriteTime: LARGE_INTEGER,
364 ChangeTime: LARGE_INTEGER,
365 FileAttributes: ATTRIBUTE,
366 };
367
368 pub const STANDARD_INFORMATION = extern struct {
369 AllocationSize: LARGE_INTEGER,
370 EndOfFile: LARGE_INTEGER,
371 NumberOfLinks: ULONG,
372 DeletePending: BOOLEAN,
373 Directory: BOOLEAN,
374 };
375
376 pub const POSITION_INFORMATION = extern struct {
377 CurrentByteOffset: LARGE_INTEGER,
378 };
379
380 pub const FS_DEVICE_INFORMATION = extern struct {
381 DeviceType: DEVICE_TYPE,
382 Characteristics: ULONG,
383 };
384
385 // ref: um/WinBase.h
386
387 pub const ATTRIBUTE_TAG_INFO = extern struct {
388 FileAttributes: DWORD,
389 ReparseTag: IO_REPARSE_TAG,
390 };
391
392 // ref: um/winnt.h
393
394 pub const SHARE = packed struct(ULONG) {
395 /// The file can be opened for read access by other threads.
396 READ: bool = false,
397 /// The file can be opened for write access by other threads.
398 WRITE: bool = false,
399 /// The file can be opened for delete access by other threads.
400 DELETE: bool = false,
401 Reserved3: u29 = 0,
402
403 pub const VALID_FLAGS: SHARE = .{
404 .READ = true,
405 .WRITE = true,
406 .DELETE = true,
407 };
408 };
409
410 pub const ATTRIBUTE = packed struct(ULONG) {
411 /// The file is read only. Applications can read the file, but cannot write to or delete it.
412 READONLY: bool = false,
413 /// The file is hidden. Do not include it in an ordinary directory listing.
414 HIDDEN: bool = false,
415 /// The file is part of or used exclusively by an operating system.
416 SYSTEM: bool = false,
417 Reserved3: u1 = 0,
418 DIRECTORY: bool = false,
419 /// The file should be archived. Applications use this attribute to mark files for backup or removal.
420 ARCHIVE: bool = false,
421 DEVICE: bool = false,
422 /// The file does not have other attributes set. This attribute is valid only if used alone.
423 NORMAL: bool = false,
424 /// The file is being used for temporary storage.
425 TEMPORARY: bool = false,
426 SPARSE_FILE: bool = false,
427 REPARSE_POINT: bool = false,
428 COMPRESSED: bool = false,
429 /// The data of a file is not immediately available. This attribute indicates that file data is physically moved to offline storage.
430 /// This attribute is used by Remote Storage, the hierarchical storage management software. Applications should not arbitrarily change this attribute.
431 OFFLINE: bool = false,
432 NOT_CONTENT_INDEXED: bool = false,
433 /// 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
434 /// the default for newly created files and subdirectories. For more information, see File Encryption.
435 ///
436 /// This flag has no effect if `SYSTEM` is also specified.
437 ///
438 /// This flag is not supported on Home, Home Premium, Starter, or ARM editions of Windows.
439 ENCRYPTED: bool = false,
440 INTEGRITY_STREAM: bool = false,
441 VIRTUAL: bool = false,
442 NO_SCRUB_DATA: bool = false,
443 EA_or_RECALL_ON_OPEN: bool = false,
444 PINNED: bool = false,
445 UNPINNED: bool = false,
446 Reserved21: u1 = 0,
447 RECALL_ON_DATA_ACCESS: bool = false,
448 Reserved23: u6 = 0,
449 STRICTLY_SEQUENTIAL: bool = false,
450 Reserved30: u2 = 0,
451 };
452
453 // ref: um/winternl.h
454
455 /// Define the create disposition values
456 pub const CREATE_DISPOSITION = enum(ULONG) {
457 /// If the file already exists, replace it with the given file. If it does not, create the given file.
458 SUPERSEDE = 0x00000000,
459 /// 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.
460 OPEN = 0x00000001,
461 /// 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.
462 CREATE = 0x00000002,
463 /// If the file already exists, open it. If it does not, create the given file.
464 OPEN_IF = 0x00000003,
465 /// If the file already exists, open it and overwrite it. If it does not, fail the request.
466 OVERWRITE = 0x00000004,
467 /// If the file already exists, open it and overwrite it. If it does not, create the given file.
468 OVERWRITE_IF = 0x00000005,
469
470 pub const MAXIMUM_DISPOSITION: CREATE_DISPOSITION = .OVERWRITE_IF;
471 };
472
473 /// Define the create/open option flags
474 pub const MODE = packed struct(ULONG) {
475 /// 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`.
476 /// With this flag, other compatible CreateOptions flags include only the following: `SYNCHRONOUS_IO`, `WRITE_THROUGH`, `OPEN_FOR_BACKUP_INTENT`, and `OPEN_BY_FILE_ID`.
477 DIRECTORY_FILE: bool = false,
478 /// Applications that write data to the file must actually transfer the data into the file before any requested write operation is considered complete.
479 /// This flag is automatically set if the CreateOptions flag `NO_INTERMEDIATE_BUFFERING` is set.
480 WRITE_THROUGH: bool = false,
481 /// All accesses to the file are sequential.
482 SEQUENTIAL_ONLY: bool = false,
483 /// The file cannot be cached or buffered in a driver's internal buffers. This flag is incompatible with the DesiredAccess `FILE_APPEND_DATA` flag.
484 NO_INTERMEDIATE_BUFFERING: bool = false,
485 IO: enum(u2) {
486 /// All operations on the file are performed asynchronously.
487 ASYNCHRONOUS = 0b00,
488 /// All operations on the file are performed synchronously. Any wait on behalf of the caller is subject to premature termination from alerts.
489 /// 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.
490 SYNCHRONOUS_ALERT = 0b01,
491 /// All operations on the file are performed synchronously. Waits in the system to synchronize I/O queuing and completion are not subject to alerts.
492 /// 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.
493 SYNCHRONOUS_NONALERT = 0b10,
494 _,
495
496 pub const VALID_FLAGS: @This() = @enumFromInt(0b11);
497 } = .ASYNCHRONOUS,
498 /// 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
499 /// device, or a volume.
500 NON_DIRECTORY_FILE: bool = false,
501 /// 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.
502 CREATE_TREE_CONNECTION: bool = false,
503 /// Complete this operation immediately with an alternate success code of `STATUS_OPLOCK_BREAK_IN_PROGRESS` if the target file is oplocked, rather than blocking
504 /// 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.
505 COMPLETE_IF_OPLOCKED: bool = false,
506 /// 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
507 /// because the caller does not understand how to deal with EAs. This flag is irrelevant for device and intermediate drivers.
508 NO_EA_KNOWLEDGE: bool = false,
509 OPEN_REMOTE_INSTANCE: bool = false,
510 /// Accesses to the file can be random, so no sequential read-ahead operations should be performed on the file by FSDs or the system.
511 RANDOM_ACCESS: bool = false,
512 /// 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.
513 DELETE_ON_CLOSE: bool = false,
514 /// 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
515 /// 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
516 /// does not support this flag. This flag is not used by device and intermediate drivers.
517 OPEN_BY_FILE_ID: bool = false,
518 /// 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
519 /// file before checking the DesiredAccess parameter against the file's security descriptor. This flag not used by device and intermediate drivers.
520 OPEN_FOR_BACKUP_INTENT: bool = false,
521 /// Suppress inheritance of `FILE_ATTRIBUTE.COMPRESSED` from the parent directory. This allows creation of a non-compressed file in a directory that is marked
522 /// compressed.
523 NO_COMPRESSION: bool = false,
524 /// 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
525 /// 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.
526 /// For more information, see the Remarks section.
527 ///
528 /// Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP: This flag is not supported.
529 ///
530 /// This flag is supported on the following file systems: NTFS, FAT, and exFAT.
531 OPEN_REQUIRING_OPLOCK: bool = false,
532 Reserved17: u3 = 0,
533 /// This flag allows an application to request a filter opportunistic lock to prevent other applications from getting share violations. If there are already open
534 /// handles, the create request will fail with STATUS_OPLOCK_NOT_GRANTED. For more information, see the Remarks section.
535 RESERVE_OPFILTER: bool = false,
536 /// Open a file with a reparse point and bypass normal reparse point processing for the file. For more information, see the Remarks section.
537 OPEN_REPARSE_POINT: bool = false,
538 /// Instructs any filters that perform offline storage or virtualization to not recall the contents of the file as a result of this open.
539 OPEN_NO_RECALL: bool = false,
540 /// This flag instructs the file system to capture the user associated with the calling thread. Any subsequent calls to `FltQueryVolumeInformation` or
541 /// `ZwQueryVolumeInformationFile` using the returned handle will assume the captured user, rather than the calling user at the time, for purposes of computing
542 /// the free space available to the caller. This applies to the following FsInformationClass values: `FileFsSizeInformation`, `FileFsFullSizeInformation`, and
543 /// `FileFsFullSizeInformationEx`.
544 OPEN_FOR_FREE_SPACE_QUERY: bool = false,
545 Reserved24: u8 = 0,
546
547 pub const VALID_OPTION_FLAGS: MODE = .{
548 .DIRECTORY_FILE = true,
549 .WRITE_THROUGH = true,
550 .SEQUENTIAL_ONLY = true,
551 .NO_INTERMEDIATE_BUFFERING = true,
552 .IO = .VALID_FLAGS,
553 .NON_DIRECTORY_FILE = true,
554 .CREATE_TREE_CONNECTION = true,
555 .COMPLETE_IF_OPLOCKED = true,
556 .NO_EA_KNOWLEDGE = true,
557 .OPEN_REMOTE_INSTANCE = true,
558 .RANDOM_ACCESS = true,
559 .DELETE_ON_CLOSE = true,
560 .OPEN_BY_FILE_ID = true,
561 .OPEN_FOR_BACKUP_INTENT = true,
562 .NO_COMPRESSION = true,
563 .OPEN_REQUIRING_OPLOCK = true,
564 .Reserved17 = 0b111,
565 .RESERVE_OPFILTER = true,
566 .OPEN_REPARSE_POINT = true,
567 .OPEN_NO_RECALL = true,
568 .OPEN_FOR_FREE_SPACE_QUERY = true,
569 };
570
571 pub const VALID_PIPE_OPTION_FLAGS: MODE = .{
572 .WRITE_THROUGH = true,
573 .IO = .VALID_FLAGS,
574 };
575
576 pub const VALID_MAILSLOT_OPTION_FLAGS: MODE = .{
577 .WRITE_THROUGH = true,
578 .IO = .VALID_FLAGS,
579 };
580
581 pub const VALID_SET_OPTION_FLAGS: MODE = .{
582 .WRITE_THROUGH = true,
583 .SEQUENTIAL_ONLY = true,
584 .IO = .VALID_FLAGS,
585 };
586
587 // ref: km/ntifs.h
588
589 pub const INFORMATION = extern struct {
590 /// The set of flags that specify the mode in which the file can be accessed. These flags are a subset of `MODE`.
591 Mode: MODE,
592 };
593 };
594};
595
596// ref: km/ntddk.h
597
598pub const PROCESSINFOCLASS = enum(c_int) {
599 BasicInformation = 0,
600 QuotaLimits = 1,
601 IoCounters = 2,
602 VmCounters = 3,
603 Times = 4,
604 BasePriority = 5,
605 RaisePriority = 6,
606 DebugPort = 7,
607 ExceptionPort = 8,
608 AccessToken = 9,
609 LdtInformation = 10,
610 LdtSize = 11,
611 DefaultHardErrorMode = 12,
612 IoPortHandlers = 13,
613 PooledUsageAndLimits = 14,
614 WorkingSetWatch = 15,
615 UserModeIOPL = 16,
616 EnableAlignmentFaultFixup = 17,
617 PriorityClass = 18,
618 Wx86Information = 19,
619 HandleCount = 20,
620 AffinityMask = 21,
621 PriorityBoost = 22,
622 DeviceMap = 23,
623 SessionInformation = 24,
624 ForegroundInformation = 25,
625 Wow64Information = 26,
626 ImageFileName = 27,
627 LUIDDeviceMapsEnabled = 28,
628 BreakOnTermination = 29,
629 DebugObjectHandle = 30,
630 DebugFlags = 31,
631 HandleTracing = 32,
632 IoPriority = 33,
633 ExecuteFlags = 34,
634 TlsInformation = 35,
635 Cookie = 36,
636 ImageInformation = 37,
637 CycleTime = 38,
638 PagePriority = 39,
639 InstrumentationCallback = 40,
640 ThreadStackAllocation = 41,
641 WorkingSetWatchEx = 42,
642 ImageFileNameWin32 = 43,
643 ImageFileMapping = 44,
644 AffinityUpdateMode = 45,
645 MemoryAllocationMode = 46,
646 GroupInformation = 47,
647 TokenVirtualizationEnabled = 48,
648 OwnerInformation = 49,
649 WindowInformation = 50,
650 HandleInformation = 51,
651 MitigationPolicy = 52,
652 DynamicFunctionTableInformation = 53,
653 HandleCheckingMode = 54,
654 KeepAliveCount = 55,
655 RevokeFileHandles = 56,
656 WorkingSetControl = 57,
657 HandleTable = 58,
658 CheckStackExtentsMode = 59,
659 CommandLineInformation = 60,
660 ProtectionInformation = 61,
661 MemoryExhaustion = 62,
662 FaultInformation = 63,
663 TelemetryIdInformation = 64,
664 CommitReleaseInformation = 65,
665 Reserved1Information = 66,
666 Reserved2Information = 67,
667 SubsystemProcess = 68,
668 InPrivate = 70,
669 RaiseUMExceptionOnInvalidHandleClose = 71,
670 SubsystemInformation = 75,
671 Win32kSyscallFilterInformation = 79,
672 EnergyTrackingState = 82,
673 NetworkIoCounters = 114,
674 _,
675
676 pub const Max: @typeInfo(@This()).@"enum".tag_type = 117;
677};
678
679pub const THREADINFOCLASS = enum(c_int) {
680 BasicInformation = 0,
681 Times = 1,
682 Priority = 2,
683 BasePriority = 3,
684 AffinityMask = 4,
685 ImpersonationToken = 5,
686 DescriptorTableEntry = 6,
687 EnableAlignmentFaultFixup = 7,
688 EventPair_Reusable = 8,
689 QuerySetWin32StartAddress = 9,
690 ZeroTlsCell = 10,
691 PerformanceCount = 11,
692 AmILastThread = 12,
693 IdealProcessor = 13,
694 PriorityBoost = 14,
695 SetTlsArrayAddress = 15,
696 IsIoPending = 16,
697 // Windows 2000+ from here
698 HideFromDebugger = 17,
699 // Windows XP+ from here
700 BreakOnTermination = 18,
701 SwitchLegacyState = 19,
702 IsTerminated = 20,
703 // Windows Vista+ from here
704 LastSystemCall = 21,
705 IoPriority = 22,
706 CycleTime = 23,
707 PagePriority = 24,
708 ActualBasePriority = 25,
709 TebInformation = 26,
710 CSwitchMon = 27,
711 // Windows 7+ from here
712 CSwitchPmu = 28,
713 Wow64Context = 29,
714 GroupInformation = 30,
715 UmsInformation = 31,
716 CounterProfiling = 32,
717 IdealProcessorEx = 33,
718 // Windows 8+ from here
719 CpuAccountingInformation = 34,
720 // Windows 8.1+ from here
721 SuspendCount = 35,
722 // Windows 10+ from here
723 HeterogeneousCpuPolicy = 36,
724 ContainerId = 37,
725 NameInformation = 38,
726 SelectedCpuSets = 39,
727 SystemThreadInformation = 40,
728 ActualGroupAffinity = 41,
729 DynamicCodePolicyInfo = 42,
730 SubsystemInformation = 45,
731
732 pub const Max: @typeInfo(@This()).@"enum".tag_type = 60;
733};
734
735// ref: km/ntifs.h
736
737pub const HEAP = opaque {
738 pub const FLAGS = packed struct(u8) {
739 /// Serialized access is not used when the heap functions access this heap. This option
740 /// applies to all subsequent heap function calls. Alternatively, you can specify this
741 /// option on individual heap function calls.
742 ///
743 /// The low-fragmentation heap (LFH) cannot be enabled for a heap created with this option.
744 ///
745 /// A heap created with this option cannot be locked.
746 NO_SERIALIZE: bool = false,
747 /// Specifies that the heap is growable. Must be specified if `HeapBase` is `NULL`.
748 GROWABLE: bool = false,
749 /// The system raises an exception to indicate failure (for example, an out-of-memory
750 /// condition) for calls to `HeapAlloc` and `HeapReAlloc` instead of returning `NULL`.
751 ///
752 /// To ensure that exceptions are generated for all calls to an allocation function, specify
753 /// `GENERATE_EXCEPTIONS` in the call to `HeapCreate`. In this case, it is not necessary to
754 /// additionally specify `GENERATE_EXCEPTIONS` in the allocation function calls.
755 GENERATE_EXCEPTIONS: bool = false,
756 /// The allocated memory will be initialized to zero. Otherwise, the memory is not
757 /// initialized to zero.
758 ZERO_MEMORY: bool = false,
759 REALLOC_IN_PLACE_ONLY: bool = false,
760 TAIL_CHECKING_ENABLED: bool = false,
761 FREE_CHECKING_ENABLED: bool = false,
762 DISABLE_COALESCE_ON_FREE: bool = false,
763
764 pub const CLASS = enum(u4) {
765 /// process heap
766 PROCESS,
767 /// private heap
768 PRIVATE,
769 /// Kernel Heap
770 KERNEL,
771 /// GDI heap
772 GDI,
773 /// User heap
774 USER,
775 /// Console heap
776 CONSOLE,
777 /// User Desktop heap
778 USER_DESKTOP,
779 /// Csrss Shared heap
780 CSRSS_SHARED,
781 /// Csr Port heap
782 CSR_PORT,
783 _,
784
785 pub const MASK: CLASS = @enumFromInt(maxInt(@typeInfo(CLASS).@"enum".tag_type));
786 };
787
788 pub const CREATE = packed struct(ULONG) {
789 COMMON: FLAGS = .{},
790 SEGMENT_HEAP: bool = false,
791 /// Only applies to segment heap. Applies pointer obfuscation which is
792 /// generally excessive and unnecessary but is necessary for certain insecure
793 /// heaps in win32k.
794 ///
795 /// Specifying HEAP_CREATE_HARDENED prevents the heap from using locks as
796 /// pointers would potentially be exposed in heap metadata lock variables.
797 /// Callers are therefore responsible for synchronizing access to hardened heaps.
798 HARDENED: bool = false,
799 Reserved10: u2 = 0,
800 CLASS: CLASS = @enumFromInt(0),
801 /// Create heap with 16 byte alignment (obsolete)
802 ALIGN_16: bool = false,
803 /// Create heap call tracing enabled (obsolete)
804 ENABLE_TRACING: bool = false,
805 /// Create heap with executable pages
806 ///
807 /// All memory blocks that are allocated from this heap allow code execution, if the
808 /// hardware enforces data execution prevention. Use this flag heap in applications that
809 /// run code from the heap. If `ENABLE_EXECUTE` is not specified and an application
810 /// attempts to run code from a protected page, the application receives an exception
811 /// with the status code `STATUS_ACCESS_VIOLATION`.
812 ENABLE_EXECUTE: bool = false,
813 Reserved19: u13 = 0,
814
815 pub const VALID_MASK: CREATE = .{
816 .COMMON = .{
817 .NO_SERIALIZE = true,
818 .GROWABLE = true,
819 .GENERATE_EXCEPTIONS = true,
820 .ZERO_MEMORY = true,
821 .REALLOC_IN_PLACE_ONLY = true,
822 .TAIL_CHECKING_ENABLED = true,
823 .FREE_CHECKING_ENABLED = true,
824 .DISABLE_COALESCE_ON_FREE = true,
825 },
826 .CLASS = .MASK,
827 .ALIGN_16 = true,
828 .ENABLE_TRACING = true,
829 .ENABLE_EXECUTE = true,
830 .SEGMENT_HEAP = true,
831 .HARDENED = true,
832 };
833 };
834
835 pub const ALLOCATION = packed struct(ULONG) {
836 COMMON: FLAGS = .{},
837 SETTABLE_USER: packed struct(u4) {
838 VALUE: u1 = 0,
839 FLAGS: packed struct(u3) {
840 FLAG1: bool = false,
841 FLAG2: bool = false,
842 FLAG3: bool = false,
843 } = .{},
844 } = .{},
845 CLASS: CLASS = @enumFromInt(0),
846 Reserved16: u2 = 0,
847 TAG: u12 = 0,
848 Reserved30: u2 = 0,
849 };
850 };
851
852 pub const RTL_PARAMETERS = extern struct {
853 Length: ULONG,
854 SegmentReserve: SIZE_T,
855 SegmentCommit: SIZE_T,
856 DeCommitFreeBlockThreshold: SIZE_T,
857 DeCommitTotalFreeThreshold: SIZE_T,
858 MaximumAllocationSize: SIZE_T,
859 VirtualMemoryThreshold: SIZE_T,
860 InitialCommit: SIZE_T,
861 InitialReserve: SIZE_T,
862 CommitRoutine: *const COMMIT_ROUTINE,
863 Reserved: [2]SIZE_T = @splat(0),
864
865 pub const COMMIT_ROUTINE = fn (
866 Base: PVOID,
867 CommitAddress: *PVOID,
868 CommitSize: *SIZE_T,
869 ) callconv(.winapi) NTSTATUS;
870
871 pub const SEGMENT = extern struct {
872 Version: VERSION,
873 Size: USHORT,
874 Flags: FLG,
875 MemorySource: MEMORY_SOURCE,
876 Reserved: [4]SIZE_T,
877
878 pub const VERSION = enum(USHORT) {
879 CURRENT = 3,
880 _,
881 };
882
883 pub const FLG = packed struct(ULONG) {
884 USE_PAGE_HEAP: bool = false,
885 NO_LFH: bool = false,
886 Reserved2: u30 = 0,
887
888 pub const VALID_FLAGS: FLG = .{
889 .USE_PAGE_HEAP = true,
890 .NO_LFH = true,
891 };
892 };
893
894 pub const MEMORY_SOURCE = extern struct {
895 Flags: ULONG,
896 MemoryTypeMask: TYPE,
897 NumaNode: ULONG,
898 u: extern union {
899 PartitionHandle: HANDLE,
900 Callbacks: *const VA_CALLBACKS,
901 },
902 Reserved: [2]SIZE_T = @splat(0),
903
904 pub const TYPE = enum(ULONG) {
905 Paged,
906 NonPaged,
907 @"64KPage",
908 LargePage,
909 HugePage,
910 Custom,
911 _,
912
913 pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
914 };
915
916 pub const VA_CALLBACKS = extern struct {
917 CallbackContext: HANDLE,
918 AllocateVirtualMemory: *const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK,
919 FreeVirtualMemory: *const FREE_VIRTUAL_MEMORY_EX_CALLBACK,
920 QueryVirtualMemory: *const QUERY_VIRTUAL_MEMORY_CALLBACK,
921
922 pub const ALLOCATE_VIRTUAL_MEMORY_EX_CALLBACK = fn (
923 CallbackContext: HANDLE,
924 BaseAddress: *PVOID,
925 RegionSize: *SIZE_T,
926 AllocationType: ULONG,
927 PageProtection: ULONG,
928 ExtendedParameters: ?[*]MEM.EXTENDED_PARAMETER,
929 ExtendedParameterCount: ULONG,
930 ) callconv(.c) NTSTATUS;
931
932 pub const FREE_VIRTUAL_MEMORY_EX_CALLBACK = fn (
933 CallbackContext: HANDLE,
934 ProcessHandle: HANDLE,
935 BaseAddress: *PVOID,
936 RegionSize: *SIZE_T,
937 FreeType: ULONG,
938 ) callconv(.c) NTSTATUS;
939
940 pub const QUERY_VIRTUAL_MEMORY_CALLBACK = fn (
941 CallbackContext: HANDLE,
942 ProcessHandle: HANDLE,
943 BaseAddress: *PVOID,
944 MemoryInformationClass: MEMORY_INFO_CLASS,
945 MemoryInformation: PVOID,
946 MemoryInformationLength: SIZE_T,
947 ReturnLength: ?*SIZE_T,
948 ) callconv(.c) NTSTATUS;
949
950 pub const MEMORY_INFO_CLASS = enum(c_int) {
951 Basic,
952 _,
953 };
954 };
955 };
956 };
957 };
958};
959
960pub const CTL_CODE = packed struct(ULONG) {
961 Method: METHOD,
962 Function: u12,
963 Access: FILE_ACCESS,
964 DeviceType: FILE_DEVICE,
965
966 pub const METHOD = enum(u2) {
967 BUFFERED = 0,
968 IN_DIRECT = 1,
969 OUT_DIRECT = 2,
970 NEITHER = 3,
971 };
972
973 pub const FILE_ACCESS = packed struct(u2) {
974 READ: bool = false,
975 WRITE: bool = false,
976
977 pub const ANY: FILE_ACCESS = .{ .READ = false, .WRITE = false };
978 pub const SPECIAL = ANY;
979 };
980
981 pub const FILE_DEVICE = enum(u16) {
982 BEEP = 0x00000001,
983 CD_ROM = 0x00000002,
984 CD_ROM_FILE_SYSTEM = 0x00000003,
985 CONTROLLER = 0x00000004,
986 DATALINK = 0x00000005,
987 DFS = 0x00000006,
988 DISK = 0x00000007,
989 DISK_FILE_SYSTEM = 0x00000008,
990 FILE_SYSTEM = 0x00000009,
991 INPORT_PORT = 0x0000000a,
992 KEYBOARD = 0x0000000b,
993 MAILSLOT = 0x0000000c,
994 MIDI_IN = 0x0000000d,
995 MIDI_OUT = 0x0000000e,
996 MOUSE = 0x0000000f,
997 MULTI_UNC_PROVIDER = 0x00000010,
998 NAMED_PIPE = 0x00000011,
999 NETWORK = 0x00000012,
1000 NETWORK_BROWSER = 0x00000013,
1001 NETWORK_FILE_SYSTEM = 0x00000014,
1002 NULL = 0x00000015,
1003 PARALLEL_PORT = 0x00000016,
1004 PHYSICAL_NETCARD = 0x00000017,
1005 PRINTER = 0x00000018,
1006 SCANNER = 0x00000019,
1007 SERIAL_MOUSE_PORT = 0x0000001a,
1008 SERIAL_PORT = 0x0000001b,
1009 SCREEN = 0x0000001c,
1010 SOUND = 0x0000001d,
1011 STREAMS = 0x0000001e,
1012 TAPE = 0x0000001f,
1013 TAPE_FILE_SYSTEM = 0x00000020,
1014 TRANSPORT = 0x00000021,
1015 UNKNOWN = 0x00000022,
1016 VIDEO = 0x00000023,
1017 VIRTUAL_DISK = 0x00000024,
1018 WAVE_IN = 0x00000025,
1019 WAVE_OUT = 0x00000026,
1020 @"8042_PORT" = 0x00000027,
1021 NETWORK_REDIRECTOR = 0x00000028,
1022 BATTERY = 0x00000029,
1023 BUS_EXTENDER = 0x0000002a,
1024 MODEM = 0x0000002b,
1025 VDM = 0x0000002c,
1026 MASS_STORAGE = 0x0000002d,
1027 SMB = 0x0000002e,
1028 KS = 0x0000002f,
1029 CHANGER = 0x00000030,
1030 SMARTCARD = 0x00000031,
1031 ACPI = 0x00000032,
1032 DVD = 0x00000033,
1033 FULLSCREEN_VIDEO = 0x00000034,
1034 DFS_FILE_SYSTEM = 0x00000035,
1035 DFS_VOLUME = 0x00000036,
1036 SERENUM = 0x00000037,
1037 TERMSRV = 0x00000038,
1038 KSEC = 0x00000039,
1039 FIPS = 0x0000003A,
1040 INFINIBAND = 0x0000003B,
1041 VMBUS = 0x0000003E,
1042 CRYPT_PROVIDER = 0x0000003F,
1043 WPD = 0x00000040,
1044 BLUETOOTH = 0x00000041,
1045 MT_COMPOSITE = 0x00000042,
1046 MT_TRANSPORT = 0x00000043,
1047 BIOMETRIC = 0x00000044,
1048 PMI = 0x00000045,
1049 EHSTOR = 0x00000046,
1050 DEVAPI = 0x00000047,
1051 GPIO = 0x00000048,
1052 USBEX = 0x00000049,
1053 CONSOLE = 0x00000050,
1054 NFP = 0x00000051,
1055 SYSENV = 0x00000052,
1056 VIRTUAL_BLOCK = 0x00000053,
1057 POINT_OF_SERVICE = 0x00000054,
1058 STORAGE_REPLICATION = 0x00000055,
1059 TRUST_ENV = 0x00000056,
1060 UCM = 0x00000057,
1061 UCMTCPCI = 0x00000058,
1062 PERSISTENT_MEMORY = 0x00000059,
1063 NVDIMM = 0x0000005a,
1064 HOLOGRAPHIC = 0x0000005b,
1065 SDFXHCI = 0x0000005c,
1066 UCMUCSI = 0x0000005d,
1067 PRM = 0x0000005e,
1068 EVENT_COLLECTOR = 0x0000005f,
1069 USB4 = 0x00000060,
1070 SOUNDWIRE = 0x00000061,
1071
1072 MOUNTMGRCONTROLTYPE = 'm',
1073
1074 _,
1075 };
1076};
1077
1078pub const IOCTL = struct {
1079 pub const MOUNTMGR = struct {
1080 pub const QUERY_POINTS: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY };
1081 pub const QUERY_DOS_VOLUME_PATH: CTL_CODE = .{ .DeviceType = .MOUNTMGRCONTROLTYPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY };
1082 };
1083};
1084
1085pub const FSCTL = struct {
1086 pub const SET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 41, .Method = .BUFFERED, .Access = .SPECIAL };
1087 pub const GET_REPARSE_POINT: CTL_CODE = .{ .DeviceType = .FILE_SYSTEM, .Function = 42, .Method = .BUFFERED, .Access = .ANY };
1088
1089 pub const PIPE = struct {
1090 pub const ASSIGN_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 0, .Method = .BUFFERED, .Access = .ANY };
1091 pub const DISCONNECT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 1, .Method = .BUFFERED, .Access = .ANY };
1092 pub const LISTEN: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2, .Method = .BUFFERED, .Access = .ANY };
1093 pub const PEEK: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 3, .Method = .BUFFERED, .Access = .{ .READ = true } };
1094 pub const QUERY_EVENT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 4, .Method = .BUFFERED, .Access = .ANY };
1095 pub const TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 5, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } };
1096 pub const WAIT: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 6, .Method = .BUFFERED, .Access = .ANY };
1097 pub const IMPERSONATE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 7, .Method = .BUFFERED, .Access = .ANY };
1098 pub const SET_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 8, .Method = .BUFFERED, .Access = .ANY };
1099 pub const QUERY_CLIENT_PROCESS: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 9, .Method = .BUFFERED, .Access = .ANY };
1100 pub const GET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 10, .Method = .BUFFERED, .Access = .ANY };
1101 pub const SET_PIPE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 11, .Method = .BUFFERED, .Access = .ANY };
1102 pub const GET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 12, .Method = .BUFFERED, .Access = .ANY };
1103 pub const SET_CONNECTION_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 13, .Method = .BUFFERED, .Access = .ANY };
1104 pub const GET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 14, .Method = .BUFFERED, .Access = .ANY };
1105 pub const SET_HANDLE_ATTRIBUTE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 15, .Method = .BUFFERED, .Access = .ANY };
1106 pub const FLUSH: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 16, .Method = .BUFFERED, .Access = .{ .WRITE = true } };
1107
1108 pub const INTERNAL_READ: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2045, .Method = .BUFFERED, .Access = .{ .READ = true } };
1109 pub const INTERNAL_WRITE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2046, .Method = .BUFFERED, .Access = .{ .WRITE = true } };
1110 pub const INTERNAL_TRANSCEIVE: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2047, .Method = .NEITHER, .Access = .{ .READ = true, .WRITE = true } };
1111 pub const INTERNAL_READ_OVFLOW: CTL_CODE = .{ .DeviceType = .NAMED_PIPE, .Function = 2048, .Method = .BUFFERED, .Access = .{ .READ = true } };
1112 };
1113};
1114
1115pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
1116
1117pub const IO_REPARSE_TAG = packed struct(ULONG) {
1118 Value: u12,
1119 Index: u4 = 0,
1120 ReservedBits: u12 = 0,
1121 /// Can have children if a directory.
1122 IsDirectory: bool = false,
1123 /// Represents another named entity in the system.
1124 IsSurrogate: bool = false,
1125 /// Must be `false` for non-Microsoft tags.
1126 IsReserved: bool = false,
1127 /// Owned by Microsoft.
1128 IsMicrosoft: bool = false,
1129
1130 pub const RESERVED_INVALID: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Index = 0x8, .Value = 0x000 };
1131 pub const MOUNT_POINT: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x003 };
1132 pub const HSM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x004 };
1133 pub const DRIVE_EXTENDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x005 };
1134 pub const HSM2: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x006 };
1135 pub const SIS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x007 };
1136 pub const WIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x008 };
1137 pub const CSV: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x009 };
1138 pub const DFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00A };
1139 pub const FILTER_MANAGER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x00B };
1140 pub const SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x00C };
1141 pub const IIS_CACHE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x010 };
1142 pub const DFSR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x012 };
1143 pub const DEDUP: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x013 };
1144 pub const APPXSTRM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsReserved = true, .Value = 0x014 };
1145 pub const NFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x014 };
1146 pub const FILE_PLACEHOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x015 };
1147 pub const DFM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x016 };
1148 pub const WOF: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x017 };
1149 pub inline fn WCI(index: u1) IO_REPARSE_TAG {
1150 return .{ .IsMicrosoft = true, .IsDirectory = index == 0x1, .Index = index, .Value = 0x018 };
1151 }
1152 pub const GLOBAL_REPARSE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x0019 };
1153 pub inline fn CLOUD(index: u4) IO_REPARSE_TAG {
1154 return .{ .IsMicrosoft = true, .IsDirectory = true, .Index = index, .Value = 0x01A };
1155 }
1156 pub const APPEXECLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01B };
1157 pub const PROJFS: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x01C };
1158 pub const LX_SYMLINK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01D };
1159 pub const STORAGE_SYNC: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x01E };
1160 pub const WCI_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x01F };
1161 pub const UNHANDLED: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x020 };
1162 pub const ONEDRIVE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x021 };
1163 pub const PROJFS_TOMBSTONE: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x022 };
1164 pub const AF_UNIX: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x023 };
1165 pub const LX_FIFO: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x024 };
1166 pub const LX_CHR: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x025 };
1167 pub const LX_BLK: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .Value = 0x026 };
1168 pub const LX_STORAGE_SYNC_FOLDER: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsDirectory = true, .Value = 0x027 };
1169 pub inline fn WCI_LINK(index: u1) IO_REPARSE_TAG {
1170 return .{ .IsMicrosoft = true, .IsSurrogate = true, .Index = index, .Value = 0x027 };
1171 }
1172 pub const DATALESS_CIM: IO_REPARSE_TAG = .{ .IsMicrosoft = true, .IsSurrogate = true, .Value = 0x28 };
1173};
1174
1175// ref: km/wdm.h
1176
1177pub const ACCESS_MASK = packed struct(DWORD) {
1178 SPECIFIC: Specific = .{ .bits = 0 },
1179 STANDARD: Standard = .{},
1180 Reserved21: u3 = 0,
1181 ACCESS_SYSTEM_SECURITY: bool = false,
1182 MAXIMUM_ALLOWED: bool = false,
1183 Reserved26: u2 = 0,
1184 GENERIC: Generic = .{},
1185
1186 pub const Specific = packed union {
1187 bits: u16,
1188
1189 // ref: km/wdm.h
1190
1191 /// Define access rights to files and directories
1192 FILE: File,
1193 FILE_DIRECTORY: File.Directory,
1194 FILE_PIPE: File.Pipe,
1195 /// Registry Specific Access Rights.
1196 KEY: Key,
1197 /// Object Manager Object Type Specific Access Rights.
1198 OBJECT_TYPE: ObjectType,
1199 /// Object Manager Directory Specific Access Rights.
1200 DIRECTORY: Directory,
1201 /// Object Manager Symbolic Link Specific Access Rights.
1202 SYMBOLIC_LINK: SymbolicLink,
1203 /// Section Access Rights.
1204 SECTION: Section,
1205 /// Session Specific Access Rights.
1206 SESSION: Session,
1207 /// Process Specific Access Rights.
1208 PROCESS: Process,
1209 /// Thread Specific Access Rights.
1210 THREAD: Thread,
1211 /// Partition Specific Access Rights.
1212 MEMORY_PARTITION: MemoryPartition,
1213 /// Generic mappings for transaction manager rights.
1214 TRANSACTIONMANAGER: TransactionManager,
1215 /// Generic mappings for transaction rights.
1216 TRANSACTION: Transaction,
1217 /// Generic mappings for resource manager rights.
1218 RESOURCEMANAGER: ResourceManager,
1219 /// Generic mappings for enlistment rights.
1220 ENLISTMENT: Enlistment,
1221 /// Event Specific Access Rights.
1222 EVENT: Event,
1223 /// Semaphore Specific Access Rights.
1224 SEMAPHORE: Semaphore,
1225
1226 // ref: km/ntifs.h
1227
1228 /// Token Specific Access Rights.
1229 TOKEN: Token,
1230
1231 // um/winnt.h
1232
1233 /// Job Object Specific Access Rights.
1234 JOB_OBJECT: JobObject,
1235 /// Mutant Specific Access Rights.
1236 MUTANT: Mutant,
1237 /// Timer Specific Access Rights.
1238 TIMER: Timer,
1239 /// I/O Completion Specific Access Rights.
1240 IO_COMPLETION: IoCompletion,
1241
1242 pub const File = packed struct(u16) {
1243 READ_DATA: bool = false,
1244 WRITE_DATA: bool = false,
1245 APPEND_DATA: bool = false,
1246 READ_EA: bool = false,
1247 WRITE_EA: bool = false,
1248 EXECUTE: bool = false,
1249 Reserved6: u1 = 0,
1250 READ_ATTRIBUTES: bool = false,
1251 WRITE_ATTRIBUTES: bool = false,
1252 Reserved9: u7 = 0,
1253
1254 pub const ALL_ACCESS: ACCESS_MASK = .{
1255 .STANDARD = .{
1256 .RIGHTS = .REQUIRED,
1257 .SYNCHRONIZE = true,
1258 },
1259 .SPECIFIC = .{ .FILE = .{
1260 .READ_DATA = true,
1261 .WRITE_DATA = true,
1262 .APPEND_DATA = true,
1263 .READ_EA = true,
1264 .WRITE_EA = true,
1265 .EXECUTE = true,
1266 .Reserved6 = maxInt(@FieldType(File, "Reserved6")),
1267 .READ_ATTRIBUTES = true,
1268 .WRITE_ATTRIBUTES = true,
1269 } },
1270 };
1271
1272 pub const GENERIC_READ: ACCESS_MASK = .{
1273 .STANDARD = .{
1274 .RIGHTS = .READ,
1275 .SYNCHRONIZE = true,
1276 },
1277 .SPECIFIC = .{ .FILE = .{
1278 .READ_DATA = true,
1279 .READ_ATTRIBUTES = true,
1280 .READ_EA = true,
1281 } },
1282 };
1283
1284 pub const GENERIC_WRITE: ACCESS_MASK = .{
1285 .STANDARD = .{
1286 .RIGHTS = .WRITE,
1287 .SYNCHRONIZE = true,
1288 },
1289 .SPECIFIC = .{ .FILE = .{
1290 .WRITE_DATA = true,
1291 .WRITE_ATTRIBUTES = true,
1292 .WRITE_EA = true,
1293 .APPEND_DATA = true,
1294 } },
1295 };
1296
1297 pub const GENERIC_EXECUTE: ACCESS_MASK = .{
1298 .STANDARD = .{
1299 .RIGHTS = .EXECUTE,
1300 .SYNCHRONIZE = true,
1301 },
1302 .SPECIFIC = .{ .FILE = .{
1303 .READ_ATTRIBUTES = true,
1304 .EXECUTE = true,
1305 } },
1306 };
1307
1308 pub const Directory = packed struct(u16) {
1309 LIST: bool = false,
1310 ADD_FILE: bool = false,
1311 ADD_SUBDIRECTORY: bool = false,
1312 READ_EA: bool = false,
1313 WRITE_EA: bool = false,
1314 TRAVERSE: bool = false,
1315 DELETE_CHILD: bool = false,
1316 READ_ATTRIBUTES: bool = false,
1317 WRITE_ATTRIBUTES: bool = false,
1318 Reserved9: u7 = 0,
1319 };
1320
1321 pub const Pipe = packed struct(u16) {
1322 READ_DATA: bool = false,
1323 WRITE_DATA: bool = false,
1324 CREATE_PIPE_INSTANCE: bool = false,
1325 Reserved3: u4 = 0,
1326 READ_ATTRIBUTES: bool = false,
1327 WRITE_ATTRIBUTES: bool = false,
1328 Reserved9: u7 = 0,
1329 };
1330 };
1331
1332 pub const Key = packed struct(u16) {
1333 /// Required to query the values of a registry key.
1334 QUERY_VALUE: bool = false,
1335 /// Required to create, delete, or set a registry value.
1336 SET_VALUE: bool = false,
1337 /// Required to create a subkey of a registry key.
1338 CREATE_SUB_KEY: bool = false,
1339 /// Required to enumerate the subkeys of a registry key.
1340 ENUMERATE_SUB_KEYS: bool = false,
1341 /// Required to request change notifications for a registry key or for subkeys of a registry key.
1342 NOTIFY: bool = false,
1343 /// Reserved for system use.
1344 CREATE_LINK: bool = false,
1345 Reserved6: u2 = 0,
1346 /// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view.
1347 /// This flag is ignored by 32-bit Windows.
1348 WOW64_64KEY: bool = false,
1349 /// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view.
1350 /// This flag is ignored by 32-bit Windows.
1351 WOW64_32KEY: bool = false,
1352 Reserved10: u6 = 0,
1353
1354 pub const WOW64_RES: ACCESS_MASK = .{
1355 .SPECIFIC = .{ .KEY = .{
1356 .WOW64_32KEY = true,
1357 .WOW64_64KEY = true,
1358 } },
1359 };
1360
1361 /// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values.
1362 pub const READ: ACCESS_MASK = .{
1363 .STANDARD = .{
1364 .RIGHTS = .READ,
1365 .SYNCHRONIZE = false,
1366 },
1367 .SPECIFIC = .{ .KEY = .{
1368 .QUERY_VALUE = true,
1369 .ENUMERATE_SUB_KEYS = true,
1370 .NOTIFY = true,
1371 } },
1372 };
1373
1374 /// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights.
1375 pub const WRITE: ACCESS_MASK = .{
1376 .STANDARD = .{
1377 .RIGHTS = .WRITE,
1378 .SYNCHRONIZE = false,
1379 },
1380 .SPECIFIC = .{ .KEY = .{
1381 .SET_VALUE = true,
1382 .CREATE_SUB_KEY = true,
1383 } },
1384 };
1385
1386 /// Equivalent to KEY_READ.
1387 pub const EXECUTE = READ;
1388
1389 pub const ALL_ACCESS: ACCESS_MASK = .{
1390 .STANDARD = .{
1391 .RIGHTS = .ALL,
1392 .SYNCHRONIZE = false,
1393 },
1394 .SPECIFIC = .{ .KEY = .{
1395 .QUERY_VALUE = true,
1396 .SET_VALUE = true,
1397 .CREATE_SUB_KEY = true,
1398 .ENUMERATE_SUB_KEYS = true,
1399 .NOTIFY = true,
1400 .CREATE_LINK = true,
1401 } },
1402 };
1403 };
1404
1405 pub const ObjectType = packed struct(u16) {
1406 CREATE: bool = false,
1407 Reserved1: u15 = 0,
1408
1409 pub const ALL_ACCESS: ACCESS_MASK = .{
1410 .STANDARD = .{ .RIGHTS = .REQUIRED },
1411 .SPECIFIC = .{ .OBJECT_TYPE = .{
1412 .CREATE = true,
1413 } },
1414 };
1415 };
1416
1417 pub const Directory = packed struct(u16) {
1418 QUERY: bool = false,
1419 TRAVERSE: bool = false,
1420 CREATE_OBJECT: bool = false,
1421 CREATE_SUBDIRECTORY: bool = false,
1422 Reserved3: u12 = 0,
1423
1424 pub const ALL_ACCESS: ACCESS_MASK = .{
1425 .STANDARD = .{ .RIGHTS = .REQUIRED },
1426 .SPECIFIC = .{ .DIRECTORY = .{
1427 .QUERY = true,
1428 .TRAVERSE = true,
1429 .CREATE_OBJECT = true,
1430 .CREATE_SUBDIRECTORY = true,
1431 } },
1432 };
1433 };
1434
1435 pub const SymbolicLink = packed struct(u16) {
1436 QUERY: bool = false,
1437 SET: bool = false,
1438 Reserved2: u14 = 0,
1439
1440 pub const ALL_ACCESS: ACCESS_MASK = .{
1441 .STANDARD = .{ .RIGHTS = .REQUIRED },
1442 .SPECIFIC = .{ .SYMBOLIC_LINK = .{
1443 .QUERY = true,
1444 } },
1445 };
1446
1447 pub const ALL_ACCESS_EX: ACCESS_MASK = .{
1448 .STANDARD = .{ .RIGHTS = .REQUIRED },
1449 .SPECIFIC = .{ .SYMBOLIC_LINK = .{
1450 .QUERY = true,
1451 .SET = true,
1452 .Reserved2 = maxInt(@FieldType(SymbolicLink, "Reserved2")),
1453 } },
1454 };
1455 };
1456
1457 pub const Section = packed struct(u16) {
1458 QUERY: bool = false,
1459 MAP_WRITE: bool = false,
1460 MAP_READ: bool = false,
1461 MAP_EXECUTE: bool = false,
1462 EXTEND_SIZE: bool = false,
1463 /// not included in `ALL_ACCESS`
1464 MAP_EXECUTE_EXPLICIT: bool = false,
1465 Reserved6: u10 = 0,
1466
1467 pub const ALL_ACCESS: ACCESS_MASK = .{
1468 .STANDARD = .{ .RIGHTS = .REQUIRED },
1469 .SPECIFIC = .{ .SECTION = .{
1470 .QUERY = true,
1471 .MAP_WRITE = true,
1472 .MAP_READ = true,
1473 .MAP_EXECUTE = true,
1474 .EXTEND_SIZE = true,
1475 } },
1476 };
1477 };
1478
1479 pub const Session = packed struct(u16) {
1480 QUERY_ACCESS: bool = false,
1481 MODIFY_ACCESS: bool = false,
1482 Reserved2: u14 = 0,
1483
1484 pub const ALL_ACCESS: ACCESS_MASK = .{
1485 .STANDARD = .{ .RIGHTS = .REQUIRED },
1486 .SPECIFIC = .{ .SESSION = .{
1487 .QUERY_ACCESS = true,
1488 .MODIFY_ACCESS = true,
1489 } },
1490 };
1491 };
1492
1493 pub const Process = packed struct(u16) {
1494 TERMINATE: bool = false,
1495 CREATE_THREAD: bool = false,
1496 SET_SESSIONID: bool = false,
1497 VM_OPERATION: bool = false,
1498 VM_READ: bool = false,
1499 VM_WRITE: bool = false,
1500 DUP_HANDLE: bool = false,
1501 CREATE_PROCESS: bool = false,
1502 SET_QUOTA: bool = false,
1503 SET_INFORMATION: bool = false,
1504 QUERY_INFORMATION: bool = false,
1505 SUSPEND_RESUME: bool = false,
1506 QUERY_LIMITED_INFORMATION: bool = false,
1507 SET_LIMITED_INFORMATION: bool = false,
1508 Reserved14: u2 = 0,
1509
1510 pub const ALL_ACCESS: ACCESS_MASK = .{
1511 .STANDARD = .{
1512 .RIGHTS = .REQUIRED,
1513 .SYNCHRONIZE = true,
1514 },
1515 .SPECIFIC = .{ .PROCESS = .{
1516 .TERMINATE = true,
1517 .CREATE_THREAD = true,
1518 .SET_SESSIONID = true,
1519 .VM_OPERATION = true,
1520 .VM_READ = true,
1521 .VM_WRITE = true,
1522 .DUP_HANDLE = true,
1523 .CREATE_PROCESS = true,
1524 .SET_QUOTA = true,
1525 .SET_INFORMATION = true,
1526 .QUERY_INFORMATION = true,
1527 .SUSPEND_RESUME = true,
1528 .QUERY_LIMITED_INFORMATION = true,
1529 .SET_LIMITED_INFORMATION = true,
1530 .Reserved14 = maxInt(@FieldType(Process, "Reserved14")),
1531 } },
1532 };
1533 };
1534
1535 pub const Thread = packed struct(u16) {
1536 TERMINATE: bool = false,
1537 SUSPEND_RESUME: bool = false,
1538 ALERT: bool = false,
1539 GET_CONTEXT: bool = false,
1540 SET_CONTEXT: bool = false,
1541 SET_INFORMATION: bool = false,
1542 QUERY_INFORMATION: bool = false,
1543 SET_THREAD_TOKEN: bool = false,
1544 IMPERSONATE: bool = false,
1545 DIRECT_IMPERSONATION: bool = false,
1546 SET_LIMITED_INFORMATION: bool = false,
1547 QUERY_LIMITED_INFORMATION: bool = false,
1548 RESUME: bool = false,
1549 Reserved13: u3 = 0,
1550
1551 pub const ALL_ACCESS: ACCESS_MASK = .{
1552 .STANDARD = .{
1553 .RIGHTS = .REQUIRED,
1554 .SYNCHRONIZE = true,
1555 },
1556 .SPECIFIC = .{ .THREAD = .{
1557 .TERMINATE = true,
1558 .SUSPEND_RESUME = true,
1559 .ALERT = true,
1560 .GET_CONTEXT = true,
1561 .SET_CONTEXT = true,
1562 .SET_INFORMATION = true,
1563 .QUERY_INFORMATION = true,
1564 .SET_THREAD_TOKEN = true,
1565 .IMPERSONATE = true,
1566 .DIRECT_IMPERSONATION = true,
1567 .SET_LIMITED_INFORMATION = true,
1568 .QUERY_LIMITED_INFORMATION = true,
1569 .RESUME = true,
1570 .Reserved13 = maxInt(@FieldType(Thread, "Reserved13")),
1571 } },
1572 };
1573 };
1574
1575 pub const MemoryPartition = packed struct(u16) {
1576 QUERY_ACCESS: bool = false,
1577 MODIFY_ACCESS: bool = false,
1578 Required2: u14 = 0,
1579
1580 pub const ALL_ACCESS: ACCESS_MASK = .{
1581 .STANDARD = .{
1582 .RIGHTS = .REQUIRED,
1583 .SYNCHRONIZE = true,
1584 },
1585 .SPECIFIC = .{ .MEMORY_PARTITION = .{
1586 .QUERY_ACCESS = true,
1587 .MODIFY_ACCESS = true,
1588 } },
1589 };
1590 };
1591
1592 pub const TransactionManager = packed struct(u16) {
1593 QUERY_INFORMATION: bool = false,
1594 SET_INFORMATION: bool = false,
1595 RECOVER: bool = false,
1596 RENAME: bool = false,
1597 CREATE_RM: bool = false,
1598 /// The following right is intended for DTC's use only; it will be deprecated, and no one else should take a dependency on it.
1599 BIND_TRANSACTION: bool = false,
1600 Reserved6: u10 = 0,
1601
1602 pub const GENERIC_READ: ACCESS_MASK = .{
1603 .STANDARD = .{ .RIGHTS = .READ },
1604 .SPECIFIC = .{ .TRANSACTIONMANAGER = .{
1605 .QUERY_INFORMATION = true,
1606 } },
1607 };
1608
1609 pub const GENERIC_WRITE: ACCESS_MASK = .{
1610 .STANDARD = .{ .RIGHTS = .WRITE },
1611 .SPECIFIC = .{ .TRANSACTIONMANAGER = .{
1612 .SET_INFORMATION = true,
1613 .RECOVER = true,
1614 .RENAME = true,
1615 .CREATE_RM = true,
1616 } },
1617 };
1618
1619 pub const GENERIC_EXECUTE: ACCESS_MASK = .{
1620 .STANDARD = .{ .RIGHTS = .EXECUTE },
1621 .SPECIFIC = .{ .TRANSACTIONMANAGER = .{} },
1622 };
1623
1624 pub const ALL_ACCESS: ACCESS_MASK = .{
1625 .STANDARD = .{ .RIGHTS = .REQUIRED },
1626 .SPECIFIC = .{ .TRANSACTIONMANAGER = .{
1627 .QUERY_INFORMATION = true,
1628 .SET_INFORMATION = true,
1629 .RECOVER = true,
1630 .RENAME = true,
1631 .CREATE_RM = true,
1632 .BIND_TRANSACTION = true,
1633 } },
1634 };
1635 };
1636
1637 pub const Transaction = packed struct(u16) {
1638 QUERY_INFORMATION: bool = false,
1639 SET_INFORMATION: bool = false,
1640 ENLIST: bool = false,
1641 COMMIT: bool = false,
1642 ROLLBACK: bool = false,
1643 PROPAGATE: bool = false,
1644 RIGHT_RESERVED1: bool = false,
1645 Reserved7: u9 = 0,
1646
1647 pub const GENERIC_READ: ACCESS_MASK = .{
1648 .STANDARD = .{
1649 .RIGHTS = .READ,
1650 .SYNCHRONIZE = true,
1651 },
1652 .SPECIFIC = .{ .TRANSACTION = .{
1653 .QUERY_INFORMATION = true,
1654 } },
1655 };
1656
1657 pub const GENERIC_WRITE: ACCESS_MASK = .{
1658 .STANDARD = .{
1659 .RIGHTS = .WRITE,
1660 .SYNCHRONIZE = true,
1661 },
1662 .SPECIFIC = .{ .TRANSACTION = .{
1663 .SET_INFORMATION = true,
1664 .COMMIT = true,
1665 .ENLIST = true,
1666 .ROLLBACK = true,
1667 .PROPAGATE = true,
1668 } },
1669 };
1670
1671 pub const GENERIC_EXECUTE: ACCESS_MASK = .{
1672 .STANDARD = .{
1673 .RIGHTS = .EXECUTE,
1674 .SYNCHRONIZE = true,
1675 },
1676 .SPECIFIC = .{ .TRANSACTION = .{
1677 .COMMIT = true,
1678 .ROLLBACK = true,
1679 } },
1680 };
1681
1682 pub const ALL_ACCESS: ACCESS_MASK = .{
1683 .STANDARD = .{
1684 .RIGHTS = .REQUIRED,
1685 .SYNCHRONIZE = true,
1686 },
1687 .SPECIFIC = .{ .TRANSACTION = .{
1688 .QUERY_INFORMATION = true,
1689 .SET_INFORMATION = true,
1690 .COMMIT = true,
1691 .ENLIST = true,
1692 .ROLLBACK = true,
1693 .PROPAGATE = true,
1694 } },
1695 };
1696
1697 pub const RESOURCE_MANAGER_RIGHTS: ACCESS_MASK = .{
1698 .STANDARD = .{
1699 .RIGHTS = .{
1700 .READ_CONTROL = true,
1701 },
1702 .SYNCHRONIZE = true,
1703 },
1704 .SPECIFIC = .{ .TRANSACTION = .{
1705 .QUERY_INFORMATION = true,
1706 .SET_INFORMATION = true,
1707 .ENLIST = true,
1708 .ROLLBACK = true,
1709 .PROPAGATE = true,
1710 } },
1711 };
1712 };
1713
1714 pub const ResourceManager = packed struct(u16) {
1715 QUERY_INFORMATION: bool = false,
1716 SET_INFORMATION: bool = false,
1717 RECOVER: bool = false,
1718 ENLIST: bool = false,
1719 GET_NOTIFICATION: bool = false,
1720 REGISTER_PROTOCOL: bool = false,
1721 COMPLETE_PROPAGATION: bool = false,
1722 Reserved7: u9 = 0,
1723
1724 pub const GENERIC_READ: ACCESS_MASK = .{
1725 .STANDARD = .{
1726 .RIGHTS = .READ,
1727 .SYNCHRONIZE = true,
1728 },
1729 .SPECIFIC = .{ .RESOURCEMANAGER = .{
1730 .QUERY_INFORMATION = true,
1731 } },
1732 };
1733
1734 pub const GENERIC_WRITE: ACCESS_MASK = .{
1735 .STANDARD = .{
1736 .RIGHTS = .WRITE,
1737 .SYNCHRONIZE = true,
1738 },
1739 .SPECIFIC = .{ .RESOURCEMANAGER = .{
1740 .SET_INFORMATION = true,
1741 .RECOVER = true,
1742 .ENLIST = true,
1743 .GET_NOTIFICATION = true,
1744 .REGISTER_PROTOCOL = true,
1745 .COMPLETE_PROPAGATION = true,
1746 } },
1747 };
1748
1749 pub const GENERIC_EXECUTE: ACCESS_MASK = .{
1750 .STANDARD = .{
1751 .RIGHTS = .EXECUTE,
1752 .SYNCHRONIZE = true,
1753 },
1754 .SPECIFIC = .{ .RESOURCEMANAGER = .{
1755 .RECOVER = true,
1756 .ENLIST = true,
1757 .GET_NOTIFICATION = true,
1758 .COMPLETE_PROPAGATION = true,
1759 } },
1760 };
1761
1762 pub const ALL_ACCESS: ACCESS_MASK = .{
1763 .STANDARD = .{
1764 .RIGHTS = .REQUIRED,
1765 .SYNCHRONIZE = true,
1766 },
1767 .SPECIFIC = .{ .RESOURCEMANAGER = .{
1768 .QUERY_INFORMATION = true,
1769 .SET_INFORMATION = true,
1770 .RECOVER = true,
1771 .ENLIST = true,
1772 .GET_NOTIFICATION = true,
1773 .REGISTER_PROTOCOL = true,
1774 .COMPLETE_PROPAGATION = true,
1775 } },
1776 };
1777 };
1778
1779 pub const Enlistment = packed struct(u16) {
1780 QUERY_INFORMATION: bool = false,
1781 SET_INFORMATION: bool = false,
1782 RECOVER: bool = false,
1783 SUBORDINATE_RIGHTS: bool = false,
1784 SUPERIOR_RIGHTS: bool = false,
1785 Reserved5: u11 = 0,
1786
1787 pub const GENERIC_READ: ACCESS_MASK = .{
1788 .STANDARD = .{ .RIGHTS = .READ },
1789 .SPECIFIC = .{ .ENLISTMENT = .{
1790 .QUERY_INFORMATION = true,
1791 } },
1792 };
1793
1794 pub const GENERIC_WRITE: ACCESS_MASK = .{
1795 .STANDARD = .{ .RIGHTS = .WRITE },
1796 .SPECIFIC = .{ .ENLISTMENT = .{
1797 .SET_INFORMATION = true,
1798 .RECOVER = true,
1799 .SUBORDINATE_RIGHTS = true,
1800 .SUPERIOR_RIGHTS = true,
1801 } },
1802 };
1803
1804 pub const GENERIC_EXECUTE: ACCESS_MASK = .{
1805 .STANDARD = .{ .RIGHTS = .EXECUTE },
1806 .SPECIFIC = .{ .ENLISTMENT = .{
1807 .RECOVER = true,
1808 .SUBORDINATE_RIGHTS = true,
1809 .SUPERIOR_RIGHTS = true,
1810 } },
1811 };
1812
1813 pub const ALL_ACCESS: ACCESS_MASK = .{
1814 .STANDARD = .{ .RIGHTS = .REQUIRED },
1815 .SPECIFIC = .{ .ENLISTMENT = .{
1816 .QUERY_INFORMATION = true,
1817 .SET_INFORMATION = true,
1818 .RECOVER = true,
1819 .SUBORDINATE_RIGHTS = true,
1820 .SUPERIOR_RIGHTS = true,
1821 } },
1822 };
1823 };
1824
1825 pub const Event = packed struct(u16) {
1826 QUERY_STATE: bool = false,
1827 MODIFY_STATE: bool = false,
1828 Reserved2: u14 = 0,
1829
1830 pub const ALL_ACCESS: ACCESS_MASK = .{
1831 .STANDARD = .{
1832 .RIGHTS = .REQUIRED,
1833 .SYNCHRONIZE = true,
1834 },
1835 .SPECIFIC = .{ .EVENT = .{
1836 .QUERY_STATE = true,
1837 .MODIFY_STATE = true,
1838 } },
1839 };
1840 };
1841
1842 pub const Semaphore = packed struct(u16) {
1843 QUERY_STATE: bool = false,
1844 MODIFY_STATE: bool = false,
1845 Reserved2: u14 = 0,
1846
1847 pub const ALL_ACCESS: ACCESS_MASK = .{
1848 .STANDARD = .{
1849 .RIGHTS = .REQUIRED,
1850 .SYNCHRONIZE = true,
1851 },
1852 .SPECIFIC = .{ .SEMAPHORE = .{
1853 .QUERY_STATE = true,
1854 .MODIFY_STATE = true,
1855 } },
1856 };
1857 };
1858
1859 pub const Token = packed struct(u16) {
1860 ASSIGN_PRIMARY: bool = false,
1861 DUPLICATE: bool = false,
1862 IMPERSONATE: bool = false,
1863 QUERY: bool = false,
1864 QUERY_SOURCE: bool = false,
1865 ADJUST_PRIVILEGES: bool = false,
1866 ADJUST_GROUPS: bool = false,
1867 ADJUST_DEFAULT: bool = false,
1868 ADJUST_SESSIONID: bool = false,
1869 Reserved9: u7 = 0,
1870
1871 pub const ALL_ACCESS_P: ACCESS_MASK = .{
1872 .STANDARD = .{ .RIGHTS = .REQUIRED },
1873 .SPECIFIC = .{ .TOKEN = .{
1874 .ASSIGN_PRIMARY = true,
1875 .DUPLICATE = true,
1876 .IMPERSONATE = true,
1877 .QUERY = true,
1878 .QUERY_SOURCE = true,
1879 .ADJUST_PRIVILEGES = true,
1880 .ADJUST_GROUPS = true,
1881 .ADJUST_DEFAULT = true,
1882 } },
1883 };
1884
1885 pub const ALL_ACCESS: ACCESS_MASK = .{
1886 .STANDARD = .{ .RIGHTS = .REQUIRED },
1887 .SPECIFIC = .{ .TOKEN = .{
1888 .ASSIGN_PRIMARY = true,
1889 .DUPLICATE = true,
1890 .IMPERSONATE = true,
1891 .QUERY = true,
1892 .QUERY_SOURCE = true,
1893 .ADJUST_PRIVILEGES = true,
1894 .ADJUST_GROUPS = true,
1895 .ADJUST_DEFAULT = true,
1896 .ADJUST_SESSIONID = true,
1897 } },
1898 };
1899
1900 pub const READ: ACCESS_MASK = .{
1901 .STANDARD = .{ .RIGHTS = .READ },
1902 .SPECIFIC = .{ .TOKEN = .{
1903 .QUERY = true,
1904 } },
1905 };
1906
1907 pub const WRITE: ACCESS_MASK = .{
1908 .STANDARD = .{ .RIGHTS = .WRITE },
1909 .SPECIFIC = .{ .TOKEN = .{
1910 .ADJUST_PRIVILEGES = true,
1911 .ADJUST_GROUPS = true,
1912 .ADJUST_DEFAULT = true,
1913 } },
1914 };
1915
1916 pub const EXECUTE: ACCESS_MASK = .{
1917 .STANDARD = .{ .RIGHTS = .EXECUTE },
1918 .SPECIFIC = .{ .TOKEN = .{} },
1919 };
1920
1921 pub const TRUST_CONSTRAINT_MASK: ACCESS_MASK = .{
1922 .STANDARD = .{ .RIGHTS = .READ },
1923 .SPECIFIC = .{ .TOKEN = .{
1924 .QUERY = true,
1925 .QUERY_SOURCE = true,
1926 } },
1927 };
1928
1929 pub const TRUST_ALLOWED_MASK: ACCESS_MASK = .{
1930 .STANDARD = .{ .RIGHTS = .READ },
1931 .SPECIFIC = .{ .TOKEN = .{
1932 .QUERY = true,
1933 .QUERY_SOURCE = true,
1934 .DUPLICATE = true,
1935 .IMPERSONATE = true,
1936 } },
1937 };
1938 };
1939
1940 pub const JobObject = packed struct(u16) {
1941 ASSIGN_PROCESS: bool = false,
1942 SET_ATTRIBUTES: bool = false,
1943 QUERY: bool = false,
1944 TERMINATE: bool = false,
1945 SET_SECURITY_ATTRIBUTES: bool = false,
1946 IMPERSONATE: bool = false,
1947 Reserved6: u10 = 0,
1948
1949 pub const ALL_ACCESS: ACCESS_MASK = .{
1950 .STANDARD = .{
1951 .RIGHTS = .REQUIRED,
1952 .SYNCHRONIZE = true,
1953 },
1954 .SPECIFIC = .{ .JOB_OBJECT = .{
1955 .ASSIGN_PROCESS = true,
1956 .SET_ATTRIBUTES = true,
1957 .QUERY = true,
1958 .TERMINATE = true,
1959 .SET_SECURITY_ATTRIBUTES = true,
1960 .IMPERSONATE = true,
1961 } },
1962 };
1963 };
1964
1965 pub const Mutant = packed struct(u16) {
1966 QUERY_STATE: bool = false,
1967 Reserved1: u15 = 0,
1968
1969 pub const ALL_ACCESS: ACCESS_MASK = .{
1970 .STANDARD = .{
1971 .RIGHTS = .REQUIRED,
1972 .SYNCHRONIZE = true,
1973 },
1974 .SPECIFIC = .{ .MUTANT = .{
1975 .QUERY_STATE = true,
1976 } },
1977 };
1978 };
1979
1980 pub const Timer = packed struct(u16) {
1981 QUERY_STATE: bool = false,
1982 MODIFY_STATE: bool = false,
1983 Reserved2: u14 = 0,
1984
1985 pub const ALL_ACCESS: ACCESS_MASK = .{
1986 .STANDARD = .{
1987 .RIGHTS = .REQUIRED,
1988 .SYNCHRONIZE = true,
1989 },
1990 .SPECIFIC = .{ .TIMER = .{
1991 .QUERY_STATE = true,
1992 .MODIFY_STATE = true,
1993 } },
1994 };
1995 };
1996
1997 pub const IoCompletion = packed struct(u16) {
1998 Reserved0: u1 = 0,
1999 MODIFY_STATE: bool = false,
2000 Reserved2: u14 = 0,
2001
2002 pub const ALL_ACCESS: ACCESS_MASK = .{
2003 .STANDARD = .{ .RIGHTS = .REQUIRED, .SYNCHRONIZE = true },
2004 .SPECIFIC = .{ .IO_COMPLETION = .{
2005 .Reserved0 = maxInt(@FieldType(IoCompletion, "Reserved0")),
2006 .MODIFY_STATE = true,
2007 } },
2008 };
2009 };
2010
2011 pub const RIGHTS_ALL: Specific = .{ .bits = maxInt(@FieldType(Specific, "bits")) };
2012 };
2013
2014 pub const Standard = packed struct(u5) {
2015 RIGHTS: Rights = .{},
2016 SYNCHRONIZE: bool = false,
2017
2018 pub const RIGHTS_ALL: Standard = .{
2019 .RIGHTS = .ALL,
2020 .SYNCHRONIZE = true,
2021 };
2022
2023 pub const Rights = packed struct(u4) {
2024 DELETE: bool = false,
2025 READ_CONTROL: bool = false,
2026 WRITE_DAC: bool = false,
2027 WRITE_OWNER: bool = false,
2028
2029 pub const REQUIRED: Rights = .{
2030 .DELETE = true,
2031 .READ_CONTROL = true,
2032 .WRITE_DAC = true,
2033 .WRITE_OWNER = true,
2034 };
2035
2036 pub const READ: Rights = .{
2037 .READ_CONTROL = true,
2038 };
2039 pub const WRITE: Rights = .{
2040 .READ_CONTROL = true,
2041 };
2042 pub const EXECUTE: Rights = .{
2043 .READ_CONTROL = true,
2044 };
2045
2046 pub const ALL = REQUIRED;
2047 };
2048 };
2049
2050 pub const Generic = packed struct(u4) {
2051 ALL: bool = false,
2052 EXECUTE: bool = false,
2053 WRITE: bool = false,
2054 READ: bool = false,
2055 };
2056};
2057
2058pub const DEVICE_TYPE = packed struct(ULONG) {
2059 FileDevice: CTL_CODE.FILE_DEVICE,
2060 Reserved16: u16 = 0,
2061};
2062
2063pub const FS_INFORMATION_CLASS = enum(c_int) {
2064 Volume = 1,
2065 Label = 2,
2066 Size = 3,
2067 Device = 4,
2068 Attribute = 5,
2069 Control = 6,
2070 FullSize = 7,
2071 ObjectId = 8,
2072 DriverPath = 9,
2073 VolumeFlags = 10,
2074 SectorSize = 11,
2075 DataCopy = 12,
2076 MetadataSize = 13,
2077 FullSizeEx = 14,
2078 Guid = 15,
2079 _,
2080
2081 pub const Maximum: @typeInfo(@This()).@"enum".tag_type = 1 + @typeInfo(@This()).@"enum".fields.len;
2082};
2083
2084pub const SECTION_INHERIT = enum(c_int) {
2085 Share = 1,
2086 Unmap = 2,
2087};
2088
2089pub const PAGE = packed struct(ULONG) {
2090 NOACCESS: bool = false,
2091 READONLY: bool = false,
2092 READWRITE: bool = false,
2093 WRITECOPY: bool = false,
2094
2095 EXECUTE: bool = false,
2096 EXECUTE_READ: bool = false,
2097 EXECUTE_READWRITE: bool = false,
2098 EXECUTE_WRITECOPY: bool = false,
2099
2100 GUARD: bool = false,
2101 NOCACHE: bool = false,
2102 WRITECOMBINE: bool = false,
2103
2104 GRAPHICS_NOACCESS: bool = false,
2105 GRAPHICS_READONLY: bool = false,
2106 GRAPHICS_READWRITE: bool = false,
2107 GRAPHICS_EXECUTE: bool = false,
2108 GRAPHICS_EXECUTE_READ: bool = false,
2109 GRAPHICS_EXECUTE_READWRITE: bool = false,
2110 GRAPHICS_COHERENT: bool = false,
2111 GRAPHICS_NOCACHE: bool = false,
2112
2113 Reserved19: u12 = 0,
2114
2115 REVERT_TO_FILE_MAP: bool = false,
2116};
2117
2118pub const MEM = struct {
2119 pub const ALLOCATE = packed struct(ULONG) {
2120 Reserved0: u12 = 0,
2121 COMMIT: bool = false,
2122 RESERVE: bool = false,
2123 REPLACE_PLACEHOLDER: bool = false,
2124 Reserved15: u3 = 0,
2125 RESERVE_PLACEHOLDER: bool = false,
2126 RESET: bool = false,
2127 TOP_DOWN: bool = false,
2128 WRITE_WATCH: bool = false,
2129 PHYSICAL: bool = false,
2130 Reserved23: u1 = 0,
2131 RESET_UNDO: bool = false,
2132 Reserved25: u4 = 0,
2133 LARGE_PAGES: bool = false,
2134 Reserved30: u1 = 0,
2135 @"4MB_PAGES": bool = false,
2136
2137 pub const @"64K_PAGES": ALLOCATE = .{
2138 .LARGE_PAGES = true,
2139 .PHYSICAL = true,
2140 };
2141 };
2142
2143 pub const FREE = packed struct(ULONG) {
2144 COALESCE_PLACEHOLDERS: bool = false,
2145 PRESERVE_PLACEHOLDER: bool = false,
2146 Reserved2: u12 = 0,
2147 DECOMMIT: bool = false,
2148 RELEASE: bool = false,
2149 FREE: bool = false,
2150 Reserved17: u15 = 0,
2151 };
2152
2153 pub const MAP = packed struct(ULONG) {
2154 Reserved0: u13 = 0,
2155 RESERVE: bool = false,
2156 REPLACE_PLACEHOLDER: bool = false,
2157 Reserved15: u14 = 0,
2158 LARGE_PAGES: bool = false,
2159 Reserved30: u2 = 0,
2160 };
2161
2162 pub const UNMAP = packed struct(ULONG) {
2163 WITH_TRANSIENT_BOOST: bool = false,
2164 PRESERVE_PLACEHOLDER: bool = false,
2165 Reserved2: u30 = 0,
2166 };
2167
2168 pub const EXTENDED_PARAMETER = extern struct {
2169 s: packed struct(ULONG64) {
2170 Type: TYPE,
2171 Reserved: u56,
2172 },
2173 u: extern union {
2174 ULong64: ULONG64,
2175 Pointer: PVOID,
2176 Size: SIZE_T,
2177 Handle: HANDLE,
2178 ULong: ULONG,
2179 },
2180
2181 pub const TYPE = enum(u8) {
2182 InvalidType = 0,
2183 AddressRequirements,
2184 NumaNode,
2185 PartitionHandle,
2186 UserPhysicalHandle,
2187 AttributeFlags,
2188 ImageMachine,
2189 _,
2190
2191 pub const Max: @typeInfo(@This()).@"enum".tag_type = @typeInfo(@This()).@"enum".fields.len;
2192 };
2193 };
2194};
2195
2196pub const SEC = packed struct(ULONG) {
2197 Reserved0: u17 = 0,
2198 HUGE_PAGES: bool = false,
2199 PARTITION_OWNER_HANDLE: bool = false,
2200 @"64K_PAGES": bool = false,
2201 Reserved19: u3 = 0,
2202 FILE: bool = false,
2203 IMAGE: bool = false,
2204 PROTECTED_IMAGE: bool = false,
2205 RESERVE: bool = false,
2206 COMMIT: bool = false,
2207 NOCACHE: bool = false,
2208 Reserved29: u1 = 0,
2209 WRITECOMBINE: bool = false,
2210 LARGE_PAGES: bool = false,
2211
2212 pub const IMAGE_NO_EXECUTE: SEC = .{
2213 .IMAGE = true,
2214 .NOCACHE = true,
2215 };
2216};
2217
2218pub const ERESOURCE = opaque {};
2219
2220// ref: shared/ntdef.h
2221
2222pub const EVENT_TYPE = enum(c_int) {
2223 Notification,
2224 Synchronization,
2225};
2226
2227pub const TIMER_TYPE = enum(c_int) {
2228 Notification,
2229 Synchronization,
2230};
2231
2232pub const WAIT_TYPE = enum(c_int) {
2233 All,
2234 Any,
2235};
2236
2237pub const LOGICAL = ULONG;
2238
2239pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
2240
2241// ref: um/heapapi.h
2242
2243pub fn GetProcessHeap() ?*HEAP {
2244 return peb().ProcessHeap;
2245}
2246
2247// ref: um/winternl.h
2248
2249pub const OBJECT_ATTRIBUTES = extern struct {
2250 Length: ULONG,
2251 RootDirectory: ?HANDLE,
2252 ObjectName: *UNICODE_STRING,
2253 Attributes: ATTRIBUTES,
2254 SecurityDescriptor: ?*anyopaque,
2255 SecurityQualityOfService: ?*anyopaque,
2256
2257 // Valid values for the Attributes field
2258 pub const ATTRIBUTES = packed struct(ULONG) {
2259 Reserved0: u1 = 0,
2260 INHERIT: bool = false,
2261 Reserved2: u2 = 0,
2262 PERMANENT: bool = false,
2263 EXCLUSIVE: bool = false,
2264 /// If name-lookup code should ignore the case of the ObjectName member rather than performing an exact-match search.
2265 CASE_INSENSITIVE: bool = true,
2266 OPENIF: bool = false,
2267 OPENLINK: bool = false,
2268 KERNEL_HANDLE: bool = false,
2269 FORCE_ACCESS_CHECK: bool = false,
2270 IGNORE_IMPERSONATED_DEVICEMAP: bool = false,
2271 DONT_REPARSE: bool = false,
2272 Reserved13: u19 = 0,
2273
2274 pub const VALID_ATTRIBUTES: ATTRIBUTES = .{
2275 .INHERIT = true,
2276 .PERMANENT = true,
2277 .EXCLUSIVE = true,
2278 .CASE_INSENSITIVE = true,
2279 .OPENIF = true,
2280 .OPENLINK = true,
2281 .KERNEL_HANDLE = true,
2282 .FORCE_ACCESS_CHECK = true,
2283 .IGNORE_IMPERSONATED_DEVICEMAP = true,
2284 .DONT_REPARSE = true,
2285 };
2286 };
2287};
2288
2289// ref none
342290
352291pub const OpenError = error{
362292 IsDir,
......@@ -52,8 +2308,8 @@ pub const OpenFileOptions = struct {
522308 access_mask: ACCESS_MASK,
532309 dir: ?HANDLE = null,
542310 sa: ?*SECURITY_ATTRIBUTES = null,
55 share_access: ULONG = FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
56 creation: ULONG,
2311 share_access: FILE.SHARE = .VALID_FLAGS,
2312 creation: FILE.CREATE_DISPOSITION,
572313 /// If true, tries to open path as a directory.
582314 /// Defaults to false.
592315 filter: Filter = .file_only,
......@@ -82,32 +2338,22 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
822338 var result: HANDLE = undefined;
832339
842340 const path_len_bytes = math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong;
85 var nt_name = UNICODE_STRING{
2341 var nt_name: UNICODE_STRING = .{
862342 .Length = path_len_bytes,
872343 .MaximumLength = path_len_bytes,
882344 .Buffer = @constCast(sub_path_w.ptr),
892345 };
90 var attr = OBJECT_ATTRIBUTES{
2346 const attr: OBJECT_ATTRIBUTES = .{
912347 .Length = @sizeOf(OBJECT_ATTRIBUTES),
922348 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
93 .Attributes = if (options.sa) |ptr| blk: { // Note we do not use OBJ_CASE_INSENSITIVE here.
94 const inherit: ULONG = if (ptr.bInheritHandle == TRUE) OBJ_INHERIT else 0;
95 break :blk inherit;
96 } else 0,
2349 .Attributes = .{
2350 .INHERIT = if (options.sa) |sa| sa.bInheritHandle != FALSE else false,
2351 },
972352 .ObjectName = &nt_name,
982353 .SecurityDescriptor = if (options.sa) |ptr| ptr.lpSecurityDescriptor else null,
992354 .SecurityQualityOfService = null,
1002355 };
1012356 var io: IO_STATUS_BLOCK = undefined;
102 const blocking_flag: ULONG = FILE_SYNCHRONOUS_IO_NONALERT;
103 const file_or_dir_flag: ULONG = switch (options.filter) {
104 .file_only => FILE_NON_DIRECTORY_FILE,
105 .dir_only => FILE_DIRECTORY_FILE,
106 .any => 0,
107 };
108 // If we're not following symlinks, we need to ensure we don't pass in any synchronization flags such as FILE_SYNCHRONOUS_IO_NONALERT.
109 const flags: ULONG = if (options.follow_symlinks) file_or_dir_flag | blocking_flag else file_or_dir_flag | FILE_OPEN_REPARSE_POINT;
110
1112357 while (true) {
1122358 const rc = ntdll.NtCreateFile(
1132359 &result,
......@@ -115,10 +2361,15 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
1152361 &attr,
1162362 &io,
1172363 null,
118 FILE_ATTRIBUTE_NORMAL,
2364 .{ .NORMAL = true },
1192365 options.share_access,
1202366 options.creation,
121 flags,
2367 .{
2368 .DIRECTORY_FILE = options.filter == .dir_only,
2369 .NON_DIRECTORY_FILE = options.filter == .file_only,
2370 .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS,
2371 .OPEN_REPARSE_POINT = !options.follow_symlinks,
2372 },
1222373 null,
1232374 0,
1242375 );
......@@ -201,16 +2452,16 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
2012452 const dev_handle = opt_dev_handle orelse blk: {
2022453 const str = std.unicode.utf8ToUtf16LeStringLiteral("\\Device\\NamedPipe\\");
2032454 const len: u16 = @truncate(str.len * @sizeOf(u16));
204 const name = UNICODE_STRING{
2455 const name: UNICODE_STRING = .{
2052456 .Length = len,
2062457 .MaximumLength = len,
2072458 .Buffer = @ptrCast(@constCast(str)),
2082459 };
209 const attrs = OBJECT_ATTRIBUTES{
2460 const attrs: OBJECT_ATTRIBUTES = .{
2102461 .ObjectName = @constCast(&name),
2112462 .Length = @sizeOf(OBJECT_ATTRIBUTES),
2122463 .RootDirectory = null,
213 .Attributes = 0,
2464 .Attributes = .{},
2142465 .SecurityDescriptor = null,
2152466 .SecurityQualityOfService = null,
2162467 };
......@@ -219,14 +2470,17 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
2192470 var handle: HANDLE = undefined;
2202471 switch (ntdll.NtCreateFile(
2212472 &handle,
222 GENERIC_READ | SYNCHRONIZE,
2473 .{
2474 .STANDARD = .{ .SYNCHRONIZE = true },
2475 .GENERIC = .{ .READ = true },
2476 },
2232477 @constCast(&attrs),
2242478 &iosb,
2252479 null,
226 0,
227 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
228 FILE_OPEN,
229 FILE_SYNCHRONOUS_IO_NONALERT,
2480 .{},
2481 .VALID_FLAGS,
2482 .OPEN,
2483 .{ .IO = .SYNCHRONOUS_NONALERT },
2302484 null,
2312485 0,
2322486 )) {
......@@ -242,16 +2496,15 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
2422496 } else break :blk handle;
2432497 };
2442498
245 const name = UNICODE_STRING{ .Buffer = null, .Length = 0, .MaximumLength = 0 };
246 var attrs = OBJECT_ATTRIBUTES{
2499 const name: UNICODE_STRING = .{ .Buffer = null, .Length = 0, .MaximumLength = 0 };
2500 var attrs: OBJECT_ATTRIBUTES = .{
2472501 .ObjectName = @constCast(&name),
2482502 .Length = @sizeOf(OBJECT_ATTRIBUTES),
2492503 .RootDirectory = dev_handle,
250 .Attributes = OBJ_CASE_INSENSITIVE,
2504 .Attributes = .{ .INHERIT = sattr.bInheritHandle != FALSE },
2512505 .SecurityDescriptor = sattr.lpSecurityDescriptor,
2522506 .SecurityQualityOfService = null,
2532507 };
254 if (sattr.bInheritHandle != 0) attrs.Attributes |= OBJ_INHERIT;
2552508
2562509 // 120 second relative timeout in 100ns units.
2572510 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
2592512 var read: HANDLE = undefined;
2602513 switch (ntdll.NtCreateNamedPipeFile(
2612514 &read,
262 GENERIC_READ | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
2515 .{
2516 .SPECIFIC = .{ .FILE_PIPE = .{
2517 .WRITE_ATTRIBUTES = true,
2518 } },
2519 .STANDARD = .{ .SYNCHRONIZE = true },
2520 .GENERIC = .{ .READ = true },
2521 },
2632522 &attrs,
2642523 &iosb,
265 FILE_SHARE_READ | FILE_SHARE_WRITE,
266 FILE_CREATE,
267 FILE_SYNCHRONOUS_IO_NONALERT,
268 FILE_PIPE_BYTE_STREAM_TYPE,
269 FILE_PIPE_BYTE_STREAM_MODE,
270 FILE_PIPE_QUEUE_OPERATION,
2524 .{ .READ = true, .WRITE = true },
2525 .CREATE,
2526 .{ .IO = .SYNCHRONOUS_NONALERT },
2527 .{ .TYPE = .BYTE_STREAM },
2528 .{ .MODE = .BYTE_STREAM },
2529 .{ .OPERATION = .QUEUE },
2712530 1,
2722531 4096,
2732532 4096,
......@@ -285,14 +2544,23 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
2852544 var write: HANDLE = undefined;
2862545 switch (ntdll.NtCreateFile(
2872546 &write,
288 GENERIC_WRITE | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
2547 .{
2548 .SPECIFIC = .{ .FILE_PIPE = .{
2549 .READ_ATTRIBUTES = true,
2550 } },
2551 .STANDARD = .{ .SYNCHRONIZE = true },
2552 .GENERIC = .{ .WRITE = true },
2553 },
2892554 &attrs,
2902555 &iosb,
2912556 null,
292 0,
293 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
294 FILE_OPEN,
295 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
2557 .{},
2558 .VALID_FLAGS,
2559 .OPEN,
2560 .{
2561 .IO = .SYNCHRONOUS_NONALERT,
2562 .NON_DIRECTORY_FILE = true,
2563 },
2962564 null,
2972565 0,
2982566 )) {
......@@ -311,6 +2579,15 @@ pub const DeviceIoControlError = error{
3112579 /// The volume does not contain a recognized file system. File system
3122580 /// drivers might not be loaded, or the volume may be corrupt.
3132581 UnrecognizedVolume,
2582 Pending,
2583 /// Attempted to connect a named pipe in the "closing" state, meaning a previous client has
2584 /// has closed their handle but we have not yet disconnected the pipe.
2585 PipeClosing,
2586 /// Attempted to connect a named pipe in the "connected" state, meaning a client has already
2587 /// opened the pipe; there is a good connection between client and server.
2588 PipeAlreadyConnected,
2589 /// Attempted to connect a non-blocking named pipe which is already listening for connections.
2590 PipeAlreadyListening,
3142591 Unexpected,
3152592};
3162593
......@@ -319,56 +2596,55 @@ pub const DeviceIoControlError = error{
3192596/// as a direct substitute for that call.
3202597/// TODO work out if we need to expose other arguments to the underlying syscalls.
3212598pub fn DeviceIoControl(
322 h: HANDLE,
323 ioControlCode: ULONG,
324 in: ?[]const u8,
325 out: ?[]u8,
2599 device: HANDLE,
2600 io_control_code: CTL_CODE,
2601 opts: struct {
2602 event: ?HANDLE = null,
2603 apc_routine: ?*const IO_APC_ROUTINE = null,
2604 apc_context: ?*anyopaque = null,
2605 io_status_block: ?*IO_STATUS_BLOCK = null,
2606 in: []const u8 = &.{},
2607 out: []u8 = &.{},
2608 },
3262609) DeviceIoControlError!void {
327 // Logic from: https://doxygen.reactos.org/d3/d74/deviceio_8c.html
328 const is_fsctl = (ioControlCode >> 16) == FILE_DEVICE_FILE_SYSTEM;
329
330 var io: IO_STATUS_BLOCK = undefined;
331 const in_ptr = if (in) |i| i.ptr else null;
332 const in_len = if (in) |i| @as(ULONG, @intCast(i.len)) else 0;
333 const out_ptr = if (out) |o| o.ptr else null;
334 const out_len = if (out) |o| @as(ULONG, @intCast(o.len)) else 0;
335
336 const rc = blk: {
337 if (is_fsctl) {
338 break :blk ntdll.NtFsControlFile(
339 h,
340 null,
341 null,
342 null,
343 &io,
344 ioControlCode,
345 in_ptr,
346 in_len,
347 out_ptr,
348 out_len,
349 );
350 } else {
351 break :blk ntdll.NtDeviceIoControlFile(
352 h,
353 null,
354 null,
355 null,
356 &io,
357 ioControlCode,
358 in_ptr,
359 in_len,
360 out_ptr,
361 out_len,
362 );
363 }
2610 var io_status_block: IO_STATUS_BLOCK = undefined;
2611 const rc = switch (io_control_code.DeviceType) {
2612 .FILE_SYSTEM, .NAMED_PIPE => ntdll.NtFsControlFile(
2613 device,
2614 opts.event,
2615 opts.apc_routine,
2616 opts.apc_context,
2617 opts.io_status_block orelse &io_status_block,
2618 io_control_code,
2619 if (opts.in.len > 0) opts.in.ptr else null,
2620 @intCast(opts.in.len),
2621 if (opts.out.len > 0) opts.out.ptr else null,
2622 @intCast(opts.out.len),
2623 ),
2624 else => ntdll.NtDeviceIoControlFile(
2625 device,
2626 opts.event,
2627 opts.apc_routine,
2628 opts.apc_context,
2629 opts.io_status_block orelse &io_status_block,
2630 io_control_code,
2631 if (opts.in.len > 0) opts.in.ptr else null,
2632 @intCast(opts.in.len),
2633 if (opts.out.len > 0) opts.out.ptr else null,
2634 @intCast(opts.out.len),
2635 ),
3642636 };
3652637 switch (rc) {
3662638 .SUCCESS => {},
2639 .PIPE_CLOSING => return error.PipeClosing,
2640 .PIPE_CONNECTED => return error.PipeAlreadyConnected,
2641 .PIPE_LISTENING => return error.PipeAlreadyListening,
3672642 .PRIVILEGE_NOT_HELD => return error.AccessDenied,
3682643 .ACCESS_DENIED => return error.AccessDenied,
3692644 .INVALID_DEVICE_REQUEST => return error.AccessDenied, // Not supported by the underlying filesystem
3702645 .INVALID_PARAMETER => unreachable,
3712646 .UNRECOGNIZED_VOLUME => return error.UnrecognizedVolume,
2647 .PENDING => return error.Pending,
3722648 else => return unexpectedStatus(rc),
3732649 }
3742650}
......@@ -704,7 +2980,7 @@ pub const SetCurrentDirectoryError = error{
7042980pub fn SetCurrentDirectory(path_name: []const u16) SetCurrentDirectoryError!void {
7052981 const path_len_bytes = math.cast(u16, path_name.len * 2) orelse return error.NameTooLong;
7062982
707 var nt_name = UNICODE_STRING{
2983 var nt_name: UNICODE_STRING = .{
7082984 .Length = path_len_bytes,
7092985 .MaximumLength = path_len_bytes,
7102986 .Buffer = @constCast(path_name.ptr),
......@@ -780,7 +3056,7 @@ pub fn CreateSymbolicLink(
7803056 is_directory: bool,
7813057) CreateSymbolicLinkError!void {
7823058 const SYMLINK_DATA = extern struct {
783 ReparseTag: ULONG,
3059 ReparseTag: IO_REPARSE_TAG,
7843060 ReparseDataLength: USHORT,
7853061 Reserved: USHORT,
7863062 SubstituteNameOffset: USHORT,
......@@ -791,9 +3067,12 @@ pub fn CreateSymbolicLink(
7913067 };
7923068
7933069 const symlink_handle = OpenFile(sym_link_path, .{
794 .access_mask = SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
3070 .access_mask = .{
3071 .STANDARD = .{ .SYNCHRONIZE = true },
3072 .GENERIC = .{ .WRITE = true, .READ = true },
3073 },
7953074 .dir = dir,
796 .creation = FILE_CREATE,
3075 .creation = .CREATE,
7973076 .filter = if (is_directory) .dir_only else .file_only,
7983077 }) catch |err| switch (err) {
7993078 error.IsDir => return error.PathAlreadyExists,
......@@ -845,8 +3124,8 @@ pub fn CreateSymbolicLink(
8453124 const buf_len = @sizeOf(SYMLINK_DATA) + final_target_path.len * 4;
8463125 const header_len = @sizeOf(ULONG) + @sizeOf(USHORT) * 2;
8473126 const target_is_absolute = std.fs.path.isAbsoluteWindowsWtf16(final_target_path);
848 const symlink_data = SYMLINK_DATA{
849 .ReparseTag = IO_REPARSE_TAG_SYMLINK,
3127 const symlink_data: SYMLINK_DATA = .{
3128 .ReparseTag = .SYMLINK,
8503129 .ReparseDataLength = @intCast(buf_len - header_len),
8513130 .Reserved = 0,
8523131 .SubstituteNameOffset = @intCast(final_target_path.len * 2),
......@@ -860,7 +3139,13 @@ pub fn CreateSymbolicLink(
8603139 @memcpy(buffer[@sizeOf(SYMLINK_DATA)..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path)));
8613140 const paths_start = @sizeOf(SYMLINK_DATA) + final_target_path.len * 2;
8623141 @memcpy(buffer[paths_start..][0 .. final_target_path.len * 2], @as([*]const u8, @ptrCast(final_target_path)));
863 _ = try DeviceIoControl(symlink_handle, FSCTL_SET_REPARSE_POINT, buffer[0..buf_len], null);
3142 _ = DeviceIoControl(symlink_handle, FSCTL.SET_REPARSE_POINT, .{ .in = buffer[0..buf_len] }) catch |err| switch (err) {
3143 error.PipeClosing => unreachable,
3144 error.PipeAlreadyConnected => unreachable,
3145 error.PipeAlreadyListening => unreachable,
3146 error.Pending => unreachable,
3147 else => |e| return e,
3148 };
8643149}
8653150
8663151pub const ReadLinkError = error{
......@@ -878,9 +3163,14 @@ pub const ReadLinkError = error{
8783163/// is safe to reuse a single buffer for both.
8793164pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLinkError![]u16 {
8803165 const result_handle = OpenFile(sub_path_w, .{
881 .access_mask = FILE_READ_ATTRIBUTES | SYNCHRONIZE,
3166 .access_mask = .{
3167 .SPECIFIC = .{ .FILE = .{
3168 .READ_ATTRIBUTES = true,
3169 } },
3170 .STANDARD = .{ .SYNCHRONIZE = true },
3171 },
8823172 .dir = dir,
883 .creation = FILE_OPEN,
3173 .creation = .OPEN,
8843174 .follow_symlinks = false,
8853175 .filter = .any,
8863176 }) catch |err| switch (err) {
......@@ -894,15 +3184,20 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi
8943184 defer CloseHandle(result_handle);
8953185
8963186 var reparse_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(REPARSE_DATA_BUFFER)) = undefined;
897 _ = DeviceIoControl(result_handle, FSCTL_GET_REPARSE_POINT, null, reparse_buf[0..]) catch |err| switch (err) {
3187 _ = DeviceIoControl(result_handle, FSCTL.GET_REPARSE_POINT, .{ .out = reparse_buf[0..] }) catch |err| switch (err) {
3188 error.PipeClosing => unreachable,
3189 error.PipeAlreadyConnected => unreachable,
3190 error.PipeAlreadyListening => unreachable,
8983191 error.AccessDenied => return error.Unexpected,
8993192 error.UnrecognizedVolume => return error.Unexpected,
3193 error.Pending => unreachable,
9003194 else => |e| return e,
9013195 };
9023196
9033197 const reparse_struct: *const REPARSE_DATA_BUFFER = @ptrCast(@alignCast(&reparse_buf[0]));
904 switch (reparse_struct.ReparseTag) {
905 IO_REPARSE_TAG_SYMLINK => {
3198 const IoReparseTagInt = @typeInfo(IO_REPARSE_TAG).@"struct".backing_integer.?;
3199 switch (@as(IoReparseTagInt, @bitCast(reparse_struct.ReparseTag))) {
3200 @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.SYMLINK)) => {
9063201 const buf: *const SYMBOLIC_LINK_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0]));
9073202 const offset = buf.SubstituteNameOffset >> 1;
9083203 const len = buf.SubstituteNameLength >> 1;
......@@ -910,16 +3205,14 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u16) ReadLi
9103205 const is_relative = buf.Flags & SYMLINK_FLAG_RELATIVE != 0;
9113206 return parseReadLinkPath(path_buf[offset..][0..len], is_relative, out_buffer);
9123207 },
913 IO_REPARSE_TAG_MOUNT_POINT => {
3208 @as(IoReparseTagInt, @bitCast(IO_REPARSE_TAG.MOUNT_POINT)) => {
9143209 const buf: *const MOUNT_POINT_REPARSE_BUFFER = @ptrCast(@alignCast(&reparse_struct.DataBuffer[0]));
9153210 const offset = buf.SubstituteNameOffset >> 1;
9163211 const len = buf.SubstituteNameLength >> 1;
9173212 const path_buf = @as([*]const u16, &buf.PathBuffer);
9183213 return parseReadLinkPath(path_buf[offset..][0..len], false, out_buffer);
9193214 },
920 else => {
921 return error.UnsupportedReparsePointType;
922 },
3215 else => return error.UnsupportedReparsePointType,
9233216 }
9243217}
9253218
......@@ -956,13 +3249,8 @@ pub const DeleteFileOptions = struct {
9563249};
9573250
9583251pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFileError!void {
959 const create_options_flags: ULONG = if (options.remove_dir)
960 FILE_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT
961 else
962 FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT; // would we ever want to delete the target instead?
963
9643252 const path_len_bytes = @as(u16, @intCast(sub_path_w.len * 2));
965 var nt_name = UNICODE_STRING{
3253 var nt_name: UNICODE_STRING = .{
9663254 .Length = path_len_bytes,
9673255 .MaximumLength = path_len_bytes,
9683256 // 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
9783266 return error.FileBusy;
9793267 }
9803268
981 var attr = OBJECT_ATTRIBUTES{
982 .Length = @sizeOf(OBJECT_ATTRIBUTES),
983 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
984 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
985 .ObjectName = &nt_name,
986 .SecurityDescriptor = null,
987 .SecurityQualityOfService = null,
988 };
9893269 var io: IO_STATUS_BLOCK = undefined;
9903270 var tmp_handle: HANDLE = undefined;
9913271 var rc = ntdll.NtCreateFile(
9923272 &tmp_handle,
993 SYNCHRONIZE | DELETE,
994 &attr,
3273 .{ .STANDARD = .{
3274 .RIGHTS = .{ .DELETE = true },
3275 .SYNCHRONIZE = true,
3276 } },
3277 &.{
3278 .Length = @sizeOf(OBJECT_ATTRIBUTES),
3279 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(sub_path_w)) null else options.dir,
3280 .Attributes = .{},
3281 .ObjectName = &nt_name,
3282 .SecurityDescriptor = null,
3283 .SecurityQualityOfService = null,
3284 },
9953285 &io,
9963286 null,
997 0,
998 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
999 FILE_OPEN,
1000 create_options_flags,
3287 .{},
3288 .VALID_FLAGS,
3289 .OPEN,
3290 .{
3291 .DIRECTORY_FILE = options.remove_dir,
3292 .NON_DIRECTORY_FILE = !options.remove_dir,
3293 .OPEN_REPARSE_POINT = true, // would we ever want to delete the target instead?
3294 },
10013295 null,
10023296 0,
10033297 );
......@@ -1031,18 +3325,17 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
10313325 // FileDispositionInformation if the return value lets us know that some aspect of it is not supported.
10323326 const need_fallback = need_fallback: {
10333327 // Deletion with posix semantics if the filesystem supports it.
1034 var info = FILE_DISPOSITION_INFORMATION_EX{
1035 .Flags = FILE_DISPOSITION_DELETE |
1036 FILE_DISPOSITION_POSIX_SEMANTICS |
1037 FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE,
1038 };
1039
3328 const info: FILE.DISPOSITION.INFORMATION.EX = .{ .Flags = .{
3329 .DELETE = true,
3330 .POSIX_SEMANTICS = true,
3331 .IGNORE_READONLY_ATTRIBUTE = true,
3332 } };
10403333 rc = ntdll.NtSetInformationFile(
10413334 tmp_handle,
10423335 &io,
10433336 &info,
1044 @sizeOf(FILE_DISPOSITION_INFORMATION_EX),
1045 .FileDispositionInformationEx,
3337 @sizeOf(FILE.DISPOSITION.INFORMATION.EX),
3338 .DispositionEx,
10463339 );
10473340 switch (rc) {
10483341 .SUCCESS => return,
......@@ -1061,16 +3354,15 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
10613354 if (need_fallback) {
10623355 // Deletion with file pending semantics, which requires waiting or moving
10633356 // files to get them removed (from here).
1064 var file_dispo = FILE_DISPOSITION_INFORMATION{
3357 const file_dispo: FILE.DISPOSITION.INFORMATION = .{
10653358 .DeleteFile = TRUE,
10663359 };
1067
10683360 rc = ntdll.NtSetInformationFile(
10693361 tmp_handle,
10703362 &io,
10713363 &file_dispo,
1072 @sizeOf(FILE_DISPOSITION_INFORMATION),
1073 .FileDispositionInformation,
3364 @sizeOf(FILE.DISPOSITION.INFORMATION),
3365 .Disposition,
10743366 );
10753367 }
10763368 switch (rc) {
......@@ -1112,8 +3404,14 @@ pub fn RenameFile(
11123404) RenameError!void {
11133405 const src_fd = OpenFile(old_path_w, .{
11143406 .dir = old_dir_fd,
1115 .access_mask = SYNCHRONIZE | GENERIC_WRITE | DELETE,
1116 .creation = FILE_OPEN,
3407 .access_mask = .{
3408 .STANDARD = .{
3409 .RIGHTS = .{ .DELETE = true },
3410 .SYNCHRONIZE = true,
3411 },
3412 .GENERIC = .{ .WRITE = true },
3413 },
3414 .creation = .OPEN,
11173415 .filter = .any, // This function is supposed to rename both files and directories.
11183416 .follow_symlinks = false,
11193417 }) catch |err| switch (err) {
......@@ -1135,29 +3433,23 @@ pub fn RenameFile(
11353433 // The strategy here is just to try using FileRenameInformationEx and fall back to
11363434 // FileRenameInformation if the return value lets us know that some aspect of it is not supported.
11373435 const need_fallback = need_fallback: {
1138 const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + (PATH_MAX_WIDE * 2);
1139 var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION_EX)) = undefined;
1140 const struct_len = @sizeOf(FILE_RENAME_INFORMATION_EX) + new_path_w.len * 2;
1141 if (struct_len > struct_buf_len) return error.NameTooLong;
1142
1143 const rename_info: *FILE_RENAME_INFORMATION_EX = @ptrCast(&rename_info_buf);
1144 var io_status_block: IO_STATUS_BLOCK = undefined;
1145
1146 var flags: ULONG = FILE_RENAME_POSIX_SEMANTICS | FILE_RENAME_IGNORE_READONLY_ATTRIBUTE;
1147 if (replace_if_exists) flags |= FILE_RENAME_REPLACE_IF_EXISTS;
1148 rename_info.* = .{
1149 .Flags = flags,
3436 const rename_info: FILE.RENAME_INFORMATION = .init(.{
3437 .Flags = .{
3438 .REPLACE_IF_EXISTS = replace_if_exists,
3439 .POSIX_SEMANTICS = true,
3440 .IGNORE_READONLY_ATTRIBUTE = true,
3441 },
11503442 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
1151 .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
1152 .FileName = undefined,
1153 };
1154 @memcpy((&rename_info.FileName).ptr, new_path_w);
3443 .FileName = new_path_w,
3444 });
3445 var io_status_block: IO_STATUS_BLOCK = undefined;
3446 const rename_info_buf = rename_info.toBuffer();
11553447 rc = ntdll.NtSetInformationFile(
11563448 src_fd,
11573449 &io_status_block,
1158 rename_info,
1159 @intCast(struct_len), // already checked for error.NameTooLong
1160 .FileRenameInformationEx,
3450 rename_info_buf.ptr,
3451 @intCast(rename_info_buf.len), // already checked for error.NameTooLong
3452 .RenameEx,
11613453 );
11623454 switch (rc) {
11633455 .SUCCESS => return,
......@@ -1174,28 +3466,19 @@ pub fn RenameFile(
11743466 };
11753467
11763468 if (need_fallback) {
1177 const struct_buf_len = @sizeOf(FILE_RENAME_INFORMATION) + (PATH_MAX_WIDE * 2);
1178 var rename_info_buf: [struct_buf_len]u8 align(@alignOf(FILE_RENAME_INFORMATION)) = undefined;
1179 const struct_len = @sizeOf(FILE_RENAME_INFORMATION) + new_path_w.len * 2;
1180 if (struct_len > struct_buf_len) return error.NameTooLong;
1181
1182 const rename_info: *FILE_RENAME_INFORMATION = @ptrCast(&rename_info_buf);
1183 var io_status_block: IO_STATUS_BLOCK = undefined;
1184
1185 rename_info.* = .{
1186 .Flags = @intFromBool(replace_if_exists),
3469 const rename_info: FILE.RENAME_INFORMATION = .init(.{
3470 .Flags = .{ .REPLACE_IF_EXISTS = replace_if_exists },
11873471 .RootDirectory = if (std.fs.path.isAbsoluteWindowsWtf16(new_path_w)) null else new_dir_fd,
1188 .FileNameLength = @intCast(new_path_w.len * 2), // already checked error.NameTooLong
1189 .FileName = undefined,
1190 };
1191 @memcpy((&rename_info.FileName).ptr, new_path_w);
1192
3472 .FileName = new_path_w,
3473 });
3474 var io_status_block: IO_STATUS_BLOCK = undefined;
3475 const rename_info_buf = rename_info.toBuffer();
11933476 rc = ntdll.NtSetInformationFile(
11943477 src_fd,
11953478 &io_status_block,
1196 rename_info,
1197 @intCast(struct_len), // already checked for error.NameTooLong
1198 .FileRenameInformation,
3479 rename_info_buf.ptr,
3480 @intCast(rename_info_buf.len), // already checked for error.NameTooLong
3481 .Rename,
11993482 );
12003483 }
12013484
......@@ -1308,7 +3591,7 @@ pub fn QueryObjectName(handle: HANDLE, out_buffer: []u16) QueryObjectNameError![
13083591
13093592 const info = @as(*OBJECT_NAME_INFORMATION, @ptrCast(out_buffer_aligned));
13103593 // buffer size is specified in bytes
1311 const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse std.math.maxInt(ULONG);
3594 const out_buffer_len = std.math.cast(ULONG, out_buffer_aligned.len * 2) orelse maxInt(ULONG);
13123595 // last argument would return the length required for full_buffer, not exposed here
13133596 return switch (ntdll.NtQueryObject(handle, .ObjectNameInformation, info, out_buffer_len, null)) {
13143597 .SUCCESS => blk: {
......@@ -1440,9 +3723,8 @@ pub fn GetFinalPathNameByHandle(
14403723 // This is the NT namespaced version of \\.\MountPointManager
14413724 const mgmt_path_u16 = std.unicode.utf8ToUtf16LeStringLiteral("\\??\\MountPointManager");
14423725 const mgmt_handle = OpenFile(mgmt_path_u16, .{
1443 .access_mask = SYNCHRONIZE,
1444 .share_access = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1445 .creation = FILE_OPEN,
3726 .access_mask = .{ .STANDARD = .{ .SYNCHRONIZE = true } },
3727 .creation = .OPEN,
14463728 }) catch |err| switch (err) {
14473729 error.IsDir => return error.Unexpected,
14483730 error.NotDir => return error.Unexpected,
......@@ -1462,8 +3744,12 @@ pub fn GetFinalPathNameByHandle(
14623744 input_struct.DeviceNameLength = @intCast(volume_name_u16.len * 2);
14633745 @memcpy(input_buf[@sizeOf(MOUNTMGR_MOUNT_POINT)..][0 .. volume_name_u16.len * 2], @as([*]const u8, @ptrCast(volume_name_u16.ptr)));
14643746
1465 DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_POINTS, &input_buf, &output_buf) catch |err| switch (err) {
3747 DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_POINTS, .{ .in = &input_buf, .out = &output_buf }) catch |err| switch (err) {
3748 error.PipeClosing => unreachable,
3749 error.PipeAlreadyConnected => unreachable,
3750 error.PipeAlreadyListening => unreachable,
14663751 error.AccessDenied => return error.Unexpected,
3752 error.Pending => unreachable,
14673753 else => |e| return e,
14683754 };
14693755 const mount_points_struct: *const MOUNTMGR_MOUNT_POINTS = @ptrCast(&output_buf[0]);
......@@ -1517,8 +3803,12 @@ pub fn GetFinalPathNameByHandle(
15173803 vol_input_struct.DeviceNameLength = @intCast(symlink.len * 2);
15183804 @memcpy(@as([*]WCHAR, &vol_input_struct.DeviceName)[0..symlink.len], symlink);
15193805
1520 DeviceIoControl(mgmt_handle, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH, &vol_input_buf, &vol_output_buf) catch |err| switch (err) {
3806 DeviceIoControl(mgmt_handle, IOCTL.MOUNTMGR.QUERY_DOS_VOLUME_PATH, .{ .in = &vol_input_buf, .out = &vol_output_buf }) catch |err| switch (err) {
3807 error.PipeClosing => unreachable,
3808 error.PipeAlreadyConnected => unreachable,
3809 error.PipeAlreadyListening => unreachable,
15213810 error.AccessDenied => return error.Unexpected,
3811 error.Pending => unreachable,
15223812 else => |e| return e,
15233813 };
15243814 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
17584048 // ntdll takes an extra level of indirection here
17594049 var addr = lpAddress;
17604050 var size = dwSize;
1761 switch (ntdll.NtProtectVirtualMemory(self_process_handle, &addr, &size, flNewProtect, lpflOldProtect)) {
4051 switch (ntdll.NtProtectVirtualMemory(GetCurrentProcess(), &addr, &size, flNewProtect, lpflOldProtect)) {
17624052 .SUCCESS => {},
17634053 .INVALID_ADDRESS => return error.InvalidAddress,
17644054 else => |st| return unexpectedStatus(st),
......@@ -2018,7 +4308,7 @@ pub const LockFileError = error{
20184308pub fn LockFile(
20194309 FileHandle: HANDLE,
20204310 Event: ?HANDLE,
2021 ApcRoutine: ?*IO_APC_ROUTINE,
4311 ApcRoutine: ?*const IO_APC_ROUTINE,
20224312 ApcContext: ?*anyopaque,
20234313 IoStatusBlock: *IO_STATUS_BLOCK,
20244314 ByteOffset: *const LARGE_INTEGER,
......@@ -2057,7 +4347,7 @@ pub fn UnlockFile(
20574347 IoStatusBlock: *IO_STATUS_BLOCK,
20584348 ByteOffset: *const LARGE_INTEGER,
20594349 Length: *const LARGE_INTEGER,
2060 Key: ?*ULONG,
4350 Key: ULONG,
20614351) !void {
20624352 const rc = ntdll.NtUnlockFile(FileHandle, IoStatusBlock, ByteOffset, Length, Key);
20634353 switch (rc) {
......@@ -2168,13 +4458,13 @@ pub fn eqlIgnoreCaseWtf16(a: []const u16, b: []const u16) bool {
21684458 // Use RtlEqualUnicodeString on Windows when not in comptime to avoid including a
21694459 // redundant copy of the uppercase data.
21704460 const a_bytes = @as(u16, @intCast(a.len * 2));
2171 const a_string = UNICODE_STRING{
4461 const a_string: UNICODE_STRING = .{
21724462 .Length = a_bytes,
21734463 .MaximumLength = a_bytes,
21744464 .Buffer = @constCast(a.ptr),
21754465 };
21764466 const b_bytes = @as(u16, @intCast(b.len * 2));
2177 const b_string = UNICODE_STRING{
4467 const b_string: UNICODE_STRING = .{
21784468 .Length = b_bytes,
21794469 .MaximumLength = b_bytes,
21804470 .Buffer = @constCast(b.ptr),
......@@ -2206,7 +4496,7 @@ pub fn eqlIgnoreCaseWtf8(a: []const u8, b: []const u8) bool {
22064496 const a_cp = a_wtf8_it.nextCodepoint() orelse break;
22074497 const b_cp = b_wtf8_it.nextCodepoint() orelse return false;
22084498
2209 if (a_cp <= std.math.maxInt(u16) and b_cp <= std.math.maxInt(u16)) {
4499 if (a_cp <= maxInt(u16) and b_cp <= maxInt(u16)) {
22104500 if (a_cp != b_cp and upcaseImpl(@intCast(a_cp)) != upcaseImpl(@intCast(b_cp))) {
22114501 return false;
22124502 }
......@@ -2783,7 +5073,10 @@ pub fn unexpectedWSAError(err: ws2_32.WinsockError) UnexpectedError {
27835073/// and you get an unexpected status.
27845074pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError {
27855075 if (std.posix.unexpected_error_tracing) {
2786 std.debug.print("error.Unexpected NTSTATUS=0x{x}\n", .{@intFromEnum(status)});
5076 std.debug.print("error.Unexpected NTSTATUS=0x{x} ({s})\n", .{
5077 @intFromEnum(status),
5078 std.enums.tagName(NTSTATUS, status) orelse "<unnamed>",
5079 });
27875080 std.debug.dumpCurrentStackTrace(.{ .first_address = @returnAddress() });
27885081 }
27895082 return error.Unexpected;
......@@ -2791,20 +5084,25 @@ pub fn unexpectedStatus(status: NTSTATUS) UnexpectedError {
27915084
27925085pub fn statusBug(status: NTSTATUS) UnexpectedError {
27935086 switch (builtin.mode) {
2794 .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{status}),
5087 .Debug => std.debug.panic("programmer bug caused syscall status: 0x{x} ({s})", .{
5088 @intFromEnum(status),
5089 std.enums.tagName(NTSTATUS, status) orelse "<unnamed>",
5090 }),
27955091 else => return error.Unexpected,
27965092 }
27975093}
27985094
27995095pub fn errorBug(err: Win32Error) UnexpectedError {
28005096 switch (builtin.mode) {
2801 .Debug => std.debug.panic("programmer bug caused syscall status: {t}", .{err}),
5097 .Debug => std.debug.panic("programmer bug caused syscall error: 0x{x} ({s})", .{
5098 @intFromEnum(err),
5099 std.enums.tagName(Win32Error, err) orelse "<unnamed>",
5100 }),
28025101 else => return error.Unexpected,
28035102 }
28045103}
28055104
28065105pub const Win32Error = @import("windows/win32error.zig").Win32Error;
2807pub const NTSTATUS = @import("windows/ntstatus.zig").NTSTATUS;
28085106pub const LANG = @import("windows/lang.zig");
28095107pub const SUBLANG = @import("windows/sublang.zig");
28105108
......@@ -2885,217 +5183,9 @@ pub const PCTSTR = @compileError("Deprecated: choose between `PCSTR` or `PCWSTR`
28855183pub const TRUE = 1;
28865184pub const FALSE = 0;
28875185
2888pub const DEVICE_TYPE = ULONG;
2889pub const FILE_DEVICE_BEEP: DEVICE_TYPE = 0x0001;
2890pub const FILE_DEVICE_CD_ROM: DEVICE_TYPE = 0x0002;
2891pub const FILE_DEVICE_CD_ROM_FILE_SYSTEM: DEVICE_TYPE = 0x0003;
2892pub const FILE_DEVICE_CONTROLLER: DEVICE_TYPE = 0x0004;
2893pub const FILE_DEVICE_DATALINK: DEVICE_TYPE = 0x0005;
2894pub const FILE_DEVICE_DFS: DEVICE_TYPE = 0x0006;
2895pub const FILE_DEVICE_DISK: DEVICE_TYPE = 0x0007;
2896pub const FILE_DEVICE_DISK_FILE_SYSTEM: DEVICE_TYPE = 0x0008;
2897pub const FILE_DEVICE_FILE_SYSTEM: DEVICE_TYPE = 0x0009;
2898pub const FILE_DEVICE_INPORT_PORT: DEVICE_TYPE = 0x000a;
2899pub const FILE_DEVICE_KEYBOARD: DEVICE_TYPE = 0x000b;
2900pub const FILE_DEVICE_MAILSLOT: DEVICE_TYPE = 0x000c;
2901pub const FILE_DEVICE_MIDI_IN: DEVICE_TYPE = 0x000d;
2902pub const FILE_DEVICE_MIDI_OUT: DEVICE_TYPE = 0x000e;
2903pub const FILE_DEVICE_MOUSE: DEVICE_TYPE = 0x000f;
2904pub const FILE_DEVICE_MULTI_UNC_PROVIDER: DEVICE_TYPE = 0x0010;
2905pub const FILE_DEVICE_NAMED_PIPE: DEVICE_TYPE = 0x0011;
2906pub const FILE_DEVICE_NETWORK: DEVICE_TYPE = 0x0012;
2907pub const FILE_DEVICE_NETWORK_BROWSER: DEVICE_TYPE = 0x0013;
2908pub const FILE_DEVICE_NETWORK_FILE_SYSTEM: DEVICE_TYPE = 0x0014;
2909pub const FILE_DEVICE_NULL: DEVICE_TYPE = 0x0015;
2910pub const FILE_DEVICE_PARALLEL_PORT: DEVICE_TYPE = 0x0016;
2911pub const FILE_DEVICE_PHYSICAL_NETCARD: DEVICE_TYPE = 0x0017;
2912pub const FILE_DEVICE_PRINTER: DEVICE_TYPE = 0x0018;
2913pub const FILE_DEVICE_SCANNER: DEVICE_TYPE = 0x0019;
2914pub const FILE_DEVICE_SERIAL_MOUSE_PORT: DEVICE_TYPE = 0x001a;
2915pub const FILE_DEVICE_SERIAL_PORT: DEVICE_TYPE = 0x001b;
2916pub const FILE_DEVICE_SCREEN: DEVICE_TYPE = 0x001c;
2917pub const FILE_DEVICE_SOUND: DEVICE_TYPE = 0x001d;
2918pub const FILE_DEVICE_STREAMS: DEVICE_TYPE = 0x001e;
2919pub const FILE_DEVICE_TAPE: DEVICE_TYPE = 0x001f;
2920pub const FILE_DEVICE_TAPE_FILE_SYSTEM: DEVICE_TYPE = 0x0020;
2921pub const FILE_DEVICE_TRANSPORT: DEVICE_TYPE = 0x0021;
2922pub const FILE_DEVICE_UNKNOWN: DEVICE_TYPE = 0x0022;
2923pub const FILE_DEVICE_VIDEO: DEVICE_TYPE = 0x0023;
2924pub const FILE_DEVICE_VIRTUAL_DISK: DEVICE_TYPE = 0x0024;
2925pub const FILE_DEVICE_WAVE_IN: DEVICE_TYPE = 0x0025;
2926pub const FILE_DEVICE_WAVE_OUT: DEVICE_TYPE = 0x0026;
2927pub const FILE_DEVICE_8042_PORT: DEVICE_TYPE = 0x0027;
2928pub const FILE_DEVICE_NETWORK_REDIRECTOR: DEVICE_TYPE = 0x0028;
2929pub const FILE_DEVICE_BATTERY: DEVICE_TYPE = 0x0029;
2930pub const FILE_DEVICE_BUS_EXTENDER: DEVICE_TYPE = 0x002a;
2931pub const FILE_DEVICE_MODEM: DEVICE_TYPE = 0x002b;
2932pub const FILE_DEVICE_VDM: DEVICE_TYPE = 0x002c;
2933pub const FILE_DEVICE_MASS_STORAGE: DEVICE_TYPE = 0x002d;
2934pub const FILE_DEVICE_SMB: DEVICE_TYPE = 0x002e;
2935pub const FILE_DEVICE_KS: DEVICE_TYPE = 0x002f;
2936pub const FILE_DEVICE_CHANGER: DEVICE_TYPE = 0x0030;
2937pub const FILE_DEVICE_SMARTCARD: DEVICE_TYPE = 0x0031;
2938pub const FILE_DEVICE_ACPI: DEVICE_TYPE = 0x0032;
2939pub const FILE_DEVICE_DVD: DEVICE_TYPE = 0x0033;
2940pub const FILE_DEVICE_FULLSCREEN_VIDEO: DEVICE_TYPE = 0x0034;
2941pub const FILE_DEVICE_DFS_FILE_SYSTEM: DEVICE_TYPE = 0x0035;
2942pub const FILE_DEVICE_DFS_VOLUME: DEVICE_TYPE = 0x0036;
2943pub const FILE_DEVICE_SERENUM: DEVICE_TYPE = 0x0037;
2944pub const FILE_DEVICE_TERMSRV: DEVICE_TYPE = 0x0038;
2945pub const FILE_DEVICE_KSEC: DEVICE_TYPE = 0x0039;
2946pub const FILE_DEVICE_FIPS: DEVICE_TYPE = 0x003a;
2947pub const FILE_DEVICE_INFINIBAND: DEVICE_TYPE = 0x003b;
2948// TODO: missing values?
2949pub const FILE_DEVICE_VMBUS: DEVICE_TYPE = 0x003e;
2950pub const FILE_DEVICE_CRYPT_PROVIDER: DEVICE_TYPE = 0x003f;
2951pub const FILE_DEVICE_WPD: DEVICE_TYPE = 0x0040;
2952pub const FILE_DEVICE_BLUETOOTH: DEVICE_TYPE = 0x0041;
2953pub const FILE_DEVICE_MT_COMPOSITE: DEVICE_TYPE = 0x0042;
2954pub const FILE_DEVICE_MT_TRANSPORT: DEVICE_TYPE = 0x0043;
2955pub const FILE_DEVICE_BIOMETRIC: DEVICE_TYPE = 0x0044;
2956pub const FILE_DEVICE_PMI: DEVICE_TYPE = 0x0045;
2957pub const FILE_DEVICE_EHSTOR: DEVICE_TYPE = 0x0046;
2958pub const FILE_DEVICE_DEVAPI: DEVICE_TYPE = 0x0047;
2959pub const FILE_DEVICE_GPIO: DEVICE_TYPE = 0x0048;
2960pub const FILE_DEVICE_USBEX: DEVICE_TYPE = 0x0049;
2961pub const FILE_DEVICE_CONSOLE: DEVICE_TYPE = 0x0050;
2962pub const FILE_DEVICE_NFP: DEVICE_TYPE = 0x0051;
2963pub const FILE_DEVICE_SYSENV: DEVICE_TYPE = 0x0052;
2964pub const FILE_DEVICE_VIRTUAL_BLOCK: DEVICE_TYPE = 0x0053;
2965pub const FILE_DEVICE_POINT_OF_SERVICE: DEVICE_TYPE = 0x0054;
2966pub const FILE_DEVICE_STORAGE_REPLICATION: DEVICE_TYPE = 0x0055;
2967pub const FILE_DEVICE_TRUST_ENV: DEVICE_TYPE = 0x0056;
2968pub const FILE_DEVICE_UCM: DEVICE_TYPE = 0x0057;
2969pub const FILE_DEVICE_UCMTCPCI: DEVICE_TYPE = 0x0058;
2970pub const FILE_DEVICE_PERSISTENT_MEMORY: DEVICE_TYPE = 0x0059;
2971pub const FILE_DEVICE_NVDIMM: DEVICE_TYPE = 0x005a;
2972pub const FILE_DEVICE_HOLOGRAPHIC: DEVICE_TYPE = 0x005b;
2973pub const FILE_DEVICE_SDFXHCI: DEVICE_TYPE = 0x005c;
2974
2975/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/buffer-descriptions-for-i-o-control-codes
2976pub const TransferType = enum(u2) {
2977 METHOD_BUFFERED = 0,
2978 METHOD_IN_DIRECT = 1,
2979 METHOD_OUT_DIRECT = 2,
2980 METHOD_NEITHER = 3,
2981};
2982
2983pub const FILE_ANY_ACCESS = 0;
2984pub const FILE_READ_ACCESS = 1;
2985pub const FILE_WRITE_ACCESS = 2;
2986
2987/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes
2988pub fn CTL_CODE(deviceType: u16, function: u12, method: TransferType, access: u2) DWORD {
2989 return (@as(DWORD, deviceType) << 16) |
2990 (@as(DWORD, access) << 14) |
2991 (@as(DWORD, function) << 2) |
2992 @intFromEnum(method);
2993}
2994
2995pub const INVALID_HANDLE_VALUE = @as(HANDLE, @ptrFromInt(maxInt(usize)));
2996
2997pub const INVALID_FILE_ATTRIBUTES = @as(DWORD, maxInt(DWORD));
2998
2999pub const FILE_ALL_INFORMATION = extern struct {
3000 BasicInformation: FILE_BASIC_INFORMATION,
3001 StandardInformation: FILE_STANDARD_INFORMATION,
3002 InternalInformation: FILE_INTERNAL_INFORMATION,
3003 EaInformation: FILE_EA_INFORMATION,
3004 AccessInformation: FILE_ACCESS_INFORMATION,
3005 PositionInformation: FILE_POSITION_INFORMATION,
3006 ModeInformation: FILE_MODE_INFORMATION,
3007 AlignmentInformation: FILE_ALIGNMENT_INFORMATION,
3008 NameInformation: FILE_NAME_INFORMATION,
3009};
3010
3011pub const FILE_BASIC_INFORMATION = extern struct {
3012 CreationTime: LARGE_INTEGER,
3013 LastAccessTime: LARGE_INTEGER,
3014 LastWriteTime: LARGE_INTEGER,
3015 ChangeTime: LARGE_INTEGER,
3016 FileAttributes: ULONG,
3017};
3018
3019pub const FILE_STANDARD_INFORMATION = extern struct {
3020 AllocationSize: LARGE_INTEGER,
3021 EndOfFile: LARGE_INTEGER,
3022 NumberOfLinks: ULONG,
3023 DeletePending: BOOLEAN,
3024 Directory: BOOLEAN,
3025};
3026
3027pub const FILE_INTERNAL_INFORMATION = extern struct {
3028 IndexNumber: LARGE_INTEGER,
3029};
3030
3031pub const FILE_EA_INFORMATION = extern struct {
3032 EaSize: ULONG,
3033};
3034
3035pub const FILE_ACCESS_INFORMATION = extern struct {
3036 AccessFlags: ACCESS_MASK,
3037};
3038
3039pub const FILE_POSITION_INFORMATION = extern struct {
3040 CurrentByteOffset: LARGE_INTEGER,
3041};
3042
3043pub const FILE_END_OF_FILE_INFORMATION = extern struct {
3044 EndOfFile: LARGE_INTEGER,
3045};
3046
3047pub const FILE_MODE_INFORMATION = extern struct {
3048 Mode: ULONG,
3049};
3050
3051pub const FILE_ALIGNMENT_INFORMATION = extern struct {
3052 AlignmentRequirement: ULONG,
3053};
3054
3055pub const FILE_NAME_INFORMATION = extern struct {
3056 FileNameLength: ULONG,
3057 FileName: [1]WCHAR,
3058};
3059
3060pub const FILE_DISPOSITION_INFORMATION_EX = extern struct {
3061 /// combination of FILE_DISPOSITION_* flags
3062 Flags: ULONG,
3063};
3064
3065pub const FILE_DISPOSITION_DO_NOT_DELETE: ULONG = 0x00000000;
3066pub const FILE_DISPOSITION_DELETE: ULONG = 0x00000001;
3067pub const FILE_DISPOSITION_POSIX_SEMANTICS: ULONG = 0x00000002;
3068pub const FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK: ULONG = 0x00000004;
3069pub const FILE_DISPOSITION_ON_CLOSE: ULONG = 0x00000008;
3070pub const FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE: ULONG = 0x00000010;
3071
3072// FILE_RENAME_INFORMATION.Flags
3073pub const FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001;
3074pub const FILE_RENAME_POSIX_SEMANTICS = 0x00000002;
3075pub const FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004;
3076pub const FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008;
3077pub const FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010;
3078pub const FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020;
3079pub const FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030;
3080pub const FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040;
3081pub const FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080;
3082pub const FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100;
3083pub const FILE_RENAME_FORCE_RESIZE_SR = 0x00000180;
3084
3085pub const FILE_RENAME_INFORMATION = extern struct {
3086 Flags: BOOLEAN,
3087 RootDirectory: ?HANDLE,
3088 FileNameLength: ULONG,
3089 FileName: [1]WCHAR,
3090};
5186pub const INVALID_HANDLE_VALUE: HANDLE = @ptrFromInt(maxInt(usize));
30915187
3092// FileRenameInformationEx (since .win10_rs1)
3093pub const FILE_RENAME_INFORMATION_EX = extern struct {
3094 Flags: ULONG,
3095 RootDirectory: ?HANDLE,
3096 FileNameLength: ULONG,
3097 FileName: [1]WCHAR,
3098};
5188pub const INVALID_FILE_ATTRIBUTES: DWORD = maxInt(DWORD);
30995189
31005190pub const IO_STATUS_BLOCK = extern struct {
31015191 // "DUMMYUNIONNAME" expands to "u"
......@@ -3106,130 +5196,6 @@ pub const IO_STATUS_BLOCK = extern struct {
31065196 Information: ULONG_PTR,
31075197};
31085198
3109pub const FILE_INFORMATION_CLASS = enum(c_int) {
3110 FileDirectoryInformation = 1,
3111 FileFullDirectoryInformation,
3112 FileBothDirectoryInformation,
3113 FileBasicInformation,
3114 FileStandardInformation,
3115 FileInternalInformation,
3116 FileEaInformation,
3117 FileAccessInformation,
3118 FileNameInformation,
3119 FileRenameInformation,
3120 FileLinkInformation,
3121 FileNamesInformation,
3122 FileDispositionInformation,
3123 FilePositionInformation,
3124 FileFullEaInformation,
3125 FileModeInformation,
3126 FileAlignmentInformation,
3127 FileAllInformation,
3128 FileAllocationInformation,
3129 FileEndOfFileInformation,
3130 FileAlternateNameInformation,
3131 FileStreamInformation,
3132 FilePipeInformation,
3133 FilePipeLocalInformation,
3134 FilePipeRemoteInformation,
3135 FileMailslotQueryInformation,
3136 FileMailslotSetInformation,
3137 FileCompressionInformation,
3138 FileObjectIdInformation,
3139 FileCompletionInformation,
3140 FileMoveClusterInformation,
3141 FileQuotaInformation,
3142 FileReparsePointInformation,
3143 FileNetworkOpenInformation,
3144 FileAttributeTagInformation,
3145 FileTrackingInformation,
3146 FileIdBothDirectoryInformation,
3147 FileIdFullDirectoryInformation,
3148 FileValidDataLengthInformation,
3149 FileShortNameInformation,
3150 FileIoCompletionNotificationInformation,
3151 FileIoStatusBlockRangeInformation,
3152 FileIoPriorityHintInformation,
3153 FileSfioReserveInformation,
3154 FileSfioVolumeInformation,
3155 FileHardLinkInformation,
3156 FileProcessIdsUsingFileInformation,
3157 FileNormalizedNameInformation,
3158 FileNetworkPhysicalNameInformation,
3159 FileIdGlobalTxDirectoryInformation,
3160 FileIsRemoteDeviceInformation,
3161 FileUnusedInformation,
3162 FileNumaNodeInformation,
3163 FileStandardLinkInformation,
3164 FileRemoteProtocolInformation,
3165 FileRenameInformationBypassAccessCheck,
3166 FileLinkInformationBypassAccessCheck,
3167 FileVolumeNameInformation,
3168 FileIdInformation,
3169 FileIdExtdDirectoryInformation,
3170 FileReplaceCompletionInformation,
3171 FileHardLinkFullIdInformation,
3172 FileIdExtdBothDirectoryInformation,
3173 FileDispositionInformationEx,
3174 FileRenameInformationEx,
3175 FileRenameInformationExBypassAccessCheck,
3176 FileDesiredStorageClassInformation,
3177 FileStatInformation,
3178 FileMemoryPartitionInformation,
3179 FileStatLxInformation,
3180 FileCaseSensitiveInformation,
3181 FileLinkInformationEx,
3182 FileLinkInformationExBypassAccessCheck,
3183 FileStorageReserveIdInformation,
3184 FileCaseSensitiveInformationForceAccessCheck,
3185 FileMaximumInformation,
3186};
3187
3188pub const FILE_ATTRIBUTE_TAG_INFO = extern struct {
3189 FileAttributes: DWORD,
3190 ReparseTag: DWORD,
3191};
3192
3193/// "If this bit is set, the file or directory represents another named entity in the system."
3194/// https://learn.microsoft.com/en-us/windows/win32/fileio/reparse-point-tags
3195pub const reparse_tag_name_surrogate_bit = 0x20000000;
3196
3197pub const FILE_DISPOSITION_INFORMATION = extern struct {
3198 DeleteFile: BOOLEAN,
3199};
3200
3201pub const FILE_FS_DEVICE_INFORMATION = extern struct {
3202 DeviceType: DEVICE_TYPE,
3203 Characteristics: ULONG,
3204};
3205
3206pub const FILE_FS_VOLUME_INFORMATION = extern struct {
3207 VolumeCreationTime: LARGE_INTEGER,
3208 VolumeSerialNumber: ULONG,
3209 VolumeLabelLength: ULONG,
3210 SupportsObjects: BOOLEAN,
3211 // Flexible array member
3212 VolumeLabel: [1]WCHAR,
3213};
3214
3215pub const FS_INFORMATION_CLASS = enum(c_int) {
3216 FileFsVolumeInformation = 1,
3217 FileFsLabelInformation,
3218 FileFsSizeInformation,
3219 FileFsDeviceInformation,
3220 FileFsAttributeInformation,
3221 FileFsControlInformation,
3222 FileFsFullSizeInformation,
3223 FileFsObjectIdInformation,
3224 FileFsDriverPathInformation,
3225 FileFsVolumeFlagsInformation,
3226 FileFsSectorSizeInformation,
3227 FileFsDataCopyInformation,
3228 FileFsMetadataSizeInformation,
3229 FileFsFullSizeInformationEx,
3230 FileFsMaximumInformation,
3231};
3232
32335199pub const OVERLAPPED = extern struct {
32345200 Internal: ULONG_PTR,
32355201 InternalHigh: ULONG_PTR,
......@@ -3331,129 +5297,16 @@ pub const PIPE_READMODE_MESSAGE = 0x00000002;
33315297pub const PIPE_WAIT = 0x00000000;
33325298pub const PIPE_NOWAIT = 0x00000001;
33335299
3334pub const GENERIC_READ = 0x80000000;
3335pub const GENERIC_WRITE = 0x40000000;
3336pub const GENERIC_EXECUTE = 0x20000000;
3337pub const GENERIC_ALL = 0x10000000;
3338
3339pub const FILE_SHARE_DELETE = 0x00000004;
3340pub const FILE_SHARE_READ = 0x00000001;
3341pub const FILE_SHARE_WRITE = 0x00000002;
3342
3343pub const DELETE = 0x00010000;
3344pub const READ_CONTROL = 0x00020000;
3345pub const WRITE_DAC = 0x00040000;
3346pub const WRITE_OWNER = 0x00080000;
3347pub const SYNCHRONIZE = 0x00100000;
3348pub const STANDARD_RIGHTS_READ = READ_CONTROL;
3349pub const STANDARD_RIGHTS_WRITE = READ_CONTROL;
3350pub const STANDARD_RIGHTS_EXECUTE = READ_CONTROL;
3351pub const STANDARD_RIGHTS_REQUIRED = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER;
3352pub const MAXIMUM_ALLOWED = 0x02000000;
3353
3354// disposition for NtCreateFile
3355pub const FILE_SUPERSEDE = 0;
3356pub const FILE_OPEN = 1;
3357pub const FILE_CREATE = 2;
3358pub const FILE_OPEN_IF = 3;
3359pub const FILE_OVERWRITE = 4;
3360pub const FILE_OVERWRITE_IF = 5;
3361pub const FILE_MAXIMUM_DISPOSITION = 5;
3362
3363// flags for NtCreateFile and NtOpenFile
3364pub const FILE_READ_DATA = 0x00000001;
3365pub const FILE_LIST_DIRECTORY = 0x00000001;
3366pub const FILE_WRITE_DATA = 0x00000002;
3367pub const FILE_ADD_FILE = 0x00000002;
3368pub const FILE_APPEND_DATA = 0x00000004;
3369pub const FILE_ADD_SUBDIRECTORY = 0x00000004;
3370pub const FILE_CREATE_PIPE_INSTANCE = 0x00000004;
3371pub const FILE_READ_EA = 0x00000008;
3372pub const FILE_WRITE_EA = 0x00000010;
3373pub const FILE_EXECUTE = 0x00000020;
3374pub const FILE_TRAVERSE = 0x00000020;
3375pub const FILE_DELETE_CHILD = 0x00000040;
3376pub const FILE_READ_ATTRIBUTES = 0x00000080;
3377pub const FILE_WRITE_ATTRIBUTES = 0x00000100;
3378
3379pub const FILE_DIRECTORY_FILE = 0x00000001;
3380pub const FILE_WRITE_THROUGH = 0x00000002;
3381pub const FILE_SEQUENTIAL_ONLY = 0x00000004;
3382pub const FILE_NO_INTERMEDIATE_BUFFERING = 0x00000008;
3383pub const FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
3384pub const FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
3385pub const FILE_NON_DIRECTORY_FILE = 0x00000040;
3386pub const FILE_CREATE_TREE_CONNECTION = 0x00000080;
3387pub const FILE_COMPLETE_IF_OPLOCKED = 0x00000100;
3388pub const FILE_NO_EA_KNOWLEDGE = 0x00000200;
3389pub const FILE_OPEN_FOR_RECOVERY = 0x00000400;
3390pub const FILE_RANDOM_ACCESS = 0x00000800;
3391pub const FILE_DELETE_ON_CLOSE = 0x00001000;
3392pub const FILE_OPEN_BY_FILE_ID = 0x00002000;
3393pub const FILE_OPEN_FOR_BACKUP_INTENT = 0x00004000;
3394pub const FILE_NO_COMPRESSION = 0x00008000;
3395pub const FILE_RESERVE_OPFILTER = 0x00100000;
3396pub const FILE_OPEN_REPARSE_POINT = 0x00200000;
3397pub const FILE_OPEN_OFFLINE_FILE = 0x00400000;
3398pub const FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000;
3399
34005300pub const CREATE_ALWAYS = 2;
34015301pub const CREATE_NEW = 1;
34025302pub const OPEN_ALWAYS = 4;
34035303pub const OPEN_EXISTING = 3;
34045304pub const TRUNCATE_EXISTING = 5;
34055305
3406pub const FILE_ATTRIBUTE_ARCHIVE = 0x20;
3407pub const FILE_ATTRIBUTE_COMPRESSED = 0x800;
3408pub const FILE_ATTRIBUTE_DEVICE = 0x40;
3409pub const FILE_ATTRIBUTE_DIRECTORY = 0x10;
3410pub const FILE_ATTRIBUTE_ENCRYPTED = 0x4000;
3411pub const FILE_ATTRIBUTE_HIDDEN = 0x2;
3412pub const FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x8000;
3413pub const FILE_ATTRIBUTE_NORMAL = 0x80;
3414pub const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x2000;
3415pub const FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x20000;
3416pub const FILE_ATTRIBUTE_OFFLINE = 0x1000;
3417pub const FILE_ATTRIBUTE_READONLY = 0x1;
3418pub const FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS = 0x400000;
3419pub const FILE_ATTRIBUTE_RECALL_ON_OPEN = 0x40000;
3420pub const FILE_ATTRIBUTE_REPARSE_POINT = 0x400;
3421pub const FILE_ATTRIBUTE_SPARSE_FILE = 0x200;
3422pub const FILE_ATTRIBUTE_SYSTEM = 0x4;
3423pub const FILE_ATTRIBUTE_TEMPORARY = 0x100;
3424pub const FILE_ATTRIBUTE_VIRTUAL = 0x10000;
3425
3426pub const FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1ff;
3427pub const FILE_GENERIC_READ = STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE;
3428pub const FILE_GENERIC_WRITE = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE;
3429pub const FILE_GENERIC_EXECUTE = STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE;
3430
3431// Flags for NtCreateNamedPipeFile
3432// NamedPipeType
3433pub const FILE_PIPE_BYTE_STREAM_TYPE = 0x0;
3434pub const FILE_PIPE_MESSAGE_TYPE = 0x1;
3435pub const FILE_PIPE_ACCEPT_REMOTE_CLIENTS = 0x0;
3436pub const FILE_PIPE_REJECT_REMOTE_CLIENTS = 0x2;
3437pub const FILE_PIPE_TYPE_VALID_MASK = 0x3;
3438// CompletionMode
3439pub const FILE_PIPE_QUEUE_OPERATION = 0x0;
3440pub const FILE_PIPE_COMPLETE_OPERATION = 0x1;
3441// ReadMode
3442pub const FILE_PIPE_BYTE_STREAM_MODE = 0x0;
3443pub const FILE_PIPE_MESSAGE_MODE = 0x1;
3444
34455306// flags for CreateEvent
34465307pub const CREATE_EVENT_INITIAL_SET = 0x00000002;
34475308pub const CREATE_EVENT_MANUAL_RESET = 0x00000001;
34485309
3449pub const EVENT_ALL_ACCESS = 0x1F0003;
3450pub const EVENT_MODIFY_STATE = 0x0002;
3451
3452// MEMORY_BASIC_INFORMATION.Type flags for VirtualQuery
3453pub const MEM_IMAGE = 0x1000000;
3454pub const MEM_MAPPED = 0x40000;
3455pub const MEM_PRIVATE = 0x20000;
3456
34575310pub const PROCESS_INFORMATION = extern struct {
34585311 hProcess: HANDLE,
34595312 hThread: HANDLE,
......@@ -3521,45 +5374,6 @@ pub const FILE_BEGIN = 0;
35215374pub const FILE_CURRENT = 1;
35225375pub const FILE_END = 2;
35235376
3524pub const HEAP_CREATE_ENABLE_EXECUTE = 0x00040000;
3525pub const HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010;
3526pub const HEAP_GENERATE_EXCEPTIONS = 0x00000004;
3527pub const HEAP_NO_SERIALIZE = 0x00000001;
3528
3529// AllocationType values
3530pub const MEM_COMMIT = 0x1000;
3531pub const MEM_RESERVE = 0x2000;
3532pub const MEM_FREE = 0x10000;
3533pub const MEM_RESET = 0x80000;
3534pub const MEM_RESET_UNDO = 0x1000000;
3535pub const MEM_LARGE_PAGES = 0x20000000;
3536pub const MEM_PHYSICAL = 0x400000;
3537pub const MEM_TOP_DOWN = 0x100000;
3538pub const MEM_WRITE_WATCH = 0x200000;
3539pub const MEM_RESERVE_PLACEHOLDER = 0x00040000;
3540pub const MEM_PRESERVE_PLACEHOLDER = 0x00000400;
3541
3542// Protect values
3543pub const PAGE_EXECUTE = 0x10;
3544pub const PAGE_EXECUTE_READ = 0x20;
3545pub const PAGE_EXECUTE_READWRITE = 0x40;
3546pub const PAGE_EXECUTE_WRITECOPY = 0x80;
3547pub const PAGE_NOACCESS = 0x01;
3548pub const PAGE_READONLY = 0x02;
3549pub const PAGE_READWRITE = 0x04;
3550pub const PAGE_WRITECOPY = 0x08;
3551pub const PAGE_TARGETS_INVALID = 0x40000000;
3552pub const PAGE_TARGETS_NO_UPDATE = 0x40000000; // Same as PAGE_TARGETS_INVALID
3553pub const PAGE_GUARD = 0x100;
3554pub const PAGE_NOCACHE = 0x200;
3555pub const PAGE_WRITECOMBINE = 0x400;
3556
3557// FreeType values
3558pub const MEM_COALESCE_PLACEHOLDERS = 0x1;
3559pub const MEM_RESERVE_PLACEHOLDERS = 0x2;
3560pub const MEM_DECOMMIT = 0x4000;
3561pub const MEM_RELEASE = 0x8000;
3562
35635377pub const PTHREAD_START_ROUTINE = *const fn (LPVOID) callconv(.winapi) DWORD;
35645378pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE;
35655379
......@@ -3743,38 +5557,8 @@ pub const PIMAGE_TLS_CALLBACK = ?*const fn (PVOID, DWORD, PVOID) callconv(.winap
37435557pub const PROV_RSA_FULL = 1;
37445558
37455559pub const REGSAM = ACCESS_MASK;
3746pub const ACCESS_MASK = DWORD;
37475560pub const LSTATUS = LONG;
37485561
3749pub const SECTION_INHERIT = enum(c_int) {
3750 ViewShare = 0,
3751 ViewUnmap = 1,
3752};
3753
3754pub const SECTION_QUERY = 0x0001;
3755pub const SECTION_MAP_WRITE = 0x0002;
3756pub const SECTION_MAP_READ = 0x0004;
3757pub const SECTION_MAP_EXECUTE = 0x0008;
3758pub const SECTION_EXTEND_SIZE = 0x0010;
3759pub const SECTION_ALL_ACCESS =
3760 STANDARD_RIGHTS_REQUIRED |
3761 SECTION_QUERY |
3762 SECTION_MAP_WRITE |
3763 SECTION_MAP_READ |
3764 SECTION_MAP_EXECUTE |
3765 SECTION_EXTEND_SIZE;
3766
3767pub const SEC_64K_PAGES = 0x80000;
3768pub const SEC_FILE = 0x800000;
3769pub const SEC_IMAGE = 0x1000000;
3770pub const SEC_PROTECTED_IMAGE = 0x2000000;
3771pub const SEC_RESERVE = 0x4000000;
3772pub const SEC_COMMIT = 0x8000000;
3773pub const SEC_IMAGE_NO_EXECUTE = SEC_IMAGE | SEC_NOCACHE;
3774pub const SEC_NOCACHE = 0x10000000;
3775pub const SEC_WRITECOMBINE = 0x40000000;
3776pub const SEC_LARGE_PAGES = 0x80000000;
3777
37785562pub const HKEY = *opaque {};
37795563
37805564pub const HKEY_CLASSES_ROOT: HKEY = @ptrFromInt(0x80000000);
......@@ -3788,34 +5572,6 @@ pub const HKEY_CURRENT_CONFIG: HKEY = @ptrFromInt(0x80000005);
37885572pub const HKEY_DYN_DATA: HKEY = @ptrFromInt(0x80000006);
37895573pub const HKEY_CURRENT_USER_LOCAL_SETTINGS: HKEY = @ptrFromInt(0x80000007);
37905574
3791/// Combines the STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE, KEY_SET_VALUE, KEY_CREATE_SUB_KEY,
3792/// KEY_ENUMERATE_SUB_KEYS, KEY_NOTIFY, and KEY_CREATE_LINK access rights.
3793pub const KEY_ALL_ACCESS = 0xF003F;
3794/// Reserved for system use.
3795pub const KEY_CREATE_LINK = 0x0020;
3796/// Required to create a subkey of a registry key.
3797pub const KEY_CREATE_SUB_KEY = 0x0004;
3798/// Required to enumerate the subkeys of a registry key.
3799pub const KEY_ENUMERATE_SUB_KEYS = 0x0008;
3800/// Equivalent to KEY_READ.
3801pub const KEY_EXECUTE = 0x20019;
3802/// Required to request change notifications for a registry key or for subkeys of a registry key.
3803pub const KEY_NOTIFY = 0x0010;
3804/// Required to query the values of a registry key.
3805pub const KEY_QUERY_VALUE = 0x0001;
3806/// Combines the STANDARD_RIGHTS_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, and KEY_NOTIFY values.
3807pub const KEY_READ = 0x20019;
3808/// Required to create, delete, or set a registry value.
3809pub const KEY_SET_VALUE = 0x0002;
3810/// Indicates that an application on 64-bit Windows should operate on the 32-bit registry view.
3811/// This flag is ignored by 32-bit Windows.
3812pub const KEY_WOW64_32KEY = 0x0200;
3813/// Indicates that an application on 64-bit Windows should operate on the 64-bit registry view.
3814/// This flag is ignored by 32-bit Windows.
3815pub const KEY_WOW64_64KEY = 0x0100;
3816/// Combines the STANDARD_RIGHTS_WRITE, KEY_SET_VALUE, and KEY_CREATE_SUB_KEY access rights.
3817pub const KEY_WRITE = 0x20006;
3818
38195575/// Open symbolic link.
38205576pub const REG_OPTION_OPEN_LINK: DWORD = 0x8;
38215577
......@@ -4466,14 +6222,14 @@ pub const EXCEPTION_DISPOSITION = i32;
44666222pub const EXCEPTION_ROUTINE = *const fn (
44676223 ExceptionRecord: ?*EXCEPTION_RECORD,
44686224 EstablisherFrame: PVOID,
4469 ContextRecord: *(Self.CONTEXT),
6225 ContextRecord: *CONTEXT,
44706226 DispatcherContext: PVOID,
44716227) callconv(.winapi) EXCEPTION_DISPOSITION;
44726228
44736229pub const UNWIND_HISTORY_TABLE_SIZE = 12;
44746230pub const UNWIND_HISTORY_TABLE_ENTRY = extern struct {
44756231 ImageBase: ULONG64,
4476 FunctionEntry: *Self.RUNTIME_FUNCTION,
6232 FunctionEntry: *RUNTIME_FUNCTION,
44776233};
44786234
44796235pub const UNWIND_HISTORY_TABLE = extern struct {
......@@ -4492,24 +6248,6 @@ pub const UNW_FLAG_EHANDLER = 0x1;
44926248pub const UNW_FLAG_UHANDLER = 0x2;
44936249pub const UNW_FLAG_CHAININFO = 0x4;
44946250
4495pub const OBJECT_ATTRIBUTES = extern struct {
4496 Length: ULONG,
4497 RootDirectory: ?HANDLE,
4498 ObjectName: *UNICODE_STRING,
4499 Attributes: ULONG,
4500 SecurityDescriptor: ?*anyopaque,
4501 SecurityQualityOfService: ?*anyopaque,
4502};
4503
4504pub const OBJ_INHERIT = 0x00000002;
4505pub const OBJ_PERMANENT = 0x00000010;
4506pub const OBJ_EXCLUSIVE = 0x00000020;
4507pub const OBJ_CASE_INSENSITIVE = 0x00000040;
4508pub const OBJ_OPENIF = 0x00000080;
4509pub const OBJ_OPENLINK = 0x00000100;
4510pub const OBJ_KERNEL_HANDLE = 0x00000200;
4511pub const OBJ_VALID_ATTRIBUTES = 0x000003F2;
4512
45136251pub const UNICODE_STRING = extern struct {
45146252 Length: c_ushort,
45156253 MaximumLength: c_ushort,
......@@ -4617,7 +6355,7 @@ pub const PEB = extern struct {
46176355 Ldr: *PEB_LDR_DATA,
46186356 ProcessParameters: *RTL_USER_PROCESS_PARAMETERS,
46196357 SubSystemData: PVOID,
4620 ProcessHeap: HANDLE,
6358 ProcessHeap: ?*HEAP,
46216359
46226360 // Versions: 5.1+
46236361 FastPebLock: *RTL_CRITICAL_SECTION,
......@@ -4862,7 +6600,7 @@ pub const FILE_DIRECTORY_INFORMATION = extern struct {
48626600 ChangeTime: LARGE_INTEGER,
48636601 EndOfFile: LARGE_INTEGER,
48646602 AllocationSize: LARGE_INTEGER,
4865 FileAttributes: ULONG,
6603 FileAttributes: FILE.ATTRIBUTE,
48666604 FileNameLength: ULONG,
48676605 FileName: [1]WCHAR,
48686606};
......@@ -4876,7 +6614,7 @@ pub const FILE_BOTH_DIR_INFORMATION = extern struct {
48766614 ChangeTime: LARGE_INTEGER,
48776615 EndOfFile: LARGE_INTEGER,
48786616 AllocationSize: LARGE_INTEGER,
4879 FileAttributes: ULONG,
6617 FileAttributes: FILE.ATTRIBUTE,
48806618 FileNameLength: ULONG,
48816619 EaSize: ULONG,
48826620 ShortNameLength: CHAR,
......@@ -4905,7 +6643,7 @@ pub fn FileInformationIterator(comptime FileInformationType: type) type {
49056643 };
49066644}
49076645
4908pub const IO_APC_ROUTINE = *const fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void;
6646pub const IO_APC_ROUTINE = fn (?*anyopaque, *IO_STATUS_BLOCK, ULONG) callconv(.winapi) void;
49096647
49106648pub const CURDIR = extern struct {
49116649 DosPath: UNICODE_STRING,
......@@ -4974,7 +6712,7 @@ pub const GetProcessMemoryInfoError = error{
49746712
49756713pub fn GetProcessMemoryInfo(hProcess: HANDLE) GetProcessMemoryInfoError!VM_COUNTERS {
49766714 var vmc: VM_COUNTERS = undefined;
4977 const rc = ntdll.NtQueryInformationProcess(hProcess, .ProcessVmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
6715 const rc = ntdll.NtQueryInformationProcess(hProcess, .VmCounters, &vmc, @sizeOf(VM_COUNTERS), null);
49786716 switch (rc) {
49796717 .SUCCESS => return vmc,
49806718 .ACCESS_DENIED => return error.AccessDenied,
......@@ -5029,7 +6767,7 @@ pub const OSVERSIONINFOW = extern struct {
50296767pub const RTL_OSVERSIONINFOW = OSVERSIONINFOW;
50306768
50316769pub const REPARSE_DATA_BUFFER = extern struct {
5032 ReparseTag: ULONG,
6770 ReparseTag: IO_REPARSE_TAG,
50336771 ReparseDataLength: USHORT,
50346772 Reserved: USHORT,
50356773 DataBuffer: [1]UCHAR,
......@@ -5049,18 +6787,11 @@ pub const MOUNT_POINT_REPARSE_BUFFER = extern struct {
50496787 PrintNameLength: USHORT,
50506788 PathBuffer: [1]WCHAR,
50516789};
5052pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: ULONG = 16 * 1024;
5053pub const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
5054pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8;
5055pub const IO_REPARSE_TAG_SYMLINK: ULONG = 0xa000000c;
5056pub const IO_REPARSE_TAG_MOUNT_POINT: ULONG = 0xa0000003;
50576790pub const SYMLINK_FLAG_RELATIVE: ULONG = 0x1;
50586791
50596792pub const SYMBOLIC_LINK_FLAG_DIRECTORY: DWORD = 0x1;
50606793pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: DWORD = 0x2;
50616794
5062pub const MOUNTMGRCONTROLTYPE = 0x0000006D;
5063
50646795pub const MOUNTMGR_MOUNT_POINT = extern struct {
50656796 SymbolicLinkNameOffset: ULONG,
50666797 SymbolicLinkNameLength: USHORT,
......@@ -5077,7 +6808,6 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
50776808 NumberOfMountPoints: ULONG,
50786809 MountPoints: [1]MOUNTMGR_MOUNT_POINT,
50796810};
5080pub const IOCTL_MOUNTMGR_QUERY_POINTS = CTL_CODE(MOUNTMGRCONTROLTYPE, 2, .METHOD_BUFFERED, FILE_ANY_ACCESS);
50816811
50826812pub const MOUNTMGR_TARGET_NAME = extern struct {
50836813 DeviceNameLength: USHORT,
......@@ -5087,7 +6817,6 @@ pub const MOUNTMGR_VOLUME_PATHS = extern struct {
50876817 MultiSzLength: ULONG,
50886818 MultiSz: [1]WCHAR,
50896819};
5090pub const IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH = CTL_CODE(MOUNTMGRCONTROLTYPE, 12, .METHOD_BUFFERED, FILE_ANY_ACCESS);
50916820
50926821pub const OBJECT_INFORMATION_CLASS = enum(c_int) {
50936822 ObjectBasicInformation = 0,
......@@ -5479,113 +7208,6 @@ pub const SYSTEM_BASIC_INFORMATION = extern struct {
54797208 NumberOfProcessors: UCHAR,
54807209};
54817210
5482pub const THREADINFOCLASS = enum(c_int) {
5483 ThreadBasicInformation,
5484 ThreadTimes,
5485 ThreadPriority,
5486 ThreadBasePriority,
5487 ThreadAffinityMask,
5488 ThreadImpersonationToken,
5489 ThreadDescriptorTableEntry,
5490 ThreadEnableAlignmentFaultFixup,
5491 ThreadEventPair_Reusable,
5492 ThreadQuerySetWin32StartAddress,
5493 ThreadZeroTlsCell,
5494 ThreadPerformanceCount,
5495 ThreadAmILastThread,
5496 ThreadIdealProcessor,
5497 ThreadPriorityBoost,
5498 ThreadSetTlsArrayAddress,
5499 ThreadIsIoPending,
5500 // Windows 2000+ from here
5501 ThreadHideFromDebugger,
5502 // Windows XP+ from here
5503 ThreadBreakOnTermination,
5504 ThreadSwitchLegacyState,
5505 ThreadIsTerminated,
5506 // Windows Vista+ from here
5507 ThreadLastSystemCall,
5508 ThreadIoPriority,
5509 ThreadCycleTime,
5510 ThreadPagePriority,
5511 ThreadActualBasePriority,
5512 ThreadTebInformation,
5513 ThreadCSwitchMon,
5514 // Windows 7+ from here
5515 ThreadCSwitchPmu,
5516 ThreadWow64Context,
5517 ThreadGroupInformation,
5518 ThreadUmsInformation,
5519 ThreadCounterProfiling,
5520 ThreadIdealProcessorEx,
5521 // Windows 8+ from here
5522 ThreadCpuAccountingInformation,
5523 // Windows 8.1+ from here
5524 ThreadSuspendCount,
5525 // Windows 10+ from here
5526 ThreadHeterogeneousCpuPolicy,
5527 ThreadContainerId,
5528 ThreadNameInformation,
5529 ThreadSelectedCpuSets,
5530 ThreadSystemThreadInformation,
5531 ThreadActualGroupAffinity,
5532};
5533
5534pub const PROCESSINFOCLASS = enum(c_int) {
5535 ProcessBasicInformation,
5536 ProcessQuotaLimits,
5537 ProcessIoCounters,
5538 ProcessVmCounters,
5539 ProcessTimes,
5540 ProcessBasePriority,
5541 ProcessRaisePriority,
5542 ProcessDebugPort,
5543 ProcessExceptionPort,
5544 ProcessAccessToken,
5545 ProcessLdtInformation,
5546 ProcessLdtSize,
5547 ProcessDefaultHardErrorMode,
5548 ProcessIoPortHandlers,
5549 ProcessPooledUsageAndLimits,
5550 ProcessWorkingSetWatch,
5551 ProcessUserModeIOPL,
5552 ProcessEnableAlignmentFaultFixup,
5553 ProcessPriorityClass,
5554 ProcessWx86Information,
5555 ProcessHandleCount,
5556 ProcessAffinityMask,
5557 ProcessPriorityBoost,
5558 ProcessDeviceMap,
5559 ProcessSessionInformation,
5560 ProcessForegroundInformation,
5561 ProcessWow64Information,
5562 ProcessImageFileName,
5563 ProcessLUIDDeviceMapsEnabled,
5564 ProcessBreakOnTermination,
5565 ProcessDebugObjectHandle,
5566 ProcessDebugFlags,
5567 ProcessHandleTracing,
5568 ProcessIoPriority,
5569 ProcessExecuteFlags,
5570 ProcessTlsInformation,
5571 ProcessCookie,
5572 ProcessImageInformation,
5573 ProcessCycleTime,
5574 ProcessPagePriority,
5575 ProcessInstrumentationCallback,
5576 ProcessThreadStackAllocation,
5577 ProcessWorkingSetWatchEx,
5578 ProcessImageFileNameWin32,
5579 ProcessImageFileMapping,
5580 ProcessAffinityUpdateMode,
5581 ProcessMemoryAllocationMode,
5582 ProcessGroupInformation,
5583 ProcessTokenVirtualizationEnabled,
5584 ProcessConsoleHostProcess,
5585 ProcessWindowInformation,
5586 MaxProcessInfoClass,
5587};
5588
55897211pub const PROCESS_BASIC_INFORMATION = extern struct {
55907212 ExitStatus: NTSTATUS,
55917213 PebBaseAddress: *PEB,
......@@ -5641,7 +7263,7 @@ pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE {
56417263 var nread: DWORD = 0;
56427264 const rc = ntdll.NtQueryInformationProcess(
56437265 handle,
5644 .ProcessBasicInformation,
7266 .BasicInformation,
56457267 &info,
56467268 @sizeOf(PROCESS_BASIC_INFORMATION),
56477269 &nread,
lib/std/os/windows/kernel32.zig+3-33
......@@ -1,6 +1,7 @@
11const std = @import("../../std.zig");
22const windows = std.os.windows;
33
4const ACCESS_MASK = windows.ACCESS_MASK;
45const BOOL = windows.BOOL;
56const CONDITION_VARIABLE = windows.CONDITION_VARIABLE;
67const CONSOLE_SCREEN_BUFFER_INFO = windows.CONSOLE_SCREEN_BUFFER_INFO;
......@@ -66,7 +67,7 @@ pub extern "kernel32" fn CancelIoEx(
6667
6768pub extern "kernel32" fn CreateFileW(
6869 lpFileName: LPCWSTR,
69 dwDesiredAccess: DWORD,
70 dwDesiredAccess: ACCESS_MASK,
7071 dwShareMode: DWORD,
7172 lpSecurityAttributes: ?*SECURITY_ATTRIBUTES,
7273 dwCreationDisposition: DWORD,
......@@ -160,7 +161,7 @@ pub extern "kernel32" fn DuplicateHandle(
160161 hSourceHandle: HANDLE,
161162 hTargetProcessHandle: HANDLE,
162163 lpTargetHandle: *HANDLE,
163 dwDesiredAccess: DWORD,
164 dwDesiredAccess: ACCESS_MASK,
164165 bInheritHandle: BOOL,
165166 dwOptions: DWORD,
166167) callconv(.winapi) BOOL;
......@@ -308,9 +309,6 @@ pub extern "kernel32" fn CreateThread(
308309 lpThreadId: ?*DWORD,
309310) callconv(.winapi) ?HANDLE;
310311
311// TODO: Wrapper around RtlDelayExecution.
312pub extern "kernel32" fn SwitchToThread() callconv(.winapi) BOOL;
313
314312// Locks, critical sections, initializers
315313
316314pub extern "kernel32" fn InitOnceExecuteOnce(
......@@ -401,34 +399,6 @@ pub extern "kernel32" fn ReadConsoleOutputCharacterW(
401399 lpNumberOfCharsRead: *DWORD,
402400) callconv(.winapi) BOOL;
403401
404// Memory Mapping/Allocation
405
406// TODO: Wrapper around RtlCreateHeap.
407pub extern "kernel32" fn HeapCreate(
408 flOptions: DWORD,
409 dwInitialSize: SIZE_T,
410 dwMaximumSize: SIZE_T,
411) callconv(.winapi) ?HANDLE;
412
413// TODO: Fowrarder to RtlFreeHeap before win11_zn.
414// Since win11_zn this function points to unexported symbol RtlFreeHeapFast.
415// See https://github.com/ziglang/zig/pull/25766#discussion_r2479727640
416pub extern "kernel32" fn HeapFree(
417 hHeap: HANDLE,
418 dwFlags: DWORD,
419 lpMem: LPVOID,
420) callconv(.winapi) BOOL;
421
422// TODO: Wrapper around RtlValidateHeap (BOOLEAN -> BOOL)
423pub extern "kernel32" fn HeapValidate(
424 hHeap: HANDLE,
425 dwFlags: DWORD,
426 lpMem: ?*const anyopaque,
427) callconv(.winapi) BOOL;
428
429// TODO: Getter for peb.ProcessHeap
430pub extern "kernel32" fn GetProcessHeap() callconv(.winapi) ?HANDLE;
431
432402// Code Libraries/Modules
433403
434404// TODO: Wrapper around LdrGetDllFullName.
lib/std/os/windows/ntdll.zig+388-263
......@@ -1,277 +1,279 @@
11const std = @import("../../std.zig");
22const windows = std.os.windows;
33
4const ACCESS_MASK = windows.ACCESS_MASK;
45const BOOL = windows.BOOL;
6const BOOLEAN = windows.BOOLEAN;
7const CONDITION_VARIABLE = windows.CONDITION_VARIABLE;
8const CONTEXT = windows.CONTEXT;
9const CRITICAL_SECTION = windows.CRITICAL_SECTION;
10const CTL_CODE = windows.CTL_CODE;
11const CURDIR = windows.CURDIR;
512const DWORD = windows.DWORD;
613const DWORD64 = windows.DWORD64;
7const ULONG = windows.ULONG;
8const ULONG_PTR = windows.ULONG_PTR;
9const NTSTATUS = windows.NTSTATUS;
10const WORD = windows.WORD;
14const ERESOURCE = windows.ERESOURCE;
15const EVENT_TYPE = windows.EVENT_TYPE;
16const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
17const FILE = windows.FILE;
18const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS;
1119const HANDLE = windows.HANDLE;
12const ACCESS_MASK = windows.ACCESS_MASK;
20const HEAP = windows.HEAP;
1321const IO_APC_ROUTINE = windows.IO_APC_ROUTINE;
14const BOOLEAN = windows.BOOLEAN;
15const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES;
16const PVOID = windows.PVOID;
1722const IO_STATUS_BLOCK = windows.IO_STATUS_BLOCK;
23const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
1824const LARGE_INTEGER = windows.LARGE_INTEGER;
25const LOGICAL = windows.LOGICAL;
26const LONG = windows.LONG;
27const LPCVOID = windows.LPCVOID;
28const LPVOID = windows.LPVOID;
29const MEM = windows.MEM;
30const NTSTATUS = windows.NTSTATUS;
31const OBJECT_ATTRIBUTES = windows.OBJECT_ATTRIBUTES;
1932const OBJECT_INFORMATION_CLASS = windows.OBJECT_INFORMATION_CLASS;
20const FILE_INFORMATION_CLASS = windows.FILE_INFORMATION_CLASS;
21const FS_INFORMATION_CLASS = windows.FS_INFORMATION_CLASS;
22const UNICODE_STRING = windows.UNICODE_STRING;
23const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW;
24const FILE_BASIC_INFORMATION = windows.FILE_BASIC_INFORMATION;
25const SIZE_T = windows.SIZE_T;
26const CURDIR = windows.CURDIR;
33const PAGE = windows.PAGE;
2734const PCWSTR = windows.PCWSTR;
35const PROCESSINFOCLASS = windows.PROCESSINFOCLASS;
36const PVOID = windows.PVOID;
37const RTL_OSVERSIONINFOW = windows.RTL_OSVERSIONINFOW;
2838const RTL_QUERY_REGISTRY_TABLE = windows.RTL_QUERY_REGISTRY_TABLE;
29const CONTEXT = windows.CONTEXT;
30const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE;
3139const RUNTIME_FUNCTION = windows.RUNTIME_FUNCTION;
32const KNONVOLATILE_CONTEXT_POINTERS = windows.KNONVOLATILE_CONTEXT_POINTERS;
33const EXCEPTION_ROUTINE = windows.EXCEPTION_ROUTINE;
40const SEC = windows.SEC;
41const SECTION_INHERIT = windows.SECTION_INHERIT;
42const SIZE_T = windows.SIZE_T;
43const SRWLOCK = windows.SRWLOCK;
3444const SYSTEM_INFORMATION_CLASS = windows.SYSTEM_INFORMATION_CLASS;
3545const THREADINFOCLASS = windows.THREADINFOCLASS;
36const PROCESSINFOCLASS = windows.PROCESSINFOCLASS;
37const LPVOID = windows.LPVOID;
38const LPCVOID = windows.LPCVOID;
39const SECTION_INHERIT = windows.SECTION_INHERIT;
46const ULONG = windows.ULONG;
47const ULONG_PTR = windows.ULONG_PTR;
48const UNICODE_STRING = windows.UNICODE_STRING;
49const UNWIND_HISTORY_TABLE = windows.UNWIND_HISTORY_TABLE;
50const USHORT = windows.USHORT;
4051const VECTORED_EXCEPTION_HANDLER = windows.VECTORED_EXCEPTION_HANDLER;
41const CRITICAL_SECTION = windows.CRITICAL_SECTION;
42const SRWLOCK = windows.SRWLOCK;
43const CONDITION_VARIABLE = windows.CONDITION_VARIABLE;
52const WORD = windows.WORD;
4453
45pub extern "ntdll" fn NtQueryInformationProcess(
46 ProcessHandle: HANDLE,
47 ProcessInformationClass: PROCESSINFOCLASS,
48 ProcessInformation: *anyopaque,
49 ProcessInformationLength: ULONG,
50 ReturnLength: ?*ULONG,
51) callconv(.winapi) NTSTATUS;
54// ref: km/ntifs.h
5255
53pub extern "ntdll" fn NtQueryInformationThread(
54 ThreadHandle: HANDLE,
55 ThreadInformationClass: THREADINFOCLASS,
56 ThreadInformation: *anyopaque,
57 ThreadInformationLength: ULONG,
58 ReturnLength: ?*ULONG,
59) callconv(.winapi) NTSTATUS;
56pub extern "ntdll" fn RtlCreateHeap(
57 Flags: HEAP.FLAGS.CREATE,
58 HeapBase: ?PVOID,
59 ReserveSize: SIZE_T,
60 CommitSize: SIZE_T,
61 Lock: ?*ERESOURCE,
62 Parameters: ?*const HEAP.RTL_PARAMETERS,
63) callconv(.winapi) ?*HEAP;
6064
61pub extern "ntdll" fn NtQuerySystemInformation(
62 SystemInformationClass: SYSTEM_INFORMATION_CLASS,
63 SystemInformation: PVOID,
64 SystemInformationLength: ULONG,
65 ReturnLength: ?*ULONG,
66) callconv(.winapi) NTSTATUS;
65pub extern "ntdll" fn RtlDestroyHeap(
66 HeapHandle: *HEAP,
67) callconv(.winapi) ?*HEAP;
6768
68pub extern "ntdll" fn NtSetInformationThread(
69 ThreadHandle: HANDLE,
70 ThreadInformationClass: THREADINFOCLASS,
71 ThreadInformation: *const anyopaque,
72 ThreadInformationLength: ULONG,
73) callconv(.winapi) NTSTATUS;
69pub extern "ntdll" fn RtlAllocateHeap(
70 HeapHandle: *HEAP,
71 Flags: HEAP.FLAGS.ALLOCATION,
72 Size: SIZE_T,
73) callconv(.winapi) ?PVOID;
74
75pub extern "ntdll" fn RtlFreeHeap(
76 HeapHandle: *HEAP,
77 Flags: HEAP.FLAGS.ALLOCATION,
78 BaseAddress: ?PVOID,
79) callconv(.winapi) LOGICAL;
7480
75pub extern "ntdll" fn RtlGetVersion(
76 lpVersionInformation: *RTL_OSVERSIONINFOW,
77) callconv(.winapi) NTSTATUS;
7881pub extern "ntdll" fn RtlCaptureStackBackTrace(
79 FramesToSkip: DWORD,
80 FramesToCapture: DWORD,
82 FramesToSkip: ULONG,
83 FramesToCapture: ULONG,
8184 BackTrace: **anyopaque,
82 BackTraceHash: ?*DWORD,
83) callconv(.winapi) WORD;
84pub extern "ntdll" fn RtlCaptureContext(ContextRecord: *CONTEXT) callconv(.winapi) void;
85pub extern "ntdll" fn RtlLookupFunctionEntry(
86 ControlPc: DWORD64,
87 ImageBase: *DWORD64,
88 HistoryTable: *UNWIND_HISTORY_TABLE,
89) callconv(.winapi) ?*RUNTIME_FUNCTION;
90pub extern "ntdll" fn RtlVirtualUnwind(
91 HandlerType: DWORD,
92 ImageBase: DWORD64,
93 ControlPc: DWORD64,
94 FunctionEntry: *RUNTIME_FUNCTION,
95 ContextRecord: *CONTEXT,
96 HandlerData: *?PVOID,
97 EstablisherFrame: *DWORD64,
98 ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS,
99) callconv(.winapi) *EXCEPTION_ROUTINE;
100pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER;
101pub extern "ntdll" fn NtQueryInformationFile(
102 FileHandle: HANDLE,
103 IoStatusBlock: *IO_STATUS_BLOCK,
104 FileInformation: *anyopaque,
105 Length: ULONG,
106 FileInformationClass: FILE_INFORMATION_CLASS,
107) callconv(.winapi) NTSTATUS;
108pub extern "ntdll" fn NtSetInformationFile(
109 FileHandle: HANDLE,
110 IoStatusBlock: *IO_STATUS_BLOCK,
111 FileInformation: PVOID,
112 Length: ULONG,
113 FileInformationClass: FILE_INFORMATION_CLASS,
114) callconv(.winapi) NTSTATUS;
85 BackTraceHash: ?*ULONG,
86) callconv(.winapi) USHORT;
11587
116pub extern "ntdll" fn NtQueryAttributesFile(
117 ObjectAttributes: *OBJECT_ATTRIBUTES,
118 FileAttributes: *FILE_BASIC_INFORMATION,
119) callconv(.winapi) NTSTATUS;
88pub extern "ntdll" fn RtlCaptureContext(
89 ContextRecord: *CONTEXT,
90) callconv(.winapi) void;
12091
121pub extern "ntdll" fn RtlQueryPerformanceCounter(PerformanceCounter: *LARGE_INTEGER) callconv(.winapi) BOOL;
122pub extern "ntdll" fn RtlQueryPerformanceFrequency(PerformanceFrequency: *LARGE_INTEGER) callconv(.winapi) BOOL;
123pub extern "ntdll" fn NtQueryPerformanceCounter(
124 PerformanceCounter: *LARGE_INTEGER,
125 PerformanceFrequency: ?*LARGE_INTEGER,
92pub extern "ntdll" fn NtSetInformationThread(
93 ThreadHandle: HANDLE,
94 ThreadInformationClass: THREADINFOCLASS,
95 ThreadInformation: *const anyopaque,
96 ThreadInformationLength: ULONG,
12697) callconv(.winapi) NTSTATUS;
12798
12899pub extern "ntdll" fn NtCreateFile(
129100 FileHandle: *HANDLE,
130101 DesiredAccess: ACCESS_MASK,
131 ObjectAttributes: *OBJECT_ATTRIBUTES,
102 ObjectAttributes: *const OBJECT_ATTRIBUTES,
132103 IoStatusBlock: *IO_STATUS_BLOCK,
133 AllocationSize: ?*LARGE_INTEGER,
134 FileAttributes: ULONG,
135 ShareAccess: ULONG,
136 CreateDisposition: ULONG,
137 CreateOptions: ULONG,
104 AllocationSize: ?*const LARGE_INTEGER,
105 FileAttributes: FILE.ATTRIBUTE,
106 ShareAccess: FILE.SHARE,
107 CreateDisposition: FILE.CREATE_DISPOSITION,
108 CreateOptions: FILE.MODE,
138109 EaBuffer: ?*anyopaque,
139110 EaLength: ULONG,
140111) callconv(.winapi) NTSTATUS;
141pub extern "ntdll" fn NtCreateSection(
142 SectionHandle: *HANDLE,
143 DesiredAccess: ACCESS_MASK,
144 ObjectAttributes: ?*OBJECT_ATTRIBUTES,
145 MaximumSize: ?*LARGE_INTEGER,
146 SectionPageProtection: ULONG,
147 AllocationAttributes: ULONG,
148 FileHandle: ?HANDLE,
149) callconv(.winapi) NTSTATUS;
150pub extern "ntdll" fn NtMapViewOfSection(
151 SectionHandle: HANDLE,
152 ProcessHandle: HANDLE,
153 BaseAddress: *PVOID,
154 ZeroBits: ?*ULONG,
155 CommitSize: SIZE_T,
156 SectionOffset: ?*LARGE_INTEGER,
157 ViewSize: *SIZE_T,
158 InheritDispostion: SECTION_INHERIT,
159 AllocationType: ULONG,
160 Win32Protect: ULONG,
161) callconv(.winapi) NTSTATUS;
162pub extern "ntdll" fn NtUnmapViewOfSection(
163 ProcessHandle: HANDLE,
164 BaseAddress: PVOID,
165) callconv(.winapi) NTSTATUS;
112
166113pub extern "ntdll" fn NtDeviceIoControlFile(
167114 FileHandle: HANDLE,
168115 Event: ?HANDLE,
169 ApcRoutine: ?IO_APC_ROUTINE,
116 ApcRoutine: ?*const IO_APC_ROUTINE,
170117 ApcContext: ?*anyopaque,
171118 IoStatusBlock: *IO_STATUS_BLOCK,
172 IoControlCode: ULONG,
119 IoControlCode: CTL_CODE,
173120 InputBuffer: ?*const anyopaque,
174121 InputBufferLength: ULONG,
175122 OutputBuffer: ?PVOID,
176123 OutputBufferLength: ULONG,
177124) callconv(.winapi) NTSTATUS;
125
178126pub extern "ntdll" fn NtFsControlFile(
179127 FileHandle: HANDLE,
180128 Event: ?HANDLE,
181 ApcRoutine: ?IO_APC_ROUTINE,
129 ApcRoutine: ?*const IO_APC_ROUTINE,
182130 ApcContext: ?*anyopaque,
183131 IoStatusBlock: *IO_STATUS_BLOCK,
184 FsControlCode: ULONG,
132 FsControlCode: CTL_CODE,
185133 InputBuffer: ?*const anyopaque,
186134 InputBufferLength: ULONG,
187135 OutputBuffer: ?PVOID,
188136 OutputBufferLength: ULONG,
189137) callconv(.winapi) NTSTATUS;
190pub extern "ntdll" fn NtClose(Handle: HANDLE) callconv(.winapi) NTSTATUS;
191pub extern "ntdll" fn RtlDosPathNameToNtPathName_U(
192 DosPathName: [*:0]const u16,
193 NtPathName: *UNICODE_STRING,
194 NtFileNamePart: ?*?[*:0]const u16,
195 DirectoryInfo: ?*CURDIR,
196) callconv(.winapi) BOOL;
197pub extern "ntdll" fn RtlFreeUnicodeString(UnicodeString: *UNICODE_STRING) callconv(.winapi) void;
198138
199/// Returns the number of bytes written to `Buffer`.
200/// If the returned count is larger than `BufferByteLength`, the buffer was too small.
201/// If the returned count is zero, an error occurred.
202pub extern "ntdll" fn RtlGetFullPathName_U(
203 FileName: [*:0]const u16,
204 BufferByteLength: ULONG,
205 Buffer: [*]u16,
206 ShortName: ?*[*:0]const u16,
207) callconv(.winapi) windows.ULONG;
139pub extern "ntdll" fn NtLockFile(
140 FileHandle: HANDLE,
141 Event: ?HANDLE,
142 ApcRoutine: ?*const IO_APC_ROUTINE,
143 ApcContext: ?*anyopaque,
144 IoStatusBlock: *IO_STATUS_BLOCK,
145 ByteOffset: *const LARGE_INTEGER,
146 Length: *const LARGE_INTEGER,
147 Key: ?*const ULONG,
148 FailImmediately: BOOLEAN,
149 ExclusiveLock: BOOLEAN,
150) callconv(.winapi) NTSTATUS;
151
152pub extern "ntdll" fn NtOpenFile(
153 FileHandle: *HANDLE,
154 DesiredAccess: ACCESS_MASK,
155 ObjectAttributes: *const OBJECT_ATTRIBUTES,
156 IoStatusBlock: *IO_STATUS_BLOCK,
157 ShareAccess: FILE.SHARE,
158 OpenOptions: FILE.MODE,
159) callconv(.winapi) NTSTATUS;
208160
209161pub extern "ntdll" fn NtQueryDirectoryFile(
210162 FileHandle: HANDLE,
211163 Event: ?HANDLE,
212 ApcRoutine: ?IO_APC_ROUTINE,
164 ApcRoutine: ?*const IO_APC_ROUTINE,
213165 ApcContext: ?*anyopaque,
214166 IoStatusBlock: *IO_STATUS_BLOCK,
215167 FileInformation: *anyopaque,
216168 Length: ULONG,
217 FileInformationClass: FILE_INFORMATION_CLASS,
169 FileInformationClass: FILE.INFORMATION_CLASS,
218170 ReturnSingleEntry: BOOLEAN,
219 FileName: ?*UNICODE_STRING,
171 FileName: ?*const UNICODE_STRING,
220172 RestartScan: BOOLEAN,
221173) callconv(.winapi) NTSTATUS;
222174
223pub extern "ntdll" fn NtCreateKeyedEvent(
224 KeyedEventHandle: *HANDLE,
225 DesiredAccess: ACCESS_MASK,
226 ObjectAttributes: ?PVOID,
227 Flags: ULONG,
175pub extern "ntdll" fn NtQueryInformationFile(
176 FileHandle: HANDLE,
177 IoStatusBlock: *IO_STATUS_BLOCK,
178 FileInformation: *anyopaque,
179 Length: ULONG,
180 FileInformationClass: FILE.INFORMATION_CLASS,
228181) callconv(.winapi) NTSTATUS;
229182
230pub extern "ntdll" fn NtReleaseKeyedEvent(
231 EventHandle: ?HANDLE,
232 Key: ?*const anyopaque,
233 Alertable: BOOLEAN,
234 Timeout: ?*const LARGE_INTEGER,
183pub extern "ntdll" fn NtQueryVolumeInformationFile(
184 FileHandle: HANDLE,
185 IoStatusBlock: *IO_STATUS_BLOCK,
186 FsInformation: *anyopaque,
187 Length: ULONG,
188 FsInformationClass: FS_INFORMATION_CLASS,
235189) callconv(.winapi) NTSTATUS;
236190
237pub extern "ntdll" fn NtWaitForKeyedEvent(
238 EventHandle: ?HANDLE,
239 Key: ?*const anyopaque,
240 Alertable: BOOLEAN,
241 Timeout: ?*const LARGE_INTEGER,
191pub extern "ntdll" fn NtReadFile(
192 FileHandle: HANDLE,
193 Event: ?HANDLE,
194 ApcRoutine: ?*const IO_APC_ROUTINE,
195 ApcContext: ?*anyopaque,
196 IoStatusBlock: *IO_STATUS_BLOCK,
197 Buffer: *anyopaque,
198 Length: ULONG,
199 ByteOffset: ?*const LARGE_INTEGER,
200 Key: ?*const ULONG,
201) callconv(.winapi) NTSTATUS;
202
203pub extern "ntdll" fn NtSetInformationFile(
204 FileHandle: HANDLE,
205 IoStatusBlock: *IO_STATUS_BLOCK,
206 FileInformation: *const anyopaque,
207 Length: ULONG,
208 FileInformationClass: FILE.INFORMATION_CLASS,
209) callconv(.winapi) NTSTATUS;
210
211pub extern "ntdll" fn NtWriteFile(
212 FileHandle: HANDLE,
213 Event: ?HANDLE,
214 ApcRoutine: ?*const IO_APC_ROUTINE,
215 ApcContext: ?*anyopaque,
216 IoStatusBlock: *IO_STATUS_BLOCK,
217 Buffer: *const anyopaque,
218 Length: ULONG,
219 ByteOffset: ?*const LARGE_INTEGER,
220 Key: ?*const ULONG,
242221) callconv(.winapi) NTSTATUS;
243222
244pub extern "ntdll" fn RtlSetCurrentDirectory_U(PathName: *UNICODE_STRING) callconv(.winapi) NTSTATUS;
223pub extern "ntdll" fn NtUnlockFile(
224 FileHandle: HANDLE,
225 IoStatusBlock: *IO_STATUS_BLOCK,
226 ByteOffset: *const LARGE_INTEGER,
227 Length: *const LARGE_INTEGER,
228 Key: ULONG,
229) callconv(.winapi) NTSTATUS;
245230
246231pub extern "ntdll" fn NtQueryObject(
247232 Handle: HANDLE,
248233 ObjectInformationClass: OBJECT_INFORMATION_CLASS,
249 ObjectInformation: PVOID,
234 ObjectInformation: ?PVOID,
250235 ObjectInformationLength: ULONG,
251236 ReturnLength: ?*ULONG,
252237) callconv(.winapi) NTSTATUS;
253238
254pub extern "ntdll" fn NtQueryVolumeInformationFile(
255 FileHandle: HANDLE,
256 IoStatusBlock: *IO_STATUS_BLOCK,
257 FsInformation: *anyopaque,
258 Length: ULONG,
259 FsInformationClass: FS_INFORMATION_CLASS,
239pub extern "ntdll" fn NtClose(
240 Handle: HANDLE,
260241) callconv(.winapi) NTSTATUS;
261242
262pub extern "ntdll" fn RtlWakeAddressAll(
263 Address: ?*const anyopaque,
264) callconv(.winapi) void;
243pub extern "ntdll" fn NtCreateSection(
244 SectionHandle: *HANDLE,
245 DesiredAccess: ACCESS_MASK,
246 ObjectAttributes: ?*const OBJECT_ATTRIBUTES,
247 MaximumSize: ?*const LARGE_INTEGER,
248 SectionPageProtection: PAGE,
249 AllocationAttributes: SEC,
250 FileHandle: ?HANDLE,
251) callconv(.winapi) NTSTATUS;
265252
266pub extern "ntdll" fn RtlWakeAddressSingle(
267 Address: ?*const anyopaque,
268) callconv(.winapi) void;
253pub extern "ntdll" fn NtAllocateVirtualMemory(
254 ProcessHandle: HANDLE,
255 BaseAddress: *PVOID,
256 ZeroBits: ULONG_PTR,
257 RegionSize: *SIZE_T,
258 AllocationType: MEM.ALLOCATE,
259 Protect: PAGE,
260) callconv(.winapi) NTSTATUS;
269261
270pub extern "ntdll" fn RtlWaitOnAddress(
271 Address: ?*const anyopaque,
272 CompareAddress: ?*const anyopaque,
273 AddressSize: SIZE_T,
274 Timeout: ?*const LARGE_INTEGER,
262pub extern "ntdll" fn NtFreeVirtualMemory(
263 ProcessHandle: HANDLE,
264 BaseAddress: *PVOID,
265 RegionSize: *SIZE_T,
266 FreeType: MEM.FREE,
267) callconv(.winapi) NTSTATUS;
268
269// ref: km/wdm.h
270
271pub extern "ntdll" fn RtlQueryRegistryValues(
272 RelativeTo: ULONG,
273 Path: PCWSTR,
274 QueryTable: [*]RTL_QUERY_REGISTRY_TABLE,
275 Context: ?*const anyopaque,
276 Environment: ?*const anyopaque,
275277) callconv(.winapi) NTSTATUS;
276278
277279pub extern "ntdll" fn RtlEqualUnicodeString(
......@@ -284,39 +286,153 @@ pub extern "ntdll" fn RtlUpcaseUnicodeChar(
284286 SourceCharacter: u16,
285287) callconv(.winapi) u16;
286288
287pub extern "ntdll" fn NtLockFile(
288 FileHandle: HANDLE,
289 Event: ?HANDLE,
290 ApcRoutine: ?*IO_APC_ROUTINE,
291 ApcContext: ?*anyopaque,
292 IoStatusBlock: *IO_STATUS_BLOCK,
293 ByteOffset: *const LARGE_INTEGER,
294 Length: *const LARGE_INTEGER,
295 Key: ?*ULONG,
296 FailImmediately: BOOLEAN,
297 ExclusiveLock: BOOLEAN,
289pub extern "ntdll" fn RtlFreeUnicodeString(
290 UnicodeString: *UNICODE_STRING,
291) callconv(.winapi) void;
292
293pub extern "ntdll" fn RtlGetVersion(
294 lpVersionInformation: *RTL_OSVERSIONINFOW,
298295) callconv(.winapi) NTSTATUS;
299296
300pub extern "ntdll" fn NtUnlockFile(
301 FileHandle: HANDLE,
297// ref: um/winnt.h
298
299pub extern "ntdll" fn RtlLookupFunctionEntry(
300 ControlPc: usize,
301 ImageBase: *usize,
302 HistoryTable: *UNWIND_HISTORY_TABLE,
303) callconv(.winapi) ?*RUNTIME_FUNCTION;
304
305pub extern "ntdll" fn RtlVirtualUnwind(
306 HandlerType: DWORD,
307 ImageBase: usize,
308 ControlPc: usize,
309 FunctionEntry: *RUNTIME_FUNCTION,
310 ContextRecord: *CONTEXT,
311 HandlerData: *?PVOID,
312 EstablisherFrame: *usize,
313 ContextPointers: ?*KNONVOLATILE_CONTEXT_POINTERS,
314) callconv(.winapi) *EXCEPTION_ROUTINE;
315
316// ref: um/winternl.h
317
318pub extern "ntdll" fn NtWaitForSingleObject(
319 Handle: HANDLE,
320 Alertable: BOOLEAN,
321 Timeout: ?*const LARGE_INTEGER,
322) callconv(.winapi) NTSTATUS;
323
324pub extern "ntdll" fn NtQueryInformationProcess(
325 ProcessHandle: HANDLE,
326 ProcessInformationClass: PROCESSINFOCLASS,
327 ProcessInformation: *anyopaque,
328 ProcessInformationLength: ULONG,
329 ReturnLength: ?*ULONG,
330) callconv(.winapi) NTSTATUS;
331
332pub extern "ntdll" fn NtQueryInformationThread(
333 ThreadHandle: HANDLE,
334 ThreadInformationClass: THREADINFOCLASS,
335 ThreadInformation: *anyopaque,
336 ThreadInformationLength: ULONG,
337 ReturnLength: ?*ULONG,
338) callconv(.winapi) NTSTATUS;
339
340pub extern "ntdll" fn NtQuerySystemInformation(
341 SystemInformationClass: SYSTEM_INFORMATION_CLASS,
342 SystemInformation: PVOID,
343 SystemInformationLength: ULONG,
344 ReturnLength: ?*ULONG,
345) callconv(.winapi) NTSTATUS;
346
347// ref none
348
349pub extern "ntdll" fn NtQueryAttributesFile(
350 ObjectAttributes: *const OBJECT_ATTRIBUTES,
351 FileAttributes: *FILE.BASIC_INFORMATION,
352) callconv(.winapi) NTSTATUS;
353
354pub extern "ntdll" fn NtCreateEvent(
355 EventHandle: *HANDLE,
356 DesiredAccess: ACCESS_MASK,
357 ObjectAttributes: ?*const OBJECT_ATTRIBUTES,
358 EventType: EVENT_TYPE,
359 InitialState: BOOLEAN,
360) callconv(.winapi) NTSTATUS;
361pub extern "ntdll" fn NtSetEvent(
362 EventHandle: HANDLE,
363 PreviousState: ?*LONG,
364) callconv(.winapi) NTSTATUS;
365
366pub extern "ntdll" fn NtCreateKeyedEvent(
367 KeyedEventHandle: *HANDLE,
368 DesiredAccess: ACCESS_MASK,
369 ObjectAttributes: ?*const OBJECT_ATTRIBUTES,
370 Flags: ULONG,
371) callconv(.winapi) NTSTATUS;
372pub extern "ntdll" fn NtReleaseKeyedEvent(
373 EventHandle: ?HANDLE,
374 Key: ?*const anyopaque,
375 Alertable: BOOLEAN,
376 Timeout: ?*const LARGE_INTEGER,
377) callconv(.winapi) NTSTATUS;
378pub extern "ntdll" fn NtWaitForKeyedEvent(
379 EventHandle: ?HANDLE,
380 Key: ?*const anyopaque,
381 Alertable: BOOLEAN,
382 Timeout: ?*const LARGE_INTEGER,
383) callconv(.winapi) NTSTATUS;
384
385pub extern "ntdll" fn NtCreateNamedPipeFile(
386 FileHandle: *HANDLE,
387 DesiredAccess: ACCESS_MASK,
388 ObjectAttributes: *const OBJECT_ATTRIBUTES,
302389 IoStatusBlock: *IO_STATUS_BLOCK,
303 ByteOffset: *const LARGE_INTEGER,
304 Length: *const LARGE_INTEGER,
305 Key: ?*ULONG,
390 ShareAccess: FILE.SHARE,
391 CreateDisposition: FILE.CREATE_DISPOSITION,
392 CreateOptions: FILE.MODE,
393 NamedPipeType: FILE.PIPE.TYPE,
394 ReadMode: FILE.PIPE.READ_MODE,
395 CompletionMode: FILE.PIPE.COMPLETION_MODE,
396 MaximumInstances: ULONG,
397 InboundQuota: ULONG,
398 OutboundQuota: ULONG,
399 DefaultTimeout: ?*const LARGE_INTEGER,
400) callconv(.winapi) NTSTATUS;
401
402pub extern "ntdll" fn NtMapViewOfSection(
403 SectionHandle: HANDLE,
404 ProcessHandle: HANDLE,
405 BaseAddress: ?*PVOID,
406 ZeroBits: ?*const ULONG,
407 CommitSize: SIZE_T,
408 SectionOffset: ?*LARGE_INTEGER,
409 ViewSize: *SIZE_T,
410 InheritDispostion: SECTION_INHERIT,
411 AllocationType: MEM.MAP,
412 PageProtection: PAGE,
413) callconv(.winapi) NTSTATUS;
414pub extern "ntdll" fn NtUnmapViewOfSection(
415 ProcessHandle: HANDLE,
416 BaseAddress: PVOID,
417) callconv(.winapi) NTSTATUS;
418pub extern "ntdll" fn NtUnmapViewOfSectionEx(
419 ProcessHandle: HANDLE,
420 BaseAddress: PVOID,
421 UnmapFlags: MEM.UNMAP,
306422) callconv(.winapi) NTSTATUS;
307423
308424pub extern "ntdll" fn NtOpenKey(
309425 KeyHandle: *HANDLE,
310426 DesiredAccess: ACCESS_MASK,
311 ObjectAttributes: OBJECT_ATTRIBUTES,
427 ObjectAttributes: *const OBJECT_ATTRIBUTES,
312428) callconv(.winapi) NTSTATUS;
313429
314pub extern "ntdll" fn RtlQueryRegistryValues(
315 RelativeTo: ULONG,
316 Path: PCWSTR,
317 QueryTable: [*]RTL_QUERY_REGISTRY_TABLE,
318 Context: ?*anyopaque,
319 Environment: ?*anyopaque,
430pub extern "ntdll" fn NtQueueApcThread(
431 ThreadHandle: HANDLE,
432 ApcRoutine: *const IO_APC_ROUTINE,
433 ApcArgument1: ?*anyopaque,
434 ApcArgument2: ?*anyopaque,
435 ApcArgument3: ?*anyopaque,
320436) callconv(.winapi) NTSTATUS;
321437
322438pub extern "ntdll" fn NtReadVirtualMemory(
......@@ -326,7 +442,6 @@ pub extern "ntdll" fn NtReadVirtualMemory(
326442 NumberOfBytesToRead: SIZE_T,
327443 NumberOfBytesRead: ?*SIZE_T,
328444) callconv(.winapi) NTSTATUS;
329
330445pub extern "ntdll" fn NtWriteVirtualMemory(
331446 ProcessHandle: HANDLE,
332447 BaseAddress: ?PVOID,
......@@ -334,51 +449,15 @@ pub extern "ntdll" fn NtWriteVirtualMemory(
334449 NumberOfBytesToWrite: SIZE_T,
335450 NumberOfBytesWritten: ?*SIZE_T,
336451) callconv(.winapi) NTSTATUS;
337
338452pub extern "ntdll" fn NtProtectVirtualMemory(
339453 ProcessHandle: HANDLE,
340454 BaseAddress: *?PVOID,
341455 NumberOfBytesToProtect: *SIZE_T,
342 NewAccessProtection: ULONG,
343 OldAccessProtection: *ULONG,
456 NewAccessProtection: PAGE,
457 OldAccessProtection: *PAGE,
344458) callconv(.winapi) NTSTATUS;
345459
346pub extern "ntdll" fn RtlExitUserProcess(
347 ExitStatus: u32,
348) callconv(.winapi) noreturn;
349
350pub extern "ntdll" fn NtCreateNamedPipeFile(
351 FileHandle: *HANDLE,
352 DesiredAccess: ULONG,
353 ObjectAttributes: *OBJECT_ATTRIBUTES,
354 IoStatusBlock: *IO_STATUS_BLOCK,
355 ShareAccess: ULONG,
356 CreateDisposition: ULONG,
357 CreateOptions: ULONG,
358 NamedPipeType: ULONG,
359 ReadMode: ULONG,
360 CompletionMode: ULONG,
361 MaximumInstances: ULONG,
362 InboundQuota: ULONG,
363 OutboundQuota: ULONG,
364 DefaultTimeout: *LARGE_INTEGER,
365) callconv(.winapi) NTSTATUS;
366
367pub extern "ntdll" fn NtAllocateVirtualMemory(
368 ProcessHandle: HANDLE,
369 BaseAddress: ?*PVOID,
370 ZeroBits: ULONG_PTR,
371 RegionSize: ?*SIZE_T,
372 AllocationType: ULONG,
373 PageProtection: ULONG,
374) callconv(.winapi) NTSTATUS;
375
376pub extern "ntdll" fn NtFreeVirtualMemory(
377 ProcessHandle: HANDLE,
378 BaseAddress: ?*PVOID,
379 RegionSize: *SIZE_T,
380 FreeType: ULONG,
381) callconv(.winapi) NTSTATUS;
460pub extern "ntdll" fn NtYieldExecution() callconv(.winapi) NTSTATUS;
382461
383462pub extern "ntdll" fn RtlAddVectoredExceptionHandler(
384463 First: ULONG,
......@@ -388,6 +467,29 @@ pub extern "ntdll" fn RtlRemoveVectoredExceptionHandler(
388467 Handle: HANDLE,
389468) callconv(.winapi) ULONG;
390469
470pub extern "ntdll" fn RtlDosPathNameToNtPathName_U(
471 DosPathName: [*:0]const u16,
472 NtPathName: *UNICODE_STRING,
473 NtFileNamePart: ?*?[*:0]const u16,
474 DirectoryInfo: ?*CURDIR,
475) callconv(.winapi) BOOL;
476
477pub extern "ntdll" fn RtlExitUserProcess(
478 ExitStatus: u32,
479) callconv(.winapi) noreturn;
480
481/// Returns the number of bytes written to `Buffer`.
482/// If the returned count is larger than `BufferByteLength`, the buffer was too small.
483/// If the returned count is zero, an error occurred.
484pub extern "ntdll" fn RtlGetFullPathName_U(
485 FileName: [*:0]const u16,
486 BufferByteLength: ULONG,
487 Buffer: [*]u16,
488 ShortName: ?*[*:0]const u16,
489) callconv(.winapi) ULONG;
490
491pub extern "ntdll" fn RtlGetSystemTimePrecise() callconv(.winapi) LARGE_INTEGER;
492
391493pub extern "ntdll" fn RtlInitializeCriticalSection(
392494 lpCriticalSection: *CRITICAL_SECTION,
393495) callconv(.winapi) NTSTATUS;
......@@ -401,6 +503,28 @@ pub extern "ntdll" fn RtlDeleteCriticalSection(
401503 lpCriticalSection: *CRITICAL_SECTION,
402504) callconv(.winapi) NTSTATUS;
403505
506pub extern "ntdll" fn RtlQueryPerformanceCounter(
507 PerformanceCounter: *LARGE_INTEGER,
508) callconv(.winapi) BOOL;
509pub extern "ntdll" fn RtlQueryPerformanceFrequency(
510 PerformanceFrequency: *LARGE_INTEGER,
511) callconv(.winapi) BOOL;
512pub extern "ntdll" fn NtQueryPerformanceCounter(
513 PerformanceCounter: *LARGE_INTEGER,
514 PerformanceFrequency: ?*LARGE_INTEGER,
515) callconv(.winapi) NTSTATUS;
516
517pub extern "ntdll" fn RtlReAllocateHeap(
518 HeapHandle: *HEAP,
519 Flags: HEAP.FLAGS.ALLOCATION,
520 BaseAddress: ?PVOID,
521 Size: SIZE_T,
522) callconv(.winapi) ?PVOID;
523
524pub extern "ntdll" fn RtlSetCurrentDirectory_U(
525 PathName: *UNICODE_STRING,
526) callconv(.winapi) NTSTATUS;
527
404528pub extern "ntdll" fn RtlTryAcquireSRWLockExclusive(
405529 SRWLock: *SRWLOCK,
406530) callconv(.winapi) BOOLEAN;
......@@ -411,21 +535,22 @@ pub extern "ntdll" fn RtlReleaseSRWLockExclusive(
411535 SRWLock: *SRWLOCK,
412536) callconv(.winapi) void;
413537
538pub extern "ntdll" fn RtlWakeAddressAll(
539 Address: ?*const anyopaque,
540) callconv(.winapi) void;
541pub extern "ntdll" fn RtlWakeAddressSingle(
542 Address: ?*const anyopaque,
543) callconv(.winapi) void;
544pub extern "ntdll" fn RtlWaitOnAddress(
545 Address: ?*const anyopaque,
546 CompareAddress: ?*const anyopaque,
547 AddressSize: SIZE_T,
548 Timeout: ?*const LARGE_INTEGER,
549) callconv(.winapi) NTSTATUS;
550
414551pub extern "ntdll" fn RtlWakeConditionVariable(
415552 ConditionVariable: *CONDITION_VARIABLE,
416553) callconv(.winapi) void;
417554pub extern "ntdll" fn RtlWakeAllConditionVariable(
418555 ConditionVariable: *CONDITION_VARIABLE,
419556) callconv(.winapi) void;
420
421pub extern "ntdll" fn RtlReAllocateHeap(
422 HeapHandle: HANDLE,
423 Flags: ULONG,
424 BaseAddress: PVOID,
425 Size: SIZE_T,
426) callconv(.winapi) ?PVOID;
427pub extern "ntdll" fn RtlAllocateHeap(
428 HeapHandle: HANDLE,
429 Flags: ULONG,
430 Size: SIZE_T,
431) callconv(.winapi) ?PVOID;
lib/std/posix.zig+8-7
......@@ -1041,18 +1041,16 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
10411041
10421042 if (native_os == .windows) {
10431043 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
1044 var eof_info = windows.FILE_END_OF_FILE_INFORMATION{
1044 const eof_info: windows.FILE.END_OF_FILE_INFORMATION = .{
10451045 .EndOfFile = signed_len,
10461046 };
1047
10481047 const rc = windows.ntdll.NtSetInformationFile(
10491048 fd,
10501049 &io_status_block,
10511050 &eof_info,
1052 @sizeOf(windows.FILE_END_OF_FILE_INFORMATION),
1053 .FileEndOfFileInformation,
1051 @sizeOf(windows.FILE.END_OF_FILE_INFORMATION),
1052 .EndOfFile,
10541053 );
1055
10561054 switch (rc) {
10571055 .SUCCESS => return,
10581056 .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 {
26912689 _ = mode;
26922690 const sub_dir_handle = windows.OpenFile(dir_path_w, .{
26932691 .dir = fs.cwd().fd,
2694 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2695 .creation = windows.FILE_CREATE,
2692 .access_mask = .{
2693 .STANDARD = .{ .SYNCHRONIZE = true },
2694 .GENERIC = .{ .READ = true },
2695 },
2696 .creation = .CREATE,
26962697 .filter = .dir_only,
26972698 }) catch |err| switch (err) {
26982699 error.IsDir => return error.Unexpected,
lib/std/process/Child.zig+9-7
......@@ -762,10 +762,12 @@ fn spawnWindows(self: *ChildProcess) SpawnError!void {
762762 const nul_handle = if (any_ignore)
763763 // "\Device\Null" or "\??\NUL"
764764 windows.OpenFile(&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }, .{
765 .access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE | windows.SYNCHRONIZE,
766 .share_access = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE,
765 .access_mask = .{
766 .STANDARD = .{ .SYNCHRONIZE = true },
767 .GENERIC = .{ .WRITE = true, .READ = true },
768 },
767769 .sa = &saAttr,
768 .creation = windows.OPEN_EXISTING,
770 .creation = .OPEN,
769771 }) catch |err| switch (err) {
770772 error.PathAlreadyExists => return error.Unexpected, // not possible for "NUL"
771773 error.PipeBusy => return error.Unexpected, // not possible for "NUL"
......@@ -1174,7 +1176,7 @@ fn windowsCreateProcessPathExt(
11741176 &io_status,
11751177 &file_information_buf,
11761178 file_information_buf.len,
1177 .FileDirectoryInformation,
1179 .Directory,
11781180 windows.FALSE, // single result
11791181 &app_name_unicode_string,
11801182 windows.FALSE, // restart iteration
......@@ -1198,7 +1200,7 @@ fn windowsCreateProcessPathExt(
11981200 var it = windows.FileInformationIterator(windows.FILE_DIRECTORY_INFORMATION){ .buf = &file_information_buf };
11991201 while (it.next()) |info| {
12001202 // Skip directories
1201 if (info.FileAttributes & windows.FILE_ATTRIBUTE_DIRECTORY != 0) continue;
1203 if (info.FileAttributes.DIRECTORY) continue;
12021204 const filename = @as([*]u16, @ptrCast(&info.FileName))[0 .. info.FileNameLength / 2];
12031205 // Because all results start with the app_name since we're using the wildcard `app_name*`,
12041206 // 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
14151417 var sattr_copy = sattr.*;
14161418 const write_handle = windows.kernel32.CreateFileW(
14171419 pipe_path.ptr,
1418 windows.GENERIC_WRITE,
1420 .{ .GENERIC = .{ .WRITE = true } },
14191421 0,
14201422 &sattr_copy,
14211423 windows.OPEN_EXISTING,
1422 windows.FILE_ATTRIBUTE_NORMAL,
1424 @bitCast(windows.FILE.ATTRIBUTE{ .NORMAL = true }),
14231425 null,
14241426 );
14251427 if (write_handle == windows.INVALID_HANDLE_VALUE) {
lib/std/zig/WindowsSdk.zig+9-4
......@@ -250,13 +250,15 @@ const RegistryWtf16Le = struct {
250250 /// After finishing work, call `closeKey`.
251251 fn openKey(hkey: windows.HKEY, key_wtf16le: [:0]const u16, options: OpenOptions) error{KeyNotFound}!RegistryWtf16Le {
252252 var key: windows.HKEY = undefined;
253 var access: windows.REGSAM = windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS;
254 if (options.wow64_32) access |= windows.KEY_WOW64_32KEY;
255253 const return_code_int: windows.HRESULT = windows.advapi32.RegOpenKeyExW(
256254 hkey,
257255 key_wtf16le,
258256 0,
259 access,
257 .{ .SPECIFIC = .{ .KEY = .{
258 .QUERY_VALUE = true,
259 .ENUMERATE_SUB_KEYS = true,
260 .WOW64_32KEY = options.wow64_32,
261 } } },
260262 &key,
261263 );
262264 const return_code: windows.Win32Error = @enumFromInt(return_code_int);
......@@ -389,7 +391,10 @@ const RegistryWtf16Le = struct {
389391 const return_code_int: windows.HRESULT = std.os.windows.advapi32.RegLoadAppKeyW(
390392 absolute_path_as_wtf16le,
391393 &key,
392 windows.KEY_QUERY_VALUE | windows.KEY_ENUMERATE_SUB_KEYS,
394 .{ .SPECIFIC = .{ .KEY = .{
395 .QUERY_VALUE = true,
396 .ENUMERATE_SUB_KEYS = true,
397 } } },
393398 0,
394399 0,
395400 );
src/link/MappedFile.zig+14-7
......@@ -953,12 +953,19 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {
953953 if (is_windows) {
954954 if (mf.section == windows.INVALID_HANDLE_VALUE) switch (windows.ntdll.NtCreateSection(
955955 &mf.section,
956 windows.STANDARD_RIGHTS_REQUIRED | windows.SECTION_QUERY |
957 windows.SECTION_MAP_WRITE | windows.SECTION_MAP_READ | windows.SECTION_EXTEND_SIZE,
956 .{
957 .SPECIFIC = .{ .SECTION = .{
958 .QUERY = true,
959 .MAP_WRITE = true,
960 .MAP_READ = true,
961 .EXTEND_SIZE = true,
962 } },
963 .STANDARD = .{ .RIGHTS = .REQUIRED },
964 },
958965 null,
959966 @constCast(&@as(i64, @intCast(aligned_capacity))),
960 windows.PAGE_READWRITE,
961 windows.SEC_COMMIT,
967 .{ .READWRITE = true },
968 .{ .COMMIT = true },
962969 mf.file.handle,
963970 )) {
964971 .SUCCESS => {},
......@@ -974,9 +981,9 @@ pub fn ensureTotalCapacityPrecise(mf: *MappedFile, new_capacity: usize) !void {
974981 0,
975982 null,
976983 &contents_len,
977 .ViewUnmap,
978 0,
979 windows.PAGE_READWRITE,
984 .Unmap,
985 .{},
986 .{ .READWRITE = true },
980987 )) {
981988 .SUCCESS => mf.contents = contents_ptr.?[0..contents_len],
982989 else => return error.MemoryMappingNotSupported,