I'm trying to monitor file changes but I am not really sure on how to read the filename in the FILE_NOTIFY_INFORMATION struct:
HANDLE dwChangeHandles[2];
DWORD dwWaitStatus;
wChangeHandles[0] = FindFirstChangeNotification(dirname.c_str(), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE);
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE) printerr(__FILE__,__LINE__,"FindFirstChangeNotification function failed.\n");
...
if ((dwChangeHandles[0] == NULL) || (dwChangeHandles[1] == NULL)) //final validation
printerr(__FILE__,__LINE__,"Unexpected NULL from FindFirstChangeNotification.\n");
while (TRUE) {
std::cout << "Waiting for notification...\n";
dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE);
if(dwWaitStatus==WAIT_OBJECT_0){
std::cout << "Something changed\n";
DWORD BytesReturned;
size_t bufLen = 1024;
FILE_NOTIFY_INFORMATION buffer[bufLen];
if (ReadDirectoryChangesW(dwChangeHandles[0], buffer, bufLen, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &BytesReturned, NULL, NULL)){
std::wcout << std::wstring(buffer->FileName)<< std::endl; //THERE IS NOTHING IN THE EXPECTED OUTPUT HERE
}
if (FindNextChangeNotification(dwChangeHandles[0]) == FALSE ) printerr(__FILE__,__LINE__,"FindNextChangeNotification function failed.\n");
}
else if(dwWaitStatus==WAIT_TIMEOUT) printerr(__FILE__,__LINE__,"No changes in the timeout period.\n");
else printerr(__FILE__,__LINE__,"Unhandled dwWaitStatus.\n");
}
Is there something I am doing wrong
You have a number of problems that I can see immediately:
According to the docs for the
ReadDirectoryChangesWfunction, the buffer needs to beDWORD-aligned. As you are using a buffer on the stack this isn't guaranteed - you should allocate one from the heap instead.You don't seem to be using the function correctly. Normally you would call
ReadDirectoryChangesWfirst, and then wait on the event. Not the other way around. WhenReadDirectoryChangesWreturns for an asynchronous call there is usually no data in the buffer at that point. You need to wait for notification that the request has been completed before using the buffer contents.FindNextChangeNotificationis only used withFindFirstChangeNotification, so this is completely wrong. When theReadDirectoryChangesWcompletes you need to use theNextEntryOffsetfield in theFILE_NOTIFY_INFORMATIONstructure to loop through the returned events.Edit: Since you've added more code to your question it's now obvious that you are mixing the two APIs.
FindFirstChangeNotificationandFindNextChangeNotificationare one API, andReadDirectoryChangesWis another. I believe you've been confused by this passage in the docs:I guess your confusion is understandable, but the two APIs can't be used together. If you're using
FindFirstChangeNotificationthen all you get is a notification that something changed, and you have to re-read the directory to find out what it was. If you want specific notifications at the file level then you have to useReadDirectoryChangesWto do the monitoring.