Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1575 lines
43 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
infocach.c
Abstract:
This module implements the name cache for file basic and standard information.
Author:
Yun Lin [YunLin] 13-Feburary-2001
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "webdav.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, MRxDAVCacheFileNotFound)
#pragma alloc_text(PAGE, MRxDAVCacheFileNotFoundWithName)
#pragma alloc_text(PAGE, MRxDAVIsFileNotFoundCached)
#pragma alloc_text(PAGE, MRxDAVIsFileNotFoundCachedWithName)
#pragma alloc_text(PAGE, MRxDAVCreateFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVCreateFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVIsFileInfoCacheFound)
#pragma alloc_text(PAGE, MRxDAVInvalidateFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVInvalidateFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVUpdateBasicFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVCreateBasicFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVCreateBasicFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVUpdateFileInfoCacheStatus)
#pragma alloc_text(PAGE, MRxDAVCreateStandardFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVCreateStandardFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVUpdateFileInfoCacheFileSize)
#pragma alloc_text(PAGE, MRxDAVUpdateStandardFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVInvalidateFileNotFoundCache)
#pragma alloc_text(PAGE, MRxDAVUpdateBasicFileInfoCacheAll)
#pragma alloc_text(PAGE, MRxDAVInvalidateBasicFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVInvalidateBasicFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVUpdateBasicFileInfoCacheStatus)
#pragma alloc_text(PAGE, MRxDAVInvalidateStandardFileInfoCache)
#pragma alloc_text(PAGE, MRxDAVInvalidateStandardFileInfoCacheWithName)
#pragma alloc_text(PAGE, MRxDAVUpdateStandardFileInfoCacheStatus)
#endif
extern FAST_MUTEX MRxDAVFileInfoCacheLock;
MRX_DAV_STATISTICS MRxDAVStatistics;
VOID
MRxDAVCreateFileInfoCache(
PRX_CONTEXT RxContext,
PDAV_USERMODE_CREATE_RETURNED_FILEINFO FileInfo,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
FileInfo - the file information package including basic and standard information
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
PAGED_CODE();
MRxDAVCreateBasicFileInfoCache(RxContext,&FileInfo->BasicInformation,Status);
MRxDAVCreateStandardFileInfoCache(RxContext,&FileInfo->StandardInformation,Status);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVCreateFileInfoCache %wZ\n",GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)));
}
VOID
MRxDAVCreateFileInfoCacheWithName(
PUNICODE_STRING FileName,
PMRX_NET_ROOT NetRoot,
PFILE_BASIC_INFORMATION Basic,
PFILE_STANDARD_INFORMATION Standard,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
FileInfo - the file information package including basic and standard information
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
PAGED_CODE();
MRxDAVCreateBasicFileInfoCacheWithName(FileName,NetRoot,Basic,Status);
MRxDAVCreateStandardFileInfoCacheWithName(FileName,NetRoot,Standard,Status);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVCreateFileInfoCacheWithName %wZ\n",FileName));
}
VOID
MRxDAVCreateBasicFileInfoCache(
PRX_CONTEXT RxContext,
PFILE_BASIC_INFORMATION Basic,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for the file basic information.
Arguments:
RxContext - the RDBSS context
Basic - the file basic information package
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot;
PAGED_CODE();
if (RxContext->MajorFunction == IRP_MJ_CREATE) {
NetRoot = RxContext->Create.pNetRoot;
} else {
ASSERT(capFcb != NULL);
NetRoot = capFcb->pNetRoot;
}
MRxDAVCreateBasicFileInfoCacheWithName(OriginalFileName,NetRoot,Basic,Status);
}
VOID
MRxDAVCreateBasicFileInfoCacheWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot,
PFILE_BASIC_INFORMATION Basic,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for the file basic information.
Arguments:
OriginalFileName - the name of the file to cache the basic information
NetRoot - the Net Root that the file belongs to
Basic - the file basic information package
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot;
PNAME_CACHE_CONTROL NameCacheCtl;
PFILE_BASIC_INFORMATION FileInfoCache = NULL;
PAGED_CODE();
DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
NameCacheCtl = &DavNetRoot->NameCacheCtlGFABasic;
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache == NULL) {
NameCache = RxNameCacheCreateEntry (
NameCacheCtl,
OriginalFileName,
TRUE); // case insensitive match
}
if (NameCache != NULL) {
FileInfoCache = (PFILE_BASIC_INFORMATION)NameCache->ContextExtension;
*FileInfoCache = *Basic;
NameCache->PriorStatus = Status;
if (FileInfoCache->FileAttributes & ~FILE_ATTRIBUTE_NORMAL) {
FileInfoCache->FileAttributes &= ~FILE_ATTRIBUTE_NORMAL;
}
RxNameCacheActivateEntry(
NameCacheCtl,
NameCache,
FileInformationCacheLifeTimeInSec,
MRxDAVStatistics.SmbsReceived.LowPart);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Create File Attrib cache : %x %wZ\n",Basic->FileAttributes,OriginalFileName));
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Create File Attrib cache : %I64X %I64X %wZ\n",Basic->CreationTime,Basic->LastAccessTime,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVCreateStandardFileInfoCache(
PRX_CONTEXT RxContext,
PFILE_STANDARD_INFORMATION Standard,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Standard - the file standard information package
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PAGED_CODE();
MRxDAVCreateStandardFileInfoCacheWithName(OriginalFileName,NetRoot,Standard,Status);
}
VOID
MRxDAVCreateStandardFileInfoCacheWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot,
PFILE_STANDARD_INFORMATION Standard,
NTSTATUS Status
)
/*++
Routine Description:
This routine creates name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Standard - the file standard information package
Status - the status returned from server response of query file information
Return Value:
none
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
PFILE_STANDARD_INFORMATION FileInfoCache = NULL;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache == NULL) {
NameCache = RxNameCacheCreateEntry (
NameCacheCtl,
OriginalFileName,
TRUE); // case insensitive match
}
if (NameCache != NULL) {
FileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
*FileInfoCache = *Standard;
NameCache->PriorStatus = Status;
RxNameCacheActivateEntry(
NameCacheCtl,
NameCache,
FileInformationCacheLifeTimeInSec,
MRxDAVStatistics.SmbsReceived.LowPart);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Create Standard cache : %I64x %I64x %I64x %wZ\n",
((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,
Standard->AllocationSize,
Standard->EndOfFile,
OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVUpdateFileInfoCacheFromDelete(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine updates the status of the name cache entry as STATUS_OBJECT_NAME_NOT_FOUND
for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
MRxDAVUpdateBasicFileInfoCacheStatus(RxContext,STATUS_OBJECT_NAME_NOT_FOUND);
MRxDAVUpdateStandardFileInfoCacheStatus(RxContext,STATUS_OBJECT_NAME_NOT_FOUND);
}
VOID
MRxDAVUpdateFileInfoCacheStatus(
PRX_CONTEXT RxContext,
NTSTATUS Status
)
/*++
Routine Description:
This routine updates the status of the name cache entry for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
Status - the status needs to be put on the cache
Return Value:
none
--*/
{
MRxDAVUpdateBasicFileInfoCacheStatus(RxContext,Status);
MRxDAVUpdateStandardFileInfoCacheStatus(RxContext,Status);
}
VOID
MRxDAVUpdateBasicFileInfoCacheStatus(
PRX_CONTEXT RxContext,
NTSTATUS Status
)
/*++
Routine Description:
This routine updates the status of the name cache entry for the file basic information.
Arguments:
RxContext - the RDBSS context
Status - the status needs to be put on the cache
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFABasic;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
NameCache->PriorStatus = Status;
RxNameCacheActivateEntry(NameCacheCtl,
NameCache,
0,
0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Update status basic : %x %wZ\n",Status,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVUpdateStandardFileInfoCacheStatus(
PRX_CONTEXT RxContext,
NTSTATUS Status
)
/*++
Routine Description:
This routine updates the status of the name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Status - the status needs to be put on the cache
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
NameCache->PriorStatus = Status;
RxNameCacheActivateEntry(NameCacheCtl,
NameCache,
0,
0);
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVInvalidateFileInfoCache(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine invalidates the name cache entry for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
PAGED_CODE();
MRxDAVInvalidateBasicFileInfoCache(RxContext);
MRxDAVInvalidateStandardFileInfoCache(RxContext);
}
VOID
MRxDAVInvalidateFileInfoCacheWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot
)
/*++
Routine Description:
This routine invalidates the name cache entry for both file basic and standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
PAGED_CODE();
MRxDAVInvalidateBasicFileInfoCacheWithName(OriginalFileName,NetRoot);
MRxDAVInvalidateStandardFileInfoCacheWithName(OriginalFileName,NetRoot);
}
VOID
MRxDAVInvalidateBasicFileInfoCache(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine invalidates the name cache entry for file basic information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PAGED_CODE();
MRxDAVInvalidateBasicFileInfoCacheWithName(OriginalFileName,NetRoot);
}
VOID
MRxDAVInvalidateBasicFileInfoCacheWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot
)
/*++
Routine Description:
This routine invalidates the name cache entry for file basic information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFABasic;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Invalid Baisc cache : %wZ\n",OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVInvalidateStandardFileInfoCache(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine invalidates the name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PAGED_CODE();
MRxDAVInvalidateStandardFileInfoCacheWithName(OriginalFileName,NetRoot);
}
VOID
MRxDAVInvalidateStandardFileInfoCacheWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot
)
/*++
Routine Description:
This routine invalidates the name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Invalid Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVUpdateFileInfoCacheFileSize(
PRX_CONTEXT RxContext,
PLARGE_INTEGER FileSize
)
/*++
Routine Description:
This routine updates file size on the name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
PFILE_STANDARD_INFORMATION FileInfoCache = NULL;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
FileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
FileInfoCache->AllocationSize.QuadPart = FileSize->QuadPart;
FileInfoCache->EndOfFile.QuadPart = FileSize->QuadPart;
RxNameCacheActivateEntry(NameCacheCtl,
NameCache,
0,
0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Update File size cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVUpdateBasicFileInfoCache(
PRX_CONTEXT RxContext,
ULONG FileAttributes,
PLARGE_INTEGER pLastWriteTime
)
/*++
Routine Description:
This routine updates file attributs and last write time on the name cache entry
for the file basic information.
Arguments:
RxContext - the RDBSS context
FileAttributes - new file attributes
pLastWriteTime - address of file last write time
Return Value:
none
--*/
{
FILE_BASIC_INFORMATION Basic;
Basic.ChangeTime.QuadPart = 0;
Basic.CreationTime.QuadPart = 0;
Basic.LastWriteTime.QuadPart = 0;
Basic.LastAccessTime.QuadPart = 0;
if (pLastWriteTime != NULL && pLastWriteTime->QuadPart != 0) {
Basic.LastWriteTime = *pLastWriteTime;
}
Basic.FileAttributes = FileAttributes;
MRxDAVUpdateBasicFileInfoCacheAll(RxContext,&Basic);
}
VOID
MRxDAVUpdateBasicFileInfoCacheAll(
PRX_CONTEXT RxContext,
PFILE_BASIC_INFORMATION Basic
)
/*++
Routine Description:
This routine updates the name cache entry for the file basic information.
Arguments:
RxContext - the RDBSS context
Basic - file basic information
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFABasic;
PFILE_BASIC_INFORMATION BasicFileInfoCache = NULL;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
BasicFileInfoCache = (PFILE_BASIC_INFORMATION)NameCache->ContextExtension;
if (Basic->CreationTime.QuadPart != 0) {
BasicFileInfoCache->CreationTime = Basic->CreationTime;
}
if (Basic->LastAccessTime.QuadPart != 0) {
BasicFileInfoCache->LastAccessTime = Basic->LastAccessTime;
}
if (Basic->LastWriteTime.QuadPart != 0) {
BasicFileInfoCache->LastWriteTime = Basic->LastWriteTime;
}
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Update File Attrib cache 2: %x %wZ\n",BasicFileInfoCache->FileAttributes,OriginalFileName));
BasicFileInfoCache->FileAttributes = Basic->FileAttributes;
if (BasicFileInfoCache->FileAttributes & ~FILE_ATTRIBUTE_NORMAL) {
BasicFileInfoCache->FileAttributes &= ~FILE_ATTRIBUTE_NORMAL;
}
RxNameCacheActivateEntry(NameCacheCtl,
NameCache,
0,
0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Update File Attrib cache 3: %x %wZ\n",BasicFileInfoCache->FileAttributes,OriginalFileName));
DavDbgTrace(DAV_TRACE_INFOCACHE,
("Update File Attrib cache : %I64X %I64X %wZ\n",BasicFileInfoCache->CreationTime,BasicFileInfoCache->LastAccessTime,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVUpdateStandardFileInfoCache(
PRX_CONTEXT RxContext,
PFILE_STANDARD_INFORMATION Standard,
BOOLEAN IsDirectory
)
/*++
Routine Description:
This routine updates the name cache entry for the file standard information.
Arguments:
RxContext - the RDBSS context
Standard - file standard information
IsDirectory - file is a directory
Return Value:
none
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
PFILE_STANDARD_INFORMATION StandardFileInfoCache = NULL;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
StandardFileInfoCache = (PFILE_STANDARD_INFORMATION)NameCache->ContextExtension;
if (Standard != NULL) {
*StandardFileInfoCache = *Standard;
} else {
StandardFileInfoCache->Directory = IsDirectory;
}
RxNameCacheActivateEntry(NameCacheCtl,
NameCache,
0,
0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Update Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
BOOLEAN
MRxDAVIsFileInfoCacheFound(
PRX_CONTEXT RxContext,
PDAV_USERMODE_CREATE_RETURNED_FILEINFO FileInfo,
NTSTATUS *Status,
PUNICODE_STRING OriginalFileName
)
/*++
Routine Description:
This routine looks for the name cache entry of both file basic and standard information.
Arguments:
RxContext - the RDBSS context
FileInfo - buffer to return file basic and standard information
Status - status retured on the last reponse from server
Return Value:
BOOLEAN - name cache found
--*/
{
BOOLEAN CacheFound = FALSE;
if (MRxDAVIsBasicFileInfoCacheFound(RxContext,&FileInfo->BasicInformation,Status,OriginalFileName)) {
if (*Status == STATUS_SUCCESS) {
if (MRxDAVIsStandardFileInfoCacheFound(RxContext,&FileInfo->StandardInformation,Status,OriginalFileName)) {
CacheFound = TRUE;
}
} else {
// if an error stored on the file basic information cache, return cache found
CacheFound = TRUE;
}
}
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVIsFileInfoCacheFound %x %x %wZ\n",*Status,CacheFound,GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext)));
return CacheFound;
}
BOOLEAN
MRxDAVIsBasicFileInfoCacheFound(
PRX_CONTEXT RxContext,
PFILE_BASIC_INFORMATION Basic,
NTSTATUS *Status,
PUNICODE_STRING OriginalFileName
)
/*++
Routine Description:
This routine looks for the name cache entry of the file basic information.
Arguments:
RxContext - the RDBSS context
Basic - buffer to return file basic information
Status - status retured on the last reponse from server
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot;
PWEBDAV_NET_ROOT DavNetRoot;
PNAME_CACHE_CONTROL NameCacheCtl;
RX_NC_CHECK_STATUS NameCacheStatus;
BOOLEAN CacheFound = FALSE;
BOOLEAN RootFound = FALSE;
ULONG RootAttributes = 0;
NTSTATUS RootStatus = STATUS_SUCCESS;
PAGED_CODE();
if (OriginalFileName == NULL) {
OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
}
if (RxContext->MajorFunction == IRP_MJ_CREATE) {
NetRoot = RxContext->Create.pNetRoot;
} else {
ASSERT(capFcb != NULL);
NetRoot = capFcb->pNetRoot;
}
DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
NameCacheCtl = &DavNetRoot->NameCacheCtlGFABasic;
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
//
// Found it. Now check entry for not expired.
// Note - The NameCache entry has been pulled off the active list.
//
NameCacheStatus = RxNameCacheCheckEntry(
NameCache,
NameCache->Context);
if (NameCacheStatus == RX_NC_SUCCESS &&
(!RootFound || *Status == RootStatus)) {
// The name cache matches if it is not expired and the attributes matches the one of
// the root file if it is a stream file. If this is a match, return the old status,
// file info and reactivate the entry but leave expiration time unchanged.
*Status = NameCache->PriorStatus;
RxNameCacheOpSaved(NameCacheCtl);
*Basic = *((PFILE_BASIC_INFORMATION)NameCache->ContextExtension);
CacheFound = TRUE;
// put the entry back to the active list without changing the expire time
RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Found Basic cache : %x %wZ\n",Basic->FileAttributes,OriginalFileName));
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Get File Attrib cache : %I64X %I64X %wZ\n",Basic->CreationTime,Basic->LastAccessTime,OriginalFileName));
} else {
// put the entry back to the expire list
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
}
} else {
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" No Basic cache : %wZ\n",OriginalFileName));
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
return CacheFound;
}
BOOLEAN
MRxDAVIsStandardFileInfoCacheFound(
PRX_CONTEXT RxContext,
PFILE_STANDARD_INFORMATION Standard,
NTSTATUS *Status,
PUNICODE_STRING OriginalFileName
)
/*++
Routine Description:
This routine looks for the name cache entry of the file standard information.
Arguments:
RxContext - the RDBSS context
Standard - buffer to return file standard information
Status - status retured on the last reponse from server
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
RxCaptureFobx;
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlGFAStandard;
RX_NC_CHECK_STATUS NameCacheStatus;
BOOLEAN CacheFound = FALSE;
BOOLEAN RootFound = FALSE;
NTSTATUS RootStatus = STATUS_SUCCESS;
PAGED_CODE();
if (OriginalFileName == NULL) {
OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
}
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
//
// Found it. Now check entry for not expired.
// Note - The NameCache entry has been pulled off the active list.
//
NameCacheStatus = RxNameCacheCheckEntry(
NameCache,
NameCache->Context);
if (NameCacheStatus == RX_NC_SUCCESS &&
(!RootFound || *Status == RootStatus)) {
// The name cache matches if it is not expired and the status matches the one of
// the root file if it is a stream file. If this is a match, return the old status,
// file info and reactivate the entry but leave expiration time unchanged.
*Status = NameCache->PriorStatus;
RxNameCacheOpSaved(NameCacheCtl);
*Standard = *((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension);
CacheFound = TRUE;
// put the entry back to the active list without changing the expire time
RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Get Standard cache : %I64x %wZ\n",((PFILE_STANDARD_INFORMATION)NameCache->ContextExtension)->EndOfFile,OriginalFileName));
} else {
// put the entry back to the expire list
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
}
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
return CacheFound;
}
NTSTATUS
MRxDAVGetFileInfoCacheStatus(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine looks for the status of the name cache entry of either file basic or standard information.
Arguments:
RxContext - the RDBSS context
Return Value:
NTSTATUS - statu of the name cache if found, otherwise, STATUS_SUCCESS
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtlBasic = &DavNetRoot->NameCacheCtlGFABasic;
PNAME_CACHE_CONTROL NameCacheCtlStandard = &DavNetRoot->NameCacheCtlGFAStandard;
NTSTATUS Status = STATUS_MORE_PROCESSING_REQUIRED;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtlBasic,OriginalFileName);
if (NameCache != NULL) {
RX_NC_CHECK_STATUS NameCacheStatus;
//
// Found it. Now check entry for not expired
//
NameCacheStatus = RxNameCacheCheckEntry(NameCache,NameCache->Context);
if (NameCacheStatus == RX_NC_SUCCESS) {
//
// If the cache has not expired, return the previous status.
//
Status = NameCache->PriorStatus;
RxNameCacheOpSaved(NameCacheCtlBasic);
// put the entry back to the active list without changing the expire time
RxNameCacheActivateEntry(NameCacheCtlBasic, NameCache, 0, 0);
DavDbgTrace(DAV_TRACE_INFOCACHE,
(" Get Basic Status : %x %wZ\n",Status,OriginalFileName));
} else {
// put the entry back to the expire list
RxNameCacheExpireEntry(NameCacheCtlBasic, NameCache);
}
} else {
NameCache = RxNameCacheFetchEntry(NameCacheCtlStandard,OriginalFileName);
if (NameCache != NULL) {
RX_NC_CHECK_STATUS NameCacheStatus;
//
// Found it. Now check entry for not expired
//
NameCacheStatus = RxNameCacheCheckEntry(NameCache,NameCache->Context);
if (NameCacheStatus == RX_NC_SUCCESS) {
//
// If the cache has not expired, return the previous status.
//
Status = NameCache->PriorStatus;
RxNameCacheOpSaved(NameCacheCtlStandard);
// put the entry back to the active list without changing the expire time
RxNameCacheActivateEntry(NameCacheCtlStandard, NameCache, 0, 0);
} else {
// put the entry back to the expire list
RxNameCacheExpireEntry(NameCacheCtlStandard, NameCache);
}
}
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
return Status;
}
BOOLEAN
MRxDAVIsFileNotFoundCached(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine checks if the name cache entry exists as File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PAGED_CODE();
return MRxDAVIsFileNotFoundCachedWithName(OriginalFileName,NetRoot);
}
BOOLEAN
MRxDAVIsFileNotFoundCachedWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot
)
/*++
Routine Description:
This routine checks if the name cache entry exists as File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlFNF;
BOOLEAN CacheFound = FALSE;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
RX_NC_CHECK_STATUS NameCacheStatus;
//
// Found it. Now check entry for not expired.
// Note - The NameCache entry has been pulled off the active list.
//
NameCacheStatus = RxNameCacheCheckEntry(
NameCache,
//MRxDAVStatistics.SmbsReceived.LowPart
NameCache->Context);
if ((NameCacheStatus == RX_NC_SUCCESS) &&
(NameCache->PriorStatus == STATUS_OBJECT_NAME_NOT_FOUND)) {
//
// This is a match. Return the old status, file info and
// reactivate the entry but leave expiration time unchanged.
//
CacheFound = TRUE;
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVIsFileNotFoundCached %wZ\n",OriginalFileName));
// put the entry back to the active list without changing the expire time
RxNameCacheActivateEntry(NameCacheCtl, NameCache, 0, 0);
} else {
// put the entry back to the expire list
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
}
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
return CacheFound;
}
VOID
MRxDAVCacheFileNotFound(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine creates the name cache entry for File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PAGED_CODE();
MRxDAVCacheFileNotFoundWithName(OriginalFileName,NetRoot);
}
VOID
MRxDAVCacheFileNotFoundWithName(
PUNICODE_STRING OriginalFileName,
PMRX_NET_ROOT NetRoot
)
/*++
Routine Description:
This routine creates the name cache entry for File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
PNAME_CACHE NameCache = NULL;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlFNF;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
RxNameCacheActivateEntry(
NameCacheCtl,
NameCache,
FileNotFoundCacheLifeTimeInSec,
MRxDAVStatistics.SmbsReceived.LowPart);
} else {
NameCache = RxNameCacheCreateEntry (
NameCacheCtl,
OriginalFileName,
TRUE); // case insensitive match
if (NameCache != NULL) {
NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
RxNameCacheActivateEntry(
NameCacheCtl,
NameCache,
FileNotFoundCacheLifeTimeInSec,
MRxDAVStatistics.SmbsReceived.LowPart);
}
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVCacheFileNotFound %wZ\n",OriginalFileName));
}
VOID
MRxDAVCacheFileNotFoundFromQueryDirectory(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine creates the name cache entry for File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
RxCaptureFobx;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PUNICODE_STRING Template = &capFobx->UnicodeQueryTemplate;
UNICODE_STRING FileName;
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlFNF;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
if (NameCache != NULL) {
if ((NameCache == NULL) &&
(OriginalFileName->Length > sizeof(WCHAR))) {
//
// Do lookup now since we may have skipped it at entry.
//
NameCache = RxNameCacheFetchEntry(NameCacheCtl,&FileName);
if (NameCache == NULL) {
NameCache = RxNameCacheCreateEntry (
NameCacheCtl,
OriginalFileName,
TRUE); // case insensitive match
}
}
if (NameCache != NULL) {
NameCache->PriorStatus = STATUS_OBJECT_NAME_NOT_FOUND;
RxNameCacheActivateEntry(
NameCacheCtl,
NameCache,
FileNotFoundCacheLifeTimeInSec,
MRxDAVStatistics.SmbsReceived.LowPart);
}
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}
VOID
MRxDAVInvalidateFileNotFoundCache(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine invalidates the name cache entry as File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
PUNICODE_STRING OriginalFileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlFNF;
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,OriginalFileName);
if (NameCache != NULL) {
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
DavDbgTrace(DAV_TRACE_INFOCACHE,
("MRxDAVInvalidateFileNotFoundCache %wZ\n",OriginalFileName));
}
VOID
MRxDAVInvalidateFileNotFoundCacheForRename(
PRX_CONTEXT RxContext
)
/*++
Routine Description:
This routine invalidates the name cache entry as File Not Found.
Arguments:
RxContext - the RDBSS context
Return Value:
BOOLEAN - name cache found
--*/
{
RxCaptureFcb;
UNICODE_STRING RenameName;
PNAME_CACHE NameCache = NULL;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PWEBDAV_NET_ROOT DavNetRoot = (PWEBDAV_NET_ROOT)NetRoot->Context;
PNAME_CACHE_CONTROL NameCacheCtl = &DavNetRoot->NameCacheCtlFNF;
PFILE_RENAME_INFORMATION RenameInformation = RxContext->Info.Buffer;
RenameName.Buffer = &RenameInformation->FileName[0];
RenameName.Length = (USHORT)RenameInformation->FileNameLength;
DavDbgTrace(DAV_TRACE_DETAIL,
("Invalidate FNF cache from rename %wZ\n", &RenameName));
PAGED_CODE();
ExAcquireFastMutex(&MRxDAVFileInfoCacheLock);
NameCache = RxNameCacheFetchEntry(NameCacheCtl,&RenameName);
if (NameCache != NULL) {
RxNameCacheExpireEntry(NameCacheCtl, NameCache);
}
ExReleaseFastMutex(&MRxDAVFileInfoCacheLock);
}