#include #include #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32 namespace efsw { /// Unpacks events and passes them to a user defined callback. void CALLBACK WatchCallback( DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped ) { if ( dwNumberOfBytesTransfered == 0 || NULL == lpOverlapped ) { return; } char szFile[MAX_PATH]; PFILE_NOTIFY_INFORMATION pNotify; WatcherStructWin32* tWatch = (WatcherStructWin32*)lpOverlapped; WatcherWin32* pWatch = tWatch->Watch; size_t offset = 0; do { bool skip = false; pNotify = (PFILE_NOTIFY_INFORMATION)&pWatch->Buffer[offset]; offset += pNotify->NextEntryOffset; int count = WideCharToMultiByte( CP_UTF8, 0, pNotify->FileName, pNotify->FileNameLength / sizeof( WCHAR ), szFile, MAX_PATH - 1, NULL, NULL ); szFile[count] = TEXT( '\0' ); std::string nfile( szFile ); if ( FILE_ACTION_MODIFIED == pNotify->Action ) { FileInfo fifile( std::string( pWatch->DirName ) + nfile ); if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && pWatch->LastModifiedEvent.file.Size == fifile.Size && pWatch->LastModifiedEvent.fileName == nfile ) { skip = true; } pWatch->LastModifiedEvent.fileName = nfile; pWatch->LastModifiedEvent.file = fifile; } if ( !skip ) { pWatch->Watch->handleAction( pWatch, nfile, pNotify->Action ); } } while ( pNotify->NextEntryOffset != 0 ); if ( !pWatch->StopNow ) { RefreshWatch( tWatch ); } } /// Refreshes the directory monitoring. bool RefreshWatch( WatcherStructWin32* pWatch ) { return ReadDirectoryChangesW( pWatch->Watch->DirHandle, pWatch->Watch->Buffer, sizeof( pWatch->Watch->Buffer ), pWatch->Watch->Recursive, pWatch->Watch->NotifyFilter, NULL, &pWatch->Overlapped, NULL ) != 0; } /// Stops monitoring a directory. void DestroyWatch( WatcherStructWin32* pWatch ) { if ( pWatch ) { WatcherWin32* tWatch = pWatch->Watch; tWatch->StopNow = true; CancelIoEx( pWatch->Watch->DirHandle, &pWatch->Overlapped ); CloseHandle( pWatch->Watch->DirHandle ); efSAFE_DELETE_ARRAY( pWatch->Watch->DirName ); efSAFE_DELETE( pWatch->Watch ); } } /// Starts monitoring a directory. WatcherStructWin32* CreateWatch( LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter, HANDLE iocp ) { WatcherStructWin32* tWatch; size_t ptrsize = sizeof( *tWatch ); tWatch = static_cast( HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize ) ); WatcherWin32* pWatch = new WatcherWin32(); tWatch->Watch = pWatch; pWatch->DirHandle = CreateFileW( szDirectory, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); if ( pWatch->DirHandle != INVALID_HANDLE_VALUE && CreateIoCompletionPort( pWatch->DirHandle, iocp, 0, 1 ) ) { pWatch->NotifyFilter = NotifyFilter; pWatch->Recursive = recursive; if ( RefreshWatch( tWatch ) ) { return tWatch; } } CloseHandle( pWatch->DirHandle ); efSAFE_DELETE( pWatch->Watch ); HeapFree( GetProcessHeap(), 0, tWatch ); return NULL; } } // namespace efsw #endif