@@ -340,19 +340,55 @@ const Os = switch (builtin.os.tag) {
340340 const reaction_set = rs : {
341341 const gop = try w .dir_table .getOrPut (gpa , path );
342342 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 ,
350370 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 ,
353375 null ,
376+ 0 ,
354377 );
355378
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+
356392 assert (dir_handle != windows .INVALID_HANDLE_VALUE );
357393
358394 // `dir_handle` may already be present in the table in
0 commit comments