Esempio n. 1
0
/*************************************************************************
*
* Function: Ext2PassDownMultiReadWriteIRP()
*
* Description:
*	pass down multiple read IRPs as Associated IRPs
*
* Expected Interrupt Level (for execution) :
*
*  ?
*
* Return Value: STATUS_SUCCESS / STATUS_PENDING / Error
*
*************************************************************************/
NTSTATUS NTAPI Ext2PassDownMultiReadWriteIRP( 
	PEXT2_IO_RUN			PtrIoRuns, 
	UINT					Count, 
	ULONG					TotalReadWriteLength,
	PtrExt2IrpContext		PtrIrpContext,
	PtrExt2FCB				PtrFCB,
	BOOLEAN					SynchronousIo)
{
	PIRP				PtrMasterIrp;
	PIRP				PtrAssociatedIrp;
    PIO_STACK_LOCATION	PtrIrpSp;
    PMDL				PtrMdl;
	PtrExt2VCB			PtrVCB;
	UINT				i;
	ULONG				BufferOffset;
	PEXT2_IO_CONTEXT	PtrIoContext = NULL;
	PKEVENT				PtrSyncEvent = NULL;
	ULONG				LogicalBlockSize;
	ULONG				ReadWriteLength;

	NTSTATUS RC = STATUS_SUCCESS;

	PtrVCB = PtrFCB->PtrVCB;
	PtrMasterIrp = PtrIrpContext->Irp;
	LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize;

	try
	{
		if( !SynchronousIo )
		{
			IoMarkIrpPending( PtrIrpContext->Irp );
			//	We will be returning STATUS_PENDING...
		}

		if( !PtrMasterIrp->MdlAddress )
		{
			Ext2LockCallersBuffer( PtrMasterIrp, TRUE, TotalReadWriteLength );
		}

		if( SynchronousIo )
		{
			PtrSyncEvent = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(KEVENT) )  );
			if ( !PtrSyncEvent )
			{
				RC = STATUS_INSUFFICIENT_RESOURCES;
				try_return();
			}
			KeInitializeEvent( PtrSyncEvent, SynchronizationEvent, FALSE );
		}
		//
		//	Allocate and initialize a completion context
		//
		PtrIoContext = Ext2AllocatePool(NonPagedPool, Ext2QuadAlign( sizeof(EXT2_IO_CONTEXT) )  );
		if ( !PtrIoContext )
		{
			RC = STATUS_INSUFFICIENT_RESOURCES;
			try_return();
		}

		RtlZeroMemory( PtrIoContext, sizeof(EXT2_IO_CONTEXT) );
		PtrIoContext->Count = Count;
		PtrIoContext->NodeIdentifier.NodeType = EXT2_NODE_TYPE_IO_CONTEXT;
		PtrIoContext->NodeIdentifier.NodeSize = sizeof( EXT2_IO_CONTEXT );
		PtrIoContext->PtrMasterIrp = PtrMasterIrp;
		PtrIoContext->PtrSyncEvent = PtrSyncEvent;
		PtrIoContext->ReadWriteLength = TotalReadWriteLength;

		

		for( ReadWriteLength = 0, BufferOffset = 0, i = 0; i < Count; i++, BufferOffset += ReadWriteLength )
		{
			
			ReadWriteLength = PtrIoRuns[ i].EndOffset - PtrIoRuns[ i].StartOffset;
			
			//
			//	Allocating an Associated IRP...
			//
			PtrAssociatedIrp = IoMakeAssociatedIrp( PtrMasterIrp,
					(CCHAR) (PtrVCB->TargetDeviceObject->StackSize + 1 ) );
			PtrIoRuns[ i].PtrAssociatedIrp = PtrAssociatedIrp;
			ASSERT ( PtrAssociatedIrp );
			PtrMasterIrp->AssociatedIrp.IrpCount ++;
			
			//
			//	Allocating a Memory Descriptor List...
			//
			PtrMdl = IoAllocateMdl( (PCHAR) PtrMasterIrp->UserBuffer + BufferOffset, //	Virtual Address
				ReadWriteLength,	FALSE, FALSE, PtrAssociatedIrp );
			
			//
			//	and building a partial MDL...
			//
			IoBuildPartialMdl( PtrMasterIrp->MdlAddress,
				PtrMdl, (PCHAR)PtrMasterIrp->UserBuffer + BufferOffset, ReadWriteLength );

			//
			//	Create an Irp stack location for ourselves...
			//
			IoSetNextIrpStackLocation( PtrAssociatedIrp );
			PtrIrpSp = IoGetCurrentIrpStackLocation( PtrAssociatedIrp );

			//
			//  Setup the Stack location to describe our read.
			//
			PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
			if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
			{
				PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
				PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = 
					PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
			}
			else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
			{
				PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
				PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = 
					PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
			}

			//	PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
			//	PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock;


			//
			//	Setup a completion routine...
			//
			IoSetCompletionRoutine( PtrAssociatedIrp, 
						SynchronousIo ?	
						Ext2MultiSyncCompletionRoutine : 
						Ext2MultiAsyncCompletionRoutine,
						PtrIoContext, TRUE, TRUE, TRUE );

			//
			//	Initialise the next stack location for the driver below us to use...
			//
			PtrIrpSp = IoGetNextIrpStackLocation( PtrAssociatedIrp );
			PtrIrpSp->MajorFunction = PtrIrpContext->MajorFunction;
			if( PtrIrpContext->MajorFunction == IRP_MJ_READ )
			{
				PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
				PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
			}
			else if( PtrIrpContext->MajorFunction == IRP_MJ_WRITE )
			{
				PtrIrpSp->Parameters.Write.Length = ReadWriteLength;
				PtrIrpSp->Parameters.Write.ByteOffset.QuadPart = PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
			}

			//	PtrIrpSp->Parameters.Read.Length = ReadWriteLength;
			//	PtrIrpSp->Parameters.Read.ByteOffset.QuadPart = 
			//	 	PtrIoRuns[i].LogicalBlock * ( LogicalBlockSize );
		}

		for( i = 0; i < Count; i++ ) {
                    // DbgPrint("PASSING DOWN IRP %d TO TARGET DEVICE\n", i);
                    IoCallDriver( PtrVCB->TargetDeviceObject, PtrIoRuns[ i].PtrAssociatedIrp );
                }

		if( SynchronousIo )
		{
			//
			//	Synchronous IO 
			//	Wait for the IO to complete...
			//
			DbgPrint("DEADLY WAIT (%d)\n", KeGetCurrentIrql());
			KeWaitForSingleObject( PtrSyncEvent,
				Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
                        DbgPrint("DEADLY WAIT DONE\n");
			try_return();
		}
		else
		{
			//	Asynchronous IO...
			RC = STATUS_PENDING;
			try_return();
		}
	
		try_exit:	NOTHING;
	}
	finally 
	{
		if( PtrSyncEvent )
		{
			DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrSyncEvent );
			ExFreePool( PtrSyncEvent );
		}
		if( PtrIoContext && ! ( RC == STATUS_PENDING || RC == STATUS_SUCCESS ) )
		{
			//
			//	This means we are getting out of 
			//	this function without doing a read
			//	due to an error, maybe...
			//
			DebugTrace( DEBUG_TRACE_FREE, "Freeing  = %lX [io]", PtrIoContext);
			ExFreePool( PtrIoContext );
		}
	}
	return(RC);
}
Esempio n. 2
0
NTSTATUS
Ext2ReadWriteBlocks(
    IN PEXT2_IRP_CONTEXT    IrpContext,
    IN PEXT2_VCB            Vcb,
    IN PEXT2_EXTENT         Chain,
    IN ULONG                Length
    )
{
    PIRP                Irp;
    PIRP                MasterIrp = IrpContext->Irp;
    PIO_STACK_LOCATION  IrpSp;
    PMDL                Mdl;
    PEXT2_RW_CONTEXT    pContext = NULL;
    PEXT2_EXTENT        Extent;
    KEVENT              Wait;
    NTSTATUS            Status = STATUS_SUCCESS;
    BOOLEAN             bMasterCompleted = FALSE;
    BOOLEAN             bBugCheck = FALSE;

    ASSERT(MasterIrp);

    __try {

        pContext = Ext2AllocatePool(NonPagedPool, sizeof(EXT2_RW_CONTEXT), EXT2_RWC_MAGIC);

        if (!pContext) {
            DEBUG(DL_ERR, ( "Ex2ReadWriteBlocks: failed to allocate pContext.\n"));
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        INC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT));
        RtlZeroMemory(pContext, sizeof(EXT2_RW_CONTEXT));
        pContext->Wait = Ext2CanIWait();
        pContext->MasterIrp = MasterIrp;
        pContext->Length = Length;

        if (IrpContext->MajorFunction == IRP_MJ_WRITE) {
            SetFlag(pContext->Flags, EXT2_RW_CONTEXT_WRITE);
        }

        if (pContext->Wait) {

            KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);

        } else if (IrpContext->Fcb->Identifier.Type == EXT2FCB) {

            if (IsFlagOn(MasterIrp->Flags, IRP_PAGING_IO)) {
                pContext->Resource = &IrpContext->Fcb->PagingIoResource;
            } else {
                pContext->Resource = &IrpContext->Fcb->MainResource;
            }

            pContext->FileObject = IrpContext->FileObject;
            pContext->ThreadId = ExGetCurrentResourceThread();
        }


        if (NULL == Chain->Next && 0 == Chain->Offset) {

            /* we get only 1 extent to dispatch, then don't bother allocating new irps */

            /* setup the Stack location to do a read from the disk driver. */
            IrpSp = IoGetNextIrpStackLocation(MasterIrp);
            IrpSp->MajorFunction = IrpContext->MajorFunction;
            IrpSp->Parameters.Read.Length = Chain->Length;
            IrpSp->Parameters.Read.ByteOffset.QuadPart = Chain->Lba;
            if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
                SetFlag(IrpSp->Flags, SL_WRITE_THROUGH);
            }
            if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) {
                SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME);
            }

            IoSetCompletionRoutine(
                    MasterIrp,
                    Ext2CanIWait() ?
                    Ext2ReadWriteBlockSyncCompletionRoutine :
                    Ext2ReadWriteBlockAsyncCompletionRoutine,
                    (PVOID) pContext,
                    TRUE,
                    TRUE,
                    TRUE );

            /* intialize context block */
            Chain->Irp = MasterIrp;
            pContext->Blocks = 1;

        } else {

            for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {

                Irp = IoMakeAssociatedIrp(
                          MasterIrp,
                          (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );

                if (!Irp) {
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    __leave;
                }

                Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
                                     Extent->Offset,
                                     Extent->Length,
                                     FALSE,
                                     FALSE,
                                     Irp );

                if (!Mdl)  {
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    __leave;
                }

                IoBuildPartialMdl( MasterIrp->MdlAddress,
                                   Mdl,
                                   (PCHAR)MasterIrp->UserBuffer +Extent->Offset,
                                   Extent->Length );

                IoSetNextIrpStackLocation(Irp);
                IrpSp = IoGetCurrentIrpStackLocation(Irp);

                IrpSp->MajorFunction = IrpContext->MajorFunction;
                IrpSp->Parameters.Read.Length = Extent->Length;
                IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba;

                IoSetCompletionRoutine(
                    Irp,
                    Ext2CanIWait() ?
                    Ext2ReadWriteBlockSyncCompletionRoutine :
                    Ext2ReadWriteBlockAsyncCompletionRoutine,
                    (PVOID) pContext,
                    TRUE,
                    TRUE,
                    TRUE );

                IrpSp = IoGetNextIrpStackLocation(Irp);

                IrpSp->MajorFunction = IrpContext->MajorFunction;
                IrpSp->Parameters.Read.Length =Extent->Length;
                IrpSp->Parameters.Read.ByteOffset.QuadPart = Extent->Lba;

                /* set write through flag */
                if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH)) {
                    SetFlag( IrpSp->Flags, SL_WRITE_THROUGH );
                }

                /* set verify flag */
                if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ)) {
                    SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME);
                }

                Extent->Irp = Irp;
                pContext->Blocks += 1;
            }

            MasterIrp->AssociatedIrp.IrpCount = pContext->Blocks;
            if (Ext2CanIWait()) {
                MasterIrp->AssociatedIrp.IrpCount += 1;
            }
        }
        if (!Ext2CanIWait()) {
            /* mark MasterIrp pending */
            IoMarkIrpPending(pContext->MasterIrp);
        }

        bBugCheck = TRUE;

        for (Extent = Chain; Extent != NULL; Extent = Extent->Next) {
            Status = IoCallDriver ( Vcb->TargetDeviceObject,
                                    Extent->Irp);
            Extent->Irp = NULL;
        }

        if (Ext2CanIWait()) {
            KeWaitForSingleObject( &(pContext->Event),
                                   Executive, KernelMode, FALSE, NULL );
            KeClearEvent( &(pContext->Event) );
        } else {
            bMasterCompleted = TRUE;
        }

    } __finally {

        for (Extent = Chain; Extent != NULL; Extent = Extent->Next)  {
            if (Extent->Irp != NULL ) {
                if (Extent->Irp->MdlAddress != NULL) {
                    IoFreeMdl(Extent->Irp->MdlAddress );
                }
                IoFreeIrp(Extent->Irp);
            }
        }

        if (IrpContext->ExceptionInProgress) {

            if (bBugCheck) {
                Ext2BugCheck(EXT2_BUGCHK_BLOCK, 0, 0, 0);
            }

        } else {

            if (Ext2CanIWait()) {
                if (MasterIrp) {
                    Status = MasterIrp->IoStatus.Status;
                }
                if (pContext) {
                    Ext2FreePool(pContext, EXT2_RWC_MAGIC);
                    DEC_MEM_COUNT(PS_RW_CONTEXT, pContext, sizeof(EXT2_RW_CONTEXT));
                }
            } else {
                if (bMasterCompleted) {
                    IrpContext->Irp = NULL;
                    Status = STATUS_PENDING;
                }
            }
        }
    }

    return Status;
}