How should I read the filename in FILE_NOTIFY_INFORMATION struct - c++

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 ReadDirectoryChangesW function, the buffer needs to be DWORD-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 ReadDirectoryChangesW first, and then wait on the event. Not the other way around. When ReadDirectoryChangesW returns 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.
FindNextChangeNotification is only used with FindFirstChangeNotification, so this is completely wrong. When the ReadDirectoryChangesW completes you need to use the NextEntryOffset field in the FILE_NOTIFY_INFORMATION structure 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. FindFirstChangeNotification and FindNextChangeNotification are one API, and ReadDirectoryChangesW is another. I believe you've been confused by this passage in the docs:
This function does not indicate the change that satisfied the wait
condition. To retrieve information about the specific change as part
of the notification, use the ReadDirectoryChangesW function.
I guess your confusion is understandable, but the two APIs can't be used together. If you're using FindFirstChangeNotification then 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 use ReadDirectoryChangesW to do the monitoring.

Related

Replacing vector with array or static vector for a better approach

My application runs particular number of processes(different executables) using createprocess(windows api) in parallel(using threads). User can refresh / close my application at any time. As of now, I am pushing the process handles into vector and whenever close request received, I am iterating the vector and terminating(using GetExitCodeProcess and TerminateProcess APIs) and closing(using CloseHandle API) the process handles. Also I am closing the handle of the process when it is completed. The problem with current model is, whenever process completed handle will be closed and when close request received again I will try to close it using vector(handle is not updated). To solve this, I have to update/remove the handle in/from the vector. To do this, need to maintain index.
Since I know the number of process, I want to create a static vector and update it rather than pushing a local object to a vector. Can someone suggest a best approach.
Below is the sample code.
//member object
std::vector<PROCESS_INFORMATION> mProcessHandles;
//this is a thread and will be called multiple times with different executable names in the application
void method(std::string executable)
{
STARTUPINFO startInfo{};
PROCESS_INFORMATION procInfo{};
bool ret = CreateProcess(NULL, executable, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo);
mProcessInfo.push_back(procInfo);
if(ret)
{
WaitForSingleObject(procInfo.hProcess, INFINITE);
CloseHandle(procInfo.hProcess);
procInfo.hProcess = NULL;
CloseHandle(procInfo.hThread);
procInfo.hThread = NULL;
}
return;
}
//this will be called when application close requested
void forceKill()
{
for (auto &processHandlesIt : mProcessHandles)
{
DWORD errorcode = 0;
GetExitCodeProcess(processHandlesIt.hProcess, &errorcode);
if (errorcode == STILL_ACTIVE)
{
TerminateProcess(processHandlesIt.hProcess, errorcode);
}
CloseHandle(processHandlesIt.hProcess);
processHandlesIt.hProcess = NULL;
CloseHandle(processHandlesIt.hThread);
processHandlesIt.hThread = NULL;
}
}
You should not use handles (in GetExitCodeProcess for example) after they are closed.
I would simply not close those process handles in the threads, and just leave them for the forceKill or other clean-up function to close.
Also, since you are not using procInfo.hThread, you could close it right after CreateProcess returns.
I guess you are not using any other members of the procInfo, so you could only store the process' handles in your vector.

How can I check whether the input buffer is empty?

I'm trying to write a simple class for operating a Serial Port on Windows, using standart windows library .
I need to check whether the input buffer is empty.
So far I've tried to use SetCommEvent, using EV_RXCHAR option, however this method doesn't work. The function seems to wait for arrival of new char. If I tried to send char, sleep for a second and the apply this, the function would not return - it keeps waiting.
bool isEmpty()
{
DWORD dwEventMask = 0;
DWORD Status = 0;
if (CheckAsyncRead())
return false;
if (!SetCommMask(hPort, EV_RXCHAR)) //wait for char receival
std::cout << "Error in creating Overlapped event" << std::endl;
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (WaitCommEvent(hPort, &dwEventMask, &osReader))
{
//close event handle
return false;
}
Status = WaitForSingleObject(osReader.hEvent, 10);
//I wait for 10 ms in case the function doesn't return immediately
//Close event handle
if (Status == WAIT_OBJECT_0)
{
return false;
}
else
return true;
}
I hoped the WaitCommEvent or WaitForSingleObject would return in case any chars were present in buffer but the does not happen if there is a longer pause between receival of a character and calling of Wait function.
You can use the ClearCommError function to find out the size of the data stored in the buffer.
As a result of calling, cbInQue of the COMSTAT structure to be notified has the size of the data stored in the input buffer.
You can use ReadFile() with a handle opened with CreateFile() with the FILE_FLAG_OVERLAPPED flag. If the ReadFile() function has nothing to return, it will return a last error ERROR_IO_PENDING which means that your buffer is currently empty.

Windows Event Hooks for File Saved

Every time I save a certain script file I'm working on in NotePad++, I am required to upload the changes to our server so that we can deploy the changes to various machines.
I sometimes forget to upload the changes after refactoring my code in NotePad++ and I was wondering if there was a way for me to create a simple application that would listen for a 'Save' event and automatically upload the file for me.
I am currently running on a Windows OS and was hoping to do this using C++. I'd like to explore Windows Events and possibly tie into an event hook to accomplish this. Any other languages would be welcome as well.
Any ideas or tips?
Here is my code thus far following Josh's recommendations below:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
void RefreshDirectory(LPTSTR);
void WatchDirectory(LPTSTR);
void _tmain(int argc, TCHAR *argv[])
{
if (argc != 2)
{
_tprintf(TEXT("Usage: %s <dir>\n"), argv[0]);
return;
}
WatchDirectory(argv[1]);
}
void WatchDirectory(LPTSTR lpDir)
{
DWORD dwWaitStatus;
HANDLE dwChangeHandles[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
_tsplitpath_s(lpDir, lpDrive, 4, NULL, 0, lpFile, _MAX_FNAME, lpExt, _MAX_EXT);
lpDrive[2] = (TCHAR)'\\';
lpDrive[3] = (TCHAR)'\0';
// Watch the directory for file creation and deletion.
dwChangeHandles[0] = FindFirstChangeNotification(
lpDir, // directory to watch
FALSE, // do not watch subtree
FILE_NOTIFY_CHANGE_LAST_WRITE); // watch file name changes
if (dwChangeHandles[0] == INVALID_HANDLE_VALUE)
{
printf("\n ERROR: FindFirstChangeNotification function failed.\n");
ExitProcess(GetLastError());
}
// Make a final validation check on our handles.
if ((dwChangeHandles[0] == NULL))
{
printf("\n ERROR: Unexpected NULL from FindFirstChangeNotification.\n");
ExitProcess(GetLastError());
}
// Change notification is set. Now wait on both notification
// handles and refresh accordingly.
while (TRUE)
{
// Wait for notification.
printf("\nWaiting for notification...\n");
// Waits until the specified object is in the signaled state or
// the time-out interval elapses.
// Because our second parameter is set to INFINITE, the function will
// return only when the object is signaled.
dwWaitStatus = WaitForSingleObject(dwChangeHandles, INFINITE);
switch (dwWaitStatus)
{
// Our return value, WAIT_OBJECT_0 signifies that the first object
// signaled the event.
case WAIT_OBJECT_0:
// A file was created, renamed, or deleted in the directory.
// Refresh this directory and restart the notification.
RefreshDirectory(lpDir);
if (FindNextChangeNotification(dwChangeHandles[0]) == FALSE)
{
printf("\n ERROR: FindNextChangeNotification function failed.\n");
ExitProcess(GetLastError());
}
break;
case WAIT_TIMEOUT:
// A timeout occurred, this would happen if some value other
// than INFINITE is used in the Wait call and no changes occur.
// In a single-threaded environment you might not want an
// INFINITE wait.
printf("\nNo changes in the timeout period.\n");
break;
default:
printf("\n ERROR: Unhandled dwWaitStatus.\n");
ExitProcess(GetLastError());
break;
}
}
}
void RefreshDirectory(LPTSTR lpDir)
{
// This is where you might place code to refresh your
// directory listing, but not the subtree because it
// would not be necessary.
_tprintf(TEXT("Directory (%s) changed.\n"), lpDir);
}
You can monitor the filesystem for changes using FindFirstChangeNotification. When you call this function, you get a HANDLE back. You can wait on that handle using WaitSingleObject (or similar). When the wait returns, you can use ReadDirectoryChanges to figure out exactly what happened. If whatever happens matches some event or change you care about for your file, you can take the appropriate action... otherwise ignore the event.
Because you'll be waiting (and thus blocking the thread), you may want to perform this work on a worker thread if you want your program in question to be doing anything else.
A simple way to start might be to listen for events with the FILE_NOTIFY_CHANGE_LAST_WRITE filter; this will release your wait when files in the monitored directory are written to.
Note that not all programs save files in the same way; some open the existing file and write to it, others delete it and replace, or some combination thereof (first writing to a temporary file, then swapping it with the original). Consequently it may not be as straightforward as waiting for just last-write notifications to accomplish precisely what you're after.
Think about writing a NP++ plugin instead.
You can register your plugin to be notified whenever a file is saved or about to be saved using NPPN_FILESAVED or NPPN_FILEBEFORESAVE.
Please look at this link:
http://docs.notepad-plus-plus.org/index.php/Messages_And_Notifications

How to check if WriteFile function is done

I want to check if the WriteFile function is done writing to UART so that i can call ReadFile on the same ComDev without causing an Exception.
It seems the WriteFile function can return before writing is done.
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
Sleep(1000); // complete write operation TBD
fComPortInUse = 0;
return (FALSE);
}
fComPortInUse = 0;
return (TRUE);
}
I used Sleep(1000) as an workaround, but how can i wait for an appropriate time?
You can create a Event, store it in your overlapped structure and wait for it to be signalled. Like this (untested):
BOOL WriteCommBlock(HANDLE * pComDev, char *pBuffer , int BytesToWrite)
{
while(fComPortInUse){}
fComPortInUse = 1;
BOOL bWriteStat = 0;
DWORD BytesWritten = 0;
COMSTAT ComStat = {0};
OVERLAPPED osWrite = {0,0,0};
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent != NULL)
{
osWrite.hEvent = hEvent;
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
short Errorcode = GetLastError();
if( Errorcode != ERROR_IO_PENDING )
short breakpoint = 5; // Error
WaitForSingleObject(hEvent, INFINITE);
fComPortInUse = 0;
return (FALSE);
}
CloseHandle(hEvent);
}
fComPortInUse = 0;
return (TRUE);
}
Note that depending on what else you are trying to do simply calling WaitForSingleObject() might not be the best idea. And neither might an INFINITE timeout.
Your problem is the incorrect use of the overlapped I/O, regardless to the UART or whatever underlying device.
The easiest (though not necessarily the most optimal) way to fix your code is to use an event to handle the I/O completion.
// ...
OVERLAPPED osWrite = {0,0,0};
osWrite.hEvent = CreateEvent(FALSE, NULL, NULL, FALSE);
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{
DWORD Errorcode = GetLastError();
// ensure it's ERROR_IO_PENDING
WaitForSingleObject(osWrite.hEvent, INFINITE);
}
CloseHandle(osWrite.hEvent);
Note however that the whole I/O is synchronous. It's handles by the OS in an asynchronous way, however your code doesn't go on until it's finished. If so, why do you use the overlapped I/O anyway?
One should use it to enable simultaneous processing of several I/Os (and other tasks) within the same thread. To do this correctly - you should allocate the OVERLAPPED structure on heap and use one of the available completion mechanisms: event, APC, completion port or etc. Your program flow logic should also be changed.
Since you didn't say that you need asynchronous I/O, you should try synchronous. It's easier. I think if you just pass a null pointer for the OVERLAPPED arg you get synchronous, blocking, I/O. Please see the example code I wrote in the "Windows C" section of this document:
http://www.pololu.com/docs/0J40/
Your Sleep(1000); is of no use, it will only execute after the writefile completes its operation.You have to wait till WriteFile is over.
if(WriteFile(*pComDev,pBuffer,BytesToWrite,&BytesWritten,&osWrite) == FALSE)
{}
You must be knowing that anything inside conditionals will only execute if the result is true.
And here the result is sent to the program after completion(whether complete or with error) of WriteFile routine.
OK, I missed the overlapped I/O OVL parameter in the read/write code, so It's just as well I only replied yesterday as a comment else I would be hammered with downvotes:(
The classic way of handling overlapped I/O is to have an _OVL struct as a data member of the buffer class that is issued in the overlapped read/write call. This makes it easy to have read and write calls loaded in at the same time, (or indeed, multiple read/write calls with separate buffer instances).
For COM posrts, I usually use an APC completion routine whose address is passed in the readFileEx/writeFileEx APIs. This leaves the hEvent field of the _OVL free to use to hold the instance pointer of the buffer so it's easy to cast it back inside the completion routine, (this means that each buffer class instance contains an _OVL memebr that contains an hEvent field that points to the buffer class instance - sounds a but weird, but works fine).

Overlapped IO and ERROR_IO_INCOMPLETE

I have had overlapped IO working for 2 years now but ive used it with a new application and its chucking this error at me (when i hide the main form).
I have googled but i fail to understand what the error means and how i should handle it?
Any ideas?
Im using this over NamedPipes and the error happens after calling GetOverlappedResult
DWORD dwWait = WaitForMultipleObjects(getNumEvents(), m_hEventsArr, FALSE, 500);
//check result. Get correct data
BOOL fSuccess = GetOverlappedResult(data->hPipe, &data->oOverlap, &cbRet, FALSE);
// error happens here
ERROR_IO_INCOMPLETE is an error code that means that the Overlapped operation is still in progress; GetOverlappedResult returns false as the operation hasn't succeeded yet.
You have two options - blocking and non-blocking:
Block until the operation completes: change your GetOverlappedResult call to:
BOOL fSuccess = GetOverlappedResult(data->hPipe, &data->oOverlap, &cbRet, TRUE);
This ensures that the Overlapped operation has completed (i.e. succeeds or fails) before returning the result.
Poll for completion: if the operation is still in progress, you can return from the function, and perform other work while waiting for the result:
BOOL fSuccess = GetOverlappedResult(data->hPipe, &data->oOverlap, &cbRet, FALSE);
if (!fSuccess) {
if (GetLastError() == ERROR_IO_INCOMPLETE) return; // operation still in progress
/* handle error */
} else {
/* handle success */
}
Generally, the second option is preferable to the first, as it does not cause your application to stop and wait for a result. (If the code is running on a separate thread, however, the first option may be preferable.)