Skip to content

Commit 572dfbf

Browse files
committed
Replace ReadDirectoryChangesW with ReadDirectoryChangesExW, out of which the FileAttributes can tell if a file or folder is being created/modified/deleted.
This raises the minimum required Windows version to Windows 10, as this is where ReadDirectoryChangesExW was introduced.
1 parent 539bc95 commit 572dfbf

File tree

1 file changed

+50
-42
lines changed

1 file changed

+50
-42
lines changed

notify/src/windows.rs

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ use windows_sys::Win32::Foundation::{
2424
INVALID_HANDLE_VALUE, WAIT_OBJECT_0,
2525
};
2626
use windows_sys::Win32::Storage::FileSystem::{
27-
CreateFileW, ReadDirectoryChangesW, FILE_ACTION_ADDED, FILE_ACTION_MODIFIED,
28-
FILE_ACTION_REMOVED, FILE_ACTION_RENAMED_NEW_NAME, FILE_ACTION_RENAMED_OLD_NAME,
29-
FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OVERLAPPED, FILE_LIST_DIRECTORY,
30-
FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_DIR_NAME,
31-
FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_SECURITY,
32-
FILE_NOTIFY_CHANGE_SIZE, FILE_NOTIFY_INFORMATION, FILE_SHARE_DELETE, FILE_SHARE_READ,
33-
FILE_SHARE_WRITE, OPEN_EXISTING,
27+
CreateFileW, ReadDirectoryChangesExW, ReadDirectoryNotifyExtendedInformation,
28+
FILE_ACTION_ADDED, FILE_ACTION_MODIFIED, FILE_ACTION_REMOVED, FILE_ACTION_RENAMED_NEW_NAME,
29+
FILE_ACTION_RENAMED_OLD_NAME, FILE_ATTRIBUTE_DIRECTORY, FILE_FLAG_BACKUP_SEMANTICS,
30+
FILE_FLAG_OVERLAPPED, FILE_LIST_DIRECTORY, FILE_NOTIFY_CHANGE_ATTRIBUTES,
31+
FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_NOTIFY_CHANGE_FILE_NAME,
32+
FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_SECURITY, FILE_NOTIFY_CHANGE_SIZE,
33+
FILE_NOTIFY_EXTENDED_INFORMATION, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
34+
OPEN_EXISTING,
3435
};
3536
use windows_sys::Win32::System::Threading::{
3637
CreateSemaphoreW, ReleaseSemaphore, WaitForSingleObjectEx, INFINITE,
@@ -305,7 +306,7 @@ fn start_read(
305306

306307
// This is using an asynchronous call with a completion routine for receiving notifications
307308
// An I/O completion port would probably be more performant
308-
let ret = ReadDirectoryChangesW(
309+
let ret = ReadDirectoryChangesExW(
309310
handle,
310311
request.buffer.as_mut_ptr() as *mut c_void,
311312
BUF_SIZE,
@@ -314,6 +315,7 @@ fn start_read(
314315
&mut 0u32 as *mut u32, // not used for async reqs
315316
overlapped,
316317
Some(handle_event),
318+
ReadDirectoryNotifyExtendedInformation,
317319
);
318320

319321
if ret == 0 {
@@ -382,12 +384,13 @@ unsafe extern "system" fn handle_event(
382384
// In Wine, FILE_NOTIFY_INFORMATION structs are packed placed in the buffer;
383385
// they are aligned to 16bit (WCHAR) boundary instead of 32bit required by FILE_NOTIFY_INFORMATION.
384386
// Hence, we need to use `read_unaligned` here to avoid UB.
385-
let mut cur_entry = ptr::read_unaligned(cur_offset as *const FILE_NOTIFY_INFORMATION);
387+
let mut cur_entry = ptr::read_unaligned(cur_offset as *const FILE_NOTIFY_EXTENDED_INFORMATION);
386388
loop {
387389
// filename length is size in bytes, so / 2
388390
let len = cur_entry.FileNameLength as usize / 2;
389391
let encoded_path: &[u16] = slice::from_raw_parts(
390-
cur_offset.offset(std::mem::offset_of!(FILE_NOTIFY_INFORMATION, FileName) as isize)
392+
cur_offset
393+
.offset(std::mem::offset_of!(FILE_NOTIFY_EXTENDED_INFORMATION, FileName) as isize)
391394
as _,
392395
len,
393396
);
@@ -422,44 +425,49 @@ unsafe extern "system" fn handle_event(
422425

423426
let event_handler = |res| emit_event(&request.event_handler, res);
424427

425-
if cur_entry.Action == FILE_ACTION_RENAMED_OLD_NAME {
426-
let mode = RenameMode::From;
427-
let kind = ModifyKind::Name(mode);
428-
let kind = EventKind::Modify(kind);
429-
let ev = newe.set_kind(kind);
430-
event_handler(Ok(ev))
431-
} else {
432-
match cur_entry.Action {
433-
FILE_ACTION_RENAMED_NEW_NAME => {
434-
let kind = EventKind::Modify(ModifyKind::Name(RenameMode::To));
435-
let ev = newe.set_kind(kind);
436-
event_handler(Ok(ev));
437-
}
438-
FILE_ACTION_ADDED => {
439-
let kind = EventKind::Create(CreateKind::Any);
440-
let ev = newe.set_kind(kind);
441-
event_handler(Ok(ev));
442-
}
443-
FILE_ACTION_REMOVED => {
444-
let kind = EventKind::Remove(RemoveKind::Any);
445-
let ev = newe.set_kind(kind);
446-
event_handler(Ok(ev));
447-
}
448-
FILE_ACTION_MODIFIED => {
449-
let kind = EventKind::Modify(ModifyKind::Any);
450-
let ev = newe.set_kind(kind);
451-
event_handler(Ok(ev));
452-
}
453-
_ => (),
454-
};
455-
}
428+
match cur_entry.Action {
429+
FILE_ACTION_RENAMED_OLD_NAME => {
430+
let kind = EventKind::Modify(ModifyKind::Name(RenameMode::From));
431+
let ev = newe.set_kind(kind);
432+
event_handler(Ok(ev))
433+
}
434+
FILE_ACTION_RENAMED_NEW_NAME => {
435+
let kind = EventKind::Modify(ModifyKind::Name(RenameMode::To));
436+
let ev = newe.set_kind(kind);
437+
event_handler(Ok(ev));
438+
}
439+
FILE_ACTION_ADDED => {
440+
let kind = if (cur_entry.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 {
441+
EventKind::Create(CreateKind::Folder)
442+
} else {
443+
EventKind::Create(CreateKind::File)
444+
};
445+
let ev = newe.set_kind(kind);
446+
event_handler(Ok(ev));
447+
}
448+
FILE_ACTION_REMOVED => {
449+
let kind = if (cur_entry.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 {
450+
EventKind::Remove(RemoveKind::Folder)
451+
} else {
452+
EventKind::Remove(RemoveKind::File)
453+
};
454+
let ev = newe.set_kind(kind);
455+
event_handler(Ok(ev));
456+
}
457+
FILE_ACTION_MODIFIED => {
458+
let kind = EventKind::Modify(ModifyKind::Any);
459+
let ev = newe.set_kind(kind);
460+
event_handler(Ok(ev));
461+
}
462+
_ => (),
463+
};
456464
}
457465

458466
if cur_entry.NextEntryOffset == 0 {
459467
break;
460468
}
461469
cur_offset = cur_offset.offset(cur_entry.NextEntryOffset as isize);
462-
cur_entry = ptr::read_unaligned(cur_offset as *const FILE_NOTIFY_INFORMATION);
470+
cur_entry = ptr::read_unaligned(cur_offset as *const FILE_NOTIFY_EXTENDED_INFORMATION);
463471
}
464472
}
465473

0 commit comments

Comments
 (0)