windows-nt/Source/XPSP1/NT/base/fs/rdr2/rdbss/proxy.mrx/openclos.c
2020-09-26 16:20:57 +08:00

1193 lines
36 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
openclos.c
Abstract:
This module implements the mini redirector call down routines pertaining to opening/
closing of file/directories.
Author:
Balan Sethu Raman [SethuR] 7-March-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
////
//// The Bug check file id for this module
////
//
//#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_CREATE)
#ifdef RX_PRIVATE_BUILD
ULONG MRxProxyDbgPrintF = 1; //0; //1;
#endif //ifdef RX_PRIVATE_BUILD
#ifdef RX_PRIVATE_BUILD
#undef IoGetTopLevelIrp
#undef IoSetTopLevelIrp
#endif //ifdef RX_PRIVATE_BUILD
NTSTATUS
MRxProxySyncIrpCompletionRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP CalldownIrp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the calldownirp is completed.
Arguments:
IN PDEVICE_OBJECT DeviceObject,
IN PIRP CalldownIrp,
IN PVOID Context
Return Value:
RXSTATUS - STATUS_MORE_PROCESSING_REQUIRED
--*/
{
PRX_CONTEXT RxContext = (PRX_CONTEXT)Context;
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
if (CalldownIrp->PendingReturned){
//pMRxProxyContext->SyncCallDownIoStatus = CalldownIrp->IoStatus;
RxSignalSynchronousWaiter(RxContext);
}
return(STATUS_MORE_PROCESSING_REQUIRED);
}
//not on the stack...just in case
ULONG DummyReturnedLengthForXxxInfo;
NTSTATUS
MRxProxySyncXxxInformation(
IN OUT PRX_CONTEXT RxContext,
IN UCHAR MajorFunction,
IN PFILE_OBJECT FileObject,
IN ULONG InformationClass,
IN ULONG Length,
OUT PVOID Information,
OUT PULONG ReturnedLength OPTIONAL
)
/*++
Routine Description:
This routine returns the requested information about a specified file
or volume. The information returned is determined by the class that
is specified, and it is placed into the caller's output buffer.
Arguments:
FsInformationClass - Specifies the type of information which should be
returned about the file/volume.
Length - Supplies the length of the buffer in bytes.
FsInformation - Supplies a buffer to receive the requested information
returned about the file. This buffer must not be pageable and must
reside in system space.
ReturnedLength - Supplies a variable that is to receive the length of the
information written to the buffer.
FileInformation - Boolean that indicates whether the information requested
is for a file or a volume.
Return Value:
The status returned is the final completion status of the operation.
--*/
{
NTSTATUS Status;
PIRP irp,TopIrp;
PIO_STACK_LOCATION irpSp;
PDEVICE_OBJECT DeviceObject;
//ULONG SetFileInfoInfo;
PAGED_CODE();
if (ReturnedLength==NULL) {
ReturnedLength = &DummyReturnedLengthForXxxInfo;
}
ASSERT (FileObject);
DeviceObject = IoGetRelatedDeviceObject( FileObject );
ASSERT (DeviceObject);
//
// Allocate and initialize the I/O Request Packet (IRP) for this operation.
// The allocation is performed with an exception handler in case the
// caller does not have enough quota to allocate the packet.
//
irp = IoAllocateIrp( DeviceObject->StackSize, TRUE );
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
irp->Tail.Overlay.OriginalFileObject = FileObject;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->RequestorMode = KernelMode;
//
// Get a pointer to the stack location for the first driver. This will be
// used to pass the original function codes and parameters.
//
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = MajorFunction;
irpSp->FileObject = FileObject;
IoSetCompletionRoutine(irp,
MRxProxySyncIrpCompletionRoutine,
RxContext,
TRUE,TRUE,TRUE); //call no matter what....
irp->AssociatedIrp.SystemBuffer = Information;
//
// Copy the caller's parameters to the service-specific portion of the
// IRP.
//
IF_DEBUG {
ASSERT( (irpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION)
|| (irpSp->MajorFunction == IRP_MJ_SET_INFORMATION)
|| (irpSp->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION) );
if (irpSp->MajorFunction == IRP_MJ_SET_INFORMATION) {
//IF_LOUD_DOWNCALLS(MiniFileObject) {
// SetFileInfoInfo = ((PFILE_END_OF_FILE_INFORMATION)Information)->EndOfFile.LowPart;
//}
}
ASSERT(&irpSp->Parameters.QueryFile.Length == &irpSp->Parameters.SetFile.Length);
ASSERT(&irpSp->Parameters.QueryFile.Length == &irpSp->Parameters.QueryVolume.Length);
ASSERT(&irpSp->Parameters.QueryFile.FileInformationClass
== &irpSp->Parameters.SetFile.FileInformationClass);
ASSERT(&irpSp->Parameters.QueryFile.FileInformationClass
== &irpSp->Parameters.QueryVolume.FsInformationClass);
}
irpSp->Parameters.QueryFile.Length = Length;
irpSp->Parameters.QueryFile.FileInformationClass = InformationClass;
//
// Now simply invoke the driver at its dispatch entry with the IRP.
//
KeInitializeEvent( &RxContext->SyncEvent,
NotificationEvent,
FALSE );
//LoudCallsDbgPrint("Ready to",
// MiniFileObject,
// irpSp->MajorFunction,
// irpSp->Parameters.QueryFile.FileInformationClass,
// irpSp->Parameters.QueryFile.Length,
// SetFileInfoInfo,0,0
// );
try {
TopIrp = IoGetTopLevelIrp();
IoSetTopLevelIrp(NULL); //tell the underlying guy he's all clear
Status = IoCallDriver(DeviceObject,irp);
} finally {
IoSetTopLevelIrp(TopIrp); //restore my context for unwind
}
//RxDbgTrace (0, Dbg, (" -->Status after iocalldriver %08lx(%08lx)\n",RxContext,Status));
if (Status == (STATUS_PENDING)) {
RxWaitSync(RxContext);
Status = irp->IoStatus.Status;
}
//LoudCallsDbgPrint("Back from",
// MiniFileObject,
// irpSp->MajorFunction,
// irpSp->Parameters.QueryFile.FileInformationClass,
// irpSp->Parameters.QueryFile.Length,
// SetFileInfoInfo,
// Status,irp->IoStatus.Information
// );
if (Status==STATUS_SUCCESS) {
*ReturnedLength = irp->IoStatus.Information;
RxDbgTrace( 0, Dbg, ("MRxProxySyncXxxInformation(%x)Info<%x> %x bytes@%x returns %08lx/%08lx\n",
RxContext,MajorFunction,
Status,*ReturnedLength));
}
IoFreeIrp(irp);
return(Status);
}
NTSTATUS
MRxProxyShouldTryToCollapseThisOpen (
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;
PAGED_CODE();
return Status;
}
VOID
MRxProxyMungeBufferingIfWriteOnlyHandles (
ULONG WriteOnlySrvOpenCount,
PMRX_SRV_OPEN SrvOpen
)
/*++
Routine Description:
This routine modifies the buffering flags on a srvopen so that
no cacheing will be allowed if there are any write-only handles
to the file. CODE.IMPROVEMENT this should be inlined.
Arguments:
WriteOnlySrvOpenCount - the number of writeonly srvopens
SrvOpen - the srvopen whose buffring flags are to be munged
Return Value:
RXSTATUS - The return status for the operation
--*/
{
BOOLEAN IsLoopBack = FALSE;
PMRX_SRV_CALL pSrvCall;
//PSMBCEDB_SERVER_ENTRY pServerEntry;
pSrvCall = SrvOpen->pVNetRoot->pNetRoot->pSrvCall;
#if 0
pServerEntry = SmbCeReferenceAssociatedServerEntry(pSrvCall);
ASSERT(pServerEntry != NULL);
IsLoopBack = pServerEntry->Server.IsLoopBack;
SmbCeDereferenceServerEntry(pServerEntry);
#endif
if (!IsLoopBack && (WriteOnlySrvOpenCount==0)) {
return;
}
SrvOpen->BufferingFlags &=
~( FCB_STATE_WRITECACHEING_ENABLED |
FCB_STATE_FILESIZECACHEING_ENABLED |
FCB_STATE_FILETIMECACHEING_ENABLED |
FCB_STATE_LOCK_BUFFERING_ENABLED |
FCB_STATE_READCACHEING_ENABLED |
FCB_STATE_COLLAPSING_ENABLED
);
}
ULONG MRxProxyLoudStringTableSize = 0;
UNICODE_STRING MRxProxyLoudStrings[50];
VOID
MRxProxySetLoud(
IN PBYTE Msg,
IN PRX_CONTEXT RxContext,
IN PUNICODE_STRING s
)
{
ULONG i;
UNICODE_STRING temp;
for (i=0;i<MRxProxyLoudStringTableSize;i++) {
PUNICODE_STRING t = &(MRxProxyLoudStrings[i]);
((PBYTE)temp.Buffer) = ((PBYTE)s->Buffer) + s->Length - t->Length;
temp.Length = t->Length;
//DbgPrint("%s %lx Comparing %wZ with %wZ from %wZ\n",Msg,t->Length,&temp,t,s);
if (RtlEqualUnicodeString(&temp,t,TRUE)) {
DbgPrint("%s Found %wZ from %wZ\n",Msg,t,s);
RxContext->LoudCompletionString = t;
break;
}
}
}
VOID
MRxProxyInitializeLoudStrings(
void
)
{
RtlInitUnicodeString(&MRxProxyLoudStrings[0],L"xsync.exe");
//RtlInitUnicodeString(&MRxProxyLoudStrings[1],L"calc.exe");
//RtlInitUnicodeString(&MRxProxyLoudStrings[2],L"ecco.exe");
MRxProxyLoudStringTableSize = 1;
}
#define MustBeDirectory(co) ((co) & FILE_DIRECTORY_FILE)
#define MustBeFile(co) ((co) & FILE_NON_DIRECTORY_FILE)
// define structures for posting of open and close calls so that they end up in the
// system process.
typedef
NTSTATUS
(*PMRX_PROXY_POSTABLE_OPERATION) (
IN OUT PRX_CONTEXT RxContext
);
#if 0
typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER {
PRX_CONTEXT RxContext;
union {
NTSTATUS PostReturnStatus;
RX_WORK_QUEUE_ITEM WorkQueueItem;
};
KEVENT PostEvent;
} MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER;
typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT {
union {
MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER;
MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT_LOWER PostedOpContext;
};
} MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT, *PMRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;;
typedef struct _MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT {
MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;
} MRX_PROXY_POSTED_CREATE_CONTEXT, *PMRX_PROXY_POSTED_CREATE_CONTEXT;
typedef struct _MRX_PROXY_POSTED_CLOSE_CONTEXT {
MRX_PROXY_COMMON_POSTED_OPERATION_CONTEXT;
} MRX_PROXY_POSTED_CLOSE_CONTEXT, *PMRX_PROXY_POSTED_CLOSE_CONTEXT;
#endif
NTSTATUS
MRxProxyPostOperation (
IN OUT PRX_CONTEXT RxContext,
IN OUT PVOID PostedOpContext,
IN PMRX_PROXY_POSTABLE_OPERATION Operation
)
{
NTSTATUS Status,PostStatus;
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
KeInitializeEvent( &RxContext->SyncEvent,
NotificationEvent,
FALSE );
pMRxProxyContext->PostedOpContext = PostedOpContext;
IF_DEBUG {
//fill the workqueue structure with deadbeef....all the better to diagnose
//a failed post
ULONG i;
for (i=0;i+sizeof(ULONG)-1<sizeof(RxContext->WorkQueueItem);i+=sizeof(ULONG)) {
PBYTE BytePtr = ((PBYTE)&RxContext->WorkQueueItem)+i;
PULONG UlongPtr = (PULONG)BytePtr;
*UlongPtr = 0xdeadbeef;
}
}
PostStatus = RxPostToWorkerThread(
&MRxProxyDeviceObject->RxDeviceObject,
DelayedWorkQueue,
&RxContext->WorkQueueItem,
Operation,
RxContext);
ASSERT(PostStatus == STATUS_SUCCESS);
RxWaitSync(RxContext);
Status = pMRxProxyContext->PostedOpStatus;
return(Status);
}
NTSTATUS
MRxProxyPostedCreate (
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;
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
RxCaptureFcb;
PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
PNT_CREATE_PARAMETERS CreateParameters = &RxContext->Create.NtCreateParameters;
ULONG Disposition = CreateParameters->Disposition;
ACCESS_MASK DesiredAccess = CreateParameters->DesiredAccess & 0x1FF;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE handle;
ULONG FilteredCreateOptions;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxProxyPostedCreate %08lx\n", RxContext ));
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
RxDbgTrace( 0, Dbg, (" Attempt to open %wZ\n", &(capFcb->AlreadyPrefixedName) ));
MRxProxySetLoud("Create ",RxContext,&(capFcb->AlreadyPrefixedName));
#if 0
// we cannot have a file cached on a write only handle. so we have to behave a little
// differently if this is a write-only open. remember this in the proxysrvopen
if ( ((DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
((DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
) {
//SetFlag(proxySrvOpen->Flags,PROXY_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
//SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING;
DesiredAccess |= FILE_READ_DATA;
}
#endif
// we cannot have a file cached on a write only handle. so if write_data is
// specified then so is read data
if ( ((DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA)) == 0) &&
((DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0)
) {
//SetFlag(proxySrvOpen->Flags,PROXY_SRVOPEN_FLAG_WRITE_ONLY_HANDLE);
//SrvOpen->Flags |= SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING;
DesiredAccess |= FILE_READ_DATA;
}
if ( ( DesiredAccess
&~ (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE) )
== 0 ){
SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_NO_BUFFERING_STATE_CHANGE);
}
InitializeObjectAttributes(
&ObjectAttributes,
RemainingName,
OBJ_CASE_INSENSITIVE, // !!! can we do this? probably need a flag BUGBUG
0,
NULL // !!! Security BUGBUG
);
FilteredCreateOptions = CreateParameters->CreateOptions;
if (!MustBeDirectory(FilteredCreateOptions)) {
FilteredCreateOptions &= ~(FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT); //always async
}
FilteredCreateOptions |= FILE_NO_INTERMEDIATE_BUFFERING;
RxDbgTrace( 0, Dbg, (" ---->FilteredCreateOptions = %08lx\n", FilteredCreateOptions));
RxLog(("-->FilteredOptions/oc %lx %lx",FilteredCreateOptions,capFcb->OpenCount));
Status = IoCreateFile(
&handle,
DesiredAccess,
&ObjectAttributes,
&IoStatusBlock,
&CreateParameters->AllocationSize,
CreateParameters->FileAttributes,
CreateParameters->ShareAccess,
CreateParameters->Disposition,
FilteredCreateOptions,
RxContext->Create.EaBuffer,
RxContext->Create.EaLength,
CreateFileTypeNone,
NULL, // extra parameters
IO_NO_PARAMETER_CHECKING
);
if (NT_SUCCESS(Status)) {
Status = ObReferenceObjectByHandle( handle,
0L,
NULL,
KernelMode,
(PVOID *) &proxySrvOpen->UnderlyingFileObject,
NULL );
if (Status == STATUS_SUCCESS) {
proxySrvOpen->UnderlyingHandle = handle;
proxySrvOpen->UnderlyingDeviceObject = IoGetRelatedDeviceObject( proxySrvOpen->UnderlyingFileObject );
} else {
ZwClose(handle);
}
}
RxDbgTrace( 0, Dbg, ("Status of underlying open %08lx\n", Status ));
RxLog(("--->UnderlyingOpen %lx",Status));
// DbgBreakPoint();
RxDbgTrace(-1, Dbg, ("MRxProxyPostedCreate %08lx exit with status=%08lx\n", RxContext, Status ));
if (NT_SUCCESS(Status)) {
RxContext->Create.ReturnedCreateInformation = IoStatusBlock.Information;
}
pMRxProxyContext->PostedOpStatus = Status;
RxSignalSynchronousWaiter(RxContext);
return(STATUS_SUCCESS);
}
NTSTATUS
MRxProxyPostedCloseHandle (
IN OUT PRX_CONTEXT RxContext
)
/*++
Routine Description:
Arguments:
RxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
//NTSTATUS Status;
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
//RxCaptureFcb;
//PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
PMRX_SRV_OPEN SrvOpen = (PMRX_SRV_OPEN)(pMRxProxyContext->PostedOpContext);
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
//HANDLE handle;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxProxyPostedCloseHandle %08lx %08lx\n", RxContext, SrvOpen ));
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
ZwClose(proxySrvOpen->UnderlyingHandle);
RxDbgTrace(-1, Dbg, ("MRxProxyPostedCloseHandle %08lx exit\n", RxContext ));
pMRxProxyContext->PostedOpStatus = STATUS_SUCCESS;
RxSignalSynchronousWaiter(RxContext);
return(STATUS_SUCCESS);
}
NTSTATUS
MRxProxyCreate (
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;
RxCaptureFcb;
PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
BOOLEAN MustRegainExclusiveResource = FALSE;
PAGED_CODE();
RxDbgTrace(+1, Dbg, ("MRxProxyCreate %08lx\n", RxContext ));
//do this BEFORE you drop the resource
SetFlag(SrvOpen->Flags,SRVOPEN_FLAG_COLLAPSING_DISABLED);
Status = MRxProxyPostOperation ( RxContext,
NULL,
MRxProxyPostedCreate );
//this Boolean should be passed......
if (MustRegainExclusiveResource) { //this is required if we do oplock breaks
RxAcquireExclusiveFcb( RxContext, capFcb );
}
if (NT_SUCCESS(Status)) {
RX_FILE_TYPE StorageType;
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
NTSTATUS InfoStatus;
FCB_INIT_PACKET InitPacket;
ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
StorageType = RxInferFileType(RxContext);
RxDbgTrace( 0, Dbg, ("Storagetype %08lx\n", StorageType ));
// if we have never obtained the characteristics, we have to get them.
if ((capFcb->OpenCount == 0)
|| !FlagOn(capFcb->FcbState,FCB_STATE_TIME_AND_SIZE_ALREADY_SET) ) {
InfoStatus = MRxProxySyncXxxInformation(
RxContext, //IN OUT PRX_CONTEXT RxContext,
IRP_MJ_QUERY_INFORMATION, //IN UCHAR MajorFunction,
proxySrvOpen->UnderlyingFileObject,//IN PFILE_OBJECT FileObject,
FileBasicInformation, //IN ULONG InformationClass,
sizeof(BasicInformation), //IN ULONG Length,
&BasicInformation, //OUT PVOID Information,
NULL); //OUT PULONG ReturnedLength OPTIONAL
ASSERT (NT_SUCCESS(InfoStatus)); //BUGBUG what if not@!
InfoStatus = MRxProxySyncXxxInformation(
RxContext, //IN OUT PRX_CONTEXT RxContext,
IRP_MJ_QUERY_INFORMATION, //IN UCHAR MajorFunction,
proxySrvOpen->UnderlyingFileObject,//IN PFILE_OBJECT FileObject,
FileStandardInformation, //IN ULONG InformationClass,
sizeof(StandardInformation),//IN ULONG Length,
&StandardInformation, //OUT PVOID Information,
NULL); //OUT PULONG ReturnedLength OPTIONAL
ASSERT (NT_SUCCESS(InfoStatus));
if (StorageType == 0) {
StorageType = StandardInformation.Directory?(FileTypeDirectory)
:(FileTypeFile);
RxDbgTrace( 0, Dbg, ("ChangedStoragetype %08lx\n", StorageType ));
}
RxDbgTrace( 0, Dbg, ("FileSize %08lx\n", StandardInformation.EndOfFile.LowPart ));
RxFinishFcbInitialization(
capFcb,
RDBSS_STORAGE_NTC(StorageType),
RxFormInitPacket(
InitPacket, //note no &
&BasicInformation.FileAttributes,
&StandardInformation.NumberOfLinks,
&BasicInformation.CreationTime,
&BasicInformation.LastAccessTime,
&BasicInformation.LastWriteTime,
&BasicInformation.ChangeTime,
&StandardInformation.AllocationSize,
&StandardInformation.EndOfFile,
&StandardInformation.EndOfFile)
);
//if (!MRxLocalNoOplocks) MRxLocalRequestOplock(SrvOpen,MRxOplockRequestType,MRxRequestLevelII);
//RxDbgTrace( 0, Dbg, ("MRxLocalCreate oplockstate =%08lx\n", localSrvOpen->OplockState ));
//SrvOpen->BufferingFlags = MRxLocalTranslateStateToBufferMode[localSrvOpen->OplockState];
SrvOpen->BufferingFlags |= FCB_STATE_COLLAPSING_ENABLED; //this can be turned off in the write path
}
}
if (Status == STATUS_SUCCESS) {
RxContext->pFobx = RxCreateNetFobx( RxContext, SrvOpen);
if (!RxContext->pFobx) {
NTSTATUS PostedCloseStatus;
PostedCloseStatus = MRxProxyPostOperation(
RxContext,
((PVOID)SrvOpen),
MRxProxyPostedCloseHandle );
ObDereferenceObject(proxySrvOpen->UnderlyingFileObject);
}
}
//note.........collapsing IS enabled on fcb but not on any srvopen........
SrvOpen->BufferingFlags |= (FCB_STATE_WRITECACHEING_ENABLED |
FCB_STATE_FILESIZECACHEING_ENABLED |
FCB_STATE_FILETIMECACHEING_ENABLED |
FCB_STATE_WRITEBUFFERING_ENABLED |
FCB_STATE_LOCK_BUFFERING_ENABLED |
FCB_STATE_READBUFFERING_ENABLED |
FCB_STATE_READCACHEING_ENABLED );
ASSERT(Status != (STATUS_PENDING));
ASSERT(RxIsFcbAcquiredExclusive( capFcb ));
RxDbgTrace(-1, Dbg, ("MRxProxyCreate %08lx exit with status=%08lx\n", RxContext, Status ));
return(Status);
}
NTSTATUS
MRxProxyCollapseOpen(
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;
//RX_BLOCK_CONDITION FinalSrvOpenCondition;
PMRX_SRV_OPEN SrvOpen = RxContext->Create.pSrvOpen;
PMRX_SRV_CALL SrvCall = RxContext->Create.pSrvCall;
PMRX_NET_ROOT NetRoot = capFcb->pNetRoot;
ASSERT(FALSE);
RxContext->pFobx = (PMRX_FOBX)RxCreateNetFobx( RxContext, SrvOpen);
if (RxContext->pFobx != NULL) {
ASSERT ( RxIsFcbAcquiredExclusive ( capFcb ) );
RxContext->pFobx->OffsetOfNextEaToReturn = 1;
Status = STATUS_SUCCESS;
} else {
Status = (STATUS_INSUFFICIENT_RESOURCES);
//DbgBreakPoint();
}
return Status;
}
NTSTATUS
MRxProxyComputeNewBufferingState(
IN OUT PMRX_SRV_OPEN pMRxSrvOpen,
IN PVOID pMRxContext,
OUT PULONG pNewBufferingState)
/*++
Routine Description:
This routine maps the PROXY 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:
--*/
{
//ULONG OplockLevel;
ULONG NewBufferingState;
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(pMRxSrvOpen);
PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(pMRxSrvOpen->pFcb);
ASSERT(pNewBufferingState != NULL);
#if 0
OplockLevel = (ULONG)pMRxContext;
if (OplockLevel == PROXY_OPLOCK_LEVEL_II) {
NewBufferingState = (FCB_STATE_READBUFFERING_ENABLED |
FCB_STATE_READCACHEING_ENABLED);
} else {
NewBufferingState = 0;
}
#endif //0
NewBufferingState = 0;
pMRxSrvOpen->BufferingFlags = NewBufferingState;
MRxProxyMungeBufferingIfWriteOnlyHandles(
proxyFcb->WriteOnlySrvOpenCount,
pMRxSrvOpen);
*pNewBufferingState = pMRxSrvOpen->BufferingFlags;
return STATUS_SUCCESS;
}
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
NTSTATUS
MRxProxyZeroExtend(
IN PRX_CONTEXT pRxContext)
/*++
Routine Description:
This routine extends the data stream of a file system object
Arguments:
pRxContext - the RDBSS context
Return Value:
RXSTATUS - The return status for the operation
--*/
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
MRxProxyTruncate(
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
MRxProxyCleanupFobx(
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;
RxCaptureFcb; RxCaptureFobx;
PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
//PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
//PMRX_PROXY_FOBX proxyFobx = MRxProxyGetFileObjectExtension(capFobx);
PAGED_CODE();
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
ASSERT ( NodeTypeIsFcb(capFcb) );
ASSERT (FlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT));
ASSERT (proxySrvOpen->UnderlyingFileObject);
//if (FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED)) {
// RxDbgTrace(-1, Dbg, ("File orphaned\n"));
// return (STATUS_SUCCESS);
//}
//
// if more fobxs are using this srvopen then just get out.
// otherwise close the handle to trigger the underlying cleanup
if (SrvOpen->UncleanFobxCount > 1) { return Status; }
RxDbgTrace(+1, Dbg, ("MRxProxyCleanup %wZ\n", RemainingName ));
RxLog(("ProxyCleanup %lx",SrvOpen));
//because we only have one handle onthe file....we do nothing for each
//individual handle being closed. in this way we avoid doing paging ios!
//we close the handle when the final close for the fcb comes down.
RxDbgTrace(-1, Dbg, ("MRxProxyCleanup exit with status=%08lx\n", Status ));
return(Status);
}
NTSTATUS
MRxProxyForcedClose(
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:
--*/
{
return STATUS_NOT_IMPLEMENTED;
}
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//------------close close close close close close close --------------------------------
//------------close close close close close close close --------------------------------
//------------close close close close close close close --------------------------------
//------------close close close close close close close --------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//
// The local debug trace level
//
#undef Dbg
#define Dbg (DEBUG_TRACE_CLOSE)
NTSTATUS
MRxProxyCloseSrvOpen(
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;
PUNICODE_STRING RemainingName = &(capFcb->AlreadyPrefixedName);
NODE_TYPE_CODE TypeOfOpen = NodeType(capFcb);
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
//PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
//PMRX_PROXY_FOBX proxyFobx = MRxProxyGetFileObjectExtension(capFobx);
//IO_STATUS_BLOCK Iosb;
//PMINIRDR_OPLOCK_COMPLETION_CONTEXT cc = localSrvOpen->Mocc;
//KIRQL oldIrql;
//BOOLEAN OplockBreakPending;
PAGED_CODE();
ASSERT ( NodeTypeIsFcb(capFcb) );
ASSERT ( SrvOpen->OpenCount == 0 );
ASSERT (proxySrvOpen->UnderlyingFileObject);
//if (capFcb->OpenCount > 0) { return STATUS_SUCCESS;}
RxDbgTrace(+1, Dbg, ("MRxProxyClose %wZ\n", RemainingName ));
RxLog(("ProxyClose fobx=%lx",capFobx));
//if (proxySrvOpen->DeferredOpenContext != NULL) {
// RxFreePool(proxySrvOpen->DeferredOpenContext);
//}
//if ((FlagOn(capFcb->FcbState,FCB_STATE_ORPHANED))) {
// RxDbgTrace(-1, Dbg, ("File orphan\n"));
// return (STATUS_SUCCESS);
//}
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
#if 0
IF WE REENABLE THIS, DONT USE IOSETINFO...USE MRxProxySyncXxxInformation INSTEAD
// first we set the real filesize.....our pagingIos may have extended it
// to a page boundary.........
if ( NodeType(capFcb) == RDBSS_NTC_STORAGE_TYPE_FILE ) {
FILE_END_OF_FILE_INFORMATION EndOfFileInformation;
EndOfFileInformation.EndOfFile = capFcb->Header.FileSize;
Status = IxxoSetInformation(
proxySrvOpen->UnderlyingFileObject, //IN PFILE_OBJECT FileObject,
FileEndOfFileInformation, //IN FILE_INFORMATION_CLASS FileInformationClass,
sizeof(EndOfFileInformation), //IN ULONG Length,
&EndOfFileInformation //IN PVOID FileInformation
);
}
//if bad status....keep going anyway........
#endif
// next, we close our handle..........
Status = MRxProxyPostOperation(
RxContext,
((PVOID)SrvOpen),
MRxProxyPostedCloseHandle );
// then, we remove our reference..........
if (proxySrvOpen->UnderlyingFileObject) {
RxDbgTrace( 0, Dbg, ("ProxyClose Attempt to close %wZ\n", &(capFcb->AlreadyPrefixedName) ));
//if (cc) {
// ASSERTMSG("Joejoe the right way to do this would be to CANCEL!!!!!!!!",FALSE);
// //since this is a force closed, we get rid of a pending break
// KeAcquireSpinLock( &MrxLocalOplockSpinLock, &oldIrql );
// OplockBreakPending = cc->OplockBreakPending;
// if (!OplockBreakPending) {
// cc->SrvOpen = NULL;
// }
// KeReleaseSpinLock( &MrxLocalOplockSpinLock, oldIrql );
// if (!OplockBreakPending) {
// //gotta lose the spinlock befoer the call
// RxDereferenceSrvOpen(SrvOpen); //elim ref!
// }
//} else {
// ASSERT (localSrvOpen->OplockState == OplockStateNone);
//}
RxLog(("MRxProxyClose %lx %lx",capFcb,capFobx));
//DbgPrint("MRxProxyClose %lx %lx\n",capFcb,capFobx);
ObDereferenceObject(proxySrvOpen->UnderlyingFileObject);
proxySrvOpen->UnderlyingFileObject = NULL;
}
Status = STATUS_SUCCESS;
RxDbgTrace(-1, Dbg, ("MRxProxyClose exit with status=%08lx\n", Status ));
return(Status);
}