test: deviosup.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# deviosup.c File Reference

`#include "UdfProcs.h"`

Go to the source code of this file.

## Classes

struct | _IO_RUN

## Defines

#define | BugCheckFileId (UDFS_BUG_CHECK_DEVIOSUP)
#define | Dbg (UDFS_DEBUG_LEVEL_DEVIOSUP)
#define | MAX_PARALLEL_IOS 5

## Typedefs

typedef _IO_RUN | IO_RUN
typedef IO_RUN * | PIO_RUN

## Functions

BOOLEAN | UdfPrepareBuffers (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFCB Fcb, IN PVOID UserBuffer, IN ULONG UserBufferOffset, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN PIO_RUN IoRuns, IN PULONG RunCount, IN PULONG ThisByteCount, OUT PBOOLEAN SparseRuns)
BOOLEAN | UdfFinishBuffers (IN PIRP_CONTEXT IrpContext, IN PIO_RUN IoRuns, IN ULONG RunCount, IN BOOLEAN FinalCleanup)
VOID | UdfMultipleAsync (IN PIRP_CONTEXT IrpContext, IN ULONG RunCount, IN PIO_RUN IoRuns)
VOID | UdfSingleAsync (IN PIRP_CONTEXT IrpContext, IN LONGLONG ByteOffset, IN ULONG ByteCount)
VOID | UdfWaitSync (IN PIRP_CONTEXT IrpContext)
NTSTATUS | UdfMultiSyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | UdfMultiAsyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | UdfSingleSyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | UdfSingleAsyncCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
NTSTATUS | UdfNonCachedRead (IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN LONGLONG StartingOffset, IN ULONG ByteCount)
NTSTATUS | UdfCreateUserMdl (IN PIRP_CONTEXT IrpContext, IN ULONG BufferLength, IN BOOLEAN RaiseOnError)
NTSTATUS | UdfPerformDevIoCtrl (IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
NTSTATUS | UdfReadSectors (IN PIRP_CONTEXT IrpContext, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN BOOLEAN ReturnError, IN OUT PVOID Buffer, IN PDEVICE_OBJECT TargetDeviceObject)
BOOLEAN | UdfPrepareBuffers (IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PFCB Fcb, IN PVOID UserBuffer, IN ULONG UserBufferOffset, IN LONGLONG StartingOffset, IN ULONG ByteCount, IN PIO_RUN IoRuns, IN PULONG RunCount, IN PULONG ThisByteCount, IN PBOOLEAN SparseRuns)

## Define Documentation

#define BugCheckFileId (UDFS_BUG_CHECK_DEVIOSUP)

| Definition at line 27 of file deviosup.c.

#define Dbg (UDFS_DEBUG_LEVEL_DEVIOSUP)

| Definition at line 33 of file deviosup.c.

#define MAX_PARALLEL_IOS 5

| Definition at line 107 of file deviosup.c. Referenced by UdfNonCachedRead(), and UdfPrepareBuffers().

## Typedef Documentation

typedef struct _IO_RUN IO_RUN

typedef IO_RUN* PIO_RUN

| Definition at line 105 of file deviosup.c. Referenced by UdfFinishBuffers(), and UdfPrepareBuffers().

## Function Documentation

NTSTATUS UdfCreateUserMdl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN ULONG | BufferLength,
|  | IN BOOLEAN | RaiseOnError
| ) |

Definition at line 474 of file deviosup.c.

References ASSERT, ASSERT_IRP, ASSERT_IRP_CONTEXT, EXCEPTION_EXECUTE_HANDLER, FALSE, FsRtlIsNtstatusExpected(), IoAllocateMdl(), IoFreeMdl(), IoWriteAccess, MmProbeAndLockPages(), NTSTATUS(), NULL, PAGED_CODE, Status, and UdfRaiseStatus().

Referenced by UdfNonCachedRead().

    00482                    :
    00483
    00484     This routine locks the specified buffer for read access (we only write into
    00485     the buffer).  The file system requires this routine since it does not
    00486     ask the I/O system to lock its buffers for direct I/O.  This routine
    00487     may only be called from the Fsd while still in the user context.
    00488
    00489     This routine is only called if there is not already an Mdl.
    00490
    00491 Arguments:
    00492
    00493     BufferLength - Length of user buffer.
    00494
    00495     RaiseOnError - Indicates if our caller wants this routine to raise on
    00496         an error condition.
    00497
    00498 Return Value:
    00499
    00500     NTSTATUS - Status from this routine.  Error status only returned if
    00501         RaiseOnError is FALSE.
    00502
    00503 --*/
    00504
    00505 {
    00506     NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
    00507     PMDL Mdl;
    00508
    00509     PAGED_CODE();
    00510
    00511     ASSERT_IRP_CONTEXT( IrpContext );
    00512     ASSERT_IRP( IrpContext->Irp );
    00513     ASSERT( IrpContext->Irp->MdlAddress == NULL );
    00514
    00515     //
    00516     // Allocate the Mdl, and Raise if we fail.
    00517     //
    00518
    00519     Mdl = IoAllocateMdl( IrpContext->Irp->UserBuffer,
    00520                          BufferLength,
    00521                          FALSE,
    00522                          FALSE,
    00523                          IrpContext->Irp );
    00524
    00525     if (Mdl != NULL) {
    00526
    00527         //
    00528         //  Now probe the buffer described by the Irp.  If we get an exception,
    00529         //  deallocate the Mdl and return the appropriate "expected" status.
    00530         //
    00531
    00532         try {
    00533
    00534             MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode, IoWriteAccess );
    00535
    00536             Status = STATUS_SUCCESS;
    00537
    00538         } except(EXCEPTION_EXECUTE_HANDLER) {
    00539
    00540             Status = GetExceptionCode();
    00541
    00542             IoFreeMdl( Mdl );
    00543             IrpContext->Irp->MdlAddress = NULL;
    00544
    00545             if (!FsRtlIsNtstatusExpected( Status )) {
    00546
    00547                 Status = STATUS_INVALID_USER_BUFFER;
    00548             }
    00549         }
    00550     }
    00551
    00552     //
    00553     //  Check if we are to raise or return
    00554     //
    00555
    00556     if (Status != STATUS_SUCCESS) {
    00557
    00558         if (RaiseOnError) {
    00559
    00560             UdfRaiseStatus( IrpContext, Status );
    00561         }
    00562     }
    00563
    00564     //
    00565     //  Return the status code.
    00566     //
    00567
    00568     return Status;
    00569 }

BOOLEAN UdfFinishBuffers | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIO_RUN | IoRuns,
|  | IN ULONG | RunCount,
|  | IN BOOLEAN | FinalCleanup
| ) |

Definition at line 1280 of file deviosup.c.

References Add2Ptr, FALSE, IoFreeIrp(), IoFreeMdl(), _IRP::MdlAddress, NULL, PAGED_CODE, PIO_RUN, _IO_RUN::SavedIrp, _IO_RUN::TransferBuffer, _IO_RUN::TransferBufferOffset, _IO_RUN::TransferByteCount, _IO_RUN::TransferMdl, TRUE, UdfFreePool(), and _IO_RUN::UserBuffer.

Referenced by UdfNonCachedRead().

    01289                    :
    01290
    01291     This routine is called to perform any data transferred required for
    01292     unaligned Io or to perform the final cleanup of the IoRuns array.
    01293
    01294     In all cases this is where we will deallocate any buffer and mdl
    01295     allocated to perform the unaligned transfer.  If this is not the
    01296     final cleanup then we also transfer the bytes to the user buffer
    01297     and flush the hardware cache.
    01298
    01299     We walk backwards through the run array because we may be shifting data
    01300     in the user's buffer.  Typical case is where we allocated a buffer for
    01301     the first part of a read and then used the user's buffer for the
    01302     next section (but stored it at the beginning of the buffer.
    01303
    01304 Arguments:
    01305
    01306     IoRuns - Pointer to the IoRuns array.
    01307
    01308     RunCount - Number of entries in the IoRuns array filled here.
    01309
    01310     FinalCleanup - Indicates if we should be deallocating temporary buffers
    01311         (TRUE) or transferring bytes for a unaligned transfers and
    01312         deallocating the buffers (FALSE).  Flush the system cache if
    01313         transferring data.
    01314
    01315 Return Value:
    01316
    01317     BOOLEAN - TRUE if this request needs the Io buffers to be flushed, FALSE otherwise.
    01318
    01319 --*/
    01320
    01321 {
    01322     BOOLEAN FlushIoBuffers = FALSE;
    01323
    01324     ULONG RemainingEntries = RunCount;
    01325     PIO_RUN ThisIoRun = &IoRuns[RunCount - 1];
    01326
    01327     PAGED_CODE();
    01328
    01329     //
    01330     //  Walk through each entry in the IoRun array.
    01331     //
    01332
    01333     while (RemainingEntries != 0) {
    01334
    01335         //
    01336         //  We only need to deal with the case of an unaligned transfer.
    01337         //
    01338
    01339         if (ThisIoRun->TransferByteCount != 0) {
    01340
    01341             //
    01342             //  If not the final cleanup then transfer the data to the
    01343             //  user's buffer and remember that we will need to flush
    01344             //  the user's buffer to memory.
    01345             //
    01346
    01347             if (!FinalCleanup) {
    01348
    01349                 //
    01350                 //  If we are shifting in the user's buffer then use
    01351                 //  MoveMemory.
    01352                 //
    01353
    01354                 if (ThisIoRun->TransferMdl == IrpContext->Irp->MdlAddress) {
    01355
    01356                     RtlMoveMemory( ThisIoRun->UserBuffer,
    01357                                    Add2Ptr( ThisIoRun->TransferBuffer,
    01358                                             ThisIoRun->TransferBufferOffset,
    01359                                             PVOID ),
    01360                                    ThisIoRun->TransferByteCount );
    01361
    01362                 } else {
    01363
    01364                     RtlCopyMemory( ThisIoRun->UserBuffer,
    01365                                    Add2Ptr( ThisIoRun->TransferBuffer,
    01366                                             ThisIoRun->TransferBufferOffset,
    01367                                             PVOID ),
    01368                                    ThisIoRun->TransferByteCount );
    01369                 }
    01370
    01371                 FlushIoBuffers = TRUE;
    01372             }
    01373
    01374             //
    01375             //  Free any Mdl we may have allocated.  If the Mdl isn't
    01376             //  present then we must have failed during the allocation
    01377             //  phase.
    01378             //
    01379
    01380             if (ThisIoRun->TransferMdl != IrpContext->Irp->MdlAddress) {
    01381
    01382                 if (ThisIoRun->TransferMdl != NULL) {
    01383
    01384                     IoFreeMdl( ThisIoRun->TransferMdl );
    01385                 }
    01386
    01387                 //
    01388                 //  Now free any buffer we may have allocated.  If the Mdl
    01389                 //  doesn't match the original Mdl then free the buffer.
    01390                 //
    01391
    01392                 if (ThisIoRun->TransferBuffer != NULL) {
    01393
    01394                     UdfFreePool( &ThisIoRun->TransferBuffer );
    01395                 }
    01396             }
    01397         }
    01398
    01399         //
    01400         //  Now handle the case where we failed in the process
    01401         //  of allocating associated Irps and Mdls.
    01402         //
    01403
    01404         if (ThisIoRun->SavedIrp != NULL) {
    01405
    01406             if (ThisIoRun->SavedIrp->MdlAddress != NULL) {
    01407
    01408                 IoFreeMdl( ThisIoRun->SavedIrp->MdlAddress );
    01409             }
    01410
    01411             IoFreeIrp( ThisIoRun->SavedIrp );
    01412         }
    01413
    01414         //
    01415         //  Move to the previous IoRun entry.
    01416         //
    01417
    01418         ThisIoRun -= 1;
    01419         RemainingEntries -= 1;
    01420     }
    01421
    01422     //
    01423     //  If we copied any data then flush the Io buffers.
    01424     //
    01425
    01426     return FlushIoBuffers;
    01427 }

NTSTATUS UdfMultiAsyncCompletionRoutine | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 1863 of file deviosup.c.

References ExReleaseResourceForThread, IoFreeIrp(), IoFreeMdl(), IoGetCurrentIrpStackLocation, IoMarkIrpPending, _IRP::IoStatus, Irp, _UDF_IO_CONTEXT::IrpCount, _UDF_IO_CONTEXT::MasterIrp, _IRP::MdlAddress, NT_SUCCESS, _UDF_IO_CONTEXT::RequestedByteCount, _UDF_IO_CONTEXT::Resource, _UDF_IO_CONTEXT::ResourceThreadId, _UDF_IO_CONTEXT::Status, and UdfFreeIoContext.

Referenced by UdfMultipleAsync().

    01871                    :
    01872
    01873     This is the completion routine for all asynchronous reads
    01874     started via UdfMultipleAsync.
    01875
    01876     The completion routine has has the following responsibilities:
    01877
    01878         If the individual request was completed with an error, then
    01879         this completion routine must see if this is the first error
    01880         and remember the error status in the Context.
    01881
    01882 Arguments:
    01883
    01884     DeviceObject - Pointer to the file system device object.
    01885
    01886     Irp - Pointer to the associated Irp which is being completed.  (This
    01887         Irp will no longer be accessible after this routine returns.)
    01888
    01889     Context - The context parameter which was specified for all of
    01890              the multiple asynch I/O requests for this MasterIrp.
    01891
    01892 Return Value:
    01893
    01894     Currently always returns STATUS_SUCCESS.
    01895
    01896 --*/
    01897
    01898 {
    01899     PUDF_IO_CONTEXT IoContext = Context;
    01900     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01901
    01902     //
    01903     //  If we got an error (or verify required), remember it in the Irp
    01904     //
    01905
    01906     if (!NT_SUCCESS( Irp->IoStatus.Status )) {
    01907
    01908         InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
    01909     }
    01910
    01911     //
    01912     //  Decrement IrpCount and see if it goes to zero.
    01913     //
    01914
    01915     if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
    01916
    01917         //
    01918         //  Mark the master Irp pending
    01919         //
    01920
    01921         IoMarkIrpPending( IoContext->MasterIrp );
    01922
    01923         //
    01924         //  Update the Master Irp with any error status from the associated Irps.
    01925         //
    01926
    01927         IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
    01928
    01929         //
    01930         //  Update the information field with the correct value.
    01931         //
    01932
    01933         IoContext->MasterIrp->IoStatus.Information = 0;
    01934
    01935         if (NT_SUCCESS( IoContext->MasterIrp->IoStatus.Status )) {
    01936
    01937             IoContext->MasterIrp->IoStatus.Information = IoContext->RequestedByteCount;
    01938         }
    01939
    01940         //
    01941         //  Now release the resource
    01942         //
    01943
    01944         ExReleaseResourceForThread( IoContext->Resource,
    01945                                     IoContext->ResourceThreadId );
    01946
    01947         //
    01948         //  and finally, free the context record.
    01949         //
    01950
    01951         UdfFreeIoContext( IoContext );
    01952
    01953         //
    01954         //  Return success in this case.
    01955         //
    01956
    01957         return STATUS_SUCCESS;
    01958
    01959     } else {
    01960
    01961         //
    01962         //  We need to cleanup the associated Irp and its Mdl.
    01963         //
    01964
    01965         IoFreeMdl( Irp->MdlAddress );
    01966         IoFreeIrp( Irp );
    01967
    01968         return STATUS_MORE_PROCESSING_REQUIRED;
    01969     }
    01970
    01971     UNREFERENCED_PARAMETER( DeviceObject );
    01972 }

VOID UdfMultipleAsync | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN ULONG | RunCount,
|  | IN PIO_RUN | IoRuns
| ) |

Definition at line 1435 of file deviosup.c.

References _IRP::AssociatedIrp, FALSE, FlagOn, IoAllocateMdl(), IoBuildPartialMdl(), IoCallDriver, IoGetCurrentIrpStackLocation, IoGetNextIrpStackLocation, IoMakeAssociatedIrp(), IoSetCompletionRoutine, IoSetNextIrpStackLocation, Irp, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_READ, _IO_STACK_LOCATION::MajorFunction, NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PIO_COMPLETION_ROUTINE, TRUE, UdfMultiAsyncCompletionRoutine(), UdfMultiSyncCompletionRoutine(), UdfRaiseStatus(), and VOID().

Referenced by UdfNonCachedRead().

    01443                    :
    01444
    01445     This routine first does the initial setup required of a Master IRP that is
    01446     going to be completed using associated IRPs.  This routine should not
    01447     be used if only one async request is needed, instead the single read
    01448     async routines should be called.
    01449
    01450     A context parameter is initialized, to serve as a communications area
    01451     between here and the common completion routine.
    01452
    01453     Next this routine reads or writes one or more contiguous sectors from
    01454     a device asynchronously, and is used if there are multiple reads for a
    01455     master IRP.  A completion routine is used to synchronize with the
    01456     completion of all of the I/O requests started by calls to this routine.
    01457
    01458     Also, prior to calling this routine the caller must initialize the
    01459     IoStatus field in the Context, with the correct success status and byte
    01460     count which are expected if all of the parallel transfers complete
    01461     successfully.  After return this status will be unchanged if all requests
    01462     were, in fact, successful.  However, if one or more errors occur, the
    01463     IoStatus will be modified to reflect the error status and byte count
    01464     from the first run (by Vbo) which encountered an error.  I/O status
    01465     from all subsequent runs will not be indicated.
    01466
    01467 Arguments:
    01468
    01469     RunCount - Supplies the number of multiple async requests
    01470         that will be issued against the master irp.
    01471
    01472     IoRuns - Supplies an array containing the Offset and ByteCount for the
    01473         separate requests.
    01474
    01475 Return Value:
    01476
    01477     None.
    01478
    01479 --*/
    01480
    01481 {
    01482     PIO_COMPLETION_ROUTINE CompletionRoutine;
    01483     PIO_STACK_LOCATION IrpSp;
    01484     PMDL Mdl;
    01485     PIRP Irp;
    01486     PIRP MasterIrp;
    01487     ULONG UnwindRunCount;
    01488
    01489     PAGED_CODE();
    01490
    01491     //
    01492     //  Set up things according to whether this is truely async.
    01493     //
    01494
    01495     CompletionRoutine = UdfMultiSyncCompletionRoutine;
    01496
    01497     if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    01498
    01499         CompletionRoutine = UdfMultiAsyncCompletionRoutine;
    01500     }
    01501
    01502     //
    01503     //  Initialize some local variables.
    01504     //
    01505
    01506     MasterIrp = IrpContext->Irp;
    01507
    01508     //
    01509     //  Itterate through the runs, doing everything that can fail.
    01510     //  We let the cleanup in CdFinishBuffers clean up on error.
    01511     //
    01512
    01513     for (UnwindRunCount = 0;
    01514          UnwindRunCount < RunCount;
    01515          UnwindRunCount += 1) {
    01516
    01517         //
    01518         //  Create an associated IRP, making sure there is one stack entry for
    01519         //  us, as well.
    01520         //
    01521
    01522         IoRuns[UnwindRunCount].SavedIrp =
    01523         Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) );
    01524
    01525         if (Irp == NULL) {
    01526
    01527             IrpContext->Irp->IoStatus.Information = 0;
    01528             UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    01529         }
    01530
    01531         //
    01532         // Allocate and build a partial Mdl for the request.
    01533         //
    01534
    01535         Mdl = IoAllocateMdl( IoRuns[UnwindRunCount].TransferVirtualAddress,
    01536                              IoRuns[UnwindRunCount].DiskByteCount,
    01537                              FALSE,
    01538                              FALSE,
    01539                              Irp );
    01540
    01541         if (Mdl == NULL) {
    01542
    01543             IrpContext->Irp->IoStatus.Information = 0;
    01544             UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    01545         }
    01546
    01547         IoBuildPartialMdl( IoRuns[UnwindRunCount].TransferMdl,
    01548                            Mdl,
    01549                            IoRuns[UnwindRunCount].TransferVirtualAddress,
    01550                            IoRuns[UnwindRunCount].DiskByteCount );
    01551
    01552         //
    01553         //  Get the first IRP stack location in the associated Irp
    01554         //
    01555
    01556         IoSetNextIrpStackLocation( Irp );
    01557         IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01558
    01559         //
    01560         //  Setup the Stack location to describe our read.
    01561         //
    01562
    01563         IrpSp->MajorFunction = IRP_MJ_READ;
    01564         IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
    01565         IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
    01566
    01567         //
    01568         // Set up the completion routine address in our stack frame.
    01569         //
    01570
    01571         IoSetCompletionRoutine( Irp,
    01572                                 CompletionRoutine,
    01573                                 IrpContext->IoContext,
    01574                                 TRUE,
    01575                                 TRUE,
    01576                                 TRUE );
    01577
    01578         //
    01579         //  Setup the next IRP stack location in the associated Irp for the disk
    01580         //  driver beneath us.
    01581         //
    01582
    01583         IrpSp = IoGetNextIrpStackLocation( Irp );
    01584
    01585         //
    01586         //  Setup the Stack location to do a read from the disk driver.
    01587         //
    01588
    01589         IrpSp->MajorFunction = IRP_MJ_READ;
    01590         IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
    01591         IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
    01592     }
    01593
    01594     //
    01595     //  We only need to set the associated IRP count in the master irp to
    01596     //  make it a master IRP.  But we set the count to one more than our
    01597     //  caller requested, because we do not want the I/O system to complete
    01598     //  the I/O.  We also set our own count.
    01599     //
    01600
    01601     IrpContext->IoContext->IrpCount = RunCount;
    01602     IrpContext->IoContext->MasterIrp = MasterIrp;
    01603
    01604     //
    01605     //  We set the count in the master Irp to 1 since typically we
    01606     //  will clean up the associated irps ourselves.  Setting this to one
    01607     //  means completing the last associated Irp with SUCCESS (in the async
    01608     //  case) will complete the master irp.
    01609     //
    01610
    01611     MasterIrp->AssociatedIrp.IrpCount = 1;
    01612
    01613     //
    01614     //  Now that all the dangerous work is done, issue the Io requests
    01615     //
    01616
    01617     for (UnwindRunCount = 0;
    01618          UnwindRunCount < RunCount;
    01619          UnwindRunCount++) {
    01620
    01621         Irp = IoRuns[UnwindRunCount].SavedIrp;
    01622         IoRuns[UnwindRunCount].SavedIrp = NULL;
    01623
    01624         //
    01625         //  If IoCallDriver returns an error, it has completed the Irp
    01626         //  and the error will be caught by our completion routines
    01627         //  and dealt with as a normal IO error.
    01628         //
    01629
    01630         (VOID) IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
    01631     }
    01632
    01633     return;
    01634 }

NTSTATUS UdfMultiSyncCompletionRoutine | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 1779 of file deviosup.c.

References FALSE, IoFreeIrp(), IoFreeMdl(), _IRP::IoStatus, Irp, _UDF_IO_CONTEXT::IrpCount, KeSetEvent(), _UDF_IO_CONTEXT::MasterIrp, _IRP::MdlAddress, NT_SUCCESS, PUDF_IO_CONTEXT, _UDF_IO_CONTEXT::Status, and _UDF_IO_CONTEXT::SyncEvent.

Referenced by UdfMultipleAsync().

    01787                    :
    01788
    01789     This is the completion routine for all synchronous reads
    01790     started via UdfMultipleAsync.
    01791
    01792     The completion routine has has the following responsibilities:
    01793
    01794         If the individual request was completed with an error, then
    01795         this completion routine must see if this is the first error
    01796         and remember the error status in the Context.
    01797
    01798         If the IrpCount goes to 1, then it sets the event in the Context
    01799         parameter to signal the caller that all of the asynch requests
    01800         are done.
    01801
    01802 Arguments:
    01803
    01804     DeviceObject - Pointer to the file system device object.
    01805
    01806     Irp - Pointer to the associated Irp which is being completed.  (This
    01807         Irp will no longer be accessible after this routine returns.)
    01808
    01809     Context - The context parameter which was specified for all of
    01810         the multiple asynch I/O requests for this MasterIrp.
    01811
    01812 Return Value:
    01813
    01814     The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
    01815     immediately complete the Master Irp without being in a race condition
    01816     with the IoCompleteRequest thread trying to decrement the IrpCount in
    01817     the Master Irp.
    01818
    01819 --*/
    01820
    01821 {
    01822     PUDF_IO_CONTEXT IoContext = Context;
    01823
    01824     //
    01825     //  If we got an error (or verify required), remember it in the Irp
    01826     //
    01827
    01828     if (!NT_SUCCESS( Irp->IoStatus.Status )) {
    01829
    01830         InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
    01831         IoContext->MasterIrp->IoStatus.Information = 0;
    01832     }
    01833
    01834     //
    01835     //  We must do this here since IoCompleteRequest won't get a chance
    01836     //  on this associated Irp.
    01837     //
    01838
    01839     IoFreeMdl( Irp->MdlAddress );
    01840     IoFreeIrp( Irp );
    01841
    01842     if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
    01843
    01844         //
    01845         //  Update the Master Irp with any error status from the associated Irps.
    01846         //
    01847
    01848         IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
    01849         KeSetEvent( &IoContext->SyncEvent, 0, FALSE );
    01850     }
    01851
    01852     UNREFERENCED_PARAMETER( DeviceObject );
    01853
    01854     return STATUS_MORE_PROCESSING_REQUIRED;
    01855 }

NTSTATUS UdfNonCachedRead | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PFCB | Fcb,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount
| ) |

Definition at line 201 of file deviosup.c.

References Add2Ptr, ASSERT, ClearFlag, DebugUnwind, FALSE, FCB_STATE_EMBEDDED_DATA, FCB_STATE_VMCB_MAPPING, FlagOn, IRP_CONTEXT_FLAG_ALLOC_IO, IRP_CONTEXT_FLAG_WAIT, KeFlushIoBuffers(), MAX_PARALLEL_IOS, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, TRUE, try_leave, UdfCreateUserMdl(), UdfFinishBuffers(), UdfMapUserBuffer, UdfMultipleAsync(), UdfPrepareBuffers(), UdfRaiseStatus(), UdfSingleAsync(), and UdfWaitSync().

Referenced by UdfCommonRead().

    00210                    :
    00211
    00212     This routine performs the non-cached reads of sectors.  This is done by
    00213     performing the following in a loop.
    00214
    00215         Fill in the IoRuns array for the next block of Io.
    00216         Send the Io to the device.
    00217         Perform any cleanup on the Io runs array.
    00218
    00219     We will not do async Io to any request that generates non-aligned Io.
    00220     Also we will not perform async Io if it will exceed the size of our
    00221     IoRuns array.  These should be the unusual cases but we will raise
    00222     or return CANT_WAIT in this routine if we detect this case.
    00223
    00224 Arguments:
    00225
    00226     Fcb - Fcb representing the file to read.
    00227
    00228     StartingOffset - Logical offset in the file to read from.
    00229
    00230     ByteCount - Number of bytes to read.
    00231
    00232 Return Value:
    00233
    00234     NTSTATUS - Status indicating the result of the operation.
    00235
    00236 --*/
    00237
    00238 {
    00239     NTSTATUS Status = STATUS_SUCCESS;
    00240
    00241     IO_RUN IoRuns[MAX_PARALLEL_IOS];
    00242     ULONG RunCount = 0;
    00243     ULONG CleanupRunCount = 0;
    00244
    00245     PVOID UserBuffer;
    00246     ULONG UserBufferOffset = 0;
    00247     LONGLONG CurrentOffset = StartingOffset;
    00248     ULONG RemainingByteCount = ByteCount;
    00249     ULONG ThisByteCount;
    00250
    00251     BOOLEAN Unaligned;
    00252     BOOLEAN SparseRuns;
    00253     BOOLEAN FlushIoBuffers = FALSE;
    00254     BOOLEAN FirstPass = TRUE;
    00255
    00256     PAGED_CODE();
    00257
    00258     //
    00259     //  We want to make sure the user's buffer is locked in all cases.
    00260     //
    00261
    00262     if (IrpContext->Irp->MdlAddress == NULL) {
    00263
    00264         UdfCreateUserMdl( IrpContext, ByteCount, TRUE );
    00265     }
    00266
    00267     //
    00268     //  Use a try-finally to perform the final cleanup.
    00269     //
    00270
    00271     try {
    00272
    00273         UdfMapUserBuffer( IrpContext, &UserBuffer);
    00274
    00275         //
    00276         //  Loop while there are more bytes to transfer.
    00277         //
    00278
    00279         do {
    00280
    00281             //
    00282             //  Call prepare buffers to set up the next entries
    00283             //  in the IoRuns array.  Remember if there are any
    00284             //  unaligned entries.
    00285             //
    00286
    00287             RtlZeroMemory( IoRuns, sizeof( IoRuns ));
    00288
    00289             Unaligned = UdfPrepareBuffers( IrpContext,
    00290                                            IrpContext->Irp,
    00291                                            Fcb,
    00292                                            UserBuffer,
    00293                                            UserBufferOffset,
    00294                                            CurrentOffset,
    00295                                            RemainingByteCount,
    00296                                            IoRuns,
    00297                                            &CleanupRunCount,
    00298                                            &ThisByteCount,
    00299                                            &SparseRuns );
    00300
    00301
    00302             RunCount = CleanupRunCount;
    00303
    00304             //
    00305             //  Quickly finish if we wound up having no IO to perform.  This will
    00306             //  occur in the presence of unrecorded sectors.
    00307             //
    00308
    00309             ASSERT( !(SparseRuns && FlagOn( Fcb->FcbState, FCB_STATE_VMCB_MAPPING|FCB_STATE_EMBEDDED_DATA )));
    00310
    00311             if (RunCount == 0) {
    00312
    00313                 try_leave( Status = IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS );
    00314             }
    00315
    00316             //
    00317             //  If this is an async request and there aren't enough entries
    00318             //  in the Io array then post the request.  This routine will
    00319             //  always raise if we are doing any unaligned Io for an
    00320             //  async request.
    00321             //
    00322
    00323             if ((ThisByteCount < RemainingByteCount) &&
    00324                 !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00325
    00326                 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    00327             }
    00328
    00329             //
    00330             //  If the entire Io is contained in a single run then
    00331             //  we can pass the Io down to the driver.  Send the driver down
    00332             //  and wait on the result if this is synchronous.  We cannot
    00333             //  do this simple form (just chucking the IRP down) if some
    00334             //  sparse runs were encountered.
    00335             //
    00336
    00337             if ((RunCount == 1) && !Unaligned && !SparseRuns && FirstPass) {
    00338
    00339                 UdfSingleAsync( IrpContext,
    00340                                 IoRuns[0].DiskOffset,
    00341                                 IoRuns[0].DiskByteCount );
    00342
    00343                 //
    00344                 //  No cleanup needed for the IoRuns array here.
    00345                 //
    00346
    00347                 CleanupRunCount = 0;
    00348
    00349                 //
    00350                 //  Wait if we are synchronous, otherwise return
    00351                 //
    00352
    00353                 if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00354
    00355                     UdfWaitSync( IrpContext );
    00356
    00357                     Status = IrpContext->Irp->IoStatus.Status;
    00358
    00359                 //
    00360                 //  Our completion routine will free the Io context but
    00361                 //  we do want to return STATUS_PENDING.
    00362                 //
    00363
    00364                 } else {
    00365
    00366                     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00367                     Status = STATUS_PENDING;
    00368                 }
    00369
    00370                 try_leave( NOTHING );
    00371             }
    00372
    00373             //
    00374             //  Otherwise we will perform multiple Io to read in the data.
    00375             //
    00376
    00377             UdfMultipleAsync( IrpContext, RunCount, IoRuns );
    00378
    00379             //
    00380             //  No cleanup needed on the IoRuns now.
    00381             //
    00382
    00383             CleanupRunCount = 0;
    00384
    00385             //
    00386             //  If this is a synchronous request then perform any necessary
    00387             //  post-processing.
    00388             //
    00389
    00390             if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    00391
    00392                 //
    00393                 //  Wait for the request to complete.
    00394                 //
    00395
    00396                 UdfWaitSync( IrpContext );
    00397
    00398                 Status = IrpContext->Irp->IoStatus.Status;
    00399
    00400                 //
    00401                 //  Exit this loop if there is an error.
    00402                 //
    00403
    00404                 if (!NT_SUCCESS( Status )) {
    00405
    00406                     try_leave( NOTHING );
    00407                 }
    00408
    00409                 //
    00410                 //  Perform post read operations on the IoRuns if
    00411                 //  necessary.
    00412                 //
    00413
    00414                 if (Unaligned &&
    00415                     UdfFinishBuffers( IrpContext, IoRuns, RunCount, FALSE )) {
    00416
    00417                     FlushIoBuffers = TRUE;
    00418                 }
    00419
    00420                 //
    00421                 //  Exit this loop if there are no more bytes to transfer
    00422                 //  or we have any error.
    00423                 //
    00424
    00425                 RemainingByteCount -= ThisByteCount;
    00426                 CurrentOffset += ThisByteCount;
    00427                 UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
    00428                 UserBufferOffset += ThisByteCount;
    00429
    00430             //
    00431             //  Otherwise this is an asynchronous request.  Always return
    00432             //  STATUS_PENDING.
    00433             //
    00434
    00435             } else {
    00436
    00437                 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
    00438                 CleanupRunCount = 0;
    00439                 try_leave( Status = STATUS_PENDING );
    00440                 break;
    00441             }
    00442
    00443             FirstPass = FALSE;
    00444         } while (RemainingByteCount != 0);
    00445
    00446         //
    00447         //  Flush the hardware cache if we performed any copy operations.
    00448         //
    00449
    00450         if (FlushIoBuffers) {
    00451
    00452             KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
    00453         }
    00454
    00455     } finally {
    00456
    00457         DebugUnwind( "UdfNonCachedRead" );
    00458
    00459         //
    00460         //  Perform final cleanup on the IoRuns if necessary.
    00461         //
    00462
    00463         if (CleanupRunCount != 0) {
    00464
    00465             UdfFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE );
    00466         }
    00467     }
    00468
    00469     return Status;
    00470 }

NTSTATUS UdfPerformDevIoCtrl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN ULONG | IoControlCode,
|  | IN PDEVICE_OBJECT | Device,
|  | OUT PVOID OutputBuffer | OPTIONAL,
|  | IN ULONG | OutputBufferLength,
|  | IN BOOLEAN | InternalDeviceIoControl,
|  | IN BOOLEAN | OverrideVerify,
|  | OUT PIO_STATUS_BLOCK Iosb | OPTIONAL
| ) |

Definition at line 573 of file deviosup.c.

References Event(), Executive, FALSE, IoBuildDeviceIoControlRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), NTSTATUS(), NULL, PAGED_CODE, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, and VOID().

Referenced by UdfDetermineVolumeBounding(), UdfMountVolume(), UdfVerifyVcb(), and UdfVerifyVolume().

    00586                    :
    00587
    00588     This routine is called to perform DevIoCtrl functions internally within
    00589     the filesystem.  We take the status from the driver and return it to our
    00590     caller.
    00591
    00592 Arguments:
    00593
    00594     IoControlCode - Code to send to driver.
    00595
    00596     Device - This is the device to send the request to.
    00597
    00598     OutPutBuffer - Pointer to output buffer.
    00599
    00600     OutputBufferLength - Length of output buffer above.
    00601
    00602     InternalDeviceIoControl - Indicates if this is an internal or external
    00603         Io control code.
    00604
    00605     OverrideVerify - Indicates if we should tell the driver not to return
    00606         STATUS_VERIFY_REQUIRED for mount and verify.
    00607
    00608     Iosb - If specified, we return the results of the operation here.
    00609
    00610 Return Value:
    00611
    00612     NTSTATUS - Status returned by next lower driver.
    00613
    00614 --*/
    00615
    00616 {
    00617     NTSTATUS Status;
    00618     PIRP Irp;
    00619     KEVENT Event;
    00620     IO_STATUS_BLOCK LocalIosb;
    00621     PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
    00622
    00623     PAGED_CODE();
    00624
    00625     //
    00626     //  Check if the user gave us an Iosb.
    00627     //
    00628
    00629     if (ARGUMENT_PRESENT( Iosb )) {
    00630
    00631         IosbToUse = Iosb;
    00632     }
    00633
    00634     IosbToUse->Status = 0;
    00635     IosbToUse->Information = 0;
    00636
    00637     KeInitializeEvent( &Event, NotificationEvent, FALSE );
    00638
    00639     Irp = IoBuildDeviceIoControlRequest( IoControlCode,
    00640                                          Device,
    00641                                          NULL,
    00642                                          0,
    00643                                          OutputBuffer,
    00644                                          OutputBufferLength,
    00645                                          InternalDeviceIoControl,
    00646                                          &Event,
    00647                                          IosbToUse );
    00648
    00649     if (Irp == NULL) {
    00650
    00651         return STATUS_INSUFFICIENT_RESOURCES;
    00652     }
    00653
    00654     if (OverrideVerify) {
    00655
    00656         SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
    00657     }
    00658
    00659     Status = IoCallDriver( Device, Irp );
    00660
    00661     //
    00662     //  We check for device not ready by first checking Status
    00663     //  and then if status pending was returned, the Iosb status
    00664     //  value.
    00665     //
    00666
    00667     if (Status == STATUS_PENDING) {
    00668
    00669         (VOID) KeWaitForSingleObject( &Event,
    00670                                       Executive,
    00671                                       KernelMode,
    00672                                       FALSE,
    00673                                       (PLARGE_INTEGER)NULL );
    00674
    00675         Status = IosbToUse->Status;
    00676     }
    00677
    00678     return Status;
    00679
    00680     UNREFERENCED_PARAMETER( IrpContext );
    00681 }

BOOLEAN UdfPrepareBuffers | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp,
|  | IN PFCB | Fcb,
|  | IN PVOID | UserBuffer,
|  | IN ULONG | UserBufferOffset,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount,
|  | IN PIO_RUN | IoRuns,
|  | IN PULONG | RunCount,
|  | IN PULONG | ThisByteCount,
|  | IN PBOOLEAN | SparseRuns
| ) |

Definition at line 883 of file deviosup.c.

References Add2Ptr, _IO_RUN::DiskByteCount, _IO_RUN::DiskOffset, FALSE, FlagOn, FsRtlAllocatePoolWithTag, IoAllocateMdl(), Irp, IRP_CONTEXT_FLAG_WAIT, LlSectorTruncate, MAX_PARALLEL_IOS, _IRP::MdlAddress, MmBuildMdlForNonPagedPool(), NULL, PAGE_SIZE, PAGED_CODE, PIO_RUN, SectorAlign, SectorOffset, SectorSize, SectorTruncate, TAG_IO_BUFFER, _IO_RUN::TransferBuffer, _IO_RUN::TransferBufferOffset, _IO_RUN::TransferByteCount, _IO_RUN::TransferMdl, _IO_RUN::TransferVirtualAddress, TRUE, UdfLookupAllocation(), UdfNonPagedPool, UdfRaiseStatus(), _IRP::UserBuffer, and _IO_RUN::UserBuffer.

Referenced by UdfNonCachedRead().

    00899                    :
    00900
    00901     This routine is the worker routine which looks up each run of an IO
    00902     request and stores an entry for it in the IoRuns array.  If the run
    00903     begins on an unaligned disk boundary then we will allocate a buffer
    00904     and Mdl for the unaligned portion and put it in the IoRuns entry.
    00905
    00906     This routine will raise CANT_WAIT if an unaligned transfer is encountered
    00907     and this request can't wait.
    00908
    00909 Arguments:
    00910
    00911     Irp - Originating Irp for this request.
    00912
    00913     Fcb - This is the Fcb for this data stream.  It may be a file, directory,
    00914         path table or the volume file.
    00915
    00916     UserBuffer - Current position in the user's buffer.
    00917
    00918     UserBufferOffset - Offset from the start of the original user buffer.
    00919
    00920     StartingOffset - Offset in the stream to begin the read.
    00921
    00922     ByteCount - Number of bytes to read.  We will fill the IoRuns array up
    00923         to this point.  We will stop early if we exceed the maximum number
    00924         of parallel Ios we support.
    00925
    00926     IoRuns - Pointer to the IoRuns array.  The entire array is zeroes when
    00927         this routine is called.
    00928
    00929     RunCount - Number of entries in the IoRuns array filled here.
    00930
    00931     ThisByteCount - Number of bytes described by the IoRun entries.  Will
    00932         not exceed the ByteCount passed in.
    00933
    00934     SparseRuns - Will indicate whether sparse runs were a component of the
    00935         range returned.  While not part of the IoRuns, this will affect
    00936         our ability to do simple IO.
    00937
    00938 Return Value:
    00939
    00940     BOOLEAN - TRUE if one of the entries in an unaligned buffer (provided
    00941         this is synchronous).  FALSE otherwise.
    00942
    00943 --*/
    00944
    00945 {
    00946     PVCB Vcb;
    00947
    00948     BOOLEAN Recorded;
    00949
    00950     BOOLEAN FoundUnaligned = FALSE;
    00951     PIO_RUN ThisIoRun = IoRuns;
    00952
    00953     //
    00954     //  Following indicate where we are in the current transfer.  Current
    00955     //  position in the file and number of bytes yet to transfer from
    00956     //  this position.
    00957     //
    00958
    00959     ULONG RemainingByteCount = ByteCount;
    00960     LONGLONG CurrentFileOffset = StartingOffset;
    00961
    00962     //
    00963     //  Following indicate the state of the user's buffer.  We have
    00964     //  the destination of the next transfer and its offset in the
    00965     //  buffer.  We also have the next available position in the buffer
    00966     //  available for a scratch buffer.  We will align this up to a sector
    00967     //  boundary.
    00968     //
    00969
    00970     PVOID CurrentUserBuffer = UserBuffer;
    00971     ULONG CurrentUserBufferOffset = UserBufferOffset;
    00972
    00973     PVOID ScratchUserBuffer = UserBuffer;
    00974     ULONG ScratchUserBufferOffset = UserBufferOffset;
    00975
    00976     //
    00977     //  The following is the next contiguous bytes on the disk to
    00978     //  transfer.  Read from the allocation package.
    00979     //
    00980
    00981     LONGLONG DiskOffset;
    00982     ULONG CurrentByteCount;
    00983
    00984     PAGED_CODE();
    00985
    00986     Vcb = Fcb->Vcb;
    00987
    00988     //
    00989     //  Initialize the RunCount, ByteCount and SparseRuns.
    00990     //
    00991
    00992     *RunCount = 0;
    00993     *ThisByteCount = 0;
    00994     *SparseRuns = FALSE;
    00995
    00996     //
    00997     //  Loop while there are more bytes to process or there are
    00998     //  available entries in the IoRun array.
    00999     //
    01000
    01001     while (TRUE) {
    01002
    01003         *RunCount += 1;
    01004
    01005         //
    01006         //  Initialize the current position in the IoRuns array.
    01007         //  Find the user's buffer for this portion of the transfer.
    01008         //
    01009
    01010         ThisIoRun->UserBuffer = CurrentUserBuffer;
    01011
    01012         //
    01013         //  Find the allocation information for the current offset in the
    01014         //  stream.
    01015         //
    01016
    01017         Recorded = UdfLookupAllocation( IrpContext,
    01018                                         Fcb,
    01019                                         CurrentFileOffset,
    01020                                         &DiskOffset,
    01021                                         &CurrentByteCount );
    01022
    01023         //
    01024         //  Limit ourselves to the data requested.
    01025         //
    01026
    01027         if (CurrentByteCount > RemainingByteCount) {
    01028
    01029             CurrentByteCount = RemainingByteCount;
    01030         }
    01031
    01032         //
    01033         //  Handle the case of unrecorded data first.
    01034         //
    01035
    01036         if (!Recorded) {
    01037
    01038             //
    01039             //  Note that we did not consume an entry.
    01040             //
    01041
    01042             *RunCount -= 1;
    01043
    01044             //
    01045             //  Immediately zero the user buffer and indicate that we found sparse
    01046             //  runs to the caller.
    01047             //
    01048
    01049             RtlZeroMemory( CurrentUserBuffer, CurrentByteCount );
    01050             *SparseRuns = TRUE;
    01051
    01052             //
    01053             //  Push the scratch buffer pointers forward so that we don't stomp
    01054             //  on the zeroed buffer.
    01055             //
    01056
    01057             ScratchUserBuffer = Add2Ptr( CurrentUserBuffer,
    01058                                          CurrentByteCount,
    01059                                          PVOID );
    01060
    01061             ScratchUserBufferOffset += CurrentByteCount;
    01062
    01063         //
    01064         //  Handle the case where this is an unaligned transfer.  The
    01065         //  following must all be true for this to be an aligned transfer.
    01066         //
    01067         //      Disk offset on a 2048 byte boundary (Start of transfer)
    01068         //
    01069         //      Byte count is a multiple of 2048 (Length of transfer)
    01070         //
    01071         //      Current buffer offset is also on a 2048 byte boundary.
    01072         //
    01073         //  If the ByteCount is at least one sector then do the
    01074         //  unaligned transfer only for the tail.  We can use the
    01075         //  user's buffer for the aligned portion.
    01076         //
    01077
    01078         } else if (SectorOffset( Vcb, DiskOffset ) ||
    01079                    SectorOffset( Vcb, CurrentUserBufferOffset ) ||
    01080                    (SectorOffset( Vcb, CurrentByteCount ) &&
    01081                     CurrentByteCount < SectorSize( Vcb ))) {
    01082
    01083             //
    01084             //  If we can't wait then raise.
    01085             //
    01086
    01087             if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    01088
    01089                 UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    01090             }
    01091
    01092             //
    01093             //  Remember the offset and the number of bytes out of
    01094             //  the transfer buffer to copy into the user's buffer.
    01095             //  We will truncate the current read to end on a sector
    01096             //  boundary.
    01097             //
    01098
    01099             ThisIoRun->TransferBufferOffset = SectorOffset( Vcb, DiskOffset );
    01100
    01101             //
    01102             //  Make sure this transfer ends on a sector boundary.
    01103             //
    01104
    01105             ThisIoRun->DiskOffset = LlSectorTruncate( Vcb, DiskOffset );
    01106
    01107             //
    01108             //  Check if we can use a free portion of the user's buffer.
    01109             //  If we can copy the bytes to an earlier portion of the
    01110             //  buffer then read into that location and slide the bytes
    01111             //  up.
    01112             //
    01113             //  We can use the user's buffer if:
    01114             //
    01115             //      The temporary location in the buffer is before the
    01116             //      final destination.
    01117             //
    01118             //      There is at least one sector of data to read.
    01119             //
    01120
    01121             if ((ScratchUserBufferOffset + ThisIoRun->TransferBufferOffset < CurrentUserBufferOffset) &&
    01122                 (ThisIoRun->TransferBufferOffset + CurrentByteCount >= SectorSize( Vcb ))) {
    01123
    01124                 ThisIoRun->DiskByteCount = SectorTruncate( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount );
    01125                 CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
    01126                 ThisIoRun->TransferByteCount = CurrentByteCount;
    01127
    01128                 //
    01129                 //  Point to the user's buffer and Mdl for this transfer.
    01130                 //
    01131
    01132                 ThisIoRun->TransferBuffer = ScratchUserBuffer;
    01133                 ThisIoRun->TransferMdl = Irp->MdlAddress;
    01134                 ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
    01135                                                              ScratchUserBufferOffset,
    01136                                                              PVOID );
    01137
    01138                 ScratchUserBuffer = Add2Ptr( ScratchUserBuffer,
    01139                                              ThisIoRun->DiskByteCount,
    01140                                              PVOID );
    01141
    01142                 ScratchUserBufferOffset += ThisIoRun->DiskByteCount;
    01143
    01144             //
    01145             //  Otherwise we need to allocate an auxilary buffer for the next sector.
    01146             //
    01147
    01148             } else {
    01149
    01150                 //
    01151                 //  Read up to a page containing the partial data
    01152                 //
    01153
    01154                 ThisIoRun->DiskByteCount = SectorAlign( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount );
    01155
    01156                 if (ThisIoRun->DiskByteCount > PAGE_SIZE) {
    01157
    01158                     ThisIoRun->DiskByteCount = PAGE_SIZE;
    01159                 }
    01160
    01161                 if (ThisIoRun->TransferBufferOffset + CurrentByteCount > ThisIoRun->DiskByteCount) {
    01162
    01163                     CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
    01164                 }
    01165
    01166                 ThisIoRun->TransferByteCount = CurrentByteCount;
    01167
    01168                 //
    01169                 //  Allocate a buffer for the non-aligned transfer.
    01170                 //
    01171
    01172                 ThisIoRun->TransferBuffer = FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    01173                                                                       PAGE_SIZE,
    01174                                                                       TAG_IO_BUFFER );
    01175
    01176                 //
    01177                 //  Allocate and build the Mdl to describe this buffer.
    01178                 //
    01179
    01180                 ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer,
    01181                                                         PAGE_SIZE,
    01182                                                         FALSE,
    01183                                                         FALSE,
    01184                                                         NULL );
    01185
    01186                 ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer;
    01187
    01188                 if (ThisIoRun->TransferMdl == NULL) {
    01189
    01190                     IrpContext->Irp->IoStatus.Information = 0;
    01191                     UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    01192                 }
    01193
    01194                 MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl );
    01195             }
    01196
    01197             //
    01198             //  Remember we found an unaligned transfer.
    01199             //
    01200
    01201             FoundUnaligned = TRUE;
    01202
    01203         //
    01204         //  Otherwise we use the buffer and Mdl from the original request.
    01205         //
    01206
    01207         } else {
    01208
    01209             //
    01210             //  Truncate the read length to a sector-aligned value.  We know
    01211             //  the length must be at least one sector or we wouldn't be
    01212             //  here now.
    01213             //
    01214
    01215             CurrentByteCount = SectorTruncate( Vcb, CurrentByteCount );
    01216
    01217             //
    01218             //  Read these sectors from the disk.
    01219             //
    01220
    01221             ThisIoRun->DiskOffset = DiskOffset;
    01222             ThisIoRun->DiskByteCount = CurrentByteCount;
    01223
    01224             //
    01225             //  Use the user's buffer and Mdl as our transfer buffer
    01226             //  and Mdl.
    01227             //
    01228
    01229             ThisIoRun->TransferBuffer = CurrentUserBuffer;
    01230             ThisIoRun->TransferMdl = Irp->MdlAddress;
    01231             ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
    01232                                                          CurrentUserBufferOffset,
    01233                                                          PVOID );
    01234
    01235             ScratchUserBuffer = Add2Ptr( CurrentUserBuffer,
    01236                                          CurrentByteCount,
    01237                                          PVOID );
    01238
    01239             ScratchUserBufferOffset += CurrentByteCount;
    01240         }
    01241
    01242         //
    01243         //  Update our position in the transfer and the RunCount and
    01244         //  ByteCount for the user.
    01245         //
    01246
    01247         RemainingByteCount -= CurrentByteCount;
    01248
    01249         //
    01250         //  Break out if no more positions in the IoRuns array or
    01251         //  we have all of the bytes accounted for.
    01252         //
    01253
    01254         *ThisByteCount += CurrentByteCount;
    01255
    01256         if ((RemainingByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) {
    01257
    01258             break;
    01259         }
    01260
    01261         //
    01262         //  Update our pointers for the user's buffer.
    01263         //
    01264
    01265         ThisIoRun = IoRuns + *RunCount;
    01266         CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID );
    01267         CurrentUserBufferOffset += CurrentByteCount;
    01268         CurrentFileOffset += CurrentByteCount;
    01269     }
    01270
    01271     return FoundUnaligned;
    01272 }

BOOLEAN UdfPrepareBuffers | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp,
|  | IN PFCB | Fcb,
|  | IN PVOID | UserBuffer,
|  | IN ULONG | UserBufferOffset,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount,
|  | IN PIO_RUN | IoRuns,
|  | IN PULONG | RunCount,
|  | IN PULONG | ThisByteCount,
|  | OUT PBOOLEAN | SparseRuns
| ) |

NTSTATUS UdfReadSectors | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN LONGLONG | StartingOffset,
|  | IN ULONG | ByteCount,
|  | IN BOOLEAN | ReturnError,
|  | IN OUT PVOID | Buffer,
|  | IN PDEVICE_OBJECT | TargetDeviceObject
| ) |

Definition at line 685 of file deviosup.c.

References ASSERT, Buffer, BytesFromSectors, Dbg, DebugTrace, Event(), Executive, FALSE, FlagOn, FsRtlLookupLargeMcbEntry(), IoBuildSynchronousFsdRequest(), IoCallDriver, IoGetNextIrpStackLocation, Irp, IRP_MJ_READ, KeInitializeEvent, KernelMode, KeWaitForSingleObject(), LlSectorsFromBytes, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, SectorSize, SetFlag, SL_OVERRIDE_VERIFY_VOLUME, Status, UdfMethod2TransformByteOffset, UdfNormalizeAndRaiseStatus(), UdfRaiseStatus(), and VCB_STATE_METHOD_2_FIXUP.

Referenced by UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfLoadSparingTables(), UdfRecognizeVolume(), and UdfUpdateVcbPhase0().

    00696                    :
    00697
    00698     This routine is called to transfer sectors from the disk to a
    00699     specified buffer.  It is used for mount and volume verify operations.
    00700
    00701     This routine is synchronous, it will not return until the operation
    00702     is complete or until the operation fails.
    00703
    00704     The routine allocates an IRP and then passes this IRP to a lower
    00705     level driver.  Errors may occur in the allocation of this IRP or
    00706     in the operation of the lower driver.
    00707
    00708 Arguments:
    00709
    00710     StartingOffset - Logical offset on the disk to start the read.  This
    00711         must be on a sector boundary, no check is made here.
    00712
    00713     ByteCount - Number of bytes to read.  This is an integral number of
    00714         sectors, or otherwise a value we know the driver can handle,
    00715         no check is made here to confirm this.
    00716
    00717     ReturnError - Indicates whether we should return TRUE or FALSE
    00718         to indicate an error or raise an error condition.  This only applies
    00719         to the result of the IO.  Any other error may cause a raise.
    00720
    00721     Buffer - Buffer to transfer the disk data into.
    00722
    00723     TargetDeviceObject - The device object for the volume to be read.
    00724
    00725 Return Value:
    00726
    00727     The final status of the operation.
    00728
    00729 --*/
    00730
    00731 {
    00732     PLONGLONG UseStartingOffset;
    00733     LONGLONG LocalStartingOffset;
    00734     NTSTATUS Status;
    00735     KEVENT  Event;
    00736     PIRP Irp;
    00737
    00738     PAGED_CODE();
    00739
    00740     DebugTrace(( +1, Dbg,
    00741                  "UdfReadSectors, %x%08x +%x -> %08x from DO %08x\n",
    00742                  ((PLARGE_INTEGER)&StartingOffset)->HighPart,
    00743                  ((PLARGE_INTEGER)&StartingOffset)->LowPart,
    00744                  ByteCount,
    00745                  Buffer,
    00746                  TargetDeviceObject ));
    00747
    00748     //
    00749     //  For the time being, we assume that we only read sector-at-a-time.
    00750     //  This simplifies sparing, and is the only way I am aware of this
    00751     //  code would not be ready for blocksize != sectorsize.  It just is
    00752     //  not worth writing dead (but straightforward) code right now.
    00753     //
    00754
    00755     ASSERT( IrpContext->Vcb == NULL || ByteCount == SectorSize( IrpContext->Vcb ));
    00756
    00757     //
    00758     //  If the volume is spared (and at a point where sparing is possible),
    00759     //  check if a mapping needs to be performed.
    00760     //
    00761
    00762     if (IrpContext->Vcb &&
    00763         IrpContext->Vcb->Pcb &&
    00764         IrpContext->Vcb->Pcb->SparingMcb) {
    00765
    00766         LONGLONG SparingPsn;
    00767
    00768         if (FsRtlLookupLargeMcbEntry( IrpContext->Vcb->Pcb->SparingMcb,
    00769                                       LlSectorsFromBytes( IrpContext->Vcb, StartingOffset ),
    00770                                       &SparingPsn,
    00771                                       NULL,
    00772                                       NULL,
    00773                                       NULL,
    00774                                       NULL ) &&
    00775             SparingPsn != -1) {
    00776
    00777             StartingOffset = BytesFromSectors( IrpContext->Vcb, (ULONG) SparingPsn );
    00778         }
    00779     }
    00780
    00781     //
    00782     //  Initialize the event.
    00783     //
    00784
    00785     KeInitializeEvent( &Event, NotificationEvent, FALSE );
    00786
    00787     //
    00788     //  Correct the starting offset by the method 2 fixup if neccesary.  This also
    00789     //  assumes sector-at-a-time and sector == block so we don't need to fragment
    00790     //  the request or check if it spans a packet boundary.
    00791     //
    00792     //  We assume that no fixups are required until a Vcb exists.  This is true
    00793     //  since volume recognition may proceed in the first packet.
    00794     //
    00795
    00796     UseStartingOffset = &StartingOffset;
    00797
    00798     if (IrpContext->Vcb &&
    00799         FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) {
    00800
    00801         LocalStartingOffset = UdfMethod2TransformByteOffset( IrpContext->Vcb, StartingOffset );
    00802         UseStartingOffset = &LocalStartingOffset;
    00803
    00804         DebugTrace(( 0, Dbg,
    00805                      "UdfReadSectors, Method2 Fixup to %x%08x\n",
    00806                      ((PLARGE_INTEGER)UseStartingOffset)->HighPart,
    00807                      ((PLARGE_INTEGER)UseStartingOffset)->LowPart ));
    00808     }
    00809
    00810     //
    00811     //  Attempt to allocate the IRP.  If unsuccessful, raise
    00812     //  STATUS_INSUFFICIENT_RESOURCES.
    00813     //
    00814
    00815     Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
    00816                                         TargetDeviceObject,
    00817                                         Buffer,
    00818                                         ByteCount,
    00819                                         (PLARGE_INTEGER) UseStartingOffset,
    00820                                         &Event,
    00821                                         &IrpContext->Irp->IoStatus );
    00822
    00823     if (Irp == NULL) {
    00824
    00825         UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
    00826     }
    00827
    00828     //
    00829     //  Ignore the change line (verify) for mount and verify requests
    00830     //
    00831
    00832     SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
    00833
    00834     //
    00835     //  Send the request down to the driver.  If an error occurs return
    00836     //  it to the caller.
    00837     //
    00838
    00839     Status = IoCallDriver( TargetDeviceObject, Irp );
    00840
    00841     //
    00842     //  If the status was STATUS_PENDING then wait on the event.
    00843     //
    00844
    00845     if (Status == STATUS_PENDING) {
    00846
    00847         Status = KeWaitForSingleObject( &Event,
    00848                                         Executive,
    00849                                         KernelMode,
    00850                                         FALSE,
    00851                                         NULL );
    00852
    00853         //
    00854         //  On a successful wait pull the status out of the IoStatus block.
    00855         //
    00856
    00857         if (NT_SUCCESS( Status )) {
    00858
    00859             Status = IrpContext->Irp->IoStatus.Status;
    00860         }
    00861     }
    00862
    00863     DebugTrace(( -1, Dbg, "UdfReadSectors -> %08x\n", Status ));
    00864
    00865     //
    00866     //  Check whether we should raise in the error case.
    00867     //
    00868
    00869     if (!NT_SUCCESS( Status ) && !ReturnError) {
    00870
    00871         UdfNormalizeAndRaiseStatus( IrpContext, Status );
    00872     }
    00873
    00874     return Status;
    00875 }

VOID UdfSingleAsync | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN LONGLONG | ByteOffset,
|  | IN ULONG | ByteCount
| ) |

Definition at line 1642 of file deviosup.c.

References FlagOn, IoCallDriver, IoGetNextIrpStackLocation, IoSetCompletionRoutine, IRP_CONTEXT_FLAG_WAIT, IRP_MJ_READ, _IO_STACK_LOCATION::MajorFunction, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PIO_COMPLETION_ROUTINE, TRUE, UdfSingleAsyncCompletionRoutine(), UdfSingleSyncCompletionRoutine(), and VOID().

Referenced by UdfNonCachedRead().

    01650                    :
    01651
    01652     This routine reads one or more contiguous sectors from a device
    01653     asynchronously, and is used if there is only one read necessary to
    01654     complete the IRP.  It implements the read by simply filling
    01655     in the next stack frame in the Irp, and passing it on.  The transfer
    01656     occurs to the single buffer originally specified in the user request.
    01657
    01658 Arguments:
    01659
    01660     ByteOffset - Supplies the starting Logical Byte Offset to begin reading from
    01661
    01662     ByteCount - Supplies the number of bytes to read from the device
    01663
    01664 Return Value:
    01665
    01666     None.
    01667
    01668 --*/
    01669
    01670 {
    01671     PIO_STACK_LOCATION IrpSp;
    01672     PIO_COMPLETION_ROUTINE CompletionRoutine;
    01673
    01674     PAGED_CODE();
    01675
    01676     //
    01677     //  Set up things according to whether this is truely async.
    01678     //
    01679
    01680     if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
    01681
    01682         CompletionRoutine = UdfSingleSyncCompletionRoutine;
    01683
    01684     } else {
    01685
    01686         CompletionRoutine = UdfSingleAsyncCompletionRoutine;
    01687     }
    01688
    01689     //
    01690     // Set up the completion routine address in our stack frame.
    01691     //
    01692
    01693     IoSetCompletionRoutine( IrpContext->Irp,
    01694                             CompletionRoutine,
    01695                             IrpContext->IoContext,
    01696                             TRUE,
    01697                             TRUE,
    01698                             TRUE );
    01699
    01700     //
    01701     //  Setup the next IRP stack location in the associated Irp for the disk
    01702     //  driver beneath us.
    01703     //
    01704
    01705     IrpSp = IoGetNextIrpStackLocation( IrpContext->Irp );
    01706
    01707     //
    01708     //  Setup the Stack location to do a read from the disk driver.
    01709     //
    01710
    01711     IrpSp->MajorFunction = IRP_MJ_READ;
    01712     IrpSp->Parameters.Read.Length = ByteCount;
    01713     IrpSp->Parameters.Read.ByteOffset.QuadPart = ByteOffset;
    01714
    01715     //
    01716     //  Issue the Io request
    01717     //
    01718
    01719     //
    01720     //  If IoCallDriver returns an error, it has completed the Irp
    01721     //  and the error will be caught by our completion routines
    01722     //  and dealt with as a normal IO error.
    01723     //
    01724
    01725     (VOID)IoCallDriver( IrpContext->Vcb->TargetDeviceObject, IrpContext->Irp );
    01726
    01727     //
    01728     //  And return to our caller
    01729     //
    01730
    01731     return;
    01732 }

NTSTATUS UdfSingleAsyncCompletionRoutine | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 2039 of file deviosup.c.

References ExReleaseResourceForThread, IoMarkIrpPending, _IRP::IoStatus, Irp, NT_SUCCESS, Resource, and UdfFreeIoContext.

Referenced by UdfSingleAsync().

    02047                    :
    02048
    02049     This is the completion routine for all asynchronous reads
    02050     started via UdfSingleAsynch.
    02051
    02052 Arguments:
    02053
    02054     DeviceObject - Pointer to the file system device object.
    02055
    02056     Irp - Pointer to the Irp for this request.  (This Irp will no longer
    02057         be accessible after this routine returns.)
    02058
    02059     Context - The context parameter which was specified in the call to
    02060         UdfSingleAsynch.
    02061
    02062 Return Value:
    02063
    02064     Currently always returns STATUS_SUCCESS.
    02065
    02066 --*/
    02067
    02068 {
    02069     //
    02070     //  Update the information field with the correct value for bytes read.
    02071     //
    02072
    02073     Irp->IoStatus.Information = 0;
    02074
    02075     if (NT_SUCCESS( Irp->IoStatus.Status )) {
    02076
    02077         Irp->IoStatus.Information = ((PUDF_IO_CONTEXT) Context)->RequestedByteCount;
    02078     }
    02079
    02080     //
    02081     //  Mark the Irp pending
    02082     //
    02083
    02084     IoMarkIrpPending( Irp );
    02085
    02086     //
    02087     //  Now release the resource
    02088     //
    02089
    02090     ExReleaseResourceForThread( ((PUDF_IO_CONTEXT) Context)->Resource,
    02091                                 ((PUDF_IO_CONTEXT) Context)->ResourceThreadId );
    02092
    02093     //
    02094     //  and finally, free the context record.
    02095     //
    02096
    02097     UdfFreeIoContext( (PUDF_IO_CONTEXT) Context );
    02098     return STATUS_SUCCESS;
    02099
    02100     UNREFERENCED_PARAMETER( DeviceObject );
    02101 }

NTSTATUS UdfSingleSyncCompletionRoutine | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN PIRP | Irp,
|  | IN PVOID | Context
| ) |

Definition at line 1980 of file deviosup.c.

References FALSE, _IRP::IoStatus, Irp, KeSetEvent(), and NT_SUCCESS.

Referenced by UdfSingleAsync().

    01988                    :
    01989
    01990     This is the completion routine for all reads started via UdfSingleAsync.
    01991
    01992     The completion routine has has the following responsibilities:
    01993
    01994         It sets the event in the Context parameter to signal the caller
    01995         that all of the asynch requests are done.
    01996
    01997 Arguments:
    01998
    01999     DeviceObject - Pointer to the file system device object.
    02000
    02001     Irp - Pointer to the Irp for this request.  (This Irp will no longer
    02002         be accessible after this routine returns.)
    02003
    02004     Context - The context parameter which was specified in the call to
    02005         UdfSingleAsynch.
    02006
    02007 Return Value:
    02008
    02009     The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
    02010     immediately complete the Master Irp without being in a race condition
    02011     with the IoCompleteRequest thread trying to decrement the IrpCount in
    02012     the Master Irp.
    02013
    02014 --*/
    02015
    02016 {
    02017     //
    02018     //  Store the correct information field into the Irp.
    02019     //
    02020
    02021     if (!NT_SUCCESS( Irp->IoStatus.Status )) {
    02022
    02023         Irp->IoStatus.Information = 0;
    02024     }
    02025
    02026     KeSetEvent( &((PUDF_IO_CONTEXT)Context)->SyncEvent, 0, FALSE );
    02027
    02028     return STATUS_MORE_PROCESSING_REQUIRED;
    02029
    02030     UNREFERENCED_PARAMETER( DeviceObject );
    02031 }

VOID UdfWaitSync | ( | IN PIRP_CONTEXT | IrpContext | ) |

Definition at line 1740 of file deviosup.c.

References Executive, FALSE, KeClearEvent, KernelMode, KeWaitForSingleObject(), NULL, and PAGED_CODE.

Referenced by UdfNonCachedRead().

    01746                    :
    01747
    01748     This routine waits for one or more previously started I/O requests
    01749     from the above routines, by simply waiting on the event.
    01750
    01751 Arguments:
    01752
    01753 Return Value:
    01754
    01755     None
    01756
    01757 --*/
    01758
    01759 {
    01760     PAGED_CODE();
    01761
    01762     KeWaitForSingleObject( &IrpContext->IoContext->SyncEvent,
    01763                            Executive,
    01764                            KernelMode,
    01765                            FALSE,
    01766                            NULL );
    01767
    01768     KeClearEvent( &IrpContext->IoContext->SyncEvent );
    01769
    01770     return;
    01771 }