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

📄 delayeddirectorychangehandler.cpp

📁 局域网来访者IP监视以及文件修改监视: 1.监听常用的局域网访问工具
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	if( InterlockedIncrement(&s_nRefCnt) == 1 )
	{
		VERIFY( StartThread() );
	}
	return s_nRefCnt;
}
long CDelayedNotificationThread::Release()
{
	if( InterlockedDecrement(&s_nRefCnt) <= 0 )
	{
		s_nRefCnt = 0;
		VERIFY( StopThread() );
	}
	return s_nRefCnt;
}

///////////////////////////////////////////////////////
//static member data for CDelayedDirectoryChangeHandler
HINSTANCE CDelayedDirectoryChangeHandler::s_hShlwapi_dll = NULL;//for the PathMatchSpec() function
BOOL CDelayedDirectoryChangeHandler::s_bShlwapi_dllExists = TRUE;
long CDelayedDirectoryChangeHandler::s_nRefCnt_hShlwapi = 0L;
FUNC_PatternMatchSpec CDelayedDirectoryChangeHandler::s_fpPatternMatchSpec = wildcmp;//default
///////////////////////////////////////////////////////
//construction destruction
CDelayedDirectoryChangeHandler::CDelayedDirectoryChangeHandler(CDirectoryChangeHandler * pRealHandler, bool bAppHasGUI, LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter, DWORD dwFilterFlags)
: m_pDelayNotifier( NULL )
 ,m_pRealHandler( pRealHandler )
 ,m_szIncludeFilter(NULL)
 ,m_szExcludeFilter(NULL)
 ,m_dwFilterFlags( dwFilterFlags )
 ,m_dwPartialPathOffset( 0UL )
 ,m_hWatchStoppedDispatchedEvent(NULL)
 ,m_nNumIncludeFilterSpecs(0)
 ,m_nNumExcludeFilterSpecs(0)
{


	ASSERT( m_pRealHandler ); 

	InitializePathMatchFunc( szIncludeFilter, szExcludeFilter );

	//
	// See that we're 
	//


	m_hWatchStoppedDispatchedEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);//AUTO-RESET, not initially signalled
	ASSERT( m_hWatchStoppedDispatchedEvent );
	
	if( bAppHasGUI )
	{
		//
		//	The value true was passed to the CDirectoryChangeWatcher constructor.
		//	It's assumed that your app has a gui, that is, it implements
		//	a message pump.  To delay the notification to another thread,
		//	we'll use a hidden notification window.
		//
		m_pDelayNotifier = new CDelayedNotificationWindow();
	}
	else
	{
		// The value 'false' was passed to the CDirectoryChangeWatcher constructor.
		//
		// Your app has no message pump... use a class that implements one for you
		// in a worker thread.
		//
		// Notifications will be executed in this worker thread.
		//
		m_pDelayNotifier = new CDelayedNotificationThread();
	}
}

CDelayedDirectoryChangeHandler::~CDelayedDirectoryChangeHandler()
{
	if( m_pRealHandler )
		delete m_pRealHandler, m_pRealHandler = NULL;
	if( m_pDelayNotifier )
		delete m_pDelayNotifier, m_pDelayNotifier = NULL;

	if( m_hWatchStoppedDispatchedEvent )
		CloseHandle(m_hWatchStoppedDispatchedEvent), m_hWatchStoppedDispatchedEvent = NULL;

	if( m_szIncludeFilter ){
		if( m_nNumIncludeFilterSpecs == 1 )
			free(m_szIncludeFilter);
		else
		{
			TCHAR ** ppTmp = (TCHAR**)m_szIncludeFilter;
			for(int i(0); i < m_nNumIncludeFilterSpecs; ++i)
			{
				free( *ppTmp++ );
			}
			free( m_szIncludeFilter );
		}
		m_szIncludeFilter = NULL;
		m_nNumIncludeFilterSpecs;
	}
	if( m_szExcludeFilter ) {
		if( m_nNumExcludeFilterSpecs == 1 )
			free(m_szExcludeFilter);
		else{
			TCHAR ** ppTmp = (TCHAR**)m_szExcludeFilter;
			for(int i(0); i < m_nNumExcludeFilterSpecs; ++i)
			{
				free( *ppTmp++ );
			}
			free( m_szExcludeFilter );
		}
		m_szExcludeFilter = NULL;
		m_nNumExcludeFilterSpecs = 0;
	}

	UninitializePathMatchFunc();
}

BOOL CDelayedDirectoryChangeHandler::_PathMatchSpec(LPCTSTR szPath, LPCTSTR szPattern)
{
	if( s_fpPatternMatchSpec )
	{
		return s_fpPatternMatchSpec(szPath, szPattern);
	}
	ASSERT( FALSE );
	return TRUE;//everything matches.
}

BOOL CDelayedDirectoryChangeHandler::InitializePathMatchFunc(LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter)
//
//
//	To support the Include and Exclude filters, the PathMatchSpec function is used.
//	PathMatchSpec is only supported on NT4.0 if IE 4.0 is installed.
//
//	for the case where this code is running on NT 4.0 w/out IE 4.0, we use
//	a different function: wildcmp ()
//
//
//	This function attempts to load shlwapi.dll dynamically and find the PathMatchSpec function.
//
//	if the function PathMatchSpec can't be found, the function pointer s_fpPathMatchSpec is set to wildcmp.
//
//
//	Note:  wildcmp doesn't support multiple file specs separated by a semi-colon
//	as PathMatchSpec does.... we'll support it by parsing them 
//	when we want to test the filters, we'll call the pattern matching functions multiple times...
//
{

	//
	//	Copy the include/exclude filters if specified...
	//
	//
	if( IsEmptyString(szIncludeFilter) 
	&&	IsEmptyString(szExcludeFilter) )
	{
		return TRUE;//both the include && exclude filters aren't specified
					//no need to initialize the pattern matching function....
					//if filters are never used, then
					//one less dll is loaded.
	}

#ifdef _TESTING_WILDCMP_ONLY_
	s_hShlwapi_dll = NULL;
	s_bShlwapi_dllExists = FALSE;
	return InitializePatterns(szIncludeFilter, szExcludeFilter);
#endif


	if( s_hShlwapi_dll != NULL )
	{
		ASSERT( s_fpPatternMatchSpec != NULL );
		InterlockedIncrement(&s_nRefCnt_hShlwapi);

		return InitializePatterns(szIncludeFilter, szExcludeFilter);
	}
	else{
		if( s_bShlwapi_dllExists == TRUE )//either the dll exists, or we haven't tried loading it yet...
		{
			//The pattern match function hasn't been initialized yet....
			//
		
			s_hShlwapi_dll = ::LoadLibrary(_T("Shlwapi.dll"));
			if( s_hShlwapi_dll == NULL )
			{
				s_bShlwapi_dllExists = FALSE;//don't try loading this dll again.
				s_fpPatternMatchSpec = wildcmp;//even though it's set buy default, and this code will only get here once, set it just for fun.

				return InitializePatterns(szIncludeFilter, szExcludeFilter);
				
			}
			else
			{
				//Shlwapi.dll was found....check it for PathMatchSpec()
#ifdef UNICODE 
				s_fpPatternMatchSpec = (FUNC_PatternMatchSpec)::GetProcAddress(s_hShlwapi_dll, "PathMatchSpecW");
#else
				s_fpPatternMatchSpec = (FUNC_PatternMatchSpec)::GetProcAddress(s_hShlwapi_dll, "PathMatchSpecA");
#endif
	
				if( s_fpPatternMatchSpec != NULL )
				{
					//UsesRealPathMatchSpec() will now return true.
					//we're on NT w/ IE 4.0 or greater...(or Win2k/XP)
					InterlockedIncrement(&s_nRefCnt_hShlwapi);
					return InitializePatterns(szIncludeFilter, szExcludeFilter);
				}
				else
				{
					//we found shlwapi.dll, but it didn't have PathMatchSpec()
					::FreeLibrary( s_hShlwapi_dll );
					s_hShlwapi_dll = NULL;
					s_bShlwapi_dllExists = FALSE;

					//instead of using PathMatchSpec()
					//we'll use wildcmp()
					s_fpPatternMatchSpec = wildcmp;
					//UsesRealPathMatchSpec() will now return false w/out asserting.

					return InitializePatterns(szIncludeFilter, szExcludeFilter);
				}
			}
			
		}
	}
	return (s_fpPatternMatchSpec != NULL);
}

BOOL CDelayedDirectoryChangeHandler::InitializePatterns(LPCTSTR szIncludeFilter, LPCTSTR szExcludeFilter)
{
	ASSERT( !IsEmptyString(szIncludeFilter)   //one of these must have something in it, 
		||  !IsEmptyString(szExcludeFilter) );//or else this function shouldn't be called.

	if( s_hShlwapi_dll != NULL )
	{
		//we're using Shlwapi.dll's PathMatchSpec function....
		//we're running on NT4.0 w/ IE 4.0 installed, or win2k/winXP(or greater)
		//
		//	Copy the include/exclude filters if specified...
		//
		//
		// we're using the real PathMatchSpec() function which
		//	supports multiple pattern specs...(separated by a semi-colon)
		//	so there's only one filter spec as far as my code is concerned.
		//
		if( !IsEmptyString(szIncludeFilter) )
		{
			m_szIncludeFilter = _tcsdup(szIncludeFilter);
			ASSERT( m_szIncludeFilter );
			m_nNumIncludeFilterSpecs = 1;
		}
		if( !IsEmptyString(szExcludeFilter) )
		{
			m_szExcludeFilter = _tcsdup(szExcludeFilter);	
			ASSERT( m_szExcludeFilter );
			m_nNumExcludeFilterSpecs = 1;
		}	
	}
	else
	{
		//shlwapi.dll isn't on this machine.... can happen on NT4.0 w/ out IE 4.0 installed.
		ASSERT( s_bShlwapi_dllExists == FALSE );

		//
		//	we're using the function wildcmp() instead of PathMatchSpec..
		//
		//	this means that multiple pattern specs aren't supported...
		// in order to support them, we'll tokenize the string into multiple
		// pattern specs and test the string multiple times(once per pattern spec) 
		// in order to support multiple patterns.
		//
		//
		//	m_szIncludeFilter & m_szExclude filter will be used like TCHAR**'s instead of TCHAR*'s
		//

		m_nNumIncludeFilterSpecs = 0;
		if( !IsEmptyString(szIncludeFilter) )
		{
			TCHAR * szTmpFilter = _tcsdup(szIncludeFilter);
			TCHAR * pTok = _tcstok( szTmpFilter, _T(";"));
			while( pTok )
			{
				m_nNumIncludeFilterSpecs++;
				pTok = _tcstok(NULL, _T(";"));
			}
			if( m_nNumIncludeFilterSpecs == 1 )
				m_szIncludeFilter = _tcsdup(szIncludeFilter);
			else
			{   //allocate room for pointers .. one for each token...
				m_szIncludeFilter = (TCHAR*)malloc( m_nNumIncludeFilterSpecs * sizeof(TCHAR*));

				free(szTmpFilter);
				szTmpFilter = _tcsdup(szIncludeFilter);
				pTok = _tcstok(szTmpFilter, _T(";"));
				TCHAR ** ppTmp = (TCHAR**)m_szIncludeFilter;
				while(pTok)
				{
					*ppTmp = _tcsdup(pTok);
					ppTmp++;
					pTok = _tcstok(NULL, _T(";"));
				}
			}

			free(szTmpFilter);
		}

		//
		//	Do the same for the Exclude filter...
		//
		m_nNumExcludeFilterSpecs = 0;
		if( !IsEmptyString(szExcludeFilter) )
		{
			TCHAR * szTmpFilter = _tcsdup(szExcludeFilter);
			TCHAR * pTok = _tcstok( szTmpFilter, _T(";"));
			while( pTok )
			{
				m_nNumExcludeFilterSpecs++;
				pTok = _tcstok(NULL, _T(";"));
			}
			if( m_nNumExcludeFilterSpecs == 1 )
				m_szExcludeFilter = _tcsdup(szExcludeFilter);
			else
			{   //allocate room for pointers .. one for each token...
				m_szExcludeFilter = (TCHAR*)malloc( m_nNumExcludeFilterSpecs * sizeof(TCHAR*));

				free(szTmpFilter);
				szTmpFilter = _tcsdup(szExcludeFilter);

				pTok = _tcstok(szTmpFilter, _T(";"));
				TCHAR ** ppTmp = (TCHAR**)m_szExcludeFilter;
				while(pTok)
				{
					*ppTmp = _tcsdup(pTok);
					ppTmp++;
					pTok = _tcstok(NULL, _T(";"));
				}
			}
			free(szTmpFilter);
		}

	}

	return (m_szExcludeFilter!= NULL || (m_szIncludeFilter != NULL));
}
void CDelayedDirectoryChangeHandler::UninitializePathMatchFunc()
{
	if( s_bShlwapi_dllExists == TRUE 
	&&  s_hShlwapi_dll != NULL )
	{
		if( InterlockedDecrement(&s_nRefCnt_hShlwapi) <= 0)
		{
			s_nRefCnt_hShlwapi = 0;
			FreeLibrary( s_hShlwapi_dll );
			s_hShlwapi_dll = NULL;
			s_fpPatternMatchSpec = wildcmp;
		}
	}
}

bool CDelayedDirectoryChangeHandler::UsesRealPathMatchSpec() const
//are we using PathMatchSpec() or wildcmp()?
{
	if( s_hShlwapi_dll != NULL && s_fpPatternMatchSpec != NULL )
		return true;
	if( s_hShlwapi_dll == NULL && s_fpPatternMatchSpec != NULL )
		return false;

	ASSERT( FALSE );//this function was called before InitializePathMatchFunc()
	//oops!
	return false;
}
static inline bool HasTrailingBackslash(const CString & str )
{
	if( str.GetLength() > 0 
	&&	str[ str.GetLength() - 1 ] == _T('\\') )
		return true;
	return false;
}
void CDelayedDirectoryChangeHandler::SetPartialPathOffset(const CString & strWatchedDirName)
{
	if( m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_CHECK_PARTIAL_PATH )
	{
		//set the offset to 
		if( HasTrailingBackslash( strWatchedDirName ) )
			m_dwPartialPathOffset = strWatchedDirName.GetLength();
		else
			m_dwPartialPathOffset = strWatchedDirName.GetLength() + 1;
	}
	else
		m_dwPartialPathOffset = 0;
}

CDirChangeNotification * CDelayedDirectoryChangeHandler::GetNotificationObject()
//
//	Maybe in future I'll keep a pool of these 
//	objects around to increase performance...
//	using objects from a cache will be faster 
//	than allocated and destroying a new one each time.
//	
//  
{
	ASSERT( m_pRealHandler );
	return new CDirChangeNotification(this, m_dwPartialPathOffset);//helps support FILTERS_CHECK_PARTIAL_PATH
}

void CDelayedDirectoryChangeHandler::DisposeOfNotification(CDirChangeNotification * pNotification)
{
	delete pNotification;
}

//These functions are called when the directory to watch has had a change made to it
void CDelayedDirectoryChangeHandler::On_FileAdded(const CString & strFileName)
{
	CDirChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p ) p->PostOn_FileAdded( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileRemoved(const CString & strFileName)
{
	CDirChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p ) p->PostOn_FileRemoved( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileModified(const CString & strFileName)
{
	CDirChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p ) p->PostOn_FileModified( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileNameChanged(const CString & strOldFileName, const CString & strNewFileName)
{
	CDirChangeNotification * p = GetNotificationObject();	
	ASSERT( p );
	if( p ) p->PostOn_FileNameChanged( strOldFileName, strNewFileName );
}

void CDelayedDirectoryChangeHandler::On_ReadDirectoryChangesError(DWORD dwError, const CString & strDirectoryName)
{
	CDirChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p ) p->PostOn_ReadDirectoryChangesError( dwError, strDirectoryName );
}

void CDelayedDirectoryChangeHandler::On_WatchStarted(DWORD dwError, const CString & strDirectoryName)
{
	if( !(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_NO_WATCHSTART_NOTIFICATION))
	{
		CDirChangeNotification * p = GetNotificationObject();

		if( p ) p->PostOn_WatchStarted(dwError, strDirectoryName);
	}
}

void CDelayedDirectoryChangeHandler::On_WatchStopped(const CString & strDirectoryName)
{
	if( !(m_dwFilterFlags & CDirectoryChangeWatcher::FILTERS_NO_WATCHSTOP_NOTIFICATION))
	{
		CDirChangeNotification * p = GetNotificationObject();

		if( p ){
			if( m_hWatchStoppedDispatchedEvent )
				::ResetEvent(m_hWatchStoppedDispatchedEvent);

			p->PostOn_WatchStopped( strDirectoryName );

			//	Wait that this function has been dispatched to the other thread
			//	before continueing.  This object may be getting deleted
			//	soon after this function returns, and before the function can be
			//	dispatched to the other thread....
			WaitForOnWatchStoppedDispatched();
		}
	}

⌨️ 快捷键说明

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