768 lines
24 KiB
C
768 lines
24 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
InnerIo.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the read, write, and lockctrl routines for the proxy minirdr
|
||
Author:
|
||
|
||
Joe Linn [JoeLinn] 11-Oct-1994
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_READ)
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#endif
|
||
|
||
NTSTATUS
|
||
MRxProxyBuildAsynchronousRequest(
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine builds an I/O Request Packet (IRP) suitable for a File System
|
||
Driver (FSD) to use in requesting an I/O operation from a device driver.
|
||
The request (RxContext->MajorFunction) must be one of the following request codes:
|
||
|
||
IRP_MJ_READ
|
||
IRP_MJ_WRITE
|
||
IRP_MJ_DIRECTORY_CONTROL
|
||
IRP_MJ_FLUSH_BUFFERS
|
||
//IRP_MJ_SHUTDOWN (not yet implemented)
|
||
|
||
|
||
Arguments:
|
||
|
||
CompletionRoutine - the IrpCompletionRoutine
|
||
|
||
Return Value:
|
||
|
||
The function value is a pointer to the IRP representing the specified
|
||
request.
|
||
|
||
--*/
|
||
|
||
{
|
||
PIRP irp;
|
||
PIO_STACK_LOCATION irpSp;
|
||
ULONG MajorFunction = RxContext->MajorFunction;
|
||
RxCaptureFcb; RxCaptureFobx;
|
||
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
||
|
||
PMRXPROXY_RX_CONTEXT pMRxProxyContext = MRxProxyGetMinirdrContext(RxContext);
|
||
|
||
PMRXPROXY_ASYNCENGINE_CONTEXT AsyncEngineContext =
|
||
(PMRXPROXY_ASYNCENGINE_CONTEXT)(pMRxProxyContext->AsyncEngineContext);
|
||
|
||
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
|
||
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(capFobx->pSrvOpen);
|
||
//PMRX_PROXY_FCB proxyFcb = MRxProxyGetFcbExtension(capFcb);
|
||
|
||
PDEVICE_OBJECT DeviceObject = proxySrvOpen->UnderlyingDeviceObject;
|
||
PFILE_OBJECT FileObject = proxySrvOpen->UnderlyingFileObject;
|
||
|
||
LARGE_INTEGER ZeroAsLI;
|
||
ULONG MdlLength = 0;
|
||
|
||
PAGED_CODE();
|
||
|
||
ASSERT (proxySrvOpen->UnderlyingFileObject);
|
||
|
||
if (DeviceObject->Flags & DO_BUFFERED_IO) {
|
||
//i cannot handled buffered_io devices....sigh
|
||
return STATUS_INVALID_DEVICE_REQUEST;
|
||
}
|
||
|
||
|
||
RxDbgTrace(0, Dbg, ("MRxProxyBuildAsynchronousRequest %08lx %08lx len/off=%08lx %08lx\n",
|
||
RxContext,SrvOpen,
|
||
LowIoContext->ParamsFor.ReadWrite.ByteCount,
|
||
(ULONG)LowIoContext->ParamsFor.ReadWrite.ByteOffset));
|
||
|
||
RxLog(("BuildAsyncIrp %lx %lx %lx %lx",
|
||
RxContext,SrvOpen,
|
||
LowIoContext->ParamsFor.ReadWrite.ByteCount,
|
||
(ULONG)LowIoContext->ParamsFor.ReadWrite.ByteOffset));
|
||
|
||
ZeroAsLI.QuadPart = 0;
|
||
|
||
// irp = IoBuildAsynchronousFsdRequest(
|
||
// MajorFunction,
|
||
// DeviceObject,
|
||
// NULL,
|
||
// 0,
|
||
// &ZeroAsLI,
|
||
// NULL
|
||
// );
|
||
//
|
||
// if (!irp) {
|
||
// return STATUS_INSUFFICIENT_RESOURCES;
|
||
// }
|
||
|
||
irp = IoAllocateIrp( DeviceObject->StackSize, FALSE ); //why not charge???
|
||
if (!irp) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Set current thread for IoSetHardErrorOrVerifyDevice.
|
||
//
|
||
|
||
irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||
|
||
//
|
||
// Get a pointer to the stack location of the first driver which will be
|
||
// invoked. This is where the function codes and the parameters are set.
|
||
//
|
||
|
||
irpSp = IoGetNextIrpStackLocation( irp ); //ok4ioget
|
||
irpSp->MajorFunction = (UCHAR) MajorFunction;
|
||
irpSp->FileObject = FileObject; //ok4->FileObj
|
||
RxLog(("BuildAsyncIrpFo %lx %lx",RxContext,FileObject));
|
||
|
||
{ BOOLEAN EnableCalls = CompletionRoutine!=NULL;
|
||
|
||
IoSetCompletionRoutine(irp, CompletionRoutine, RxContext,
|
||
EnableCalls,EnableCalls,EnableCalls);
|
||
}
|
||
|
||
|
||
if ( (MajorFunction == IRP_MJ_READ) || (MajorFunction == IRP_MJ_WRITE) ) {
|
||
|
||
// never paging io
|
||
BOOLEAN PagingIo = FALSE;
|
||
//BOOLEAN PagingIo =
|
||
// BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,LOWIO_READWRITEFLAG_PAGING_IO);
|
||
|
||
irp->Flags |= IRP_NOCACHE;
|
||
|
||
|
||
//
|
||
// Set the parameters according to whether this is a read or a write
|
||
// operation. Notice that these parameters must be set even if the
|
||
// driver has not specified buffered or direct I/O.
|
||
//
|
||
|
||
ASSERT (&irpSp->Parameters.Write.Key == &irpSp->Parameters.Read.Key);
|
||
ASSERT (&irpSp->Parameters.Write.Length == &irpSp->Parameters.Read.Length);
|
||
ASSERT (&irpSp->Parameters.Write.ByteOffset == &irpSp->Parameters.Read.ByteOffset);
|
||
irpSp->Parameters.Read.Key = LowIoContext->ParamsFor.ReadWrite.Key;
|
||
irpSp->Parameters.Read.ByteOffset.QuadPart = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
|
||
irp->RequestorMode = KernelMode;
|
||
|
||
irp->UserBuffer = RxLowIoGetBufferAddress(RxContext);
|
||
|
||
MdlLength = RxContext->CurrentIrp->MdlAddress->ByteCount;
|
||
|
||
if (PagingIo) {
|
||
irpSp->Parameters.Read.Length = MdlLength;
|
||
} else {
|
||
irpSp->Parameters.Read.Length = LowIoContext->ParamsFor.ReadWrite.ByteCount;
|
||
}
|
||
|
||
} else if (MajorFunction == IRP_MJ_FLUSH_BUFFERS) {
|
||
|
||
MdlLength = 0;
|
||
//nothing else to do!!!
|
||
|
||
} else {
|
||
|
||
FILE_INFORMATION_CLASS FileInformationClass = RxContext->Info.FileInformationClass;
|
||
PVOID Buffer = RxContext->Info.Buffer;
|
||
PULONG pLengthRemaining = &RxContext->Info.LengthRemaining;
|
||
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
|
||
|
||
ASSERT( MajorFunction == IRP_MJ_DIRECTORY_CONTROL );
|
||
irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
|
||
//CODE.IMPROVEMENT it would be better to actually get the stuff out of the context.info
|
||
irpSp->Parameters.QueryDirectory = RxContext->CurrentIrpSp->Parameters.QueryDirectory;
|
||
ASSERT (
|
||
(irpSp->Parameters.QueryDirectory.FileInformationClass == FileInformationClass)
|
||
&& (irpSp->Parameters.QueryDirectory.Length == *pLengthRemaining)
|
||
);
|
||
irpSp->Flags = RxContext->CurrentIrpSp->Flags;
|
||
irp->UserBuffer = Buffer;
|
||
MdlLength = *pLengthRemaining;
|
||
|
||
if (Wait) {
|
||
irp->Flags |= IRP_SYNCHRONOUS_API;
|
||
}
|
||
}
|
||
|
||
// Build an mdl if necessary....
|
||
|
||
if (MdlLength != 0) {
|
||
irp->MdlAddress = IoAllocateMdl(irp->UserBuffer,MdlLength,
|
||
FALSE,FALSE,NULL);
|
||
if (!irp->MdlAddress) {
|
||
//whoops.......sorry..........
|
||
IoFreeIrp(irp);
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
MmBuildMdlForNonPagedPool(irp->MdlAddress);
|
||
}
|
||
|
||
//
|
||
// Finally, return a pointer to the IRP.
|
||
//
|
||
|
||
AsyncEngineContext->CalldownIrp = irp;
|
||
RxLog(("BAsyIrpX %lx %lx %lx %lx %lx %lx %lx",
|
||
RxContext,
|
||
irpSp->MajorFunction,
|
||
irpSp->Flags,
|
||
irpSp->Parameters.Others.Argument1,
|
||
irpSp->Parameters.Others.Argument2,
|
||
irpSp->Parameters.Others.Argument3,
|
||
irpSp->Parameters.Others.Argument4));
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#undef Dbg
|
||
#define Dbg (DEBUG_TRACE_WRITE)
|
||
|
||
//everything else in here is ifdef'd out....also CODE.IMPROVEMENT we should change over
|
||
//to a common irp building routine in Rx. the code is already in the csc driver
|
||
#if 0
|
||
NTSTATUS
|
||
MRxProxyBuildInnerIoAsyncWrite (
|
||
IN PRX_CONTEXT RxContext,
|
||
IN PBYTE Buffer,
|
||
IN ULONG WriteByteCount,
|
||
IN PLARGE_INTEGER FileOffset,
|
||
IN OUT PIRP *CalldownIrp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine fills in the calldown irp for a proxy read
|
||
|
||
Arguments:
|
||
|
||
RxContext,
|
||
PBYTE Buffer - the write buffer
|
||
ULONG Count - amount of data to written
|
||
PLARGE_INTEGER FileOffset - fileoffset where the write begins
|
||
PIRP *CallDownIrp - where the Irp is to be stored
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - Returns the status for the write
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
RxCaptureFcb; RxCaptureFobx;
|
||
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
||
|
||
PMRX_SRV_OPEN SrvOpen = capFobx->pSrvOpen;
|
||
PMRX_PROXY_SRV_OPEN proxySrvOpen = MRxProxyGetSrvOpenExtension(SrvOpen);
|
||
|
||
RxDbgTrace(+1, Dbg, ("MRxProxyInnerIoWrite.... ByteCount = %08lx, ByteOffset = %08lx %08lx\n",
|
||
LowIoContext->ParamsFor.ReadWrite.ByteCount,
|
||
FileOffset->LowPart, FileOffset->HighPart));
|
||
|
||
RxLog(("MRxProxyInnerIoWrite %lx %lx %lx",
|
||
SrvOpen,
|
||
LowIoContext->ParamsFor.ReadWrite.ByteCount,
|
||
FileOffset->LowPart));
|
||
|
||
|
||
RxDbgTrace ( 0, Dbg, ( "MRxProxyInnerIoWrite.... ->Buffer = %8lx\n", Buffer));
|
||
|
||
*CalldownIrp = MRxProxyBuildAsynchronousReadWriteRequest(
|
||
RxContext, // IN PVOID Context
|
||
MRxProxyAsyncEngineCalldownIrpCompletion // IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
|
||
);
|
||
|
||
if (!*CalldownIrp){
|
||
Status = (STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
RxDbgTrace(-1, Dbg, ("MRxProxyInnerIoWrite.... exit\n"));
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//----------------------------------------------------------------------------------------------
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#undef Dbg
|
||
#define Dbg (DEBUG_TRACE_LOCKCTRL)
|
||
|
||
|
||
PIRP
|
||
MRxBuildLockRequest (
|
||
IN PIRP irp OPTIONAL,
|
||
IN PFILE_OBJECT fileObject,
|
||
IN PETHREAD UsersThread,
|
||
IN UCHAR MinorCode,
|
||
IN RXVBO ByteOffset,
|
||
IN PLARGE_INTEGER Length,
|
||
IN ULONG Key,
|
||
IN UCHAR Flags,
|
||
IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
|
||
IN PVOID Context OPTIONAL
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function builds an I/O request packet for a lock request.
|
||
|
||
Arguments:
|
||
|
||
Irp - Supplies a pointer to an IRP; allocates one if one is not provided.
|
||
|
||
FileObject - Supplies a pointer the file object to which this
|
||
request is directed. This pointer is copied into the IRP, so
|
||
that the called driver can find its file-based context. NOTE
|
||
THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
|
||
that the file object is not deleted while the I/O operation is
|
||
in progress. The proxy minirdr accomplishes this by holding a pointer
|
||
(a REFERENCED ptr) to the fileobject in its srvopen while the fileobject is
|
||
open.
|
||
|
||
Context - Supplies a PVOID value that is passed to the completion
|
||
routine.
|
||
|
||
StartingBlock - the block number of the beginning of the locked
|
||
range.
|
||
|
||
ByteOffset - the offset within block of the beginning of the locked
|
||
range.
|
||
|
||
Length - the length of the locked range.
|
||
|
||
Key - the key value to be associated with the lock.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
PDEVICE_OBJECT deviceObject;
|
||
PIO_STACK_LOCATION irpSp;
|
||
|
||
PAGED_CODE( );
|
||
|
||
deviceObject = IoGetRelatedDeviceObject( fileObject );
|
||
|
||
//
|
||
// 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.
|
||
|
||
if (irp) {
|
||
ASSERT( irp->StackCount >= deviceObject->StackSize );
|
||
} else {
|
||
irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); //joejoe should i charge quota??
|
||
}
|
||
|
||
if (!irp) {
|
||
|
||
//
|
||
// An IRP could not be allocated.
|
||
|
||
return NULL;
|
||
}
|
||
|
||
// we have to make sure that the thread that takes the lock is the same as the one that reads
|
||
irp->Tail.Overlay.Thread = UsersThread;
|
||
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 );
|
||
|
||
{ BOOLEAN EnableCalls = CompletionRoutine!=NULL;
|
||
|
||
IoSetCompletionRoutine(irp, CompletionRoutine, Context,
|
||
EnableCalls,EnableCalls,EnableCalls);
|
||
}
|
||
|
||
|
||
|
||
irpSp->MajorFunction = IRP_MJ_LOCK_CONTROL;
|
||
irpSp->MinorFunction = MinorCode;
|
||
irpSp->FileObject = fileObject; //ok4->FileObj
|
||
irpSp->DeviceObject = deviceObject;
|
||
|
||
irpSp->Flags = Flags;
|
||
|
||
irpSp->Parameters.LockControl.Length = Length;
|
||
irpSp->Parameters.LockControl.Key = Key;
|
||
irpSp->Parameters.LockControl.ByteOffset.QuadPart = ByteOffset;
|
||
|
||
return irp;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
MRxProxyCalldownLockCompletion (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP CalldownIrp,
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the I/O completion routine for calldown lock requests. we just call the lowio completion
|
||
and exit
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to target device object for the request.
|
||
|
||
CalldownIrp - Pointer to I/O request packet used to call down to the underlying filesystem
|
||
|
||
Context - Irpcontext of the original request to the rdbss
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - (STATUS_MORE_PROCESSING_REQUIRED) is returned.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
PRX_CONTEXT RxContext = Context;
|
||
|
||
RxDbgTrace ( 0, Dbg, ("MRxProxyCalldownLockCompletion = %08lx\n", 0));
|
||
//DbgBreakPoint();
|
||
if (CalldownIrp->PendingReturned){
|
||
RxContext->CurrentIrp->IoStatus = CalldownIrp->IoStatus;
|
||
RxContext->StoredStatus = CalldownIrp->IoStatus.Status;
|
||
}
|
||
RxLowIoCompletion(RxContext);
|
||
|
||
IoFreeIrp(CalldownIrp);
|
||
return((STATUS_MORE_PROCESSING_REQUIRED));
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxProxyLocks (
|
||
IN PRX_CONTEXT RxContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine implements proxy read call. we fill in the info and stuff here BUT we
|
||
do not complete the Irp.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - Returns the status for the read
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
RxCaptureRequestPacket;
|
||
PIRP CalldownIrp;
|
||
RxCaptureFcb; RxCaptureFobx; RxCaptureParamBlock;
|
||
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
||
|
||
PSRV_OPEN SrvOpen = capFobx->SrvOpen;
|
||
PMRX_LOCAL_SRV_OPEN proxySrvOpen = (PMRX_LOCAL_SRV_OPEN)SrvOpen;
|
||
|
||
BOOLEAN Wait = FlagOn(RxContext->Flags,RX_CONTEXT_FLAG_WAIT)!=0;
|
||
PLARGE_INTEGER LengthAsLI = (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.Length;
|
||
PLARGE_INTEGER OffsetAsLI = (PLARGE_INTEGER)&LowIoContext->ParamsFor.Locks.ByteOffset;
|
||
|
||
char *whichop;
|
||
|
||
switch (LowIoContext->Operation) {
|
||
case LOWIO_OP_SHAREDLOCK: whichop = "SHAREDLOCK"; break;
|
||
case LOWIO_OP_EXCLUSIVELOCK: whichop = "EXCLUSIVELOCK"; break;
|
||
case LOWIO_OP_UNLOCK: whichop = "UNLOCK"; break;
|
||
case LOWIO_OP_UNLOCKALL: whichop = "UNLOCKALL"; break;
|
||
case LOWIO_OP_UNLOCKALLBYKEY: whichop = "UNLOCKALLBYKEY"; break;
|
||
}
|
||
|
||
RxDbgTrace (+1, Dbg, ("MRxExclusiveLock...%s, Flags = %08lx, Key = %08lx\n", whichop,
|
||
LowIoContext->ParamsFor.Locks.Flags,
|
||
LowIoContext->ParamsFor.Locks.Key));
|
||
RxDbgTrace( 0, Dbg, (" ->Length = %08lx %08lx\n",
|
||
LengthAsLI->LowPart,
|
||
LengthAsLI->HighPart));
|
||
RxDbgTrace( 0, Dbg, (" ->ByteOffset = %08lx %08lx\n",
|
||
OffsetAsLI->LowPart,
|
||
OffsetAsLI->HighPart));
|
||
RxLog(('kLz',3,SrvOpen, LengthAsLI->LowPart, OffsetAsLI->LowPart));
|
||
|
||
ASSERT (proxySrvOpen->UnderlyingFileObject);
|
||
|
||
CalldownIrp = MRxBuildLockRequest (
|
||
NULL ,//IN PIRP irp OPTIONAL,
|
||
proxySrvOpen->UnderlyingFileObject ,//IN PFILE_OBJECT fileObject,
|
||
capReqPacket->Tail.Overlay.Thread ,//IN PTHREAD UsersThread,
|
||
capPARAMS->MinorFunction ,//IN UCHAR MinorCode,
|
||
LowIoContext->ParamsFor.Locks.ByteOffset,//IN RXVBO ByteOffset,
|
||
LengthAsLI ,//IN PLARGE_INTEGER Length,
|
||
LowIoContext->ParamsFor.Locks.Key ,//IN ULONG Key,
|
||
(UCHAR)LowIoContext->ParamsFor.Locks.Flags ,//IN UCHAR Flags,
|
||
MRxProxyCalldownLockCompletion ,//IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
|
||
RxContext //IN PVOID Context OPTIONAL
|
||
);
|
||
|
||
|
||
if (!CalldownIrp){
|
||
Status = RxContext->StoredStatus = (STATUS_INSUFFICIENT_RESOURCES);
|
||
return(Status);
|
||
}
|
||
|
||
Status = RxContext->StoredStatus =
|
||
IoCallDriver(
|
||
proxySrvOpen->UnderlyingDeviceObject,
|
||
CalldownIrp
|
||
);
|
||
|
||
if (Status != (STATUS_PENDING)) {
|
||
//copy up the status
|
||
capReqPacket->IoStatus = CalldownIrp->IoStatus;
|
||
}
|
||
|
||
RxDbgTrace ( 0, Dbg, (" ---->Initial Status = %08lx\n", Status));
|
||
RxDbgTrace(-1, Dbg, (" ------> Initial Block status/Info = %08lx %08lx\n",
|
||
capReqPacket->IoStatus.Status, capReqPacket->IoStatus.Information));
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxProxyAssertLockCompletion (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP CalldownIrp,
|
||
IN PVOID Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the I/O completion routine for calldown ios like querydirectory. the rub is that we
|
||
turned synchronous opens into async opens. what we do here is set an event (in the case of a pended
|
||
packet for a sync that we turned async) OR copyup the status;complete;free in the case of a call
|
||
that was always async.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - Pointer to target device object for the request.
|
||
|
||
CalldownIrp - Pointer to I/O request packet used to call down to the underlying filesystem
|
||
|
||
Context - Irpcontext of the original request to the rdbss
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - If (STATUS_MORE_PROCESSING_REQUIRED) is returned.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
PKEVENT Event = Context;
|
||
|
||
RxDbgTrace ( 0, Dbg, (" MRxProxyAssertLockCompletion = %08lx\n", 0));
|
||
|
||
if (CalldownIrp->PendingReturned){
|
||
KeSetEvent( Event, 0, FALSE );
|
||
}
|
||
|
||
return((STATUS_MORE_PROCESSING_REQUIRED));
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MRxProxyAssertBufferedFileLocks (
|
||
IN PSRV_OPEN SrvOpen
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is called to assert all buffered file locks on a srvopen.
|
||
|
||
|
||
Arguments:
|
||
|
||
SrvOpen - Supplies the file whose locks are to be asserted.
|
||
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - Status of operation.
|
||
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status;
|
||
PFILE_LOCK_INFO FileLock;
|
||
PFCB Fcb = SrvOpen->Fcb;
|
||
|
||
PIRP CalldownIrp = NULL;
|
||
|
||
PMRX_LOCAL_SRV_OPEN proxySrvOpen = (PMRX_LOCAL_SRV_OPEN)SrvOpen;
|
||
|
||
UCHAR Flags;
|
||
BOOLEAN Wait = TRUE;
|
||
|
||
PKEVENT Event;
|
||
|
||
PAGED_CODE();
|
||
|
||
RxDbgTrace (+1, Dbg, ("MRxProxyAssertBufferedFileLocks SrvOpen = %08lx", SrvOpen));
|
||
ASSERT (proxySrvOpen->UnderlyingFileObject);
|
||
|
||
Event = RxAllocatePoolWithTag( NonPagedPool, sizeof(KEVENT), 'LAxR' );
|
||
if (!CalldownIrp){
|
||
Status = (STATUS_INSUFFICIENT_RESOURCES);
|
||
return(Status);
|
||
}
|
||
|
||
try {
|
||
for (FileLock = FsRtlGetNextFileLock(&Fcb->Specific.Fcb.FileLock, TRUE);
|
||
FileLock != NULL;
|
||
FileLock = FsRtlGetNextFileLock(&Fcb->Specific.Fcb.FileLock, FALSE)) {
|
||
|
||
RxDbgTrace (0, Dbg, ("MRxProxyAssertBufferedFileLocks Exclusive = %08lx, Key = %08lx\n",
|
||
FileLock->ExclusiveLock,
|
||
FileLock->Key));
|
||
RxDbgTrace( 0, Dbg, (" ->Length = %08lx %08lx\n",
|
||
FileLock->Length.LowPart,
|
||
FileLock->Length.HighPart));
|
||
RxDbgTrace( 0, Dbg, (" ->ByteOffset = %08lx %08lx\n",
|
||
FileLock->StartingByte.LowPart,
|
||
FileLock->StartingByte.HighPart));
|
||
|
||
if (FileLock->ExclusiveLock) {
|
||
Flags = SL_EXCLUSIVE_LOCK | SL_FAIL_IMMEDIATELY;
|
||
} else {
|
||
Flags = SL_FAIL_IMMEDIATELY;
|
||
}
|
||
|
||
//joejoe we should reuse the irp.........
|
||
CalldownIrp = MRxBuildLockRequest (
|
||
NULL ,//IN PIRP irp OPTIONAL,
|
||
proxySrvOpen->UnderlyingFileObject ,//IN PFILE_OBJECT fileObject,
|
||
proxySrvOpen->OriginalThread ,//IN PTHREAD UsersThread,
|
||
IRP_MN_LOCK ,//IN UCHAR MinorCode,
|
||
FileLock->StartingByte.QuadPart ,//IN RXVBO ByteOffset,
|
||
&FileLock->Length ,//IN PLARGE_INTEGER Length,
|
||
FileLock->Key ,//IN ULONG Key,
|
||
Flags ,//IN UCHAR Flags,
|
||
MRxProxyAssertLockCompletion ,//IN PIO_COMPLETION_ROUTINE CompletionRoutine OPTIONAL,
|
||
&Event //IN PVOID Context OPTIONAL
|
||
);
|
||
|
||
if (!CalldownIrp){
|
||
Status = (STATUS_INSUFFICIENT_RESOURCES);
|
||
try_return(Status);
|
||
}
|
||
|
||
CalldownIrp->Flags |= IRP_SYNCHRONOUS_API;
|
||
|
||
KeInitializeEvent( Event, SynchronizationEvent, FALSE );
|
||
|
||
Status = IoCallDriver(
|
||
proxySrvOpen->UnderlyingDeviceObject,
|
||
CalldownIrp
|
||
);
|
||
|
||
if (Status == (STATUS_PENDING)) {
|
||
KeWaitForSingleObject(Event, UserRequest, KernelMode, FALSE, NULL);
|
||
Status = CalldownIrp->IoStatus.Status;
|
||
}
|
||
|
||
RxDbgTrace ( 0, Dbg, (" ---->PerLock Status = %08lx\n", Status));
|
||
|
||
}
|
||
|
||
try_exit:
|
||
NOTHING;
|
||
|
||
} finally {
|
||
|
||
ExFreePool(Event);
|
||
if (CalldownIrp) {
|
||
IoFreeIrp(CalldownIrp);
|
||
}
|
||
}
|
||
|
||
RxDbgTrace (-1, Dbg, ("--------->Final Status = %08lx\n", Status));
|
||
return Status;
|
||
|
||
}
|
||
|
||
#endif
|
||
|
||
|