3

I want to open directory handle so that I can watch that directory for file changes. I have written a simple class wrapper over the winapi, and this is how I set the directory path before starting the watch:

bool SetDirectory(const std::string& dirname)
{
  HANDLE dirHandleNew = CreateFile(
    dirname.c_str(),
    // Just normal reading
    FILE_GENERIC_READ,
    // Share all, do not lock the file
    FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL
  );

  if (INVALID_HANDLE_VALUE != dirHandleNew)
  {
    _dirHandle = dirHandleNew;
    return true;
  }
  else
  {
    _dirHandle = 0;
    RLog("Cannot open directory %s for filesystem watching. Win error: %d (%s)", dirname.c_str(), GetLastError(), GetLastErrorAsString().c_str());
    return false;
  }
}

The error is always:

Cannot open directory D:\tools for filesystem watching. Win error: 5 (Access is denied.)

I tried different folders on different volumes to see if this is an actual permissions issue, but it doesn't seem like it. D:\tools in my PC is a normal folder, accessible to all users. But as I said, I tried other folders too, error is always the same.

I also tried to instead open with FILE_LIST_DIRECTORY (I only need dir listing) and GENERIC_READ. Error was still the same.

Maybe the CreateFile parameters are wrong?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • [FindFirstChangeNotification](https://learn.microsoft.com/en-gb/windows/win32/api/fileapi/nf-fileapi-findfirstchangenotificationw) doesn't take a file handle, what are you trying to do? – Alan Birtles Jul 11 '19 at 10:26
  • Possible duplicate of [How do I make my program watch for file modification in C++?](https://stackoverflow.com/questions/931093/how-do-i-make-my-program-watch-for-file-modification-in-c) – Alan Birtles Jul 11 '19 at 10:29
  • 2
    Did you try the one mandatory flag for "opening" a directory handle with CreateFile ? Namely `FILE_FLAG_BACKUP_SEMANTICS` ? `CreateFile` clearly documents this: *"You must set this flag to obtain a handle to a directory. A directory handle can be passed to some functions instead of a file handle."*. Not that it matters; I suspect a directory handle acquisition is the Y of what appears to be an XY problem. – WhozCraig Jul 11 '19 at 10:29
  • 1
    because win32 errors very bad design. you not got access denied. you got `STATUS_FILE_IS_A_DIRECTORY` if call `RtlGetLastNtStatus()`. because you not add `FILE_FLAG_BACKUP_SEMANTICS`. simply win32 convert `STATUS_FILE_IS_A_DIRECTORY` to `ERROR_ACCESS_DENIED` – RbMm Jul 11 '19 at 10:29
  • 1
    @AlanBirtles `FindFirstChangeNotification` not enough functional, compare `ReadDirectoryChangesW`. must not be used – RbMm Jul 11 '19 at 10:32
  • @AlanBirtles Thi is not a duplicate of the linked question at all. As you observed yourself, in this question I am concerned about opening the directory, not watching the files. RbMm's comments are correct. – Tomáš Zato Jul 11 '19 at 12:23

1 Answers1

4

Don't use FILE_ATTRIBUTE_NORMAL!

To open a directory with CreateFile, Use FILE_FLAG_BACKUP_SEMANTICS instead of FILE_ATTRIBUTE_NORMAL.

You should specify FILE_FLAG_BACKUP_SEMANTICS in the dwFlagsAndAttributes parameter.

This should work now.

MARSHMALLOW
  • 1,315
  • 2
  • 12
  • 24