mirror of https://github.com/tongzx/nt5src
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.
1193 lines
36 KiB
1193 lines
36 KiB
/*++
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|