A customer was using ReadÂDirectoryÂChangesW to monitor the contents of a directory, and they were concerned about the FILE_ and FILE_ pair of actions. The documentation doesn’t guarantee that the two always occur consecutively, or even that they always appear in pairs. For peace of mind, the customer was looking for a way to match up each FILE_ with a FILE_ to make sure they were tracking the rename properly.
Yes, you can do it by switching from ReadÂDirectoryÂChangesW. to ReadÂDirectoryÂChangesÂExW and asking for ReadÂDirectoryÂNotifyÂExtendedÂInformation. This produces the FILE_ structure, and that structure includes the FileId of the affected file. You can then match that up between the FILE_ and FILE_ to confirm that they are the two halves of the same rename operation.
Maybe it was considered unnecessary?
https://devblogs.microsoft.com/oldnewthing/20110812-00/?p=9913 says, “The intended purpose of the ReadÂDirectoryÂChangesW function is to assist programs like Windows Explorer which display the contents of a directory.”
So I would assume that Explorer does something like this:
– FILE_ACTION_RENAMED_OLD_FILE => remove the old entry (unless already filtered out)
– FILE_ACTION_RENAMED_NEW_FILE => check the file’s metadata and add a new entry accordingly (unless filtered out)
Maybe, but usually Explorer tries to keep the set of selected files stable despite renames. Try it: open the same folder in two different Explorer windows, select some of the files in one window, rename some of the files in the other window, see what happens. I haven’t bothered to check how far back this behavior exists though.
Worth noting, ReadÂDirectoryÂChangesW is supported in UWP but ReadÂDirectoryÂChangesÂExW is not, at least according to the documentation.
Any insight into why ReadÂDirectoryÂChangesW provides the two events without the ability to correlate them? Lack of design review? It required rewriting some part of the kernel, so out of scope?
FAT/FAT32 does not have a FileId. NTFS has. I guess FAT was the s*** back then? I guess they did not want the pain with all the FAT issues and complaints that it does not work on FAT (I assume FileId is always 0 on FAT?)
GetFileInformationByHandle gives interesting information on this. The BY_HANDLE_FILE_INFORMATION structure contains two fields, nFileIndexLow and nFileIndexHigh, what's more, it states that the volume serial number and the combined file index uniquely identify a file on a single computer. Without double checking, I would guess that the file ID given by ReadDirectoryChangesExW is this combined file index. GetFileInformationByHandle will also give a file id when you use this with a file on a FAT32 formatted drive. The only quirk that I noticed is that you need to use GetFileInformationByHandle to get the FAT32 file id. GetFileInformationByHandleEx will give an invalid parameter error...
It could have easily been design considerations based upon when it was introduced.
ReadDirectoryChangesW was introduced with Windows NT 4. It is in the WinBase.h file found in Visual C++ 5. So any considerations for this function would have been decided upon in the early to mid 90s.
The other big thing is that in 1996, not only were we still using ATA (not retroactively renamed to PATA, since SATA didn't exist at that point), but the variants that sped things up, like the UDMA modes hadn't been standardised. Even the SCSI standards weren't that much better. So it was very unlikely...
Could be an oversight, just like how AMD forgot to provide a way to retrieve the kernel stack pointer when it created its fast syscall instruction for x86, rendering the instruction virtually unusable, until it was supplemented by the swapgs instruction in the new x86_64 architecture.