windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/w3cache/cachedir.cxx
2020-09-26 16:20:57 +08:00

231 lines
5.3 KiB
C++

/*++
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 );
}