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
|
|||
|
|
|||
|
|