369 lines
11 KiB
C
369 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
write.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the mini redirector call down routines pertaining
|
|||
|
to write of file system objects.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Balan Sethu Raman [SethuR] 7-March-1995
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// The local debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_WRITE)
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// External declartions
|
|||
|
//
|
|||
|
NTSTATUS
|
|||
|
MRxProxyWriteContinuation(
|
|||
|
MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MRxProxyWrite(
|
|||
|
IN PRX_CONTEXT RxContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles network read requests.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RxContext - the RDBSS context
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - The return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
//RxCaptureFcb; RxCaptureFobx;
|
|||
|
//PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("MRxProxyWrite\n", 0 ));
|
|||
|
//in outerwrapper ASSERT( NodeType(capFobx->pSrvOpen) == RDBSS_NTC_SRVOPEN );
|
|||
|
|
|||
|
Status = MRxProxyAsyncEngineOuterWrapper(
|
|||
|
RxContext,
|
|||
|
MRXPROXY_ASYNCENG_CTX_FROM_WRITE,
|
|||
|
MRxProxyWriteContinuation,
|
|||
|
"MRxProxyWrite",
|
|||
|
FALSE, //loudprocessing
|
|||
|
FALSE
|
|||
|
);
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("MRxProxyWrite exit with status=%08lx\n", Status ));
|
|||
|
return(Status);
|
|||
|
|
|||
|
} // MRxProxyWrite
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MRxProxyWriteContinuation(
|
|||
|
MRXPROXY_ASYNCENGINE_ARGUMENT_SIGNATURE
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the start routine for read.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - The return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status; //this is initialized to proxybufstatus on a reenter
|
|||
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|||
|
ULONG ContinueEntryCount;
|
|||
|
|
|||
|
RxCaptureFcb; RxCaptureFobx;
|
|||
|
//PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
|
|||
|
//PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
|
|||
|
PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
|
|||
|
|
|||
|
BOOLEAN SynchronousIo =
|
|||
|
!BooleanFlagOn(RxContext->Flags,RX_CONTEXT_FLAG_ASYNC_OPERATION);
|
|||
|
BOOLEAN PagingIo =
|
|||
|
BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,LOWIO_READWRITEFLAG_PAGING_IO);
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("MRxProxyWriteContinuation\n", 0 ));
|
|||
|
|
|||
|
ASSERT_ASYNCENG_CONTEXT(AsyncEngineContext);
|
|||
|
|
|||
|
AsyncEngineContext->ContinueEntryCount++;
|
|||
|
ContinueEntryCount = AsyncEngineContext->ContinueEntryCount;
|
|||
|
|
|||
|
|
|||
|
for (;;) {
|
|||
|
//
|
|||
|
// Case on the current state
|
|||
|
//
|
|||
|
|
|||
|
switch (AsyncEngineContext->OpSpecificState) {
|
|||
|
|
|||
|
case MRxProxyAsyncEngOEInnerIoStates_Initial:
|
|||
|
AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_ReadyToSend;
|
|||
|
|
|||
|
//
|
|||
|
// If not a synchronous write, then continue here when resumed
|
|||
|
//
|
|||
|
// CODE.IMPROVEMENT don't use presense of continuation as the async marker...use a flag
|
|||
|
if (!SynchronousIo) {
|
|||
|
SetFlag(AsyncEngineContext->Flags,MRXPROXY_ASYNCENG_CTX_FLAG_ASYNC_OPERATION);
|
|||
|
AsyncEngineContext->Continuation = MRxProxyWriteContinuation;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//lack of break is intentional
|
|||
|
|
|||
|
case MRxProxyAsyncEngOEInnerIoStates_ReadyToSend:
|
|||
|
AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_OperationOutstanding;
|
|||
|
|
|||
|
if (PagingIo) {
|
|||
|
if (TRUE) {
|
|||
|
RxLog(("PageWrite: rx/offset/len %lx/%lx/%lx",
|
|||
|
RxContext,
|
|||
|
(ULONG)(LowIoContext->ParamsFor.ReadWrite.ByteOffset),
|
|||
|
LowIoContext->ParamsFor.ReadWrite.ByteCount
|
|||
|
));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Status = MRxProxyBuildAsynchronousRequest(
|
|||
|
RxContext, // IN PVOID Context
|
|||
|
MRxProxyAsyncEngineCalldownIrpCompletion // IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
|
|||
|
);
|
|||
|
|
|||
|
if (Status != STATUS_SUCCESS) {
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
Status = MRxProxySubmitAsyncEngRequest(
|
|||
|
MRXPROXY_ASYNCENGINE_ARGUMENTS,
|
|||
|
MRXPROXY_ASYNCENG_AECTXTYPE_WRITE
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If the status is PENDING, then we're done for now. We must
|
|||
|
// wait until we're re-entered when the receive happens.
|
|||
|
//
|
|||
|
|
|||
|
if (Status==(STATUS_PENDING)) {
|
|||
|
ASSERT(!SynchronousIo);
|
|||
|
goto FINALLY;
|
|||
|
}
|
|||
|
|
|||
|
AsyncEngineContext->Status = Status;
|
|||
|
//lack of break is intentional
|
|||
|
|
|||
|
case MRxProxyAsyncEngOEInnerIoStates_OperationOutstanding:
|
|||
|
|
|||
|
AsyncEngineContext->OpSpecificState = MRxProxyAsyncEngOEInnerIoStates_ReadyToSend;
|
|||
|
Status = AsyncEngineContext->Status;
|
|||
|
RxContext->InformationToReturn += AsyncEngineContext->Information;
|
|||
|
goto FINALLY;
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
FINALLY:
|
|||
|
//CODE.IMPROVEMENT read_start and write_start and locks_start should be combined.....we use this
|
|||
|
//macro until then to keep the async stuff identical
|
|||
|
if ( Status != (STATUS_PENDING) ) {
|
|||
|
MRxProxyAsyncEngAsyncCompletionIfNecessary(AsyncEngineContext,RxContext);
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("MRxProxyWriteContinuation exit w %08lx\n", Status ));
|
|||
|
return Status;
|
|||
|
} // ProxyPseExchangeStart_Write
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MRxProxyExtendForCache(
|
|||
|
IN OUT PRX_CONTEXT RxContext,
|
|||
|
IN OUT PLARGE_INTEGER pNewFileSize,
|
|||
|
OUT PLARGE_INTEGER pNewAllocationSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine extends the file allocation so that the we can do a copywrite. the fcb lock
|
|||
|
is exclusive here; we will take the opportunity to find out the actual allocation so that
|
|||
|
we'll get the fast path. another minirdr might want to guess instead since it might be actual net ios
|
|||
|
otherwise.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RxContext - the RDBSS context
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - Returns the status for the set file allocation...could be an error if disk full
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
//PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
|
|||
|
|
|||
|
RxCaptureFcb; RxCaptureFobx;
|
|||
|
//PMRX_PROXY_FOBX proxyFobx = MRxProxyGetFileObjectExtension(capFobx);
|
|||
|
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
|
|||
|
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
|
|||
|
//PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
|
|||
|
PFILE_OBJECT UnderlyingFileObject = proxySrvOpen->UnderlyingFileObject;
|
|||
|
|
|||
|
PFILE_ALLOCATION_INFORMATION Buffer;
|
|||
|
FILE_ALLOCATION_INFORMATION FileAllocationInformationBuffer;
|
|||
|
ULONG Length = sizeof(FILE_ALLOCATION_INFORMATION);
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("MRxProxyExtendForNonCache %08lx %08lx %08lx %08lx\n",
|
|||
|
capFcb->Header.FileSize.LowPart,
|
|||
|
capFcb->Header.AllocationSize.LowPart,
|
|||
|
pNewFileSize->LowPart,
|
|||
|
pNewAllocationSize->LowPart
|
|||
|
));
|
|||
|
|
|||
|
Buffer = &FileAllocationInformationBuffer;
|
|||
|
ASSERT (UnderlyingFileObject);
|
|||
|
|
|||
|
//don't need this!!!
|
|||
|
//if (capFcb->Header.AllocationSize.QuadPart >= *pNewFileSize) {
|
|||
|
// Status = RxStatus(SUCCESS);
|
|||
|
// RxDbgTrace(-1, Dbg, (" PlentyAllocation = %08lx\n", Status));
|
|||
|
// return(Status);
|
|||
|
//}
|
|||
|
|
|||
|
//pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
|
|||
|
{ LONGLONG CurrentExtend = pNewFileSize->QuadPart - capFcb->Header.AllocationSize.QuadPart;
|
|||
|
Buffer->AllocationSize.QuadPart = capFcb->Header.AllocationSize.QuadPart
|
|||
|
+ 32 * CurrentExtend;
|
|||
|
}
|
|||
|
RxDbgTrace( 0, Dbg, (" Extending to %08lx from %08lx!\n",
|
|||
|
Buffer->AllocationSize.LowPart,
|
|||
|
capFcb->Header.AllocationSize.LowPart));
|
|||
|
Status = MRxProxySyncXxxInformation(
|
|||
|
RxContext, //IN OUT PRX_CONTEXT RxContext,
|
|||
|
IRP_MJ_SET_INFORMATION, //IN UCHAR MajorFunction,
|
|||
|
UnderlyingFileObject, //IN PFILE_OBJECT FileObject,
|
|||
|
FileAllocationInformation, //IN ULONG InformationClass,
|
|||
|
Length, //IN ULONG Length,
|
|||
|
Buffer, //OUT PVOID Information,
|
|||
|
NULL //OUT PULONG ReturnedLength OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
//CODE.IMPROVEMENT here we should now read it back and see what we actually got;
|
|||
|
// for smallio we will be seeing subcluster extension when, in fact, we get a
|
|||
|
// cluster at a time. we could just round it up.
|
|||
|
|
|||
|
if (Status == STATUS_SUCCESS) {
|
|||
|
*pNewAllocationSize = Buffer->AllocationSize;
|
|||
|
RxDbgTrace(-1, Dbg, (" ---->Status (extend1) = %08lx\n", Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace( 0, Dbg, (" EXTEND1 FAILED!!!!!!%c\n", '!'));
|
|||
|
|
|||
|
//try for exactly what we need
|
|||
|
|
|||
|
Buffer->AllocationSize.QuadPart = pNewFileSize->QuadPart;
|
|||
|
Status = MRxProxySyncXxxInformation(
|
|||
|
RxContext, //IN OUT PRX_CONTEXT RxContext,
|
|||
|
IRP_MJ_SET_INFORMATION, //IN UCHAR MajorFunction,
|
|||
|
UnderlyingFileObject, //IN PFILE_OBJECT FileObject,
|
|||
|
FileAllocationInformation, //IN ULONG InformationClass,
|
|||
|
Length, //IN ULONG Length,
|
|||
|
Buffer, //OUT PVOID Information,
|
|||
|
NULL //OUT PULONG ReturnedLength OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
if (Status == STATUS_SUCCESS) {
|
|||
|
*pNewAllocationSize = Buffer->AllocationSize;
|
|||
|
RxDbgTrace(-1, Dbg, (" ---->Status (extend2) = %08lx\n", Status));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace( 0, Dbg, (" EXTEND2 FAILED!!!!!!%c\n", '!'));
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, (" ---->Status (notextended) = %08lx\n", Status));
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
MRxProxyExtendForNonCache(
|
|||
|
IN OUT PRX_CONTEXT RxContext,
|
|||
|
IN OUT PLARGE_INTEGER pNewFileSize,
|
|||
|
OUT PLARGE_INTEGER pNewAllocationSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles requests to extend the file for noncached IO. we just let the write extend the file
|
|||
|
so we don't do anything here.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
RxContext - the RDBSS context
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
RXSTATUS - The return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
RxCaptureFcb; RxCaptureFobx;
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("MRxProxyExtendForNonCache %08lx %08lx %08lx %08lx\n",
|
|||
|
capFcb->Header.FileSize.LowPart,
|
|||
|
capFcb->Header.AllocationSize.LowPart,
|
|||
|
pNewFileSize->LowPart,
|
|||
|
pNewAllocationSize->LowPart
|
|||
|
));
|
|||
|
pNewAllocationSize->QuadPart = pNewFileSize->QuadPart;
|
|||
|
RxDbgTrace(-1, Dbg, ("MRxProxyExtendForCache exit with status=%08lx %08lx %08lx\n",
|
|||
|
Status, pNewFileSize->LowPart, pNewAllocationSize->LowPart));
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|