@@ -340,19 +340,55 @@ const Os = switch (builtin.os.tag) {
340
340
const reaction_set = rs: {
341
341
const gop = try w.dir_table.getOrPut(gpa, path);
342
342
if (!gop.found_existing) {
343
- var realpath_buf: [std.fs.max_path_bytes]u8 = undefined;
344
- const realpath = try path.root_dir.handle.realpath(path.sub_path, &realpath_buf);
345
- const realpath_w = try windows.sliceToPrefixedFileW(null, realpath);
346
- const dir_handle = windows.kernel32.CreateFileW(
347
- realpath_w.span().ptr,
348
- windows.GENERIC_READ,
349
- windows.FILE_SHARE_DELETE | windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE,
343
+ // The following code is a drawn out NtCreateFile call. (mostly adapted from std.fs.Dir.makeOpenDirAccessMaskW)
344
+ // It's necessary in order to get the flags are required when calling ReadDirectoryChangesW.
345
+ const root_fd = path.root_dir.handle.fd;
346
+ const sub_path = path.subPathOrDot();
347
+ const sub_path_w = try windows.sliceToPrefixedFileW(root_fd, sub_path);
348
+ const path_len_bytes = std.math.cast(u16, sub_path_w.len * 2) orelse return error.NameTooLong;
349
+
350
+ var nt_name = windows.UNICODE_STRING{
351
+ .Length = @intCast(path_len_bytes),
352
+ .MaximumLength = @intCast(path_len_bytes),
353
+ .Buffer = @constCast(sub_path_w.span().ptr),
354
+ };
355
+ var attr = windows.OBJECT_ATTRIBUTES{
356
+ .Length = @sizeOf(windows.OBJECT_ATTRIBUTES),
357
+ .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w.span())) null else root_fd,
358
+ .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
359
+ .ObjectName = &nt_name,
360
+ .SecurityDescriptor = null,
361
+ .SecurityQualityOfService = null,
362
+ };
363
+ var io: windows.IO_STATUS_BLOCK = undefined;
364
+ var dir_handle: windows.HANDLE = undefined;
365
+ const rc = windows.ntdll.NtCreateFile(
366
+ &dir_handle,
367
+ windows.SYNCHRONIZE | windows.GENERIC_READ | windows.FILE_LIST_DIRECTORY,
368
+ &attr,
369
+ &io,
350
370
null,
351
- windows.OPEN_EXISTING,
352
- windows.FILE_FLAG_BACKUP_SEMANTICS | windows.FILE_FLAG_OVERLAPPED,
371
+ 0,
372
+ windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE | windows.FILE_SHARE_DELETE,
373
+ windows.FILE_OPEN,
374
+ windows.FILE_DIRECTORY_FILE | windows.FILE_OPEN_FOR_BACKUP_INTENT,
353
375
null,
376
+ 0,
354
377
);
355
378
379
+ switch (rc) {
380
+ .SUCCESS => {},
381
+ .OBJECT_NAME_INVALID => return error.BadPathName,
382
+ .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
383
+ .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
384
+ .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
385
+ .NOT_A_DIRECTORY => return error.NotDir,
386
+ // This can happen if the directory has 'List folder contents' permission set to 'Deny'
387
+ .ACCESS_DENIED => return error.AccessDenied,
388
+ .INVALID_PARAMETER => unreachable,
389
+ else => return windows.unexpectedStatus(rc),
390
+ }
391
+
356
392
assert(dir_handle != windows.INVALID_HANDLE_VALUE);
357
393
358
394
// `dir_handle` may already be present in the table in
0 commit comments