/*++ Copyright (c) 1989 - 1999 Microsoft Corporation Module Name: openclos.c Abstract: This module implements the mini redirector call down routines pertaining to opening/ closing of file/directories. --*/ #include "precomp.h" #pragma hdrstop // // The debug trace level // #define Dbg (DEBUG_TRACE_CREATE) // // forwards & pragmas // NTSTATUS NulMRxProcessCreate( IN PNULMRX_FCB_EXTENSION pFcbExtension, IN PVOID EaBuffer, IN ULONG EaLength, OUT PLONGLONG pEndOfFile, OUT PLONGLONG pAllocationSize ); NTSTATUS NulMRxCreateFileSuccessTail ( PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, ULONG CreateAction, FILE_BASIC_INFORMATION* pFileBasicInfo, FILE_STANDARD_INFORMATION* pFileStandardInfo ); VOID NulMRxSetSrvOpenFlags ( PRX_CONTEXT RxContext, RX_FILE_TYPE StorageType, PMRX_SRV_OPEN SrvOpen ); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, NulMRxCreate) #pragma alloc_text(PAGE, NulMRxShouldTryToCollapseThisOpen) #pragma alloc_text(PAGE, NulMRxProcessCreate) #pragma alloc_text(PAGE, NulMRxCreateFileSuccessTail) #pragma alloc_text(PAGE, NulMRxSetSrvOpenFlags) #endif NTSTATUS NulMRxShouldTryToCollapseThisOpen ( IN PRX_CONTEXT RxContext ) /*++ Routine Description: This routine determines if the mini knows of a good reason not to try collapsing on this open. Presently, the only reason would be if this were a copychunk open. Arguments: RxContext - the RDBSS context Return Value: NTSTATUS - The return status for the operation SUCCESS --> okay to try collapse other (MORE_PROCESSING_REQUIRED) --> dont collapse --*/ { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFcb; PAGED_CODE(); return Status; } NTSTATUS NulMRxCreate( IN OUT PRX_CONTEXT RxContext ) /*++ Routine Description: This routine opens a file across the network Arguments: RxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; BOOLEAN fMustRegainExclusiveResource = FALSE; RX_FILE_TYPE StorageType = FileTypeFile; ULONG CreateAction = FILE_CREATED; LARGE_INTEGER liSystemTime; LONGLONG EndOfFile = 0, AllocationSize = 0; FILE_BASIC_INFORMATION FileBasicInfo; FILE_STANDARD_INFORMATION FileStandardInfo; RxCaptureFcb; NulMRxGetFcbExtension(capFcb,pFcbExtension); RX_BLOCK_CONDITION FinalSrvOpenCondition; PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall; PMRX_NET_ROOT NetRoot = capFcb->pNetRoot; PUNICODE_STRING RemainingName = SrvOpen->pAlreadyPrefixedName; PVOID EaBuffer = RxContext->Create.EaBuffer; ULONG EaLength = RxContext->Create.EaLength; ACCESS_MASK DesiredAccess = RxContext->Create.NtCreateParameters.DesiredAccess; NulMRxGetNetRootExtension(NetRoot,pNetRootExtension); RxTraceEnter("NulMRxCreate"); PAGED_CODE(); RxDbgTrace(0, Dbg, (" Attempt to open %wZ Len is %d\n", RemainingName, RemainingName->Length )); if( NetRoot->Type == NET_ROOT_DISK && NT_SUCCESS(Status) ) { RxDbgTrace(0, Dbg, ("NulMRxCreate: Type supported \n")); // // Squirrel away the scatter list in the FCB extension. // This is done only for data files. // Status = NulMRxProcessCreate( pFcbExtension, EaBuffer, EaLength, &EndOfFile, &AllocationSize ); if( Status != STATUS_SUCCESS ) { // // error.. // RxDbgTrace(0, Dbg, ("Failed to initialize scatter list\n")); goto Exit; } // // Complete CreateFile contract // RxDbgTrace(0,Dbg,("EOF is %d AllocSize is %d\n",(ULONG)EndOfFile,(ULONG)AllocationSize)); FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; KeQuerySystemTime(&liSystemTime); FileBasicInfo.CreationTime = liSystemTime; FileBasicInfo.LastAccessTime = liSystemTime; FileBasicInfo.LastWriteTime = liSystemTime; FileBasicInfo.ChangeTime = liSystemTime; FileStandardInfo.AllocationSize.QuadPart = AllocationSize; FileStandardInfo.EndOfFile.QuadPart = EndOfFile; FileStandardInfo.NumberOfLinks = 0; Status = NulMRxCreateFileSuccessTail ( RxContext, &fMustRegainExclusiveResource, StorageType, CreateAction, &FileBasicInfo, &FileStandardInfo ); if( Status != STATUS_SUCCESS ) { // // alloc error.. // RxDbgTrace(0, Dbg, ("Failed to allocate Fobx \n")); goto Exit; } if (!RxIsFcbAcquiredExclusive(capFcb)) { ASSERT(!RxIsFcbAcquiredShared(capFcb)); RxAcquireExclusiveFcbResourceInMRx( capFcb ); } } else { RxDbgTrace(0, Dbg, ("NulMRxCreate: Type not supported or invalid open\n")); Status = STATUS_NOT_IMPLEMENTED; } ASSERT(Status != (STATUS_PENDING)); ASSERT(RxIsFcbAcquiredExclusive( capFcb )); RxDbgTrace(0, Dbg, ("NetRoot is 0x%x Fcb is 0x%x SrvOpen is 0x%x Fobx is 0x%x\n", NetRoot,capFcb, SrvOpen,RxContext->pFobx)); RxDbgTrace(0, Dbg, ("NulMRxCreate exit with status=%08lx\n", Status )); Exit: RxTraceLeave(Status); return(Status); } NTSTATUS NulMRxProcessCreate( IN PNULMRX_FCB_EXTENSION pFcbExtension, IN PVOID EaBuffer, IN ULONG EaLength, OUT PLONGLONG pEndOfFile, OUT PLONGLONG pAllocationSize ) /*++ Routine Description: This routine processes a create calldown. Arguments: pFcbExtension - ptr to the FCB extension EaBuffer - ptr to the EA param buffer EaLength - len of EaBuffer pEndOfFile - return end of file value pAllocationSize - return allocation size (which maybe > EOF) Notes: It is possible to create a file with no EAs Return Value: None --*/ { NTSTATUS Status = STATUS_SUCCESS; RxDbgTrace(0, Dbg, ("NulMRxInitializeFcbExtension\n")); *pAllocationSize = *pEndOfFile = 0; return Status; } VOID NulMRxSetSrvOpenFlags ( PRX_CONTEXT RxContext, RX_FILE_TYPE StorageType, PMRX_SRV_OPEN SrvOpen ) { PMRX_SRV_CALL SrvCall = (PMRX_SRV_CALL)RxContext->Create.pSrvCall; // // set this only if cache manager will be used for mini-rdr handles ! // SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHING_ENABLED | FCB_STATE_FILESIZECACHEING_ENABLED | FCB_STATE_FILETIMECACHEING_ENABLED | FCB_STATE_WRITEBUFFERING_ENABLED | FCB_STATE_LOCK_BUFFERING_ENABLED | FCB_STATE_READBUFFERING_ENABLED | FCB_STATE_READCACHING_ENABLED); } NTSTATUS NulMRxCreateFileSuccessTail ( PRX_CONTEXT RxContext, PBOOLEAN MustRegainExclusiveResource, RX_FILE_TYPE StorageType, ULONG CreateAction, FILE_BASIC_INFORMATION* pFileBasicInfo, FILE_STANDARD_INFORMATION* pFileStandardInfo ) /*++ Routine Description: This routine finishes the initialization of the fcb and srvopen for a successful open. Arguments: Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFcb; PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; FCB_INIT_PACKET InitPacket; RxDbgTrace(0, Dbg, ("MRxExCreateFileSuccessTail\n")); PAGED_CODE(); ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN ); ASSERT( NodeType(RxContext) == RDBSS_NTC_RX_CONTEXT ); if (*MustRegainExclusiveResource) { //this is required because of oplock breaks RxAcquireExclusiveFcbResourceInMRx( capFcb ); *MustRegainExclusiveResource = FALSE; } // This Fobx should be cleaned up by the wrapper RxContext->pFobx = RxCreateNetFobx( RxContext, SrvOpen); if( RxContext->pFobx == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; } ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) ); RxDbgTrace(0, Dbg, ("Storagetype %08lx/Action %08lx\n", StorageType, CreateAction )); RxContext->Create.ReturnedCreateInformation = CreateAction; RxFormInitPacket( InitPacket, &pFileBasicInfo->FileAttributes, &pFileStandardInfo->NumberOfLinks, &pFileBasicInfo->CreationTime, &pFileBasicInfo->LastAccessTime, &pFileBasicInfo->LastWriteTime, &pFileBasicInfo->ChangeTime, &pFileStandardInfo->AllocationSize, &pFileStandardInfo->EndOfFile, &pFileStandardInfo->EndOfFile); if (capFcb->OpenCount == 0) { RxFinishFcbInitialization( capFcb, RDBSS_STORAGE_NTC(StorageType), &InitPacket ); } else { ASSERT( StorageType == 0 || NodeType(capFcb) == RDBSS_STORAGE_NTC(StorageType)); } NulMRxSetSrvOpenFlags(RxContext,StorageType,SrvOpen); RxContext->pFobx->OffsetOfNextEaToReturn = 1; //transition happens later return Status; } NTSTATUS NulMRxCollapseOpen( IN OUT PRX_CONTEXT RxContext ) /*++ Routine Description: This routine collapses a open locally Arguments: RxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status; RxCaptureFcb; RxCaptureRequestPacket; PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen; PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall; PMRX_NET_ROOT NetRoot = capFcb->pNetRoot; RxTraceEnter("NulMRxCollapseOpen"); RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen); if (RxContext->pFobx != NULL) { ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) ); RxContext->pFobx->OffsetOfNextEaToReturn = 1; capReqPacket->IoStatus.Information = FILE_OPENED; Status = STATUS_SUCCESS; } else { Status = (STATUS_INSUFFICIENT_RESOURCES); DbgBreakPoint(); } RxTraceLeave(Status); return Status; } NTSTATUS NulMRxComputeNewBufferingState( IN OUT PMRX_SRV_OPEN pMRxSrvOpen, IN PVOID pMRxContext, OUT PULONG pNewBufferingState) /*++ Routine Description: This routine maps specific oplock levels into the appropriate RDBSS buffering state flags Arguments: pMRxSrvOpen - the MRX SRV_OPEN extension pMRxContext - the context passed to RDBSS at Oplock indication time pNewBufferingState - the place holder for the new buffering state Return Value: Notes: --*/ { NTSTATUS Status = STATUS_NOT_IMPLEMENTED; DbgPrint("NulMRxComputeNewBufferingState \n"); return(Status); } NTSTATUS NulMRxDeallocateForFcb ( IN OUT PMRX_FCB pFcb ) { NTSTATUS Status = STATUS_SUCCESS; NulMRxGetFcbExtension(pFcb,pFcbExtension); PMRX_NET_ROOT pNetRoot = pFcb->pNetRoot; NulMRxGetNetRootExtension(pNetRoot,pNetRootExtension); RxTraceEnter("NulMRxDeallocateForFcb\n"); RxTraceLeave(Status); return(Status); } NTSTATUS NulMRxTruncate( IN PRX_CONTEXT pRxContext) /*++ Routine Description: This routine truncates the contents of a file system object Arguments: pRxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { ASSERT(!"Found a truncate"); return STATUS_NOT_IMPLEMENTED; } NTSTATUS NulMRxCleanupFobx( IN PRX_CONTEXT RxContext) /*++ Routine Description: This routine cleansup a file system object...normally a noop. unless it's a pipe in which case we do the close at cleanup time and mark the file as being not open. Arguments: pRxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; PUNICODE_STRING RemainingName; RxCaptureFcb; RxCaptureFobx; NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb); PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen; BOOLEAN SearchHandleOpen = FALSE; PAGED_CODE(); ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN ); ASSERT ( NodeTypeIsFcb(capFcb) ); RxDbgTrace( 0, Dbg, ("NulMRxCleanupFobx\n")); if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) { RxDbgTrace( 0, Dbg, ("File orphaned\n")); return (STATUS_SUCCESS); } if ((capFcb->pNetRoot->Type != NET_ROOT_PIPE) && !SearchHandleOpen) { RxDbgTrace( 0, Dbg, ("File not for closing at cleanup\n")); return (STATUS_SUCCESS); } RxDbgTrace( 0, Dbg, ("NulMRxCleanup exit with status=%08lx\n", Status )); return(Status); } NTSTATUS NulMRxForcedClose( IN PMRX_SRV_OPEN pSrvOpen) /*++ Routine Description: This routine closes a file system object Arguments: pSrvOpen - the instance to be closed Return Value: RXSTATUS - The return status for the operation Notes: --*/ { RxDbgTrace( 0, Dbg, ("NulMRxForcedClose\n")); return STATUS_SUCCESS; } // // The local debug trace level // #undef Dbg #define Dbg (DEBUG_TRACE_CLOSE) NTSTATUS NulMRxCloseSrvOpen( IN PRX_CONTEXT RxContext ) /*++ Routine Description: This routine closes a file across the network Arguments: RxContext - the RDBSS context Return Value: RXSTATUS - The return status for the operation --*/ { NTSTATUS Status = STATUS_SUCCESS; RxCaptureFcb; RxCaptureFobx; PMRX_SRV_OPEN pSrvOpen = capFobx->pSrvOpen; PUNICODE_STRING RemainingName = pSrvOpen->pAlreadyPrefixedName; PMRX_SRV_OPEN SrvOpen; NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb); PMRX_NET_ROOT pNetRoot = capFcb->pNetRoot; NulMRxGetNetRootExtension(pNetRoot,pNetRootExtension); RxDbgTrace( 0, Dbg, ("NulMRxCloseSrvOpen \n")); SrvOpen = capFobx->pSrvOpen; return(Status); } NTSTATUS NulMRxDeallocateForFobx ( IN OUT PMRX_FOBX pFobx ) { RxDbgTrace( 0, Dbg, ("NulMRxDeallocateForFobx\n")); return(STATUS_SUCCESS); }