BOOL CDirWatcher::StartWatch(HWND hNotifyWnd, LPCTSTR lpszPath) { m_hNotifyWnd = hNotifyWnd; m_strPath = lpszPath; m_hFileHandle = CreateFile(m_strPath, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL); if (m_hFileHandle == INVALID_HANDLE_VALUE) return FALSE; m_hCompPort = CreateIoCompletionPort(m_hFileHandle, m_hCompPort, DWORD(this), 0); memset(&m_overlapped, 0, sizeof(OVERLAPPED)); ReadDirectoryChangesW(m_hFileHandle, m_lpBuffer, 4096, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &m_dwSize, &m_overlapped, NULL); m_hThread = CreateThread(NULL, 0, _WatchProc, (void*)this, 0, &m_dwThreadID); return TRUE; }
static BOOL register_monitoring_entry(WDM_PEntry entry) { BOOL success; DWORD bytes; bytes = 0; // Not used because the process callback gets passed the written bytes success = ReadDirectoryChangesW( entry->dir_handle, // handle to directory entry->buffer, // read results buffer WDM_BUFFER_SIZE, // length of buffer entry->user_data->watch_childeren, // monitoring option entry->user_data->flags, // filter conditions &bytes, // bytes returned &entry->event_container, // overlapped buffer &handle_entry_change // process callback ); if ( ! success ) { WDM_DEBUG("ReadDirectoryChangesW failed with error (%d): %s", GetLastError(), rb_w32_strerror(GetLastError())); return FALSE; } return TRUE; }
void resman_check_watch(struct resman *rman) { struct watch_dir *wdir; unsigned int idx; unsigned int num_handles = dynarr_size(rman->watch_handles); if(!num_handles) { return; } idx = WaitForMultipleObjectsEx(num_handles, rman->watch_handles, FALSE, 0, TRUE); if(idx == WAIT_FAILED) { unsigned int err = GetLastError(); fprintf(stderr, "failed to check for file modification: %u\n", err); return; } if(idx >= WAIT_OBJECT_0 && idx < WAIT_OBJECT_0 + num_handles) { if(!(wdir = rb_find(rman->wdirbyev, rman->watch_handles[idx]))) { fprintf(stderr, "got change handle, but failed to find corresponding watch_dir!\n"); return; } handle_event(rman, rman->watch_handles[idx], wdir); /* restart the watch call */ ReadDirectoryChangesW(wdir->handle, wdir->buf, RES_BUF_SIZE, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, 0, &wdir->over, 0); } }
DWORD WINAPI FileSystemWatcher::Routine( LPVOID lParam ) { FileSystemWatcher* pFsw = (FileSystemWatcher*)lParam; CString tem1,tem2; CString str = (_T("[") + pFsw->WatchedDir + "] 开始监视!"); pFsw->hDir = CreateFile( pFsw->WatchedDir, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL ); if( INVALID_HANDLE_VALUE == pFsw->hDir ) return false; char buf[ 2*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH) ]; FILE_NOTIFY_INFORMATION* pNotify=(FILE_NOTIFY_INFORMATION *)buf; DWORD BytesReturned; while(true) { if( ReadDirectoryChangesW( pFsw->hDir, pNotify, sizeof(buf), true, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_DIR_NAME| FILE_NOTIFY_CHANGE_ATTRIBUTES| FILE_NOTIFY_CHANGE_SIZE| FILE_NOTIFY_CHANGE_LAST_WRITE| FILE_NOTIFY_CHANGE_LAST_ACCESS| FILE_NOTIFY_CHANGE_CREATION| FILE_NOTIFY_CHANGE_SECURITY, &BytesReturned, NULL, NULL ) ) { char tmp[MAX_PATH], str1[MAX_PATH], str2[MAX_PATH]; memset( tmp, 0, sizeof(tmp) ); WideCharToMultiByte( CP_ACP,0,pNotify->FileName,pNotify->FileNameLength/2,tmp,99,NULL,NULL ); strcpy_s( str1,260, tmp ); if( 0 != pNotify->NextEntryOffset ) { PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify+pNotify->NextEntryOffset); memset( tmp, 0, sizeof(tmp) ); WideCharToMultiByte( CP_ACP,0,p->FileName,p->FileNameLength/2,tmp,99,NULL,NULL ); strcpy_s( str2,260, tmp ); } tem1= str1; tem2= str2; pFsw->DealFunc((ACTION)pNotify->Action, tem1, tem2); } else { break; } } return 0; }
void FileWatcher::Init(const WCHAR* fileFullPath) { // if the thread already exists then stop it if (IsThreadRunning()) SynchronousAbort(); str::ReplacePtr(&filePath, fileFullPath); WCHAR *dirPath = path::GetDir(filePath); hDir = CreateFile( dirPath, // pointer to the directory containing the tex files FILE_LIST_DIRECTORY, // access (read-write) mode FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, // share mode NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED , // file attributes NULL); // file with attributes to copy free(dirPath); ZeroMemory(&overl, sizeof(overl)); ZeroMemory(buffer, sizeof(buffer)); overl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // watch the directory ReadDirectoryChangesW( hDir, /* handle to directory */ &buffer[curBuffer], /* read results buffer */ sizeof(buffer[curBuffer]), /* length of buffer */ FALSE, /* monitoring option */ //FILE_NOTIFY_CHANGE_CREATION| FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */ NULL, /* bytes returned */ &overl, /* overlapped buffer */ NULL); /* completion routine */ }
void CDirectoryMonitor::WatchDirectoryInternal(ULONG_PTR dwParam) { CDirInfo *pDirInfo = NULL; pDirInfo = reinterpret_cast<CDirInfo *>(dwParam); if(pDirInfo->m_hDirectory == INVALID_HANDLE_VALUE) { free(pDirInfo->m_pData); return; } pDirInfo->m_FileNotifyBuffer = (FILE_NOTIFY_INFORMATION *)malloc(PRIMARY_BUFFER_SIZE); pDirInfo->m_bDirMonitored = ReadDirectoryChangesW(pDirInfo->m_hDirectory, pDirInfo->m_FileNotifyBuffer,PRIMARY_BUFFER_SIZE, pDirInfo->m_bWatchSubTree,pDirInfo->m_WatchFlags,NULL,&pDirInfo->m_Async, CompletionRoutine); if(!pDirInfo->m_bDirMonitored) { free(pDirInfo->m_FileNotifyBuffer); CancelIo(pDirInfo->m_hDirectory); CloseHandle(pDirInfo->m_hDirectory); } }
void gep::DirectoryWatcher::doRead() { memset(&m_overlapped, 0, sizeof(m_overlapped)); ReadDirectoryChangesW(m_directoryHandle, m_buffer, GEP_ARRAY_SIZE(m_buffer), (m_watchSubdirs == WatchSubdirs::yes), m_filter, nullptr, &m_overlapped, nullptr); }
//----------------------------------------------------------------------------- static void start_watch(struct watch_entry * watch_entry_p) { //----------------------------------------------------------------------------- BOOL start_read_result; memset(&watch_entry_p->overlap, 0, sizeof(watch_entry_p->overlap)); // start an overlapped 'read' to look for a filesystem change start_read_result = ReadDirectoryChangesW( watch_entry_p->hDirectory, watch_entry_p->changes_buffer, CHANGES_BUFFER_SIZE, TRUE, DIRECTORY_CHANGES_FILTER, NULL, (LPOVERLAPPED) watch_entry_p, NULL ); if (!start_read_result) { DWORD err = GetLastError(); report_error(L"ReadDirectoryChangesW", err); /* This error is reported for a handle to a file, meaning a folder has been recreated as a file after it was selected for backup. */ if (err != ERROR_INVALID_PARAMETER) ExitProcess(10); } } // start_watch
void sbWin32FileSystemWatcher::WatchNextChange() { TRACE("%s", __FUNCTION__); DWORD const flags = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION; if (mRootDirHandle != INVALID_HANDLE_VALUE) { BOOL result = ReadDirectoryChangesW(mRootDirHandle, mBuffer, BUFFER_LEN, TRUE, // watch subdirs flags, NULL, &mOverlapped, ReadDirectoryChangesWCallbackRoutine); if (!result) { NS_WARNING("ERROR: Could not ReadDirectoryChangesW()"); if (mRootDirHandle != INVALID_HANDLE_VALUE) { CloseHandle(mRootDirHandle); mRootDirHandle = INVALID_HANDLE_VALUE; } } } }
static unsigned int __stdcall tr_watchdir_win32_thread (void * context) { const tr_watchdir_t handle = context; tr_watchdir_win32 * const backend = BACKEND_UPCAST (tr_watchdir_get_backend (handle)); DWORD bytes_transferred; while (tr_get_overlapped_result_ex (backend->fd, &backend->overlapped, &bytes_transferred, INFINITE, FALSE)) { PFILE_NOTIFY_INFORMATION info = (PFILE_NOTIFY_INFORMATION) backend->buffer; while (info->NextEntryOffset != 0) *((BYTE **) &info) += info->NextEntryOffset; info->NextEntryOffset = bytes_transferred - ((BYTE *) info - (BYTE *) backend->buffer); send (backend->notify_pipe[1], (const char *) backend->buffer, bytes_transferred, 0); if (!ReadDirectoryChangesW (backend->fd, backend->buffer, sizeof (backend->buffer), FALSE, WIN32_WATCH_MASK, NULL, &backend->overlapped, NULL)) { log_error ("Failed to read directory changes"); return 0; } } if (GetLastError () != ERROR_OPERATION_ABORTED) log_error ("Failed to wait for directory changes"); return 0; }
static int beginMonitor(VPLFS_MonitorHandle_t* handle) { // VPL_REPORT_INFO("beginMonitor called"); int rv = 0; handle->overlapped.Internal = 0; handle->overlapped.InternalHigh = 0; handle->overlapped.Offset = 0; handle->overlapped.OffsetHigh = 0; handle->overlapped.hEvent = handle; // hEvent not used by system, used as ctx ptr. #ifdef VPL_PLAT_IS_WINRT // TODO: using WinRT APIs to implement file monitor rv = VPL_ERR_NOOP; #else if(!ReadDirectoryChangesW(handle->hDir, handle->pBuffer, //<--FILE_NOTIFY_INFORMATION records are put into this buffer handle->nBufferLength, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_DIR_NAME| FILE_NOTIFY_CHANGE_SIZE| FILE_NOTIFY_CHANGE_LAST_WRITE| FILE_NOTIFY_CHANGE_CREATION, NULL, // Only defined for synchronous calls. &handle->overlapped, &ChDirCompletionRoutine) ) { rv = VPLError_GetLastWinError(); } #endif return rv; }
static WatchedDir *NewWatchedDir(const WCHAR *dirPath) { WatchedDir *wd = AllocStruct<WatchedDir>(); wd->dirPath = str::Dup(dirPath); wd->hDir = CreateFile( dirPath, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (!wd->hDir) goto Failed; wd->overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!wd->overlapped.hEvent) goto Failed; // start watching the directory wd->currBuffer = 0; ReadDirectoryChangesW( wd->hDir, &wd->buffer[wd->currBuffer], /* read results buffer */ sizeof(wd->buffer[wd->currBuffer]), /* length of buffer */ FALSE, /* monitoring option */ FILE_NOTIFY_CHANGE_LAST_WRITE, /* filter conditions */ NULL, /* bytes returned */ &wd->overlapped, /* overlapped buffer */ NULL); /* completion routine */ return wd; Failed: FreeWatchedDir(wd); return NULL; }
static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, uv_fs_event_t* handle) { assert(handle->dir_handle != INVALID_HANDLE_VALUE); assert(!handle->req_pending); memset(&(handle->req.u.io.overlapped), 0, sizeof(handle->req.u.io.overlapped)); if (!ReadDirectoryChangesW(handle->dir_handle, handle->buffer, uv_directory_watcher_buffer_size, (handle->flags & UV_FS_EVENT_RECURSIVE) ? TRUE : FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, NULL, &handle->req.u.io.overlapped, NULL)) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(&handle->req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)&handle->req); } handle->req_pending = 1; }
int FileSystemWatcherTask::task() { m_handle = CreateFile(m_path, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, nullptr); if (m_handle == INVALID_HANDLE_VALUE) return -1; Lumix::setMemory(&m_overlapped, 0, sizeof(m_overlapped)); m_overlapped.hEvent = this; m_finished = false; while (!m_finished) { PROFILE_BLOCK("Change handling"); BOOL status = ReadDirectoryChangesW(m_handle, m_info, sizeof(m_info), TRUE, READ_DIR_CHANGE_FILTER, &m_received, &m_overlapped, ¬if); if (status == FALSE) break; SleepEx(INFINITE, TRUE); } return 0; }
VOID CFileMonitorRequest::CheckFileChange() { DWORD dwBytes = 0; if ( FALSE == ReadDirectoryChangesW( m_hMonitorPath , &m_vecShareMem[0] , (DWORD)m_vecShareMem.size() , m_bRecursive , m_dwFilter , &dwBytes , &m_overlapped , CFileMonitorRequest::OnChangeComplete ) ) { CWUtils::ShowDebugMsg(); } }
bool FileMon::monitor(const std::string &path) { #ifdef WIN32 #ifdef UNICODE wchar_t path2[512]; MultiByteToWideChar(CP_ACP,0,path.c_str(),-1,path2,512); #else const char *path2=path.c_str(); #endif WatchStruct* pWatch; size_t ptrsize = sizeof(*pWatch); pWatch = static_cast<WatchStruct*>(HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,ptrsize)); pWatch->mDirHandle = CreateFile(path2,FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,NULL, OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,NULL); pWatch->fileMon=this; if(pWatch->mDirHandle != INVALID_HANDLE_VALUE) { pWatch->mOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); pWatch->mNotifyFilter = FILE_NOTIFY_CHANGE_CREATION|FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_FILE_NAME; if(ReadDirectoryChangesW( pWatch->mDirHandle,pWatch->mBuffer,sizeof(pWatch->mBuffer),FALSE, pWatch->mNotifyFilter,NULL,&pWatch->mOverlapped,WatchCallback) != 0) { pWatch->mDirName=path; mWatches.insert(std::make_pair(path,pWatch)); return true; } else { CloseHandle(pWatch->mOverlapped.hEvent); CloseHandle(pWatch->mDirHandle); } } HeapFree(GetProcessHeap(),0,pWatch); return false; #endif #ifdef LINUX int watch = inotify_add_watch(notify,path.c_str(),IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | IN_DELETE); if(watch < 0) { if(errno == ENOENT) { std::cout << "File monitor: File/dir not found error.\n"; return false; } else { std::cout << "File monitor: " << strerror(errno) << std::endl;; return false; } } else { watchMap[watch]=path; } return true; #endif }
static int refresh_dirmonitor(FileMonitor *fm, int is_clear) { enum { NOTIFY_FILTER = FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE, }; return ReadDirectoryChangesW( fm->hDir, fm->buffer, sizeof(fm->buffer), FALSE, NOTIFY_FILTER, NULL, &fm->overlapped, is_clear ? NULL : file_monitor_callback) != 0; }
//Register a watch to receive events void register_watch(WatchData &watch){ std::memset(&watch.info_buf[0], 0, watch.info_buf.size()); bool status = ReadDirectoryChangesW(watch.dir_handle, &watch.info_buf[0], watch.info_buf.size(), false, remap_file_notify(watch.filter), nullptr, &watch.overlapped, watch_callback); if (!status){ std::cerr << "lfw Error: could not register watch on " << watch.dir_name << ": " << get_error_msg(GetLastError()) << std::endl; } }
BOOL STDCALL OSFileHasChanged (OSFileChangeData *data) { BOOL hasModified = FALSE; if(HasOverlappedIoCompleted(&data->directoryChange)) { FILE_NOTIFY_INFORMATION *notify = (FILE_NOTIFY_INFORMATION*)data->changeBuffer; for (;;) { if (notify->Action != FILE_ACTION_RENAMED_OLD_NAME && notify->Action != FILE_ACTION_REMOVED) { String strFileName; strFileName.SetLength(notify->FileNameLength); scpy_n(strFileName, notify->FileName, notify->FileNameLength/2); strFileName.KillSpaces(); String strFileChanged; strFileChanged << data->strDirectory << strFileName; if(strFileChanged.CompareI(data->targetFileName)) { hasModified = TRUE; break; } } if (!notify->NextEntryOffset) break; notify = (FILE_NOTIFY_INFORMATION*)((BYTE *)notify + notify->NextEntryOffset); } CloseHandle (data->directoryChange.hEvent); DWORD test; zero(&data->directoryChange, sizeof(data->directoryChange)); zero(data->changeBuffer, sizeof(data->changeBuffer)); data->directoryChange.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if(ReadDirectoryChangesW(data->hDirectory, data->changeBuffer, 2048, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &test, &data->directoryChange, NULL)) { } else { CloseHandle(data->directoryChange.hEvent); CloseHandle(data->hDirectory); return hasModified; } } return hasModified; }
/// Refreshes the directory monitoring. bool RefreshWatch(WatchStruct* pWatch, bool _clear) { return ReadDirectoryChangesW( pWatch->mDirHandle, pWatch->mBuffer, sizeof(pWatch->mBuffer), pWatch->mRecursive, pWatch->mNotifyFilter, NULL, &pWatch->mOverlapped, _clear ? 0 : WatchCallback) != 0; }
bool C4FileMonitor::Execute(int iTimeout, pollfd *) { // Check event if (WaitForSingleObject(hEvent, iTimeout) != WAIT_OBJECT_0) return true; // Check handles for (TreeWatch *pWatch = pWatches; pWatch; pWatch = pWatch->Next) { DWORD dwBytes = 0; // Has a notification? if (GetOverlappedResult(pWatch->hDir, &pWatch->ov, &dwBytes, false)) { // Read notifications const char *pPos = pWatch->Buffer; for (;;) { const _FILE_NOTIFY_INFORMATION *pNotify = reinterpret_cast<const _FILE_NOTIFY_INFORMATION *>(pPos); // Handle HandleNotify(pWatch->DirName.getData(), pNotify); // Get next entry if (!pNotify->NextEntryOffset) break; pPos += pNotify->NextEntryOffset; if (pPos >= pWatch->Buffer + Min<size_t>(sizeof(pWatch->Buffer), dwBytes)) break; break; } // Restart directory change notification (flush queue) ReadDirectoryChangesW(pWatch->hDir, pWatch->Buffer, sizeof(pWatch->Buffer), false, C4FileMonitorNotifies, NULL, &pWatch->ov, NULL); dwBytes = 0; while (GetOverlappedResult(pWatch->hDir, &pWatch->ov, &dwBytes, false)) { ReadDirectoryChangesW(pWatch->hDir, pWatch->Buffer, sizeof(pWatch->Buffer), false, C4FileMonitorNotifies, NULL, &pWatch->ov, NULL); dwBytes = 0; } } } ResetEvent(hEvent); return true; }
static void CALLBACK callback(DWORD errorCode, DWORD tferred, LPOVERLAPPED over) { if (errorCode > 0) { return; } FileSystemWatcherPC* watcher = (FileSystemWatcherPC*)over->hEvent; if (tferred > 0) { FILE_NOTIFY_INFORMATION* info = &watcher->m_info[0]; while (info) { switch (info->Action) { case FILE_ACTION_RENAMED_NEW_NAME: case FILE_ACTION_ADDED: case FILE_ACTION_MODIFIED: { char tmp[MAX_PATH]; wcharToCharArray( info->FileName, tmp, info->FileNameLength); watcher->m_callback.invoke(tmp); // watcher->m_asset_browser->emitFileChanged(tmp); } break; case FILE_ACTION_RENAMED_OLD_NAME: case FILE_ACTION_REMOVED: // do not do anything break; default: ASSERT(false); break; } info = info->NextEntryOffset == 0 ? nullptr : (FILE_NOTIFY_INFORMATION*)(((char*)info) + info->NextEntryOffset); } } BOOL b = ReadDirectoryChangesW(watcher->m_handle, watcher->m_info, sizeof(watcher->m_info), TRUE, READ_DIR_CHANGE_FILTER, &watcher->m_received, &watcher->m_overlapped, callback); ASSERT(b); }
FileMon::~FileMon() { #ifdef WIN32 for(auto i : mWatches) { WatchStruct* pWatch=i.second; DWORD dwWaitResult = WaitForSingleObject(ghMutex,INFINITE); while(true) { if(dwWaitResult==WAIT_OBJECT_0) { pWatch->mStopNow = TRUE; if(!ReleaseMutex(ghMutex)) { std::cout << "FileMon : Release mutex err.\n"; } break; } else if(dwWaitResult==WAIT_ABANDONED) { break; } } CancelIo(pWatch->mDirHandle); ReadDirectoryChangesW( pWatch->mDirHandle,pWatch->mBuffer,sizeof(pWatch->mBuffer),FALSE, pWatch->mNotifyFilter,NULL,&pWatch->mOverlapped,0); if(!HasOverlappedIoCompleted(&pWatch->mOverlapped)) { SleepEx(5,TRUE); } CloseHandle(pWatch->mOverlapped.hEvent); CloseHandle(pWatch->mDirHandle); HeapFree(GetProcessHeap(),0,pWatch); } CloseHandle(ghMutex); #endif #ifdef LINUX if(notify) { for(auto i : watchMap) { inotify_rm_watch(notify,i.first); //unnecessary because of close below? } } if(notify) { close(notify); } #endif }
unsigned int CFileWatcher::Worker(void* arg) { CFileWatcher* watcher = (CFileWatcher*)arg; DWORD error; DWORD bytes; ULONG_PTR key; LPOVERLAPPED overlapped; while (TRUE) { error = S_OK; if (!GetQueuedCompletionStatus( watcher->completionPort, &bytes, &key, &overlapped, watcher->uncFileSharePollingInterval)) { error = GetLastError(); } if (-1L == key) // terminate thread { break; } else if (S_OK == error) // a change in registered directory detected (local file system) { WatchedDirectory* directory = (WatchedDirectory*)key; watcher->ScanDirectory(directory, FALSE); RtlZeroMemory(&directory->overlapped, sizeof directory->overlapped); ReadDirectoryChangesW( directory->watchHandle, &directory->info, sizeof directory->info, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, NULL, &directory->overlapped, NULL); } else // timeout - scan all registered UNC files for changes { WatchedDirectory* current = watcher->directories; while (current) { watcher->ScanDirectory(current, TRUE); current = current->next; } } } return 0; }
bool CCheckDirChange::WatchDirChanges(PReadDirChangeInfo pChangeInfo) { pChangeInfo->pFileNotification = (FILE_NOTIFY_INFORMATION*)(new char[pChangeInfo->dwMaxBufferLen]); memset(pChangeInfo->pFileNotification,0,pChangeInfo->dwMaxBufferLen); return ReadDirectoryChangesW(m_hDirectory, pChangeInfo->pFileNotification, pChangeInfo->dwMaxBufferLen, TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_DIR_NAME, &pChangeInfo->dwReturnLen, &pChangeInfo->overlapped, NULL)?true:false; }
void FileSystem::ListenForDirectoryChanges(std::string directory) { HANDLE h_Directory = ::CreateFile( directory.c_str(), // pointer to the file name FILE_LIST_DIRECTORY, // access (read/write) mode FILE_SHARE_READ // share mode | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, // security descriptor OPEN_EXISTING, // how to create FILE_FLAG_BACKUP_SEMANTICS // file attributes | FILE_FLAG_OVERLAPPED, NULL); // file with attributes to copy if (h_Directory == INVALID_HANDLE_VALUE) { std::cout << "ERROR: Error opening directory to watch: " << directory << std::endl; } int nCounter = 0; FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024]; DWORD dwBytesReturned = 0; while(TRUE) { int count = 0; if( ReadDirectoryChangesW ( h_Directory, (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL) == 0) { } else { wchar_t filename[MAX_PATH]; if (strFileNotifyInfo[0].FileNameLength) { wcsncpy_s(filename, MAX_PATH, strFileNotifyInfo[0].FileName, strFileNotifyInfo[0].FileNameLength / 2); filename[strFileNotifyInfo[0].FileNameLength / 2] = 0; std::wstring ws( filename ); std::string convert_str( ws.begin(), ws.end()); std::replace(convert_str.begin(), convert_str.end(), '\\', '/' ); for(std::vector<void (*)(std::string modified_file)>::iterator it = _change_listeners.begin(); it != _change_listeners.end(); ++it) { (*it)(directory + "/" + convert_str); } } } boost::this_thread::sleep(boost::posix_time::milliseconds(2000)); } }
OSFileChangeData * STDCALL OSMonitorFileStart(String path, bool suppressLogging) { HANDLE hDirectory; OSFileChangeData *data = (OSFileChangeData *)Allocate(sizeof(*data)); String strDirectory = path; strDirectory.FindReplace(TEXT("\\"), TEXT("/")); strDirectory = GetPathDirectory(strDirectory); strDirectory.FindReplace(TEXT("/"), TEXT("\\")); strDirectory << TEXT("\\"); scpy_n (data->strDirectory, strDirectory.Array(), _countof(data->strDirectory)-1); hDirectory = CreateFile(data->strDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL); if(hDirectory != INVALID_HANDLE_VALUE) { DWORD test; zero(&data->directoryChange, sizeof(data->directoryChange)); data->directoryChange.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if(ReadDirectoryChangesW(hDirectory, data->changeBuffer, 2048, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &test, &data->directoryChange, NULL)) { scpy_n (data->targetFileName, path.Array(), _countof(data->targetFileName)-1); data->hDirectory = hDirectory; return data; } else { int err = GetLastError(); CloseHandle(data->directoryChange.hEvent); CloseHandle(hDirectory); if(!suppressLogging) Log(TEXT("OSMonitorFileStart: Unable to monitor file '%s', error %d"), path.Array(), err); Free(data); return NULL; } } else { if(!suppressLogging) { int err = GetLastError(); Log(TEXT("OSMonitorFileStart: Unable to open directory '%s', error %d"), data->strDirectory, err); } Free(data); return NULL; } }
void DirectoryWatcherImpl::watch() { m_fileHandle = CreateFileA(m_directory.c_str(), FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (m_fileHandle == INVALID_HANDLE_VALUE) { JOP_DEBUG_ERROR("Failed to start directory watcher, directory: " << m_directory); m_active = false; m_error = true; m_fileHandle = nullptr; return; } FILE_NOTIFY_INFORMATION fileNotifyInfo[4]; DWORD bytesReturned = sizeof(FILE_NOTIFY_INFORMATION); while (!m_shouldClose) { while (!m_active) { std::this_thread::sleep_for(std::chrono::seconds(1)); continue; } if (ReadDirectoryChangesW(m_fileHandle, &fileNotifyInfo, sizeof(fileNotifyInfo), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &bytesReturned, NULL, NULL)) { if (fileNotifyInfo[0].Action == FILE_ACTION_MODIFIED) { DirectoryWatcher::Info info; info.filename = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(std::wstring(fileNotifyInfo[0].FileName, fileNotifyInfo[0].FileNameLength / sizeof(wchar_t))); if (!(info == m_lastEvent)) { m_lastEvent = info; m_callback(m_lastEvent); } } } } }
void MonitorDirectory(HANDLE hDir,LPTSTR lpServer) { time_t rawtime; TCHAR szBuffer[640] = {0}; DWORD dwOffset = 0; FILE_NOTIFY_INFORMATION* pInfo = NULL; DWORD dwbytes =0; BOOL retval; //synchronous (blocking) function. Will return when a monitored change has occured retval = ReadDirectoryChangesW(hDir, szBuffer, sizeof(szBuffer)/sizeof(TCHAR), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_SIZE, &dwbytes, NULL, NULL); if (0 == retval) { printf("\n ERROR: ReadDirectoryChanges function failed. \n"); return; } do { pInfo = (FILE_NOTIFY_INFORMATION*) &szBuffer[dwOffset]; TCHAR szFileName[MAX_PATH] = {0}; WideCharToMultiByte(CP_ACP,NULL,pInfo->FileName,pInfo->FileNameLength,szFileName,sizeof(szFileName)/sizeof(TCHAR),NULL,NULL); if(FILE_ACTION_ADDED == pInfo->Action || FILE_ACTION_MODIFIED == pInfo->Action) { time(&rawtime); _tprintf(TEXT("Filename (%s) changed at time %s.\n"), szFileName, ctime(&rawtime)); TransferFile(szFileName,lpServer); } dwOffset += pInfo->NextEntryOffset; } while (pInfo->NextEntryOffset != 0); }
static GObject * g_win32_directory_monitor_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { GObject *obj; GWin32DirectoryMonitorClass *klass; GObjectClass *parent_class; GWin32DirectoryMonitor *self; wchar_t *wdirname; gboolean result; klass = G_WIN32_DIRECTORY_MONITOR_CLASS (g_type_class_peek (G_TYPE_WIN32_DIRECTORY_MONITOR)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); obj = parent_class->constructor (type, n_construct_properties, construct_properties); self = G_WIN32_DIRECTORY_MONITOR (obj); wdirname = g_utf8_to_utf16 (G_LOCAL_DIRECTORY_MONITOR (obj)->dirname, -1, NULL, NULL, NULL); self->priv->hDirectory = CreateFileW (wdirname, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); g_free (wdirname); if (self->priv->hDirectory == INVALID_HANDLE_VALUE) { /* Ignore errors */ return obj; } result = ReadDirectoryChangesW (self->priv->hDirectory, (gpointer)self->priv->file_notify_buffer, self->priv->buffer_allocated_bytes, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE, &self->priv->buffer_filled_bytes, &self->priv->overlapped, g_win32_directory_monitor_callback); /* Ignore errors */ return obj; }