⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directorychanges.cpp

📁 局域网来访者IP监视以及文件修改监视: 1.监听常用的局域网访问工具
💻 CPP
📖 第 1 页 / 共 5 页
字号:
************************************/
{
	ASSERT( pChangeHandler );

	CSingleLock lock(&m_csDirWatchInfo, TRUE);
	
	ASSERT( lock.IsLocked() );
	
	int nUnwatched = 0;
	int nIdx = -1;
	CDirWatchInfo * pDirInfo;
	//
	//	go through and unwatch any directory that is 
	//	that is using this pChangeHandler as it's file change notification handler.
	//
	while( (pDirInfo = GetDirWatchInfo( pChangeHandler, nIdx )) != NULL )
	{
		VERIFY( pDirInfo->UnwatchDirectory( m_hCompPort ) );

		nUnwatched++;
		m_DirectoriesToWatch.SetAt(nIdx, NULL);
		pDirInfo->DeleteSelf(this);	
	}
	return (BOOL)(nUnwatched != 0);
}

BOOL CDirectoryChangeWatcher::UnwatchDirectoryBecauseOfError(CDirWatchInfo * pWatchInfo)
//
//	Called in the worker thread in the case that ReadDirectoryChangesW() fails
//	during normal operation. One way to force this to happen is to watch a folder
//	using a UNC path and changing that computer's IP address.
//	
{
	ASSERT( pWatchInfo );
	ASSERT( m_dwThreadID == GetCurrentThreadId() );//this should be called from the worker thread only.
	BOOL bRetVal = FALSE;
	if( pWatchInfo )
	{
		CSingleLock lock(&m_csDirWatchInfo, TRUE);
		
		ASSERT( lock.IsLocked() );
		int nIdx = -1;
		if( GetDirWatchInfo(pWatchInfo, nIdx) == pWatchInfo )
		{
			// we are actually watching this....

			//
			//	Remove this CDirWatchInfo object from the list of watched directories.
			//
			m_DirectoriesToWatch.SetAt(nIdx, NULL);//mark the space as free for the next watch...

			//
			//	and delete it...
			//

			pWatchInfo->DeleteSelf(this);
		
		}

	}
	return bRetVal;
}

int	CDirectoryChangeWatcher::AddToWatchInfo(CDirectoryChangeWatcher::CDirWatchInfo * pWatchInfo)
//
//	
//	To add the CDirWatchInfo  * to an array.
//	The array is used to keep track of which directories 
//	are being watched.
//
//	Add the ptr to the first non-null slot in the array.
{
	CSingleLock lock( &m_csDirWatchInfo, TRUE);
	ASSERT( lock.IsLocked() );
	
	//first try to add it to the first empty slot in m_DirectoriesToWatch
	int max = m_DirectoriesToWatch.GetSize();
	for(int i = 0; i < max; ++i)
	{
		if( m_DirectoriesToWatch[i] == NULL )
		{
			m_DirectoriesToWatch[i] = pWatchInfo;
			break;
		}
	}
	if( i == max )
	{
		// there where no empty slots, add it to the end of the array
		try{
			i = m_DirectoriesToWatch.Add( pWatchInfo );
		}
		catch(CMemoryException * e){
			e->ReportError();
			e->Delete();//??? delete this? I thought CMemoryException objects where pre allocated in mfc? -- sample code in msdn does, so will i
			i = -1;
		}
	}

	return (BOOL)(i != -1);
}

//
//	functions for retrieving the directory watch info based on different parameters
//
CDirectoryChangeWatcher::CDirWatchInfo * CDirectoryChangeWatcher::GetDirWatchInfo(const CString & strDirName, int & ref_nIdx)const
{
	if( strDirName.IsEmpty() )// can't be watching a directory if it's you don't pass in the name of it...
		return FALSE;		  //
	
	CSingleLock lock(const_cast<CCriticalSection*>(&m_csDirWatchInfo), TRUE);

	int max = m_DirectoriesToWatch.GetSize();
	CDirWatchInfo * p = NULL;
	for(int i = 0; i < max; ++i )
	{
		if( (p = m_DirectoriesToWatch[i]) != NULL
		&&	p->m_strDirName.CompareNoCase( strDirName ) == 0 )
		{
			ref_nIdx = i;
			return p;
		}
	}
			
	return NULL;//NOT FOUND
}

CDirectoryChangeWatcher::CDirWatchInfo * CDirectoryChangeWatcher::GetDirWatchInfo(CDirectoryChangeWatcher::CDirWatchInfo * pWatchInfo, int & ref_nIdx)const
{
	ASSERT( pWatchInfo != NULL );

	CSingleLock lock( const_cast<CCriticalSection*>(&m_csDirWatchInfo), TRUE);
	int i(0), max = m_DirectoriesToWatch.GetSize();
	CDirWatchInfo * p;
	for(; i < max; ++i)
	{
		if( (p = m_DirectoriesToWatch[i]) != NULL
		&&	 p == pWatchInfo )
		{
			ref_nIdx = i;
			return p;
		}
	}
	return NULL;//NOT FOUND
}

CDirectoryChangeWatcher::CDirWatchInfo * CDirectoryChangeWatcher::GetDirWatchInfo(CDirectoryChangeHandler * pChangeHandler, int & ref_nIdx)const
{
	ASSERT( pChangeHandler != NULL );
	CSingleLock lock( const_cast<CCriticalSection*>(&m_csDirWatchInfo), TRUE);
	int i(0),max = m_DirectoriesToWatch.GetSize();
	CDirWatchInfo * p;
	for( ; i < max; ++i)
	{
		if( (p = m_DirectoriesToWatch[i]) != NULL
		&&	p->GetRealChangeHandler() == pChangeHandler )
		{
			ref_nIdx = i;
			return p;
		}
	}
	return NULL;//NOT FOUND
}

long CDirectoryChangeWatcher::ReleaseReferenceToWatcher(CDirectoryChangeHandler * pChangeHandler)
{
	ASSERT( pChangeHandler );
	return pChangeHandler->ReleaseReferenceToWatcher(this);
}

CDirectoryChangeWatcher::CDirWatchInfo::CDirWatchInfo(HANDLE hDir, 
													  const CString & strDirectoryName, 
													  CDirectoryChangeHandler * pChangeHandler,
													  DWORD dwChangeFilter, 
													  BOOL bWatchSubDir,
													  bool bAppHasGUI,
													  LPCTSTR szIncludeFilter,
													  LPCTSTR szExcludeFilter,
													  DWORD dwFilterFlags)
 :	m_pChangeHandler( NULL ), 
	m_hDir(hDir),
	m_dwChangeFilter( dwChangeFilter ),
	m_bWatchSubDir( bWatchSubDir ),
	m_strDirName( strDirectoryName ),
	m_dwBufLength(0),
	m_dwReadDirError(ERROR_SUCCESS),
	m_StartStopEvent(FALSE, TRUE), //NOT SIGNALLED, MANUAL RESET
	m_RunningState( RUNNING_STATE_NOT_SET )
{ 
	
	ASSERT( hDir != INVALID_HANDLE_VALUE 
		&& !strDirectoryName.IsEmpty() );
	
	//
	//	This object 'decorates' the pChangeHandler passed in
	//	so that notifications fire in the context a thread other than
	//	CDirectoryChangeWatcher::MonitorDirectoryChanges()
	//
	//	Supports the include and exclude filters
	//
	//
	m_pChangeHandler = new CDelayedDirectoryChangeHandler( pChangeHandler, bAppHasGUI, szIncludeFilter, szExcludeFilter, dwFilterFlags );
	if( m_pChangeHandler ) 
		m_pChangeHandler->SetPartialPathOffset( m_strDirName );//to support FILTERS_CHECK_PARTIAL_PATH..this won't change for the duration of the watch, so set it once... HERE!
	ASSERT( m_pChangeHandler );

	ASSERT( GetChangeHandler() );
	ASSERT( GetRealChangeHandler() );
	if( GetRealChangeHandler() )
		GetRealChangeHandler()->AddRef();
	
	memset(&m_Overlapped, 0, sizeof(m_Overlapped));
	//memset(m_Buffer, 0, sizeof(m_Buffer));
}

CDirectoryChangeWatcher::CDirWatchInfo::~CDirWatchInfo()
{
	if( GetChangeHandler() )
	{//If this call to CDirectoryChangeHandler::Release() causes m_pChangeHandler to delete itself,
		//the dtor for CDirectoryChangeHandler will call CDirectoryChangeWatcher::UnwatchDirectory( CDirectoryChangeHandler * ),
		//which will make try to delete this object again.
		//if m_pChangeHandler is NULL, it won't try to delete this object again...
		CDirectoryChangeHandler * pTmp = SetRealDirectoryChangeHandler( NULL );
		if( pTmp )
			pTmp->Release();
		else{
			ASSERT( FALSE );
		}
	}
	
	CloseDirectoryHandle();

	delete m_pChangeHandler;
	m_pChangeHandler = NULL;
	
}
void CDirectoryChangeWatcher::CDirWatchInfo::DeleteSelf(CDirectoryChangeWatcher * pWatcher)
//
//	There's a reason for this function!
//
//	the dtor is private to enforce that it is used.
//
//
//	pWatcher can be NULL only if CDirecotryChangeHandler::ReferencesWatcher() has NOT been called.
//	ie: in certain sections of WatchDirectory() it's ok to pass this w/ NULL, but no where else.
//
{
	//ASSERT( pWatcher != NULL );


	ASSERT( GetRealChangeHandler() );
	if( pWatcher )
	{
	//
	//
	//	Before this object is deleted, the CDirectoryChangeHandler object
	//	needs to release it's reference count to the CDirectoryChangeWatcher object.
	//	I might forget to do this since I getting rid of CDirWatchInfo objects
	//	in more than one place...hence the reason for this function.
	//
		pWatcher->ReleaseReferenceToWatcher( GetRealChangeHandler() );
	}
	
	delete this;
}

CDelayedDirectoryChangeHandler* CDirectoryChangeWatcher::CDirWatchInfo::GetChangeHandler() const 
{ 
	return m_pChangeHandler; 
}

CDirectoryChangeHandler * CDirectoryChangeWatcher::CDirWatchInfo::GetRealChangeHandler() const
//
//	The 'real' change handler is the CDirectoryChangeHandler object 
//	passed to CDirectoryChangeWatcher::WatchDirectory() -- this is the object
//	that really handles the changes.
//
{	
	ASSERT( m_pChangeHandler ); 
	return m_pChangeHandler->GetRealChangeHandler(); 
}

CDirectoryChangeHandler * CDirectoryChangeWatcher::CDirWatchInfo::SetRealDirectoryChangeHandler(CDirectoryChangeHandler * pChangeHandler)
//
//	Allows you to switch out, at run time, which object really handles the change notifications.
//
{
	CDirectoryChangeHandler * pOld = GetRealChangeHandler();
	m_pChangeHandler->GetRealChangeHandler() = pChangeHandler; 
	return pOld;
}

BOOL CDirectoryChangeWatcher::CDirWatchInfo::CloseDirectoryHandle()
//
//	Closes the directory handle that was opened in CDirectoryChangeWatcher::WatchDirecotry()
//
//
{
	BOOL b = TRUE;
	if( m_hDir != INVALID_HANDLE_VALUE )
	{
		b = CloseHandle(m_hDir);
		m_hDir = INVALID_HANDLE_VALUE;
	}
	return b;
}

DWORD CDirectoryChangeWatcher::CDirWatchInfo::StartMonitor(HANDLE hCompPort)
/*********************************************
  Sets the running state of the object to perform the initial call to ReadDirectoryChangesW()
  , wakes up the thread waiting on GetQueuedCompletionStatus()
  and waits for an event to be set before returning....

  The return value is either ERROR_SUCCESS if ReadDirectoryChangesW is successfull,
  or is the value of GetLastError() for when ReadDirectoryChangesW() failed.
**********************************************/
{
	ASSERT( hCompPort );

	//Guard the properties of this object 
	VERIFY( LockProperties() );
	

		
	m_RunningState = RUNNING_STATE_START_MONITORING;//set the state member to indicate that the object is to START monitoring the specified directory
	PostQueuedCompletionStatus(hCompPort, sizeof(this), (DWORD)this, &m_Overlapped);//make the thread waiting on GetQueuedCompletionStatus() wake up

	VERIFY( UnlockProperties() );//unlock this object so that the thread can get at them...

	//wait for signal that the initial call 
	//to ReadDirectoryChanges has been made
	DWORD dwWait = 0;
	do{
		dwWait = WaitForSingleObject(m_StartStopEvent, 10 * 1000);
		if( dwWait != WAIT_OBJECT_0 )
		{
			//
			//	shouldn't ever see this one....but just in case you do, notify me of the problem wesj@hotmail.com.
			//
			TRACE(_T("WARNING! Possible lockup detected. FILE: %s Line: %d\n"), _T( __FILE__ ), __LINE__);
		}
	} while( dwWait != WAIT_OBJECT_0 );

	ASSERT( dwWait == WAIT_OBJECT_0 );
	m_StartStopEvent.ResetEvent();
	
	return m_dwReadDirError;//This value is set in the worker thread when it first calls ReadDirectoryChangesW().
}

BOOL CDirectoryChangeWatcher::CDirWatchInfo::UnwatchDirectory(HANDLE hCompPort)
/*******************************************

    Sets the running state of the object to stop monitoring a directory,
	Causes the worker thread to wake up and to stop monitoring the dierctory
	
********************************************/
{
	ASSERT( hCompPort );
	//
	// Signal that the worker thread is to stop watching the directory
	//
	if( SignalShutdown(hCompPort) )
	{
		//and wait for the thread to signal that it has shutdown
		return WaitForShutdown();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -