/*++ Copyright (c) 1990 Microsoft Corporation Module Name: cache.c Abstract: This module implements the cache management routines for the Rx FSD and FSP, by calling the Common Cache Manager. Author: JoeLinn Created. Revision History: --*/ #include "precomp.h" #pragma hdrstop // // The Bug check file id for this module // #define BugCheckFileId (RDBSS_BUG_CHECK_CACHESUP) // // Local debug trace level // #define Dbg (DEBUG_TRACE_CACHESUP) BOOLEAN RxLockEnumerator ( IN OUT PMRX_SRV_OPEN SrvOpen, IN OUT PVOID *ContinuationHandle, OUT PLARGE_INTEGER FileOffset, OUT PLARGE_INTEGER LockRange, OUT PBOOLEAN IsLockExclusive ); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, RxCompleteMdl) //#pzragma alloc_text(PAGE, RxZeroData) #pragma alloc_text(PAGE, RxSyncUninitializeCacheMap) #pragma alloc_text(PAGE, RxLockEnumerator) #endif // // we can't use the Io system exported form of this because he does it on a file object. during a state // change, we don't know which fileobject it applies to (although, i suppose we could walk the list and // find out). so we need to apply this to the fcb instead. // #define RxIsFcbOpenedExclusively( FCB ) (((FCB)->ShareAccess.SharedRead \ + (FCB)->ShareAccess.SharedWrite \ + (FCB)->ShareAccess.SharedDelete) == 0) NTSTATUS RxCompleteMdl ( IN PRX_CONTEXT RxContext, IN PIRP Irp ) /*++ Routine Description: This routine performs the function of completing Mdl read and write requests. It should be called only from RxFsdRead and RxFsdWrite. Arguments: RxContext - the Rx Context Return Value: RXSTATUS - Will always be RxStatus(PENDING) or STATUS_SUCCESS. --*/ { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); PFILE_OBJECT FileObject = IrpSp->FileObject; PAGED_CODE(); RxDbgTrace( +1, Dbg, ("RxCompleteMdl\n", 0 )); RxDbgTrace( 0, Dbg, ("RxContext = %08lx\n", RxContext )); RxDbgTrace( 0, Dbg, ("Irp = %08lx\n", Irp )); switch( RxContext->MajorFunction ) { case IRP_MJ_READ: CcMdlReadComplete( FileObject, Irp->MdlAddress ); break; case IRP_MJ_WRITE: ASSERT( FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT )); CcMdlWriteComplete( FileObject, &IrpSp->Parameters.Write.ByteOffset, Irp->MdlAddress ); Irp->IoStatus.Status = STATUS_SUCCESS; break; default: RxDbgTrace( 0, (DEBUG_TRACE_ERROR), ("Illegal Mdl Complete.\n", 0 )); RxBugCheck( RxContext->MajorFunction, 0, 0 ); } // // Mdl is now deallocated. // Irp->MdlAddress = NULL; // // Complete the request and exit right away. // RxCompleteRequest( RxContext, STATUS_SUCCESS ); RxDbgTrace(-1, Dbg, ("RxCompleteMdl -> RxStatus(SUCCESS\n)", 0 )); return STATUS_SUCCESS; } VOID RxSyncUninitializeCacheMap ( IN PRX_CONTEXT RxContext, IN PFILE_OBJECT FileObject ) /*++ Routine Description: The routine performs a CcUnitializeCacheMap to LargeZero synchronously. That is it waits on the Cc event. This call is useful when we want to be certain when a close will actually some in. Return Value: None. --*/ { CACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent; NTSTATUS WaitStatus; PAGED_CODE(); KeInitializeEvent( &UninitializeCompleteEvent.Event, SynchronizationEvent, FALSE ); CcUninitializeCacheMap( FileObject, &RxLargeZero, &UninitializeCompleteEvent ); // // Now wait for the cache manager to finish purging the file. // This will garentee that Mm gets the purge before we // delete the Vcb. // WaitStatus = KeWaitForSingleObject( &UninitializeCompleteEvent.Event, Executive, KernelMode, FALSE, NULL); ASSERT( NT_SUCCESS( WaitStatus )); } BOOLEAN RxLockEnumerator ( IN OUT PMRX_SRV_OPEN SrvOpen, IN OUT PVOID *ContinuationHandle, OUT PLARGE_INTEGER FileOffset, OUT PLARGE_INTEGER LockRange, OUT PBOOLEAN IsLockExclusive ) /*++ Routine Description: This routine is called from a minirdr to enumerate the filelocks on an FCB; it gets one lock on each call. currently, we just pass thru to the fsrtl routine which is very funky because it keeps the enumeration state internally; as a result, only one enumeration can be in progress at any time. we can change over to something better if it's ever required. Arguments: SrvOpen - a srvopen on the fcb to be enumerated. ContinuationHandle - a handle passed back and forth representing the state of the enumeration. if a NULL is passed in, then we are to start at the beginning. FileOffset,LockRange,IsLockExclusive - the description of the returned lock Return Value: a BOOLEAN. FALSE means you've reached the end of the list; TRUE means the returned lock data is valid --*/ { PFILE_LOCK_INFO LockInfo; ULONG LockNumber; PFCB Fcb = ((PSRV_OPEN)SrvOpen)->Fcb; PAGED_CODE(); RxDbgTrace( 0, Dbg, ("FCB (%lx) LOCK Enumeration Buffering Flags(%lx)\n", Fcb, Fcb->FcbState) ); if (!FlagOn( Fcb->FcbState, FCB_STATE_LOCK_BUFFERING_ENABLED )) { return FALSE; } LockNumber = PtrToUlong( *ContinuationHandle ); LockInfo = FsRtlGetNextFileLock( &Fcb->FileLock, (BOOLEAN)(LockNumber == 0) ); LockNumber += 1; if (LockInfo == NULL) { return FALSE; } RxDbgTrace( 0, Dbg, ("Rxlockenum %08lx\n", LockNumber )); *FileOffset = LockInfo->StartingByte; *LockRange = LockInfo->Length; *IsLockExclusive = LockInfo->ExclusiveLock; *ContinuationHandle = LongToPtr( LockNumber ); return TRUE; }