/*++ Copyright (c) 1999 Microsoft Corporation Module Name : cachedir.cxx Abstract: Dir monitor for cache manager Author: Bilal Alam (balam) 11-Nov-2000 Environment: Win32 - User Mode Project: ULW3.DLL --*/ #include "precomp.hxx" #define DIR_CHANGE_FILTER (FILE_NOTIFY_VALID_MASK & ~FILE_NOTIFY_CHANGE_LAST_ACCESS) BOOL CacheDirMonitorEntry::ActOnNotification( DWORD dwStatus, DWORD dwBytesWritten ) /*++ Routine Description: Do any work associated with a change notification, i.e. Arguments: dwStatus - Win32 status for dirmon completion dwBytesWritten - Bytes written in dir change buffer Return Value: TRUE if directory should continue to be monitored, otherwise FALSE --*/ { FILE_NOTIFY_INFORMATION * pNotify = NULL; FILE_NOTIFY_INFORMATION * pNextNotify = NULL; STACK_STRU( strFileChanged, MAX_PATH ); DWORD cch = 0; HANDLE hDir; BOOL fContinueMonitoring = TRUE; HRESULT hr = NO_ERROR; // // If there was an error monitoring directory, then flush the entire // directory // if ( dwStatus != ERROR_SUCCESS ) { // // Access denied means directory either was deleted or secured // Stop monitoring in that case // if ( dwStatus == ERROR_ACCESS_DENIED ) { fContinueMonitoring = FALSE; } else { _cNotificationFailures++; if ( _cNotificationFailures > MAX_NOTIFICATION_FAILURES ) { fContinueMonitoring = FALSE; } } } else { _cNotificationFailures = 0; } // // If no bytes were written, then take the conservative approach and flush // everything for this physical prefix // if ( dwBytesWritten == 0 ) { FileChanged( L"", TRUE ); } else { pNextNotify = (FILE_NOTIFY_INFORMATION *) m_pbBuffer; while ( pNextNotify != NULL ) { BOOL bDoFlush = TRUE; pNotify = pNextNotify; pNextNotify = (FILE_NOTIFY_INFORMATION*) ((PCHAR) pNotify + pNotify->NextEntryOffset); // // Get the unicode file name from the notification struct // pNotify->FileNameLength returns the wstr's length in **bytes** not wchars // hr = strFileChanged.Copy( pNotify->FileName, pNotify->FileNameLength / 2 ); if ( FAILED( hr ) ) { SetLastError( WIN32_FROM_HRESULT( hr ) ); return FALSE; } // Take the appropriate action for the directory change switch (pNotify->Action) { case FILE_ACTION_MODIFIED: // // Since this change won't change the pathname of // any files, we don't have to do a flush. // bDoFlush = FALSE; case FILE_ACTION_REMOVED: case FILE_ACTION_RENAMED_OLD_NAME: FileChanged(strFileChanged.QueryStr(), bDoFlush); break; case FILE_ACTION_ADDED: case FILE_ACTION_RENAMED_NEW_NAME: default: break; } if( pNotify == pNextNotify ) { break; } } } return fContinueMonitoring; } VOID CacheDirMonitorEntry::FileChanged( const WCHAR * pszScriptName, BOOL bDoFlush ) /*++ Routine Description: An existing file has been modified or deleted Flush scripts from cache or mark application as expired Arguments: pszScriptName - Name of file that changed bDoFlush - Should we flush all entries prefixed wih pszScriptName Return Value: None --*/ { STACK_STRU( strLongName, MAX_PATH ); STACK_STRU( strFullPath, MAX_PATH ); const WCHAR * pszLongName; DWORD cchLongName; HRESULT hr; // // Convert any short file names // if ( wcschr( pszScriptName, L'~' ) != NULL ) { cchLongName = GetLongPathName( pszScriptName, strLongName.QueryStr(), MAX_PATH ); if ( cchLongName == 0 || cchLongName > MAX_PATH ) { pszLongName = L""; } else { pszLongName = strLongName.QueryStr(); } } else { pszLongName = pszScriptName; } // // Create full path of file changed // hr = strFullPath.Copy( m_pszPath ); if ( FAILED( hr ) ) { return; } hr = strFullPath.Append( L"\\", 1 ); if ( FAILED( hr ) ) { return; } hr = strFullPath.Append( pszLongName ); if ( FAILED( hr ) ) { return; } _wcsupr( strFullPath.QueryStr() ); // // Now call the caches // g_pCacheManager->HandleDirMonitorInvalidation( strFullPath.QueryStr(), bDoFlush ); }