/// Stops monitoring a directory. void DestroyWatch(WatchStruct* pWatch) { if(!pWatch) return; pWatch->mStopNow = TRUE; // Cancels all pending input and output (I/O) operations // that are issued by the calling thread for the specified file. // The function does not cancel I/O operations that other threads issue for a file handle. // If the function succeeds, the return value is nonzero. // //const BOOL bCancelIoResult = CancelIo(pWatch->mDirHandle); //(void)bCancelIoResult; RefreshWatch(pWatch, true); if (!HasOverlappedIoCompleted(&pWatch->mOverlapped)) { SleepEx(5, TRUE); } CloseHandle(pWatch->mOverlapped.hEvent); CloseHandle(pWatch->mDirHandle); HeapFree(GetProcessHeap(), 0, pWatch); Assert(numWatches > 0); --numWatches; }
/// Starts monitoring a directory. WatchStruct* CreateWatch(LPCTSTR szDirectory, bool recursive, DWORD mNotifyFilter) { WatchStruct* pWatch; size_t ptrsize = sizeof(*pWatch); pWatch = static_cast<WatchStruct*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize)); pWatch->mDirHandle = CreateFile(szDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); if (pWatch->mDirHandle != INVALID_HANDLE_VALUE) { pWatch->mOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pWatch->mNotifyFilter = mNotifyFilter; pWatch->mIsRecursive = recursive; if (RefreshWatch(pWatch)) { return pWatch; } else { CloseHandle(pWatch->mOverlapped.hEvent); CloseHandle(pWatch->mDirHandle); } } HeapFree(GetProcessHeap(), 0, pWatch); return nullptr; }
LRESULT CWatchPage::OnEditEnd(WPARAM nItem, LPARAM nSubItem) { // Get item label CString label = m_List.GetItemText(nItem, 1); CString text = m_List.GetItemText(nItem, nSubItem); __int64 iValue = _atoi64(text); double fValue = atof(text); // Resume updating pausedUpdating = false; WatchLine& wl = lastDisplay[nItem]; CRunObject* pMyObject = wl.pKey->first.obj; // Check for common labels if (wl.pKey->first.type == WATCH_INSTANCE || wl.pKey->first.type == WATCH_INSTANCEPRIVATEVAR && pMyObject != NULL) { if (label == "X") pMyObject->info.x = fValue; else if (label == "Y") pMyObject->info.y = fValue; else if (label == "Width") pMyObject->info.w = fValue; else if (label == "Height") pMyObject->info.h = fValue; else if (label == "Angle") pMyObject->info.angle = fValue; else if (label == "Opacity") { pMyObject->info.pInfo->filter.a = fValue / 100.0; } pMyObject->OnDebuggerValueChanged(label, text); pRuntime->UpdateBoundingBox(pMyObject); } // Check for system object if (pMyObject->pType == NULL) { pMyObject->OnDebuggerValueChanged(label, text); } // Save scroll position int nScroll = m_List.GetScrollPos(SB_VERT); // Force full refresh by clearing old display lastDisplay.resize(0); RefreshWatch(); // Restore scroll position m_List.SetSelectionMark(nItem); m_List.SetCurSel(nItem, TRUE); m_List.SetScrollPos(SB_VERT, nScroll, TRUE); return 0; }
void FileWatcherWin32::run() { if ( mHandles.empty() ) { return; } do { if ( !mHandles.empty() ) { mWatchesLock.lock(); for ( std::size_t i = 0; i < mWatches.size(); i++ ) { WatcherStructWin32 * watch = mWatches[ i ]; // If the overlapped struct was cancelled ( because the creator thread doesn't exists anymore ), // we recreate the overlapped in the current thread and refresh the watch if ( /*STATUS_CANCELED*/0xC0000120 == watch->Overlapped.Internal ) { watch->Overlapped = OVERLAPPED(); RefreshWatch(watch); } // First ensure that the handle is the same, this means that the watch was not removed. if ( HasOverlappedIoCompleted( &watch->Overlapped ) && mHandles[ i ] == watch->Watch->DirHandle ) { DWORD bytes; if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) ) { WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped ); } } } mWatchesLock.unlock(); if ( mInitOK ) { System::sleep( 10 ); } } else { // Wait for a new handle to be added System::sleep( 10 ); } } while ( mInitOK ); }
/// Unpacks events and passes them to a user defined callback. static void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { TCHAR szFile[MAX_PATH]; PFILE_NOTIFY_INFORMATION pNotify; WatchStruct* pWatch = (WatchStruct*) lpOverlapped; size_t offset = 0; if(dwNumberOfBytesTransfered == 0) return; if( numWatches == 0) { return; } if (dwErrorCode == ERROR_SUCCESS) { do { pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset]; offset += pNotify->NextEntryOffset; #if defined(UNICODE) { lstrcpynW(szFile, pNotify->FileName, std::min(MAX_PATH, static_cast<int>( pNotify->FileNameLength / sizeof(WCHAR) + 1) )); } #else { int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), szFile, MAX_PATH - 1, nullptr, nullptr); szFile[count] = TEXT('\0'); } #endif pWatch->mWatcher->handleAction(pWatch, szFile, pNotify->Action); } while (pNotify->NextEntryOffset != 0); } if (!pWatch->mStopNow) { RefreshWatch(pWatch); } }
/// Unpacks events and passes them to a user defined callback. void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { PFILE_NOTIFY_INFORMATION pNotify; WatchStruct* pWatch = (WatchStruct*) lpOverlapped; if(dwNumberOfBytesTransfered == 0) return; if (dwErrorCode == ERROR_SUCCESS) { size_t offset = 0; do { pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset]; offset += pNotify->NextEntryOffset; int requiredSize = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), NULL, 0, NULL, NULL); if (!requiredSize) continue; PCHAR szFile = new CHAR[requiredSize + 1]; int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), szFile, requiredSize, NULL, NULL); if (!count) { delete[] szFile; continue; } szFile[requiredSize] = 0; pWatch->mFileWatcher->handleAction(pWatch, szFile, pNotify->Action); if (szFile != NULL) { delete[] szFile; } } while (pNotify->NextEntryOffset != 0); } if (!pWatch->mStopNow) { RefreshWatch(pWatch); } }
/// Unpacks events and passes them to a user defined callback. void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { // TCHAR is wide char if UNICODE has been defined // otherwise it's just regular char TCHAR szFile[MAX_PATH]; PFILE_NOTIFY_INFORMATION pNotify; WatchStruct* pWatch = (WatchStruct*) lpOverlapped; size_t offset = 0; if(dwNumberOfBytesTransfered == 0) return; if (dwErrorCode == ERROR_SUCCESS) { do { pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset]; offset += pNotify->NextEntryOffset; # if defined(UNICODE) { lstrcpynW(szFile, pNotify->FileName, min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1)); } # else { int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), szFile, MAX_PATH - 1, NULL, NULL); szFile[count] = TEXT('\0'); } # endif pWatch->mFileWatcher->handleAction(pWatch, (const char*)szFile, pNotify->Action); } while (pNotify->NextEntryOffset != 0); } if (!pWatch->mStopNow) { RefreshWatch(pWatch); } }
/// Stops monitoring a directory. void DestroyWatch(WatchStruct* pWatch) { if (pWatch) { pWatch->mStopNow = TRUE; CancelIo(pWatch->mDirHandle); RefreshWatch(pWatch, true); if (!HasOverlappedIoCompleted(&pWatch->mOverlapped)) { SleepEx(5, TRUE); } CloseHandle(pWatch->mOverlapped.hEvent); CloseHandle(pWatch->mDirHandle); delete pWatch->mDirName; HeapFree(GetProcessHeap(), 0, pWatch); } }