BOOL CBackgroundUpdater::Stop() { #ifdef THREADDISABLE_BACKROUNDUPDATER return TRUE; #else BuDebugMessage("BU: Stop"); if (m_hThread==NULL) { if (GetLocateDlg()->m_pBackgroundUpdater!=NULL) delete this; return FALSE; } // Creating a copy of thread handle and using HANDLE hThread; DuplicateHandle(GetCurrentProcess(),m_hThread,GetCurrentProcess(), &hThread,0,FALSE,DUPLICATE_SAME_ACCESS); DebugOpenThread(hThread); DWORD status; BOOL bRet=::GetExitCodeThread(hThread,&status); if (bRet && status==STILL_ACTIVE) { InterlockedExchange(&m_lIgnoreItemsAndGoToSleep,TRUE); // Signal stop event SetEvent(m_phEvents[0]); // Wait for ending WaitForSingleObject(hThread,750); if (GetLocateDlg()->m_pBackgroundUpdater!=NULL) { BOOL bTerminated=FALSE; status=0; bRet=::GetExitCodeThread(hThread,&status); if (bRet && status==STILL_ACTIVE) { if (TerminateThread(hThread,1,TRUE)) bTerminated=TRUE; } if (bTerminated) delete this; } } CloseHandle(hThread); DebugCloseThread(hThread); return TRUE; #endif }
void CSubAction::DoMenuCommand() { CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg==NULL) return; if (GetCurrentThreadId()==GetTrayIconWnd()->GetLocateDlgThread()->GetThreadId()) pLocateDlg->OnCommand(LOWORD(m_nMenuCommand),0,NULL); else pLocateDlg->SendMessage(WM_COMMAND,MAKEWPARAM(LOWORD(m_nMenuCommand),0),0); }
void CSubAction::DoResultListItems() { if (m_nResultList==ExecuteCommand) { if (m_szCommand!=NULL) CLocateDlg::ExecuteCommand(m_szCommand); return; } CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg==NULL) return; /*if (GetCurrentThreadId()==GetTrayIconWnd()->m_pLocateDlgThread->m_nThreadID) pLocateDlg->OnExecuteResultAction(m_nResultList,m_pExtraInfo); else*/ pLocateDlg->SendMessage(WM_RESULTLISTACTION,m_nSubAction,(LPARAM)m_pExtraInfo); }
CBackgroundUpdater::~CBackgroundUpdater() { InterlockedExchangePointer((PVOID*)&GetLocateDlg()->m_pBackgroundUpdater,NULL); CloseHandle(m_phEvents[0]); DebugCloseEvent(m_phEvents[0]); CloseHandle(m_phEvents[1]); DebugCloseEvent(m_phEvents[1]); DeleteCriticalSection(&m_csUpdateList); // Closing handle if (m_hThread!=NULL) { // We are still running CloseHandle(m_hThread); DebugCloseThread(m_hThread); m_hThread=NULL; } }
inline CCheckFileNotificationsThread::~CCheckFileNotificationsThread() { FnDebugMessage("FN: destructor called"); ASSERT((m_lState==sInitializing && m_nHandles==0) || m_lState==sStopping || m_lState==sTerminated); ASSERT(m_lState==sTerminated || m_hThread!=NULL); InterlockedExchangePointer((PVOID*)&GetLocateDlg()->m_pFileNotificationsThread,NULL); // Freeing handles DestroyHandles(); // Delete file if (m_pFile!=NULL) delete[] m_pFile; // Closing stop event CloseHandle(m_hStopEvent); DebugCloseEvent(m_hStopEvent); // Closing handle if (m_hThread!=NULL) { // We are still running CloseHandle(m_hThread); DebugCloseThread(m_hThread); m_hThread=NULL; } }
BOOL CShortcut::IsWhenAndWhereSatisfied(HWND hSystemTrayWnd) const { if ((m_dwFlags&sfKeyTypeMask)==sfLocal) { #ifndef KEYHOOK_EXPORTS CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg!=NULL) { // Check if desired tab is chosen switch (pLocateDlg->GetCurrentTab()) { case 0: // Name tab if (!(m_wWhenPressed&wpNameTabShown)) return FALSE; break; case 1: // Size and Date tab if (!(m_wWhenPressed&wpSizeDateTabShown)) return FALSE; break; case 2: // Advanced tab if (!(m_wWhenPressed&wpAdvancedTabShown)) return FALSE; break; } // Check if "Find as you tybe" is running when not desired and vise verca if (pLocateDlg->IsInstantSearchingFlagSet(CLocateDlg::isRunning)) { if (m_wWhenPressed&wpDisableWhenISRunning) return FALSE; } else { if (m_wWhenPressed&wpDisableWhenISNotRunning) return FALSE; } } return TRUE; #else return FALSE; #endif } if (m_pClass==NULL && m_pTitle==NULL) return TRUE; HWND hWnd=GetForegroundWindow(); if (hWnd==NULL) return FALSE; // Checking class if (m_pClass!=NULL) { if (m_pClass==LPCSTR(-1)) return HWND(SendMessage(hSystemTrayWnd,WM_GETLOCATEDLG,0,0))==hWnd; char szClassName[200]=""; GetClassName(hWnd,szClassName,200); if (!DoClassOrTitleMatch(szClassName,m_pClass)) return FALSE; } // Checking class name if (m_pTitle!=NULL) { char szTitleName[200]; GetWindowText(hWnd,szTitleName,200); if (!DoClassOrTitleMatch(szTitleName,m_pTitle)) return FALSE; } return TRUE; }
void CSubAction::DoMisc() { if (m_nMisc==ExecuteCommandMisc) { if (m_szCommand!=NULL) CLocateDlg::ExecuteCommand(m_szCommand); return; } else if (m_nMisc==InsertAsterisks) { CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg==NULL) return; CStringW Text; pLocateDlg->m_NameDlg.m_Name.GetText(Text); DWORD dwSelStart=pLocateDlg->m_NameDlg.m_Name.GetEditSel(); WORD wSelEnd=HIWORD(dwSelStart); dwSelStart&=0xFFFF; // If asterisks are already at the beginning and the end, replace spaces if (Text[0]==L'*' && Text.LastChar()==L'*') Text.ReplaceChars(L' ',L'*'); else { if (Text[0]!=L'*') { Text.InsChar(0,L'*'); // Update selection if (dwSelStart==wSelEnd) { dwSelStart++; wSelEnd++; } else { if (dwSelStart>0) dwSelStart++; wSelEnd++; } } if (Text.LastChar()!=L'*') { // Update selection first if (wSelEnd==Text.GetLength()) { if (dwSelStart==wSelEnd) dwSelStart++; wSelEnd++; } Text.Append(L'*'); } } pLocateDlg->m_NameDlg.m_Name.SetText(Text); pLocateDlg->m_NameDlg.m_Name.SetEditSel(dwSelStart,wSelEnd); pLocateDlg->OnFieldChange(CLocateDlg::isNameChanged); return; } // Send/Post Message BOOL bFreeWParam=FALSE,bFreeLParam=FALSE; HWND hWnd=NULL; WPARAM wParam=NULL,lParam=NULL; if (m_pSendMessage->szWindow[0]=='0') { if (m_pSendMessage->szWindow[1]=='x' || m_pSendMessage->szWindow[1]=='X') { // Hex value LPWSTR szTemp; hWnd=(HWND)wcstoul(m_pSendMessage->szWindow+2,&szTemp,16); } } else if (strcasecmp(m_pSendMessage->szWindow,L"HWND_BROADCAST")==0) hWnd=HWND_BROADCAST; else if (GetLocateDlg()!=NULL && strcasecmp(m_pSendMessage->szWindow,L"LOCATEDLG")==0) hWnd=*GetLocateDlg(); else if (strcasecmp(m_pSendMessage->szWindow,L"LOCATEST")==0) hWnd=*GetTrayIconWnd(); else if (wcsncmp(m_pSendMessage->szWindow,L"Find",4)==0) { int nIndex=(int)FirstCharIndex(m_pSendMessage->szWindow,L'('); if (nIndex!=-1) { LPCWSTR pText=m_pSendMessage->szWindow+nIndex+1; LPWSTR pClassAndWindow[3]={NULL,NULL,NULL}; nIndex=(int)FirstCharIndex(pText,L','); if (nIndex==-1) { nIndex=(int)FirstCharIndex(pText,L')'); if (nIndex==-1) pClassAndWindow[0]=alloccopy(pText); else pClassAndWindow[0]=alloccopy(pText,nIndex); } else { pClassAndWindow[0]=alloccopy(pText,nIndex); pText+=nIndex+1; nIndex=(int)FirstCharIndex(pText,L')'); pClassAndWindow[1]=alloccopy(pText,nIndex); } EnumWindows(WindowEnumProc,LPARAM(pClassAndWindow)); // Third cell is handle to window hWnd=(HWND)pClassAndWindow[2]; delete[] pClassAndWindow[0]; if (pClassAndWindow[1]) delete[] pClassAndWindow[1]; } } // Parse wParam if (m_pSendMessage->szWParam!=NULL) { if (m_pSendMessage->szWParam[0]=='0') { if (m_pSendMessage->szWParam[1]=='x' || m_pSendMessage->szWParam[1]=='X') { // Hex value LPWSTR szTemp; wParam=(WPARAM)wcstoul(m_pSendMessage->szWParam+2,&szTemp,16); } else if (m_pSendMessage->szWParam[1]!='\0') { DWORD dwLength; wParam=(WPARAM)dataparser(m_pSendMessage->szWParam,istrlen(m_pSendMessage->szWParam),gmalloc,&dwLength); *((BYTE*)wParam+dwLength)=0; bFreeWParam=TRUE; } } else if ((wParam=_wtoi(m_pSendMessage->szWParam))==0) { DWORD dwLength; wParam=(WPARAM)dataparser(m_pSendMessage->szWParam,istrlen(m_pSendMessage->szWParam),gmalloc,&dwLength); *((BYTE*)wParam+dwLength)=0; bFreeWParam=TRUE; } } // Parse lParam if (m_pSendMessage->szLParam!=NULL) { if (m_pSendMessage->szLParam[0]=='0') { if (m_pSendMessage->szLParam[1]=='x' || m_pSendMessage->szLParam[1]=='X') { // Hex value LPWSTR szTemp; lParam=(WPARAM)wcstoul(m_pSendMessage->szLParam+2,&szTemp,16); } else if (m_pSendMessage->szLParam[1]!='\0') { DWORD dwLength; lParam=(WPARAM)dataparser(m_pSendMessage->szLParam,istrlen(m_pSendMessage->szLParam),gmalloc,&dwLength); *((BYTE*)lParam+dwLength)=0; bFreeLParam=TRUE; } } else if ((lParam=_wtoi(m_pSendMessage->szLParam))==0) { DWORD dwLength; lParam=(WPARAM)dataparser(m_pSendMessage->szLParam,istrlen(m_pSendMessage->szLParam),gmalloc,&dwLength); *((BYTE*)lParam+dwLength)=0; bFreeLParam=TRUE; } } if (hWnd!=NULL) { if (m_nMisc==PostMessage) ::PostMessage(hWnd,m_pSendMessage->nMessage,wParam,lParam); else ::SendMessage(hWnd,m_pSendMessage->nMessage,wParam,lParam); } if (bFreeWParam) GlobalFree((HANDLE)wParam); if (bFreeLParam) GlobalFree((HANDLE)lParam); }
void CSubAction::DoPresets() { CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg!=NULL && m_szPreset!=NULL) pLocateDlg->LoadPreset(m_szPreset); }
void CSubAction::DoChangeValue() { CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg==NULL || m_szValue==NULL) return; // Get handle to control CWnd Control(pLocateDlg->GetDlgItem(LOWORD(m_nControl))); HWND hInDialog=*pLocateDlg; if (Control.GetHandle()==NULL) Control.SetHandle(pLocateDlg->m_NameDlg.GetDlgItem(LOWORD(m_nControl))); if (Control.GetHandle()==NULL) Control.SetHandle(pLocateDlg->m_SizeDateDlg.GetDlgItem(LOWORD(m_nControl))); if (Control.GetHandle()==NULL) Control.SetHandle(pLocateDlg->m_AdvancedDlg.GetDlgItem(LOWORD(m_nControl))); ASSERT(Control.GetHandle()!=NULL); if (!Control.IsWindowEnabled()) return; char szClass[100]; GetClassName(Control,szClass,100); if (_stricmp(szClass,"EDIT")==0) { Control.SetWindowText(m_szValue); ::SendMessage(Control.GetParent(),WM_COMMAND,MAKEWPARAM(m_nControl,EN_CHANGE),LPARAM((HWND)Control)); } else if (_stricmp(szClass,"COMBOBOX")==0) { if ((Control.GetStyle()&CBS_DROPDOWNLIST)!=CBS_DROPDOWNLIST) { Control.SetWindowText(m_szValue); ::SendMessage(Control.GetParent(),WM_COMMAND,MAKEWPARAM(m_nControl,CBN_EDITCHANGE),LPARAM((HWND)Control)); } else { Control.SendMessage(CB_SETCURSEL,_wtoi(m_szValue)); ::SendMessage(Control.GetParent(),WM_COMMAND,MAKEWPARAM(m_nControl,CBN_SELCHANGE),LPARAM((HWND)Control)); } } else if (_stricmp(szClass,"BUTTON")==0) { if (Control.GetStyle()&BS_CHECKBOX) // This also takes radiobuttons { Control.SendMessage(BM_SETCHECK,_wtoi(m_szValue)); ::SendMessage(Control.GetParent(),WM_COMMAND,MAKEWPARAM(m_nControl,BN_CLICKED),LPARAM((HWND)Control)); } } else if (_stricmp(szClass,"ComboBoxEx32")==0) { CComboBoxEx cb(Control); cb.SetCurSel(-1); cb.SetItemText(-1,m_szValue); } else if (_stricmp(szClass,"SysDateTimePick32")==0) { SYSTEMTIME st; GetLocalTime(&st); st.wHour=0; st.wMinute=0; st.wSecond=0; st.wMilliseconds=0; if (wcslen(m_szValue)>=8) { WCHAR szTemp[5]; MemCopyW(szTemp,m_szValue,4); szTemp[4]='\0'; st.wYear=(WORD)_wtol(szTemp); MemCopyW(szTemp,m_szValue+4,2); szTemp[2]='\0'; st.wMonth=(WORD)_wtol(szTemp); MemCopyW(szTemp,m_szValue+6,2); szTemp[2]='\0'; st.wDay=(WORD)_wtol(szTemp); } else { int nIndex=CTime::GetIndex(st.wDay,st.wMonth,st.wYear); if (m_szValue[0]='-') nIndex-=(WORD)_wtol(m_szValue+1); else nIndex+=(WORD)_wtol(m_szValue); CTime::GetDayFromIndex(nIndex,st.wDay,st.wMonth,st.wYear); } Control.SendMessage(DTM_SETSYSTEMTIME,GDT_VALID,LPARAM(&st)); } }
void CSubAction::DoHelp() { CTargetWnd* pWnd=GetLocateDlg(); if (pWnd==NULL) pWnd=GetTrayIconWnd(); switch(m_nHelp) { case HelpShowHelp: { HELPINFO h; h.cbSize=sizeof(HELPINFO); h.iContextType=HELPINFO_WINDOW; h.hItemHandle=GetFocus(); if (pWnd==GetLocateDlg()) { // If comboboxes are selected, the edit in size of combo // may have focus. HWND hParent=GetParent((HWND)h.hItemHandle); while (hParent!=NULL && hParent!=*pWnd && hParent!=((CLocateDlg*)pWnd)->m_NameDlg && hParent!=((CLocateDlg*)pWnd)->m_SizeDateDlg && hParent!=((CLocateDlg*)pWnd)->m_AdvancedDlg) { h.hItemHandle=hParent; hParent=GetParent(hParent); } } h.iCtrlId=GetDlgCtrlID((HWND)h.hItemHandle); h.dwContextId=0; GetCursorPos(&h.MousePos); pWnd->OnHelp(&h); break; } case HelpCloseHelp: pWnd->HtmlHelp(HH_CLOSE_ALL,0); break; case HelpShowTopics: pWnd->HtmlHelp(HH_DISPLAY_TOPIC,0); break; case HelpIndex: pWnd->HtmlHelp(HH_DISPLAY_INDEX,0); break; case HelpTOC: pWnd->HtmlHelp(HH_DISPLAY_TOC,0); break; case HelpSearch: { HH_FTS_QUERY q; ZeroMemory(&q,sizeof(HH_FTS_QUERY)); q.cbStruct=sizeof(HH_FTS_QUERY); pWnd->HtmlHelp(HH_DISPLAY_SEARCH,(DWORD_PTR)&q); break; } }; }
void CSubAction::DoShowHideDialog() { CLocateDlg* pLocateDlg=GetLocateDlg(); switch(m_nDialogCommand) { case ShowDialog: GetTrayIconWnd()->OnLocate(); break; case MinimizeDialog: if (pLocateDlg!=NULL) pLocateDlg->ShowWindow(CWnd::swMinimize); break; case CloseDialog: if (pLocateDlg!=NULL) pLocateDlg->PostMessage(WM_CLOSE); break; case ShowOrHideDialog: if (pLocateDlg!=NULL) { WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); pLocateDlg->GetWindowPlacement(&wp); if (wp.showCmd!=SW_SHOWMINIMIZED &&wp.showCmd!=SW_HIDE) pLocateDlg->ShowWindow(CWnd::swMinimize); else GetTrayIconWnd()->OnLocate(); } break; case OpenOrCloseDialog: if (pLocateDlg!=NULL) { WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); pLocateDlg->GetWindowPlacement(&wp); if (wp.showCmd!=SW_SHOWMINIMIZED && wp.showCmd!=SW_HIDE) pLocateDlg->PostMessage(WM_CLOSE); else GetTrayIconWnd()->OnLocate(); } else GetTrayIconWnd()->OnLocate(); break; case RestoreDialog: if (pLocateDlg!=NULL) pLocateDlg->ShowWindow(CWnd::swRestore); break; case MaximizeDialog: if (pLocateDlg!=NULL) pLocateDlg->ShowWindow(CWnd::swMaximize); break; case MaximizeOrRestoreDialog: if (pLocateDlg!=NULL) { WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); pLocateDlg->GetWindowPlacement(&wp); if (wp.showCmd!=SW_SHOWMAXIMIZED) pLocateDlg->ShowWindow(CWnd::swMaximize); else pLocateDlg->ShowWindow(CWnd::swRestore); } break; case ShowOpenOrHideDialog: if (pLocateDlg==NULL) GetTrayIconWnd()->OnLocate(); else if (pLocateDlg!=NULL) { WINDOWPLACEMENT wp; wp.length=sizeof(WINDOWPLACEMENT); pLocateDlg->GetWindowPlacement(&wp); if (wp.showCmd!=SW_SHOWMINIMIZED &&wp.showCmd!=SW_HIDE) pLocateDlg->ShowWindow(CWnd::swMinimize); else GetTrayIconWnd()->OnLocate(); } break; case ShowDialogAndGetDirFromExplorer: { LPWSTR pPath=GetPathFromExplorer(); GetTrayIconWnd()->OnLocate(); if (pPath!=NULL) { CLocateDlg* pLocateDlg=GetLocateDlg(); if (pLocateDlg!=NULL) pLocateDlg->SetPath(pPath); delete[] pPath; } break; } break; case StopLocatingOrCloseWindow: if (pLocateDlg!=NULL) { if (pLocateDlg->IsLocating()) pLocateDlg->OnStop(); else pLocateDlg->PostMessage(WM_CLOSE); } break; } }
BOOL CCheckFileNotificationsThread::CreateHandlesOld() { ASSERT(m_pEventHandles==NULL); ASSERT(m_lState==sInitializing); FnDebugMessage("FN: creating handles (old method)"); CLocateDlg* pLocateDlg=GetLocateDlg(); ASSERT(pLocateDlg!=NULL); // Loads roods from databases so that we know what to listen CArrayFAP<LPWSTR> aRoots; const CArray<PDATABASE>& aAllDatabases=GetLocateApp()->GetDatabases(); CArray<PDATABASE> aUsedDatabases; for (int i=0;i<aAllDatabases.GetSize();i++) { if (pLocateDlg->IsDatabaseUsedInSearch(aAllDatabases[i]->GetID())) aUsedDatabases.Add(aAllDatabases[i]); } if (aUsedDatabases.GetSize()==0) return FALSE; CDatabaseInfo::GetRootsFromDatabases(aRoots,aUsedDatabases); if (aRoots.GetSize()==0) return FALSE; // Create arrays for event handles and data structures // // The first handle in m_pEventHandles is stop event, the rest are change notification // objects returned by FindFirstChangeNotification function. // The first pointer in m_pRoots is NULL, the rest are pointers // to root directory. The lists are terminated with NULL // Allocating arraysn, note that the size of the list is not // necessary aRoots.GetSize()+2 if FindFirstChangeNotification returns error m_pEventHandles=new HANDLE[aRoots.GetSize()+1]; ASSERT(m_pEventHandles!=NULL); m_pRoots=new LPWSTR[aRoots.GetSize()+1]; ASSERT(m_pRoots!=NULL); // First handle in event handles array is stop handle and // first pointer to root directory is NULL, // so that each element in m_pEventHandles (with index >0) // corresponds to element in m_pRoots array with the same index m_pEventHandles[0]=m_hStopEvent; m_pRoots[0]=NULL; // Creating handles for directories in aRoots array using FindFirstChangeNotification m_nHandles=1; for (int i=0;i<aRoots.GetSize();i++) { if (m_lFlags&fwStopWhenPossible) { // Notify to Stop() that we are going to stop what // we are doing SetEvent(m_hStopEvent); InterlockedExchange(&m_lState,sStopping); break; } CStringW sRoot=aRoots.GetAt(i); // If root of the type "X:", change it to "X:\" if (sRoot[1]==':' && sRoot[2]=='\0') sRoot << L'\\'; #ifdef _DEBUG_LOGGING // If logging is on, do not use change notifications for root containing log file LPCSTR pLogFile=GetDebugLoggingFile(); if (pLogFile!=NULL) { // No debug logging for drive containing hfcdebug.log char* szPath=alloccopyWtoA(sRoot); MakeLower(szPath); BOOL bSame=strncmp(szPath,pLogFile,sRoot.GetLength())==0; delete[] szPath; if (bSame) continue; } #endif // Create find change notification objects if (IsUnicodeSystem()) m_pEventHandles[m_nHandles]=FindFirstChangeNotificationW(sRoot,TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE); else m_pEventHandles[m_nHandles]=FindFirstChangeNotification(W2A(sRoot),TRUE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE); if (m_pEventHandles[m_nHandles]==INVALID_HANDLE_VALUE) { // FindFirstChangeNotification returned error, skipping this directory continue; } DebugOpenEvent(m_pEventHandles[m_nHandles]); sRoot.MakeLower(); sRoot.FreeExtra(); m_pRoots[m_nHandles]=sRoot.GiveBuffer(); m_nHandles++; } FnDebugMessage("FN handles created"); return TRUE; }
BOOL CCheckFileNotificationsThread::Stop() { // Stopping background notifier FnDebugMessage("FN: stopping"); // First check whether thread is already stopped if (m_hThread==NULL) { FnDebugMessage("FN: already stopped"); return FALSE; } // Creating a copy of thread handle and using HANDLE hThread; DuplicateHandle(GetCurrentProcess(),m_hThread,GetCurrentProcess(), &hThread,0,FALSE,DUPLICATE_SAME_ACCESS); DebugOpenThread(hThread); ASSERT(m_lState==sInitializing || m_lState==sWaiting || m_lState==sProcessing || m_lState==sStopping); // First, try some friendly ways to terminate thread switch (m_lState) { case sInitializing: // Still initializing, say that processing can be stopped FnDebugMessage("FN: thread still initializing"); InterlockedExchange(&m_lFlags,m_lFlags|fwStopWhenPossible); // First wait that initialization is ended if (WaitForSingleObject(m_hStopEvent,500)!=WAIT_OBJECT_0) break; // Wait that ending processes are handled WaitForSingleObject(m_hThread,1000); break; case sWaiting: FnDebugMessage("FN: thread waiting"); // Waiting events, so give it SetEvent(m_hStopEvent); // Wait that ending processes are handled WaitForSingleObject(m_hThread,1000); break; case sProcessing: FnDebugMessage("FN: thread is processing"); InterlockedExchange(&m_lFlags,m_lFlags|fwStopWhenPossible); // Wait that ending processes are handled if (GetCurrentThreadId()==GetTrayIconWnd()->GetLocateDlgThread()->GetThreadId()) { // This Stop() is called from CLocateDlg, it is possible // that RunninProcNew sens messages to this window. // Taking care of that for (int i=0;i<40;i++) { PostQuitMessage(0); GetTrayIconWnd()->GetLocateDlgThread()->ModalLoop(); if (WaitForSingleObject(hThread,50)!=WAIT_TIMEOUT) break; } } else WaitForSingleObject(hThread,2000); break; }; if (GetLocateDlg()->m_pFileNotificationsThread!=NULL) { // So that didn't go very well, use harder ways InterlockedExchange(&m_lState,sTerminated); DWORD status=0; BOOL bRet=::GetExitCodeThread(hThread,&status); BOOL bTerminated=FALSE; if (bRet && status==STILL_ACTIVE) { if (::TerminateThread(hThread,1,TRUE)) bTerminated=TRUE; } if (bTerminated) delete this; } // Closing dublicated handle CloseHandle(hThread); DebugCloseThread(hThread); return TRUE; }
BOOL CCheckFileNotificationsThread::CreateHandlesNew() { ASSERT(m_pEventHandles==NULL); ASSERT(m_lState==sInitializing); FnDebugMessage("FN: creating handles"); CLocateDlg* pLocateDlg=GetLocateDlg(); ASSERT(pLocateDlg!=NULL); // Loads roods from databases so that we know what to listen CArrayFAP<LPWSTR> aRoots; const CArray<PDATABASE>& aAllDatabases=GetLocateApp()->GetDatabases(); CArray<PDATABASE> aUsedDatabases; for (int i=0;i<aAllDatabases.GetSize();i++) { if (pLocateDlg->IsDatabaseUsedInSearch(aAllDatabases[i]->GetID())) aUsedDatabases.Add(aAllDatabases[i]); } if (aUsedDatabases.GetSize()==0) return FALSE; CDatabaseInfo::GetRootsFromDatabases(aRoots,aUsedDatabases); if (aRoots.GetSize()==0) return FALSE; // Create arrays for event handles and data structures // // The first handle in m_pEventHandles is stop event, the rest of // handles are events which are used in overlay structure (m_pDirDatas[i].ol) // The first pointer in m_pDirDatas is NULL, the rest are pointers // to DIRCHANGEDATA structures. // The lists are terminated with NULL // Allocating arraysn, note that the size of the list is not // necessary aRoots.GetSize()+2 if CreateFileW or m_pReadDirectoryChangesW // return error m_pEventHandles=new HANDLE[aRoots.GetSize()+1]; ASSERT(m_pEventHandles!=NULL); m_pDirDatas=new DIRCHANGEDATA*[aRoots.GetSize()+1]; ASSERT(m_pDirDatas!=NULL); // First event in events array is stop event and first pointer to // DIRCHANGEDATA structure is NULL, so that each element in m_pEventHandles (with index >0) // corresponds to element in m_pChangeDatas with the same index m_pEventHandles[0]=m_hStopEvent; m_pDirDatas[0]=NULL; // Creating handles and DIRCHANGEDATA structures for directories in aRoots array m_nHandles=1; // Number of handles currently in arrays, first element is stop event / NULL DIRCHANGEDATA* pDirData=NULL; for (int i=0;i<aRoots.GetSize();i++) { if (m_lFlags&fwStopWhenPossible) { // Notify to Stop() that we are going to stop what // we are doing InterlockedExchange(&m_lState,sStopping); SetEvent(m_hStopEvent); break; } CStringW sRoot=aRoots.GetAt(i); // If root of the type "X:", change it to "X:\" if (sRoot[1]==':' && sRoot[2]=='\0') sRoot << L'\\'; /* #ifdef _DEBUG_LOGGING // If logging is on, do not use change notifications for root containing log file LPCSTR pLogFile=GetDebugLoggingFile(); if (pLogFile!=NULL) { // No debug logging for drive containing hfcdebug.log char* szPath=alloccopyWtoA(sRoot); MakeLower(szPath); BOOL bSame=strncmp(szPath,pLogFile,sRoot.GetLength())==0; delete[] szPath; if (bSame) continue; } #endif */ // Allocating new DIRCHANGEDATA struct if (pDirData==NULL) { pDirData=new DIRCHANGEDATA; // Create event for overlay structure pDirData->ol.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL); DebugOpenEvent(pDirData->ol.hEvent); // Allocate buffer pDirData->pBuffer=new BYTE[CHANGE_BUFFER_LEN]; } // Create handle to directory if (IsUnicodeSystem()) pDirData->hDirHandle=CreateFileW(sRoot,GENERIC_READ /*FILE_LIST_DIRECTORY*/,FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,NULL); else pDirData->hDirHandle=CreateFile(W2A(sRoot),GENERIC_READ /*FILE_LIST_DIRECTORY*/,FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE, NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,NULL); // If pDirData handle is invalid, skip this root if (pDirData->hDirHandle==INVALID_HANDLE_VALUE) continue; DebugOpenHandle(dhtFile,pDirData->hDirHandle,sRoot); // Test this again if (m_lFlags&fwStopWhenPossible) { // Notify to Stop() that we are going to stop what // we are doing InterlockedExchange(&m_lState,sStopping); SetEvent(m_hStopEvent); break; } // Start to read directory changes, asynchronous mode BOOL bRet=m_pReadDirectoryChangesW(pDirData->hDirHandle,pDirData->pBuffer,CHANGE_BUFFER_LEN,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_CREATION|FILE_NOTIFY_CHANGE_SECURITY, NULL,&pDirData->ol,NULL); if (!bRet) { // Cannot read directory changes (maybe UNC path), closing directory handle and skipping // this directory. Allocated pDirData can be left untouched for the next try CloseHandle(pDirData->hDirHandle); DebugCloseHandle(dhtFile,pDirData->hDirHandle,sRoot); continue; } // And yet again if (m_lFlags&fwStopWhenPossible) { // Notify to Stop() that we are going to stop what // we are doing SetEvent(m_hStopEvent); InterlockedExchange(&m_lState,sStopping); break; } // Copy root path to pDirData structure if (sRoot.LastChar()!=L'\\') sRoot << L'\\'; sRoot.MakeLower(); sRoot.FreeExtra(); pDirData->dwRootLength=sRoot.GetLength(); pDirData->pRoot=sRoot.GiveBuffer(); // Handle in m_pEventHandles was the event used in overlay structure, set it m_pEventHandles[m_nHandles]=pDirData->ol.hEvent; // Add pointer to m_pDirDatas structure ASSERT(m_nHandles<UINT(aRoots.GetSize()+2)); m_pDirDatas[m_nHandles]=pDirData; m_nHandles++; // New DIRCHANGEDATA structure should be allocated pDirData=NULL; } // Free extra DIRCHANGEDATA structure if (pDirData!=NULL) delete pDirData; FnDebugMessage("FN handles created"); return TRUE; }
BOOL CCheckFileNotificationsThread::RunningProcOld() { // Delete this when this functions ends CAutoPtr<CCheckFileNotificationsThread> thisPtr=this; if (!CreateHandlesOld()) return FALSE; for (;;) { FnDebugMessage("FN goes to sleep"); InterlockedExchange(&m_lState,sWaiting); DWORD nRet=WaitForMultipleObjects(m_nHandles,m_pEventHandles,FALSE,INFINITE); InterlockedExchange(&m_lState,sProcessing); FnDebugMessage1("FN waked nRet=%X",nRet); if (nRet==WAIT_OBJECT_0) // The first is end event { // First event signalled, this event is for stopping // So do nothing here and exit FnDebugMessage("FN stopping event signalled, exiting"); break; } else if (nRet>WAIT_OBJECT_0 && nRet<WAIT_OBJECT_0+m_nHandles) { //BkgDebugFormatMessage4("Something is changed in %S",m_pRoots[nRet-WAIT_OBJECT_0],0,0,0); CLocateDlg* pLocateDlg=GetLocateDlg(); // Locate dialog is also closed, stopping this process if (pLocateDlg==NULL) break; if (!pLocateDlg->IsLocating()) // if locating in process, do nothing { while (pLocateDlg->m_pBackgroundUpdater!=NULL && !pLocateDlg->m_pBackgroundUpdater->m_lIsWaiting) Sleep(200); // Stop if required if (m_lFlags&fwStopWhenPossible) break; // Updating changed items by checking all items UpdateItemsInRoot(m_pRoots[nRet-WAIT_OBJECT_0],pLocateDlg); } // Check this again if (m_lFlags&fwStopWhenPossible) break; #ifdef _DEBUG_LOGGING BOOL bRet=FindNextChangeNotification(m_pEventHandles[nRet-WAIT_OBJECT_0]); FnDebugMessage3("CCheckFileNotificationsThread::RunningProcOld(): FindNextChangeNotification returns %X, nret=%X, nRet-WAIT_OBJECT_0=%X",bRet,nRet,nRet-WAIT_OBJECT_0); #else FindNextChangeNotification(m_pEventHandles[nRet-WAIT_OBJECT_0]); #endif // Finally, before going to sleep, check that shell we continue if (m_lFlags&fwStopWhenPossible) break; } else { FnDebugMessage3("FN nRet not handled, nRet=0x%X, handles=%d, GetLastError()=0x%X",nRet,m_nHandles,GetLastError()); } } InterlockedExchange(&m_lState,sStopping); //BkgDebugMessage("CCheckFileNotificationsThread::RunningProcOld() END"); return FALSE; }
BOOL CCheckFileNotificationsThread::RunningProcNew() { FnDebugMessage("FN: RunningProcNew started"); // Delete this when this functions ends CAutoPtr<CCheckFileNotificationsThread> thisPtr=this; // Creating handles if (!CreateHandlesNew()) return FALSE; DWORD dwOut; for (;;) { FnDebugMessage("FN goes to sleep"); InterlockedExchange(&m_lState,sWaiting); DWORD nRet=WaitForMultipleObjects(m_nHandles,m_pEventHandles,FALSE,INFINITE); InterlockedExchange(&m_lState,sProcessing); FnDebugMessage1("FN waked nRet=%X",nRet); if (nRet==WAIT_OBJECT_0) { // First event signalled, this event is for stopping // So do nothing here and exit FnDebugMessage("FN stopping event signalled, exiting"); break; } else if (nRet>WAIT_OBJECT_0 && nRet<WAIT_OBJECT_0+m_nHandles) { CLocateDlg* pLocateDlg=GetLocateDlg(); // Locate dialog is also closed, stopping this process if (pLocateDlg==NULL) break; DIRCHANGEDATA* pChangeData=m_pDirDatas[nRet-WAIT_OBJECT_0]; // Asking changes if (!pLocateDlg->IsLocating()) // if locating in process, do nothing { if (GetOverlappedResult(pChangeData->hDirHandle,&pChangeData->ol,&dwOut,FALSE)) { // If GetOverlappedResults took so long that Stop() has given during this time // stop right now if (m_lFlags&fwStopWhenPossible) break; while (pLocateDlg->m_pBackgroundUpdater!=NULL && !pLocateDlg->m_pBackgroundUpdater->m_lIsWaiting) Sleep(200); if (dwOut==0) UpdateItemsInRoot(pChangeData->pRoot,pLocateDlg); else { FILE_NOTIFY_INFORMATION* pStruct=(FILE_NOTIFY_INFORMATION*)pChangeData->pBuffer; while (1) { // Check stop state again if (m_lFlags&fwStopWhenPossible) break; DWORD dwLength=pStruct->FileNameLength/2; // Skip log files BOOL bSkipThisFile=FALSE; int nFilePart; for (nFilePart=dwLength-1;nFilePart>=0 && pStruct->FileName[nFilePart]!=L'\\';nFilePart--); nFilePart++; // Skipping ntuser.dat.log file if (dwLength-nFilePart==14) { if (_wcsnicmp(pStruct->FileName+nFilePart,L"ntuser.dat.log",14)==0) bSkipThisFile=TRUE; } #ifdef _DEBUG // Skipping HFCDebug.log if (dwLength-nFilePart==12) { if (_wcsnicmp(pStruct->FileName+nFilePart,L"HFCDebug.log",12)==0) bSkipThisFile=TRUE; } #endif if (!bSkipThisFile) { m_pFile=new WCHAR[pChangeData->dwRootLength+dwLength+2]; MemCopyW(m_pFile,pChangeData->pRoot,pChangeData->dwRootLength); MemCopyW(m_pFile+pChangeData->dwRootLength,pStruct->FileName,dwLength); dwLength+=pChangeData->dwRootLength; m_pFile[dwLength]='\0'; MakeLower(m_pFile); //DebugFormatMessage("BN: file=%S action=%d",m_pFile,pStruct->Action); switch(pStruct->Action) { case FILE_ACTION_ADDED: case FILE_ACTION_RENAMED_NEW_NAME: FileCreated(m_pFile,dwLength,pLocateDlg); break; case FILE_ACTION_REMOVED: case FILE_ACTION_RENAMED_OLD_NAME: FileDeleted(m_pFile,dwLength,pLocateDlg); break; case FILE_ACTION_MODIFIED: FileModified(m_pFile,dwLength,pLocateDlg); break; } delete[] m_pFile; m_pFile=NULL; } if (pStruct->NextEntryOffset==0) break; *((char**)&pStruct)+=pStruct->NextEntryOffset; } } } } // Check this again if (m_lFlags&fwStopWhenPossible) break; // Coing to listen changes FnDebugMessage("FN: going to listen changes"); BOOL bRet=m_pReadDirectoryChangesW(pChangeData->hDirHandle,pChangeData->pBuffer,CHANGE_BUFFER_LEN,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_CREATION|FILE_NOTIFY_CHANGE_SECURITY, &dwOut,&pChangeData->ol,NULL); FnDebugMessage("FN: m_pReadDirectoryChangesW returned"); if (!bRet) { // ReadDirectoryChangesW failed, reset event manually FnDebugMessage("FN: ReadDirectoryChangesW failed"); ResetEvent(pChangeData->ol.hEvent); } // Finally, before going to sleep, check that shell we continue if (m_lFlags&fwStopWhenPossible) break; } } InterlockedExchange(&m_lState,sStopping); FnDebugMessage("FN RunningProcNew ends"); return FALSE; }