377 lines
8.3 KiB
C++
377 lines
8.3 KiB
C++
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name :
|
||
|
||
dirchang.cxx
|
||
|
||
Abstract:
|
||
|
||
This module contains the directory change manager routines
|
||
|
||
Author:
|
||
|
||
MuraliK
|
||
|
||
--*/
|
||
|
||
#include "tsunamip.Hxx"
|
||
#pragma hdrstop
|
||
|
||
#include "dbgutil.h"
|
||
#include <mbstring.h>
|
||
|
||
extern "C" {
|
||
#include <lmuse.h>
|
||
}
|
||
|
||
//
|
||
// list and cs for the virtual roots
|
||
//
|
||
|
||
LIST_ENTRY GlobalVRootList;
|
||
CRITICAL_SECTION csVirtualRoots;
|
||
|
||
VOID
|
||
DcmRemoveItem(
|
||
PCACHE_OBJECT pCacheObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Remove the cache object from the Directory change manager list
|
||
|
||
Arguments
|
||
|
||
pCacheObject - Cache object to remove
|
||
|
||
Returns
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ASSERT( !IsListEmpty( &pCacheObject->DirChangeList ) );
|
||
|
||
RemoveEntryList( &pCacheObject->DirChangeList );
|
||
return;
|
||
|
||
} // DcmRemoveItem
|
||
|
||
BOOL
|
||
DcmAddNewItem(
|
||
IN PIIS_SERVER_INSTANCE pInstance,
|
||
IN PCHAR pszFileName,
|
||
IN PCACHE_OBJECT pCacheObject
|
||
)
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Adds a new cache object to the directory change list
|
||
|
||
Arguments
|
||
|
||
pCacheObject - Cache object to add
|
||
|
||
Returns
|
||
|
||
TRUE, if successful
|
||
FALSE, otherwise
|
||
--*/
|
||
{
|
||
PLIST_ENTRY pEntry;
|
||
PVIRTUAL_ROOT_MAPPING pVrm;
|
||
PDIRECTORY_CACHING_INFO pDci;
|
||
BOOLEAN bResult = FALSE;
|
||
PIIS_VROOT_TABLE pTable = pInstance->QueryVrootTable();
|
||
|
||
ASSERT( !DisableTsunamiCaching ); // This should never get called
|
||
|
||
//
|
||
// Must always take the Vroot table lock BEFORE the csVirtualRoots lock
|
||
// because DcmAddRoot is called with the vroot table locked then takes
|
||
// the csVirtualRoots lock
|
||
//
|
||
|
||
pTable->LockTable();
|
||
EnterCriticalSection( &csVirtualRoots );
|
||
|
||
__try {
|
||
|
||
for( pEntry = pTable->m_vrootListHead.Flink;
|
||
pEntry != &pTable->m_vrootListHead;
|
||
pEntry = pEntry->Flink ) {
|
||
|
||
pVrm = CONTAINING_RECORD(
|
||
pEntry,
|
||
VIRTUAL_ROOT_MAPPING,
|
||
TableListEntry );
|
||
|
||
//
|
||
// If the directory of this virtual root doesn't match the
|
||
// beginning of the directory that we are being asked to cache
|
||
// within, skip this entry.
|
||
//
|
||
|
||
if ( _mbsnicmp(
|
||
(PUCHAR) pszFileName,
|
||
(PUCHAR) pVrm->pszDirectoryA,
|
||
_mbslen((PUCHAR)pVrm->pszDirectoryA) ) ) {
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// The virtual root contains the directory of interest.
|
||
//
|
||
|
||
if ( !pVrm->fCachingAllowed ) {
|
||
break;
|
||
}
|
||
|
||
pDci = ( PDIRECTORY_CACHING_INFO)( pVrm+1 );
|
||
|
||
ASSERT( IsListEmpty( &pCacheObject->DirChangeList ) );
|
||
|
||
InsertHeadList(
|
||
&pDci->listCacheObjects,
|
||
&pCacheObject->DirChangeList
|
||
);
|
||
|
||
bResult = TRUE;
|
||
break;
|
||
}
|
||
|
||
} __finally {
|
||
LeaveCriticalSection( &csVirtualRoots );
|
||
pTable->UnlockTable();
|
||
}
|
||
return( bResult );
|
||
} // DcmNewItem
|
||
|
||
BOOL
|
||
DcmInitialize(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Initialize the directory change manager.
|
||
|
||
Arguments
|
||
|
||
hQuitEvent - HANDLE to an event which get signalled during
|
||
shutdown
|
||
hNewItem - HANDLE to an event which gets signalled when a
|
||
new item is added.
|
||
|
||
Returns
|
||
TRUE, if successful
|
||
FALSE, otherwise
|
||
|
||
--*/
|
||
{
|
||
DWORD ThreadId;
|
||
|
||
InitializeListHead( &GlobalVRootList );
|
||
InitializeCriticalSection( &csVirtualRoots );
|
||
SET_CRITICAL_SECTION_SPIN_COUNT( &csVirtualRoots,
|
||
IIS_DEFAULT_CS_SPIN_COUNT);
|
||
//
|
||
// If tsunami caching is disabled, don't start the thread
|
||
//
|
||
|
||
if ( DisableTsunamiCaching ) {
|
||
return(TRUE);
|
||
}
|
||
|
||
g_hChangeWaitThread = CreateThread( ( LPSECURITY_ATTRIBUTES )NULL,
|
||
0,
|
||
ChangeWaitThread,
|
||
0,
|
||
0,
|
||
&ThreadId );
|
||
|
||
if ( g_hChangeWaitThread != NULL ) {
|
||
return TRUE;
|
||
}
|
||
|
||
DeleteCriticalSection( &csVirtualRoots );
|
||
return( FALSE );
|
||
} // DcmInitialize
|
||
|
||
BOOL
|
||
DcmAddRoot(
|
||
PVIRTUAL_ROOT_MAPPING pVrm
|
||
)
|
||
/*++
|
||
|
||
Routine Description
|
||
|
||
Adds a virtual root to the DCM list
|
||
|
||
Arguments
|
||
|
||
pVrm - pointer to the VR mapping structure describing a VR
|
||
|
||
Returns
|
||
TRUE, if successful
|
||
FALSE, otherwise
|
||
|
||
--*/
|
||
{
|
||
BOOL bSuccess;
|
||
PDIRECTORY_CACHING_INFO pDci;
|
||
|
||
//
|
||
// Check if Caching is disabled
|
||
//
|
||
|
||
if ( DisableTsunamiCaching ) {
|
||
return(TRUE);
|
||
}
|
||
|
||
IF_DEBUG( DIRECTORY_CHANGE ) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Opening directory file %s\n", pVrm->pszDirectoryA ));
|
||
}
|
||
|
||
pDci = ( PDIRECTORY_CACHING_INFO)( pVrm+1 );
|
||
|
||
InitializeListHead( &pDci->listCacheObjects );
|
||
|
||
//
|
||
// Open the file. If this is a UNC path name, we need to
|
||
// append a trailing / or the SMB server will barf
|
||
//
|
||
|
||
if ( pVrm->fUNC &&
|
||
!IS_CHAR_TERM_A(pVrm->pszDirectoryA, pVrm->cchDirectoryA-1) ) {
|
||
|
||
pVrm->pszDirectoryA[pVrm->cchDirectoryA++] = '\\';
|
||
pVrm->pszDirectoryA[pVrm->cchDirectoryA] = '\0';
|
||
|
||
}
|
||
|
||
pDci->hDirectoryFile = CreateFile(
|
||
pVrm->pszDirectoryA,
|
||
FILE_LIST_DIRECTORY,
|
||
FILE_SHARE_READ |
|
||
FILE_SHARE_WRITE |
|
||
FILE_SHARE_DELETE,
|
||
NULL,
|
||
OPEN_EXISTING,
|
||
FILE_FLAG_BACKUP_SEMANTICS |
|
||
FILE_FLAG_OVERLAPPED,
|
||
NULL );
|
||
|
||
//
|
||
// remove the trailing slash
|
||
//
|
||
|
||
if ( pVrm->fUNC &&
|
||
IS_CHAR_TERM_A(pVrm->pszDirectoryA, pVrm->cchDirectoryA-1) ) {
|
||
|
||
pVrm->pszDirectoryA[--pVrm->cchDirectoryA] = '\0';
|
||
}
|
||
|
||
if ( pDci->hDirectoryFile == INVALID_HANDLE_VALUE ) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"Can't open directory %s, error %lx\n",
|
||
pVrm->pszDirectoryA,
|
||
GetLastError() ));
|
||
|
||
if ( GetLastError() == ERROR_FILE_NOT_FOUND ) {
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"[AddRoot] Mapping File Not Found to Path Not Found\n" ));
|
||
|
||
SetLastError( ERROR_PATH_NOT_FOUND );
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Now add this to the list
|
||
//
|
||
|
||
EnterCriticalSection( &csVirtualRoots );
|
||
|
||
InsertTailList( &GlobalVRootList, &pVrm->GlobalListEntry );
|
||
|
||
LeaveCriticalSection( &csVirtualRoots );
|
||
|
||
//
|
||
// At this point, the entry in the list contains an open directory
|
||
// file. This would imply that each contains a valid directory name,
|
||
// and is therefore a valid mapping between a "virtual root" and a
|
||
// directory name.
|
||
//
|
||
// The next step is to wait on this directory if we can, and enable
|
||
// caching if we succesfully wait.
|
||
//
|
||
|
||
bSuccess = SetEvent( g_hNewItem );
|
||
|
||
ASSERT( bSuccess );
|
||
|
||
return( TRUE );
|
||
} // DcmAddRoot
|
||
|
||
|
||
VOID
|
||
DcmRemoveRoot(
|
||
PVIRTUAL_ROOT_MAPPING pVrm
|
||
)
|
||
{
|
||
|
||
//
|
||
// Remove this from global list
|
||
//
|
||
|
||
EnterCriticalSection( &csVirtualRoots );
|
||
RemoveEntryList( &pVrm->GlobalListEntry );
|
||
LeaveCriticalSection( &csVirtualRoots );
|
||
|
||
} // DcmRemoveRoot
|
||
|
||
/*******************************************************************
|
||
|
||
NAME: IsCharTermA (DBCS enabled)
|
||
|
||
SYNOPSIS: check the character in string is terminator or not.
|
||
terminator is '/', '\0' or '\\'
|
||
|
||
ENTRY: lpszString - string
|
||
|
||
cch - offset for char to check
|
||
|
||
RETURNS: BOOL - TRUE if it is a terminator
|
||
|
||
HISTORY:
|
||
v-ChiKos 15-May-1997 Created.
|
||
|
||
********************************************************************/
|
||
BOOL
|
||
IsCharTermA(
|
||
IN LPCSTR lpszString,
|
||
IN INT cch
|
||
)
|
||
{
|
||
CHAR achLast;
|
||
|
||
achLast = *(lpszString + cch);
|
||
|
||
if ( achLast == '/' || achLast == '\0' )
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
achLast = *CharPrev(lpszString, lpszString + cch + 1);
|
||
|
||
return (achLast == '\\');
|
||
}
|
||
|
||
|