Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2426 lines
66 KiB

  1. /*++
  2. Copyright (c) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. DevIoSup.c
  5. Abstract:
  6. This module implements the low lever disk read/write support for Udfs.
  7. // @@BEGIN_DDKSPLIT
  8. Author:
  9. Dan Lovinger [DanLo] 11-Jun-1996
  10. Tom Jolly [tomjolly] 21-Jan-2000
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "UdfProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (UDFS_BUG_CHECK_DEVIOSUP)
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (UDFS_DEBUG_LEVEL_DEVIOSUP)
  23. //
  24. // Local structure definitions
  25. //
  26. //
  27. // An array of these structures is passed to UdfMultipleAsync describing
  28. // a set of runs to execute in parallel.
  29. //
  30. typedef struct _IO_RUN {
  31. //
  32. // Disk offset to read from and number of bytes to read. These
  33. // must be a multiple of a sector and the disk offset is also a
  34. // multiple of sector.
  35. //
  36. LONGLONG DiskOffset;
  37. ULONG DiskByteCount;
  38. //
  39. // Current position in user buffer. This is the final destination for
  40. // this portion of the Io transfer.
  41. //
  42. PVOID UserBuffer;
  43. //
  44. // Buffer to perform the transfer to. If this is the same as the
  45. // user buffer above then we are using the user's buffer. Otherwise
  46. // we either allocated a temporary buffer or are using a different portion
  47. // of the user's buffer.
  48. //
  49. // TransferBuffer - Read full sectors into this location. This can
  50. // be a pointer into the user's buffer at the exact location the
  51. // data should go. It can also be an earlier point in the user's
  52. // buffer if the complete I/O doesn't start on a sector boundary.
  53. // It may also be a pointer into an allocated buffer.
  54. //
  55. // TransferByteCount - Count of bytes to transfer to user's buffer. A
  56. // value of zero indicates that we did do the transfer into the
  57. // user's buffer directly.
  58. //
  59. // TransferBufferOffset - Offset in this buffer to begin the transfer
  60. // to the user's buffer.
  61. //
  62. PVOID TransferBuffer;
  63. ULONG TransferByteCount;
  64. ULONG TransferBufferOffset;
  65. //
  66. // This is the Mdl describing the locked pages in memory. It may
  67. // be allocated to describe the allocated buffer. Or it may be
  68. // the Mdl in the originating Irp. The MdlOffset is the offset of
  69. // the current buffer from the beginning of the buffer described by
  70. // the Mdl below. If the TransferMdl is not the same as the Mdl
  71. // in the user's Irp then we know we have allocated it.
  72. //
  73. PMDL TransferMdl;
  74. PVOID TransferVirtualAddress;
  75. //
  76. // Associated Irp used to perform the Io.
  77. //
  78. PIRP SavedIrp;
  79. } IO_RUN;
  80. typedef IO_RUN *PIO_RUN;
  81. #define MAX_PARALLEL_IOS 5
  82. //
  83. // Local support routines
  84. //
  85. BOOLEAN
  86. UdfPrepareBuffers (
  87. IN PIRP_CONTEXT IrpContext,
  88. IN PIRP Irp,
  89. IN PFCB Fcb,
  90. IN PCCB Ccb,
  91. IN PVOID UserBuffer,
  92. IN ULONG UserBufferOffset,
  93. IN LONGLONG StartingOffset,
  94. IN ULONG ByteCount,
  95. IN PIO_RUN IoRuns,
  96. IN PULONG RunCount,
  97. IN PULONG ThisByteCount,
  98. OUT PBOOLEAN SparseRuns
  99. );
  100. BOOLEAN
  101. UdfFinishBuffers (
  102. IN PIRP_CONTEXT IrpContext,
  103. IN PIO_RUN IoRuns,
  104. IN ULONG RunCount,
  105. IN BOOLEAN FinalCleanup
  106. );
  107. VOID
  108. UdfMultipleAsync (
  109. IN PIRP_CONTEXT IrpContext,
  110. IN ULONG RunCount,
  111. IN PIO_RUN IoRuns
  112. );
  113. VOID
  114. UdfSingleAsync (
  115. IN PIRP_CONTEXT IrpContext,
  116. IN LONGLONG ByteOffset,
  117. IN ULONG ByteCount
  118. );
  119. VOID
  120. UdfWaitSync (
  121. IN PIRP_CONTEXT IrpContext
  122. );
  123. NTSTATUS
  124. UdfMultiSyncCompletionRoutine (
  125. IN PDEVICE_OBJECT DeviceObject,
  126. IN PIRP Irp,
  127. IN PVOID Context
  128. );
  129. NTSTATUS
  130. UdfMultiAsyncCompletionRoutine (
  131. IN PDEVICE_OBJECT DeviceObject,
  132. IN PIRP Irp,
  133. IN PVOID Context
  134. );
  135. NTSTATUS
  136. UdfSingleSyncCompletionRoutine (
  137. IN PDEVICE_OBJECT DeviceObject,
  138. IN PIRP Irp,
  139. IN PVOID Context
  140. );
  141. NTSTATUS
  142. UdfSingleAsyncCompletionRoutine (
  143. IN PDEVICE_OBJECT DeviceObject,
  144. IN PIRP Irp,
  145. IN PVOID Context
  146. );
  147. #ifdef EXPERIMENTAL_MOUNT_OPEN_R_MEDIA
  148. #pragma alloc_text(PAGE, UdfSendSptCdb)
  149. #endif
  150. #ifdef ALLOC_PRAGMA
  151. #pragma alloc_text(PAGE, UdfCreateUserMdl)
  152. #pragma alloc_text(PAGE, UdfMultipleAsync)
  153. #pragma alloc_text(PAGE, UdfNonCachedRead)
  154. #pragma alloc_text(PAGE, UdfFinishBuffers)
  155. #pragma alloc_text(PAGE, UdfPrepareBuffers)
  156. #pragma alloc_text(PAGE, UdfSingleAsync)
  157. #pragma alloc_text(PAGE, UdfWaitSync)
  158. #pragma alloc_text(PAGE, UdfPerformDevIoCtrl)
  159. #pragma alloc_text(PAGE, UdfReadSectors)
  160. #endif
  161. NTSTATUS
  162. UdfNonCachedRead (
  163. IN PIRP_CONTEXT IrpContext,
  164. IN PFCB Fcb,
  165. IN PCCB Ccb,
  166. IN LONGLONG StartingOffset,
  167. IN ULONG ByteCount
  168. )
  169. /*++
  170. Routine Description:
  171. This routine performs the non-cached reads of sectors. This is done by
  172. performing the following in a loop.
  173. Fill in the IoRuns array for the next block of Io.
  174. Send the Io to the device.
  175. Perform any cleanup on the Io runs array.
  176. We will not do async Io to any request that generates non-aligned Io.
  177. Also we will not perform async Io if it will exceed the size of our
  178. IoRuns array. These should be the unusual cases but we will raise
  179. or return CANT_WAIT in this routine if we detect this case.
  180. Arguments:
  181. Fcb - Fcb representing the file to read.
  182. StartingOffset - Logical offset in the file to read from.
  183. ByteCount - Number of bytes to read.
  184. Return Value:
  185. NTSTATUS - Status indicating the result of the operation.
  186. --*/
  187. {
  188. NTSTATUS Status = STATUS_SUCCESS;
  189. IO_RUN IoRuns[MAX_PARALLEL_IOS];
  190. ULONG RunCount = 0;
  191. ULONG CleanupRunCount = 0;
  192. PVOID UserBuffer;
  193. ULONG UserBufferOffset = 0;
  194. LONGLONG CurrentOffset = StartingOffset;
  195. ULONG RemainingByteCount = ByteCount;
  196. ULONG ThisByteCount;
  197. BOOLEAN Unaligned;
  198. BOOLEAN SparseRuns;
  199. BOOLEAN FlushIoBuffers = FALSE;
  200. BOOLEAN FirstPass = TRUE;
  201. PAGED_CODE();
  202. //
  203. // We want to make sure the user's buffer is locked in all cases.
  204. //
  205. if (IrpContext->Irp->MdlAddress == NULL) {
  206. UdfCreateUserMdl( IrpContext, ByteCount, TRUE, IoWriteAccess );
  207. }
  208. //
  209. // Use a try-finally to perform the final cleanup.
  210. //
  211. try {
  212. UdfMapUserBuffer( IrpContext, &UserBuffer);
  213. //
  214. // Loop while there are more bytes to transfer.
  215. //
  216. do {
  217. //
  218. // Call prepare buffers to set up the next entries
  219. // in the IoRuns array. Remember if there are any
  220. // unaligned entries.
  221. //
  222. RtlZeroMemory( IoRuns, sizeof( IoRuns ));
  223. Unaligned = UdfPrepareBuffers( IrpContext,
  224. IrpContext->Irp,
  225. Fcb,
  226. Ccb,
  227. UserBuffer,
  228. UserBufferOffset,
  229. CurrentOffset,
  230. RemainingByteCount,
  231. IoRuns,
  232. &CleanupRunCount,
  233. &ThisByteCount,
  234. &SparseRuns );
  235. RunCount = CleanupRunCount;
  236. //
  237. // Quickly finish if we wound up having no IO to perform. This will
  238. // occur in the presence of unrecorded sectors.
  239. //
  240. ASSERT( !(SparseRuns && FlagOn( Fcb->FcbState, FCB_STATE_EMBEDDED_DATA )));
  241. if (RunCount == 0) {
  242. try_leave( Status = IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS );
  243. }
  244. //
  245. // If this is an async request and there aren't enough entries
  246. // in the Io array then post the request. This routine will
  247. // always raise if we are doing any unaligned Io for an
  248. // async request.
  249. //
  250. if ((ThisByteCount < RemainingByteCount) &&
  251. !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  252. UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
  253. }
  254. //
  255. // If the entire Io is contained in a single run then
  256. // we can pass the Io down to the driver. Send the driver down
  257. // and wait on the result if this is synchronous. We cannot
  258. // do this simple form (just chucking the IRP down) if some
  259. // sparse runs were encountered.
  260. //
  261. if ((RunCount == 1) && !Unaligned && !SparseRuns && FirstPass) {
  262. UdfSingleAsync( IrpContext,
  263. IoRuns[0].DiskOffset,
  264. IoRuns[0].DiskByteCount );
  265. //
  266. // No cleanup needed for the IoRuns array here.
  267. //
  268. CleanupRunCount = 0;
  269. //
  270. // Wait if we are synchronous, otherwise return
  271. //
  272. if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  273. UdfWaitSync( IrpContext );
  274. Status = IrpContext->Irp->IoStatus.Status;
  275. //
  276. // Our completion routine will free the Io context but
  277. // we do want to return STATUS_PENDING.
  278. //
  279. } else {
  280. ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
  281. Status = STATUS_PENDING;
  282. }
  283. try_leave( NOTHING );
  284. }
  285. //
  286. // Otherwise we will perform multiple Io to read in the data.
  287. //
  288. UdfMultipleAsync( IrpContext, RunCount, IoRuns );
  289. //
  290. // If this is a synchronous request then perform any necessary
  291. // post-processing.
  292. //
  293. if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  294. //
  295. // Wait for the request to complete.
  296. //
  297. UdfWaitSync( IrpContext );
  298. Status = IrpContext->Irp->IoStatus.Status;
  299. //
  300. // Exit this loop if there is an error.
  301. //
  302. if (!NT_SUCCESS( Status )) {
  303. try_leave( NOTHING );
  304. }
  305. //
  306. // Perform post read operations on the IoRuns if
  307. // necessary.
  308. //
  309. if (Unaligned &&
  310. UdfFinishBuffers( IrpContext, IoRuns, RunCount, FALSE )) {
  311. FlushIoBuffers = TRUE;
  312. }
  313. //
  314. // No cleanup needed on the IoRuns now.
  315. //
  316. CleanupRunCount = 0;
  317. //
  318. // Exit this loop if there are no more bytes to transfer
  319. // or we have any error.
  320. //
  321. RemainingByteCount -= ThisByteCount;
  322. CurrentOffset += ThisByteCount;
  323. UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
  324. UserBufferOffset += ThisByteCount;
  325. //
  326. // Otherwise this is an asynchronous request. Always return
  327. // STATUS_PENDING.
  328. //
  329. } else {
  330. ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
  331. CleanupRunCount = 0;
  332. try_leave( Status = STATUS_PENDING );
  333. break;
  334. }
  335. FirstPass = FALSE;
  336. } while (RemainingByteCount != 0);
  337. //
  338. // Flush the hardware cache if we performed any copy operations.
  339. //
  340. if (FlushIoBuffers) {
  341. KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
  342. }
  343. } finally {
  344. DebugUnwind( "UdfNonCachedRead" );
  345. //
  346. // Perform final cleanup on the IoRuns if necessary.
  347. //
  348. if (CleanupRunCount != 0) {
  349. UdfFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE );
  350. }
  351. }
  352. return Status;
  353. }
  354. NTSTATUS
  355. UdfCreateUserMdl (
  356. IN PIRP_CONTEXT IrpContext,
  357. IN ULONG BufferLength,
  358. IN BOOLEAN RaiseOnError,
  359. IN ULONG Operation
  360. )
  361. /*++
  362. Routine Description:
  363. This routine locks the specified buffer for read access (we only write into
  364. the buffer). The file system requires this routine since it does not
  365. ask the I/O system to lock its buffers for direct I/O. This routine
  366. may only be called from the Fsd while still in the user context.
  367. This routine is only called if there is not already an Mdl.
  368. Arguments:
  369. BufferLength - Length of user buffer.
  370. RaiseOnError - Indicates if our caller wants this routine to raise on
  371. an error condition.
  372. Return Value:
  373. NTSTATUS - Status from this routine. Error status only returned if
  374. RaiseOnError is FALSE.
  375. --*/
  376. {
  377. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  378. PMDL Mdl;
  379. PAGED_CODE();
  380. ASSERT_IRP_CONTEXT( IrpContext );
  381. ASSERT_IRP( IrpContext->Irp );
  382. ASSERT( IrpContext->Irp->MdlAddress == NULL );
  383. //
  384. // Allocate the Mdl, and Raise if we fail.
  385. //
  386. Mdl = IoAllocateMdl( IrpContext->Irp->UserBuffer,
  387. BufferLength,
  388. FALSE,
  389. FALSE,
  390. IrpContext->Irp );
  391. if (Mdl != NULL) {
  392. //
  393. // Now probe the buffer described by the Irp. If we get an exception,
  394. // deallocate the Mdl and return the appropriate "expected" status.
  395. //
  396. try {
  397. MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode, Operation );
  398. Status = STATUS_SUCCESS;
  399. } except(EXCEPTION_EXECUTE_HANDLER) {
  400. Status = GetExceptionCode();
  401. IoFreeMdl( Mdl );
  402. IrpContext->Irp->MdlAddress = NULL;
  403. if (!FsRtlIsNtstatusExpected( Status )) {
  404. Status = STATUS_INVALID_USER_BUFFER;
  405. }
  406. }
  407. }
  408. //
  409. // Check if we are to raise or return
  410. //
  411. if (Status != STATUS_SUCCESS) {
  412. if (RaiseOnError) {
  413. UdfRaiseStatus( IrpContext, Status );
  414. }
  415. }
  416. //
  417. // Return the status code.
  418. //
  419. return Status;
  420. }
  421. #ifdef EXPERIMENTAL_MOUNT_OPEN_R_MEDIA
  422. typedef struct {
  423. SCSI_PASS_THROUGH Spt;
  424. UCHAR SenseInfoBuffer[18];
  425. UCHAR DataBuffer[0];
  426. // Allocate buffer space after this
  427. } SPT_WITH_BUFFERS, *PSPT_WITH_BUFFERS;
  428. NTSTATUS
  429. UdfSendSptCdb(
  430. IN PDEVICE_OBJECT Device,
  431. IN PCDB Cdb,
  432. IN PUCHAR Buffer,
  433. IN OUT PULONG BufferSize,
  434. IN BOOLEAN InputOperation,
  435. IN ULONG TimeOut,
  436. IN OPTIONAL PVOID TempBuffer,
  437. IN OPTIONAL ULONG TempBufferSize,
  438. OUT PULONG SenseKeyCodeQualifier,
  439. OUT PUSHORT ProgressIndication
  440. )
  441. /*++
  442. Routine Description:
  443. Sends the caller supplied SCSI CDB to the specified device.
  444. Arguments:
  445. Device - target device object
  446. Cdb - command to send
  447. Buffer - Buffer containing input data, or to receive data returned from
  448. the device (depending on InputOperation parameter)
  449. BufferSize - Size of the above buffer. For input operations this value will
  450. be updated to reflect actual length of data returned by the device.
  451. InputOperation - if TRUE then the operation is querying the drive for data. FALSE
  452. and we are sending data to the device.
  453. TimeOut - Time to wait for this operation to complete (seconds)
  454. TempBuffer - Scratch buffer used for building the request. If NULL or too small
  455. a buffer will be allocated.
  456. TempBufferSize - Size of above buffer.
  457. SenseKeyCodeQualifier - In error cases contains the detailed error information
  458. from the device (see SCSI spec). 0x00QqCcKk
  459. ProgressIndication - Returns the progress value from the drive for certain error
  460. classes (see SCSI spec).
  461. Return Value:
  462. NTSTATUS - Status returned by next lower driver or...
  463. STATUS_BUFFER_OVERFLOW - the device returned too much data to fit in caller's
  464. buffer. *BufferSize will be update to indicate the amount
  465. of data returned by the drive.
  466. --*/
  467. {
  468. PSPT_WITH_BUFFERS P;
  469. ULONG PacketSize;
  470. PSENSE_DATA SenseBuffer;
  471. BOOLEAN CopyData;
  472. UCHAR CdbSize;
  473. BOOLEAN FromPool = FALSE;
  474. USHORT Progress;
  475. ULONG SenseInfo;
  476. NTSTATUS Status;
  477. ASSERT( NULL != Cdb);
  478. ASSERT( (0 == TempBufferSize) || (NULL != TempBuffer));
  479. ASSERT( (0 == *BufferSize) || (NULL != Buffer));
  480. if (ProgressIndication) {
  481. *ProgressIndication = 0;
  482. }
  483. if (SenseKeyCodeQualifier) {
  484. *SenseKeyCodeQualifier = 0;
  485. }
  486. //
  487. // Calculate CDB length from operation code.
  488. //
  489. switch ((Cdb->AsByte[0] >> 5) & 0x7) {
  490. case 0:
  491. CdbSize = 6;
  492. break;
  493. case 1:
  494. case 2:
  495. CdbSize = 10;
  496. break;
  497. case 5:
  498. CdbSize = 12;
  499. break;
  500. default:
  501. ASSERT(FALSE);
  502. break;
  503. }
  504. if (*BufferSize && InputOperation) {
  505. RtlZeroMemory( Buffer, *BufferSize);
  506. }
  507. //
  508. // If the caller temp buffer is not large enough to contain the
  509. // request packet, allocate.
  510. //
  511. PacketSize = sizeof( SPT_WITH_BUFFERS) + *BufferSize;
  512. if (PacketSize > TempBufferSize) {
  513. P = FsRtlAllocatePoolWithTag( PagedPool,
  514. PacketSize,
  515. TAG_IOCTL_BUFFER);
  516. FromPool = TRUE;
  517. }
  518. else {
  519. P = TempBuffer;
  520. }
  521. //
  522. // Fill in the packet.
  523. //
  524. RtlZeroMemory( P, PacketSize);
  525. RtlCopyMemory( P->Spt.Cdb, Cdb, CdbSize);
  526. P->Spt.Length = sizeof(SCSI_PASS_THROUGH);
  527. P->Spt.CdbLength = CdbSize;
  528. P->Spt.SenseInfoLength = SENSE_BUFFER_SIZE;
  529. P->Spt.DataIn = (InputOperation ? 1 : 0);
  530. P->Spt.DataTransferLength = (*BufferSize);
  531. P->Spt.TimeOutValue = TimeOut;
  532. P->Spt.SenseInfoOffset =
  533. FIELD_OFFSET(SPT_WITH_BUFFERS, SenseInfoBuffer[0]);
  534. P->Spt.DataBufferOffset =
  535. FIELD_OFFSET(SPT_WITH_BUFFERS, DataBuffer[0]);
  536. //
  537. // If we're sending the device data, copy the user's buffer into the packet.
  538. //
  539. if ((*BufferSize != 0) && !InputOperation) {
  540. RtlCopyMemory( &(P->DataBuffer[0]), Buffer, *BufferSize);
  541. }
  542. //
  543. // Send it.
  544. //
  545. Status = UdfPerformDevIoCtrl( NULL,
  546. IOCTL_SCSI_PASS_THROUGH,
  547. Device,
  548. P,
  549. PacketSize,
  550. P,
  551. PacketSize,
  552. FALSE,
  553. TRUE,
  554. NULL);
  555. if (!NT_SUCCESS(Status)) {
  556. DebugTrace((0,Dbg,"UdfSendSptCdb() failed %x\n", Status));
  557. // TODO: DO WE NEED TO LOOK AT SENSE DATA IN THIS CASE?
  558. if (FromPool) {
  559. ExFreePool( P);
  560. }
  561. return Status;
  562. }
  563. SenseBuffer = (PSENSE_DATA)P->SenseInfoBuffer;
  564. CopyData = FALSE;
  565. if (SenseBuffer->SenseKey & 0xf) {
  566. //
  567. // Some error (possibly recovered).
  568. //
  569. Status = STATUS_IO_DEVICE_ERROR;
  570. CopyData = TRUE;
  571. } else if (P->Spt.ScsiStatus != 0) {
  572. //
  573. // SCSI protocol error.
  574. //
  575. Status = STATUS_INVALID_PARAMETER;
  576. } else {
  577. CopyData = TRUE;
  578. Status = STATUS_SUCCESS;
  579. }
  580. //
  581. // Extract sense information for the caller if there was an error.
  582. //
  583. if (!NT_SUCCESS(Status)) {
  584. SenseInfo = SenseBuffer->SenseKey |
  585. (SenseBuffer->AdditionalSenseCode << 8) |
  586. (SenseBuffer->AdditionalSenseCodeQualifier << 16);
  587. #ifdef UDF_SANITY
  588. if (SenseInfo & 0xff) {
  589. DebugTrace(( 0, Dbg, "Request: 0x%x -> QQ/CC/KK %06x\n", Cdb->AsByte[0], SenseInfo));
  590. }
  591. #endif
  592. //
  593. // If the sense key specific part is valid we'll return the
  594. // data portion as a possible progress indication.
  595. //
  596. if (SenseBuffer->SenseKeySpecific[0] & 0x80) {
  597. Progress = SenseBuffer->SenseKeySpecific[2] |
  598. (SenseBuffer->SenseKeySpecific[1] << 8);
  599. #ifdef UDF_SANITY
  600. //
  601. // If this wasn't a not ready code, then this is probably a
  602. // packet parameter format error. Print it. Most drives don't
  603. // seem to utilise this detailed error reporting.... sigh.
  604. //
  605. if (SenseBuffer->SenseKey != SCSI_SENSE_NOT_READY) {
  606. if (SenseBuffer->SenseKeySpecific[0] & 0x40) {
  607. DebugTrace((0, Dbg, "CDB error at 0x%x\n", Progress));
  608. }
  609. else {
  610. DebugTrace((0, Dbg, "CDB data parameter error at 0x%x\n", Progress));
  611. }
  612. if (SenseBuffer->SenseKeySpecific[0] & 8) {
  613. DebugTrace(( 0, Dbg, "Bit position %d\n", SenseBuffer->SenseKeySpecific[0] & 7));
  614. }
  615. }
  616. #endif
  617. if (ProgressIndication) {
  618. *ProgressIndication = Progress;
  619. }
  620. }
  621. if (SenseKeyCodeQualifier) {
  622. *SenseKeyCodeQualifier = SenseInfo;
  623. }
  624. }
  625. //
  626. // If this was an input operation, copy the return data to caller buffer.
  627. //
  628. if (CopyData && InputOperation) {
  629. if (*BufferSize < P->Spt.DataTransferLength) {
  630. Status = STATUS_BUFFER_OVERFLOW;
  631. }
  632. *BufferSize = P->Spt.DataTransferLength;
  633. if (STATUS_BUFFER_OVERFLOW != Status) {
  634. RtlCopyMemory(Buffer, P->DataBuffer, *BufferSize);
  635. }
  636. }
  637. if (FromPool) {
  638. ExFreePool( P);
  639. }
  640. return Status;
  641. }
  642. #endif
  643. NTSTATUS
  644. UdfPerformDevIoCtrl (
  645. IN PIRP_CONTEXT IrpContext,
  646. IN ULONG IoControlCode,
  647. IN PDEVICE_OBJECT Device,
  648. IN PVOID InputBuffer OPTIONAL,
  649. IN ULONG InputBufferLength,
  650. OUT PVOID OutputBuffer OPTIONAL,
  651. IN ULONG OutputBufferLength,
  652. IN BOOLEAN InternalDeviceIoControl,
  653. IN BOOLEAN OverrideVerify,
  654. OUT PIO_STATUS_BLOCK Iosb OPTIONAL
  655. )
  656. /*++
  657. Routine Description:
  658. This routine is called to perform DevIoCtrl functions internally within
  659. the filesystem. We take the status from the driver and return it to our
  660. caller.
  661. Arguments:
  662. IoControlCode - Code to send to driver.
  663. Device - This is the device to send the request to.
  664. OutPutBuffer - Pointer to output buffer.
  665. OutputBufferLength - Length of output buffer above.
  666. InternalDeviceIoControl - Indicates if this is an internal or external
  667. Io control code.
  668. OverrideVerify - Indicates if we should tell the driver not to return
  669. STATUS_VERIFY_REQUIRED for mount and verify.
  670. Iosb - If specified, we return the results of the operation here.
  671. Return Value:
  672. NTSTATUS - Status returned by next lower driver.
  673. --*/
  674. {
  675. NTSTATUS Status;
  676. PIRP Irp;
  677. KEVENT Event;
  678. IO_STATUS_BLOCK LocalIosb;
  679. PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
  680. PAGED_CODE();
  681. //
  682. // Check if the user gave us an Iosb.
  683. //
  684. if (ARGUMENT_PRESENT( Iosb )) {
  685. IosbToUse = Iosb;
  686. }
  687. IosbToUse->Status = 0;
  688. IosbToUse->Information = 0;
  689. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  690. Irp = IoBuildDeviceIoControlRequest( IoControlCode,
  691. Device,
  692. InputBuffer,
  693. InputBufferLength,
  694. OutputBuffer,
  695. OutputBufferLength,
  696. InternalDeviceIoControl,
  697. &Event,
  698. IosbToUse );
  699. if (Irp == NULL) {
  700. return STATUS_INSUFFICIENT_RESOURCES;
  701. }
  702. if (OverrideVerify) {
  703. SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
  704. }
  705. Status = IoCallDriver( Device, Irp );
  706. //
  707. // We check for device not ready by first checking Status
  708. // and then if status pending was returned, the Iosb status
  709. // value.
  710. //
  711. if (Status == STATUS_PENDING) {
  712. (VOID) KeWaitForSingleObject( &Event,
  713. Executive,
  714. KernelMode,
  715. FALSE,
  716. (PLARGE_INTEGER)NULL );
  717. Status = IosbToUse->Status;
  718. }
  719. ASSERT( !(OverrideVerify && (STATUS_VERIFY_REQUIRED == Status)));
  720. return Status;
  721. UNREFERENCED_PARAMETER( IrpContext );
  722. }
  723. NTSTATUS
  724. UdfReadSectors (
  725. IN PIRP_CONTEXT IrpContext,
  726. IN LONGLONG StartingOffset,
  727. IN ULONG ByteCount,
  728. IN BOOLEAN ReturnError,
  729. IN OUT PVOID Buffer,
  730. IN PDEVICE_OBJECT TargetDeviceObject
  731. )
  732. /*++
  733. Routine Description:
  734. This routine is called to transfer sectors from the disk to a
  735. specified buffer. It is used for mount and volume verify operations.
  736. This routine is synchronous, it will not return until the operation
  737. is complete or until the operation fails.
  738. The routine allocates an IRP and then passes this IRP to a lower
  739. level driver. Errors may occur in the allocation of this IRP or
  740. in the operation of the lower driver.
  741. Arguments:
  742. StartingOffset - Logical offset on the disk to start the read. This
  743. must be on a sector boundary, no check is made here.
  744. ByteCount - Number of bytes to read. This is an integral number of
  745. sectors, or otherwise a value we know the driver can handle,
  746. no check is made here to confirm this.
  747. ReturnError - Indicates whether we should return TRUE or FALSE
  748. to indicate an error or raise an error condition. This only applies
  749. to the result of the IO. Any other error may cause a raise.
  750. Buffer - Buffer to transfer the disk data into.
  751. TargetDeviceObject - The device object for the volume to be read.
  752. Return Value:
  753. The final status of the operation.
  754. --*/
  755. {
  756. PLONGLONG UseStartingOffset;
  757. LONGLONG LocalStartingOffset;
  758. NTSTATUS Status;
  759. KEVENT Event;
  760. PIRP Irp;
  761. PAGED_CODE();
  762. DebugTrace(( +1, Dbg,
  763. "UdfReadSectors, %x%08x +%x -> %08x from DO %08x\n",
  764. ((PLARGE_INTEGER)&StartingOffset)->HighPart,
  765. ((PLARGE_INTEGER)&StartingOffset)->LowPart,
  766. ByteCount,
  767. Buffer,
  768. TargetDeviceObject ));
  769. //
  770. // For the time being, we assume that we only read sector-at-a-time.
  771. // This simplifies sparing, and is the only way I am aware of this
  772. // code would not be ready for blocksize != sectorsize. It just is
  773. // not worth writing dead (but straightforward) code right now.
  774. //
  775. ASSERT( IrpContext->Vcb == NULL || ByteCount == SectorSize( IrpContext->Vcb ));
  776. //
  777. // If the volume is spared (and at a point where sparing is possible),
  778. // check if a mapping needs to be performed.
  779. //
  780. if (IrpContext->Vcb &&
  781. IrpContext->Vcb->Pcb &&
  782. IrpContext->Vcb->Pcb->SparingMcb) {
  783. LONGLONG SparingPsn;
  784. if (FsRtlLookupLargeMcbEntry( IrpContext->Vcb->Pcb->SparingMcb,
  785. LlSectorsFromBytes( IrpContext->Vcb, StartingOffset ),
  786. &SparingPsn,
  787. NULL,
  788. NULL,
  789. NULL,
  790. NULL ) &&
  791. SparingPsn != -1) {
  792. StartingOffset = BytesFromSectors( IrpContext->Vcb, (ULONG) SparingPsn );
  793. }
  794. }
  795. //
  796. // Initialize the event.
  797. //
  798. KeInitializeEvent( &Event, NotificationEvent, FALSE );
  799. //
  800. // Correct the starting offset by the method 2 fixup if neccesary. This also
  801. // assumes sector-at-a-time and sector == block so we don't need to fragment
  802. // the request or check if it spans a packet boundary.
  803. //
  804. // We assume that no fixups are required until a Vcb exists. This is true
  805. // since volume recognition may proceed in the first packet.
  806. //
  807. UseStartingOffset = &StartingOffset;
  808. if (IrpContext->Vcb &&
  809. FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP )) {
  810. LocalStartingOffset = UdfMethod2TransformByteOffset( IrpContext->Vcb, StartingOffset );
  811. UseStartingOffset = &LocalStartingOffset;
  812. DebugTrace(( 0, Dbg,
  813. "UdfReadSectors, Method2 Fixup to %x%08x\n",
  814. ((PLARGE_INTEGER)UseStartingOffset)->HighPart,
  815. ((PLARGE_INTEGER)UseStartingOffset)->LowPart ));
  816. }
  817. //
  818. // Attempt to allocate the IRP. If unsuccessful, raise
  819. // STATUS_INSUFFICIENT_RESOURCES.
  820. //
  821. Irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
  822. TargetDeviceObject,
  823. Buffer,
  824. ByteCount,
  825. (PLARGE_INTEGER) UseStartingOffset,
  826. &Event,
  827. &IrpContext->Irp->IoStatus );
  828. if (Irp == NULL) {
  829. UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
  830. }
  831. //
  832. // Ignore the change line (verify) for mount and verify requests
  833. //
  834. SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );
  835. //
  836. // Send the request down to the driver. If an error occurs return
  837. // it to the caller.
  838. //
  839. Status = IoCallDriver( TargetDeviceObject, Irp );
  840. //
  841. // If the status was STATUS_PENDING then wait on the event.
  842. //
  843. if (Status == STATUS_PENDING) {
  844. Status = KeWaitForSingleObject( &Event,
  845. Executive,
  846. KernelMode,
  847. FALSE,
  848. NULL );
  849. //
  850. // On a successful wait pull the status out of the IoStatus block.
  851. //
  852. if (NT_SUCCESS( Status )) {
  853. Status = IrpContext->Irp->IoStatus.Status;
  854. }
  855. }
  856. DebugTrace(( -1, Dbg, "UdfReadSectors -> %08x\n", Status ));
  857. //
  858. // Check whether we should raise in the error case.
  859. //
  860. if (!NT_SUCCESS( Status ) && !ReturnError) {
  861. UdfNormalizeAndRaiseStatus( IrpContext, Status );
  862. }
  863. return Status;
  864. }
  865. //
  866. // Local support routine
  867. //
  868. BOOLEAN
  869. UdfPrepareBuffers (
  870. IN PIRP_CONTEXT IrpContext,
  871. IN PIRP Irp,
  872. IN PFCB Fcb,
  873. IN PCCB Ccb,
  874. IN PVOID UserBuffer,
  875. IN ULONG UserBufferOffset,
  876. IN LONGLONG StartingOffset,
  877. IN ULONG ByteCount,
  878. IN PIO_RUN IoRuns,
  879. IN PULONG RunCount,
  880. IN PULONG ThisByteCount,
  881. IN PBOOLEAN SparseRuns
  882. )
  883. /*++
  884. Routine Description:
  885. This routine is the worker routine which looks up each run of an IO
  886. request and stores an entry for it in the IoRuns array. If the run
  887. begins on an unaligned disk boundary then we will allocate a buffer
  888. and Mdl for the unaligned portion and put it in the IoRuns entry.
  889. This routine will raise CANT_WAIT if an unaligned transfer is encountered
  890. and this request can't wait.
  891. Arguments:
  892. Irp - Originating Irp for this request.
  893. Fcb - This is the Fcb for this data stream. It may be a file, directory,
  894. path table or the volume file.
  895. UserBuffer - Current position in the user's buffer.
  896. UserBufferOffset - Offset from the start of the original user buffer.
  897. StartingOffset - Offset in the stream to begin the read.
  898. ByteCount - Number of bytes to read. We will fill the IoRuns array up
  899. to this point. We will stop early if we exceed the maximum number
  900. of parallel Ios we support.
  901. IoRuns - Pointer to the IoRuns array. The entire array is zeroes when
  902. this routine is called.
  903. RunCount - Number of entries in the IoRuns array filled here.
  904. ThisByteCount - Number of bytes described by the IoRun entries. Will
  905. not exceed the ByteCount passed in.
  906. SparseRuns - Will indicate whether sparse runs were a component of the
  907. range returned. While not part of the IoRuns, this will affect
  908. our ability to do simple IO.
  909. Return Value:
  910. BOOLEAN - TRUE if one of the entries in an unaligned buffer (provided
  911. this is synchronous). FALSE otherwise.
  912. --*/
  913. {
  914. PVCB Vcb;
  915. BOOLEAN Recorded;
  916. BOOLEAN FoundUnaligned = FALSE;
  917. PIO_RUN ThisIoRun = IoRuns;
  918. //
  919. // Following indicate where we are in the current transfer. Current
  920. // position in the file and number of bytes yet to transfer from
  921. // this position.
  922. //
  923. ULONG RemainingByteCount = ByteCount;
  924. LONGLONG CurrentFileOffset = StartingOffset;
  925. //
  926. // Following indicate the state of the user's buffer. We have
  927. // the destination of the next transfer and its offset in the
  928. // buffer. We also have the next available position in the buffer
  929. // available for a scratch buffer. We will align this up to a sector
  930. // boundary.
  931. //
  932. PVOID CurrentUserBuffer = UserBuffer;
  933. ULONG CurrentUserBufferOffset = UserBufferOffset;
  934. PVOID ScratchUserBuffer = UserBuffer;
  935. ULONG ScratchUserBufferOffset = UserBufferOffset;
  936. //
  937. // The following is the next contiguous bytes on the disk to
  938. // transfer. Read from the allocation package.
  939. //
  940. LONGLONG DiskOffset;
  941. ULONG CurrentByteCount;
  942. PAGED_CODE();
  943. Vcb = Fcb->Vcb;
  944. //
  945. // Initialize the RunCount, ByteCount and SparseRuns.
  946. //
  947. *RunCount = 0;
  948. *ThisByteCount = 0;
  949. *SparseRuns = FALSE;
  950. //
  951. // Loop while there are more bytes to process or there are
  952. // available entries in the IoRun array.
  953. //
  954. while (TRUE) {
  955. *RunCount += 1;
  956. //
  957. // Initialize the current position in the IoRuns array.
  958. // Find the user's buffer for this portion of the transfer.
  959. //
  960. ThisIoRun->UserBuffer = CurrentUserBuffer;
  961. //
  962. // Find the allocation information for the current offset in the
  963. // stream.
  964. //
  965. Recorded = UdfLookupAllocation( IrpContext,
  966. Fcb,
  967. Ccb,
  968. CurrentFileOffset,
  969. &DiskOffset,
  970. &CurrentByteCount );
  971. //
  972. // Limit ourselves to the data requested.
  973. //
  974. if (CurrentByteCount > RemainingByteCount) {
  975. CurrentByteCount = RemainingByteCount;
  976. }
  977. //
  978. // Handle the case of unrecorded data first.
  979. //
  980. if (!Recorded) {
  981. //
  982. // Note that we did not consume an entry.
  983. //
  984. *RunCount -= 1;
  985. //
  986. // Immediately zero the user buffer and indicate that we found sparse
  987. // runs to the caller.
  988. //
  989. RtlZeroMemory( CurrentUserBuffer, CurrentByteCount );
  990. *SparseRuns = TRUE;
  991. //
  992. // Push the scratch buffer pointers forward so that we don't stomp
  993. // on the zeroed buffer.
  994. //
  995. ScratchUserBuffer = Add2Ptr( CurrentUserBuffer,
  996. CurrentByteCount,
  997. PVOID );
  998. ScratchUserBufferOffset += CurrentByteCount;
  999. //
  1000. // Handle the case where this is an unaligned transfer. The
  1001. // following must all be true for this to be an aligned transfer.
  1002. //
  1003. // Disk offset on a 2048 byte boundary (Start of transfer)
  1004. //
  1005. // Byte count is a multiple of 2048 (Length of transfer)
  1006. //
  1007. // Current buffer offset is also on a 2048 byte boundary.
  1008. //
  1009. // If the ByteCount is at least one sector then do the
  1010. // unaligned transfer only for the tail. We can use the
  1011. // user's buffer for the aligned portion.
  1012. //
  1013. } else if (SectorOffset( Vcb, DiskOffset ) ||
  1014. SectorOffset( Vcb, CurrentUserBufferOffset ) ||
  1015. (SectorOffset( Vcb, CurrentByteCount ) &&
  1016. CurrentByteCount < SectorSize( Vcb ))) {
  1017. //
  1018. // If we can't wait then raise.
  1019. //
  1020. if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  1021. UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
  1022. }
  1023. //
  1024. // Remember the offset and the number of bytes out of
  1025. // the transfer buffer to copy into the user's buffer.
  1026. // We will truncate the current read to end on a sector
  1027. // boundary.
  1028. //
  1029. ThisIoRun->TransferBufferOffset = SectorOffset( Vcb, DiskOffset );
  1030. //
  1031. // Make sure this transfer ends on a sector boundary.
  1032. //
  1033. ThisIoRun->DiskOffset = LlSectorTruncate( Vcb, DiskOffset );
  1034. //
  1035. // Check if we can use a free portion of the user's buffer.
  1036. // If we can copy the bytes to an earlier portion of the
  1037. // buffer then read into that location and slide the bytes
  1038. // up.
  1039. //
  1040. // We can use the user's buffer if:
  1041. //
  1042. // The temporary location in the buffer is before the
  1043. // final destination.
  1044. //
  1045. // There is at least one sector of data to read.
  1046. //
  1047. if ((ScratchUserBufferOffset + ThisIoRun->TransferBufferOffset < CurrentUserBufferOffset) &&
  1048. (ThisIoRun->TransferBufferOffset + CurrentByteCount >= SectorSize( Vcb ))) {
  1049. ThisIoRun->DiskByteCount = SectorTruncate( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount );
  1050. CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
  1051. ThisIoRun->TransferByteCount = CurrentByteCount;
  1052. //
  1053. // Point to the user's buffer and Mdl for this transfer.
  1054. //
  1055. ThisIoRun->TransferBuffer = ScratchUserBuffer;
  1056. ThisIoRun->TransferMdl = Irp->MdlAddress;
  1057. ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
  1058. ScratchUserBufferOffset,
  1059. PVOID );
  1060. ScratchUserBuffer = Add2Ptr( ScratchUserBuffer,
  1061. ThisIoRun->DiskByteCount,
  1062. PVOID );
  1063. ScratchUserBufferOffset += ThisIoRun->DiskByteCount;
  1064. //
  1065. // Otherwise we need to allocate an auxilary buffer for the next sector.
  1066. //
  1067. } else {
  1068. //
  1069. // Read up to a page containing the partial data
  1070. //
  1071. ThisIoRun->DiskByteCount = SectorAlign( Vcb, ThisIoRun->TransferBufferOffset + CurrentByteCount );
  1072. if (ThisIoRun->DiskByteCount > PAGE_SIZE) {
  1073. ThisIoRun->DiskByteCount = PAGE_SIZE;
  1074. }
  1075. if (ThisIoRun->TransferBufferOffset + CurrentByteCount > ThisIoRun->DiskByteCount) {
  1076. CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
  1077. }
  1078. ThisIoRun->TransferByteCount = CurrentByteCount;
  1079. //
  1080. // Allocate a buffer for the non-aligned transfer.
  1081. //
  1082. ThisIoRun->TransferBuffer = FsRtlAllocatePoolWithTag( UdfNonPagedPool,
  1083. PAGE_SIZE,
  1084. TAG_IO_BUFFER );
  1085. //
  1086. // Allocate and build the Mdl to describe this buffer.
  1087. //
  1088. ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer,
  1089. PAGE_SIZE,
  1090. FALSE,
  1091. FALSE,
  1092. NULL );
  1093. ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer;
  1094. if (ThisIoRun->TransferMdl == NULL) {
  1095. IrpContext->Irp->IoStatus.Information = 0;
  1096. UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
  1097. }
  1098. MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl );
  1099. }
  1100. //
  1101. // Remember we found an unaligned transfer.
  1102. //
  1103. FoundUnaligned = TRUE;
  1104. //
  1105. // Otherwise we use the buffer and Mdl from the original request.
  1106. //
  1107. } else {
  1108. //
  1109. // Truncate the read length to a sector-aligned value. We know
  1110. // the length must be at least one sector or we wouldn't be
  1111. // here now.
  1112. //
  1113. CurrentByteCount = SectorTruncate( Vcb, CurrentByteCount );
  1114. //
  1115. // Read these sectors from the disk.
  1116. //
  1117. ThisIoRun->DiskOffset = DiskOffset;
  1118. ThisIoRun->DiskByteCount = CurrentByteCount;
  1119. //
  1120. // Use the user's buffer and Mdl as our transfer buffer
  1121. // and Mdl.
  1122. //
  1123. ThisIoRun->TransferBuffer = CurrentUserBuffer;
  1124. ThisIoRun->TransferMdl = Irp->MdlAddress;
  1125. ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
  1126. CurrentUserBufferOffset,
  1127. PVOID );
  1128. ScratchUserBuffer = Add2Ptr( CurrentUserBuffer,
  1129. CurrentByteCount,
  1130. PVOID );
  1131. ScratchUserBufferOffset += CurrentByteCount;
  1132. }
  1133. //
  1134. // Update our position in the transfer and the RunCount and
  1135. // ByteCount for the user.
  1136. //
  1137. RemainingByteCount -= CurrentByteCount;
  1138. //
  1139. // Break out if no more positions in the IoRuns array or
  1140. // we have all of the bytes accounted for.
  1141. //
  1142. *ThisByteCount += CurrentByteCount;
  1143. if ((RemainingByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) {
  1144. break;
  1145. }
  1146. //
  1147. // Update our pointers for the user's buffer.
  1148. //
  1149. ThisIoRun = IoRuns + *RunCount;
  1150. CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID );
  1151. CurrentUserBufferOffset += CurrentByteCount;
  1152. CurrentFileOffset += CurrentByteCount;
  1153. }
  1154. return FoundUnaligned;
  1155. }
  1156. //
  1157. // Local support routine
  1158. //
  1159. BOOLEAN
  1160. UdfFinishBuffers (
  1161. IN PIRP_CONTEXT IrpContext,
  1162. IN PIO_RUN IoRuns,
  1163. IN ULONG RunCount,
  1164. IN BOOLEAN FinalCleanup
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. This routine is called to perform any data transferred required for
  1169. unaligned Io or to perform the final cleanup of the IoRuns array.
  1170. In all cases this is where we will deallocate any buffer and mdl
  1171. allocated to perform the unaligned transfer. If this is not the
  1172. final cleanup then we also transfer the bytes to the user buffer
  1173. and flush the hardware cache.
  1174. We walk backwards through the run array because we may be shifting data
  1175. in the user's buffer. Typical case is where we allocated a buffer for
  1176. the first part of a read and then used the user's buffer for the
  1177. next section (but stored it at the beginning of the buffer.
  1178. Arguments:
  1179. IoRuns - Pointer to the IoRuns array.
  1180. RunCount - Number of entries in the IoRuns array filled here.
  1181. FinalCleanup - Indicates if we should be deallocating temporary buffers
  1182. (TRUE) or transferring bytes for a unaligned transfers and
  1183. deallocating the buffers (FALSE). Flush the system cache if
  1184. transferring data.
  1185. Return Value:
  1186. BOOLEAN - TRUE if this request needs the Io buffers to be flushed, FALSE otherwise.
  1187. --*/
  1188. {
  1189. BOOLEAN FlushIoBuffers = FALSE;
  1190. ULONG RemainingEntries = RunCount;
  1191. PIO_RUN ThisIoRun = &IoRuns[RunCount - 1];
  1192. PAGED_CODE();
  1193. //
  1194. // Walk through each entry in the IoRun array.
  1195. //
  1196. while (RemainingEntries != 0) {
  1197. //
  1198. // We only need to deal with the case of an unaligned transfer.
  1199. //
  1200. if (ThisIoRun->TransferByteCount != 0) {
  1201. //
  1202. // If not the final cleanup then transfer the data to the
  1203. // user's buffer and remember that we will need to flush
  1204. // the user's buffer to memory.
  1205. //
  1206. if (!FinalCleanup) {
  1207. //
  1208. // If we are shifting in the user's buffer then use
  1209. // MoveMemory.
  1210. //
  1211. if (ThisIoRun->TransferMdl == IrpContext->Irp->MdlAddress) {
  1212. RtlMoveMemory( ThisIoRun->UserBuffer,
  1213. Add2Ptr( ThisIoRun->TransferBuffer,
  1214. ThisIoRun->TransferBufferOffset,
  1215. PVOID ),
  1216. ThisIoRun->TransferByteCount );
  1217. } else {
  1218. RtlCopyMemory( ThisIoRun->UserBuffer,
  1219. Add2Ptr( ThisIoRun->TransferBuffer,
  1220. ThisIoRun->TransferBufferOffset,
  1221. PVOID ),
  1222. ThisIoRun->TransferByteCount );
  1223. }
  1224. FlushIoBuffers = TRUE;
  1225. }
  1226. //
  1227. // Free any Mdl we may have allocated. If the Mdl isn't
  1228. // present then we must have failed during the allocation
  1229. // phase.
  1230. //
  1231. if (ThisIoRun->TransferMdl != IrpContext->Irp->MdlAddress) {
  1232. if (ThisIoRun->TransferMdl != NULL) {
  1233. IoFreeMdl( ThisIoRun->TransferMdl );
  1234. }
  1235. //
  1236. // Now free any buffer we may have allocated. If the Mdl
  1237. // doesn't match the original Mdl then free the buffer.
  1238. //
  1239. if (ThisIoRun->TransferBuffer != NULL) {
  1240. UdfFreePool( &ThisIoRun->TransferBuffer );
  1241. }
  1242. }
  1243. }
  1244. //
  1245. // Now handle the case where we failed in the process
  1246. // of allocating associated Irps and Mdls.
  1247. //
  1248. if (ThisIoRun->SavedIrp != NULL) {
  1249. if (ThisIoRun->SavedIrp->MdlAddress != NULL) {
  1250. IoFreeMdl( ThisIoRun->SavedIrp->MdlAddress );
  1251. }
  1252. IoFreeIrp( ThisIoRun->SavedIrp );
  1253. }
  1254. //
  1255. // Move to the previous IoRun entry.
  1256. //
  1257. ThisIoRun -= 1;
  1258. RemainingEntries -= 1;
  1259. }
  1260. //
  1261. // If we copied any data then flush the Io buffers.
  1262. //
  1263. return FlushIoBuffers;
  1264. }
  1265. //
  1266. // Local support routine
  1267. //
  1268. VOID
  1269. UdfMultipleAsync (
  1270. IN PIRP_CONTEXT IrpContext,
  1271. IN ULONG RunCount,
  1272. IN PIO_RUN IoRuns
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. This routine first does the initial setup required of a Master IRP that is
  1277. going to be completed using associated IRPs. This routine should not
  1278. be used if only one async request is needed, instead the single read
  1279. async routines should be called.
  1280. A context parameter is initialized, to serve as a communications area
  1281. between here and the common completion routine.
  1282. Next this routine reads or writes one or more contiguous sectors from
  1283. a device asynchronously, and is used if there are multiple reads for a
  1284. master IRP. A completion routine is used to synchronize with the
  1285. completion of all of the I/O requests started by calls to this routine.
  1286. Also, prior to calling this routine the caller must initialize the
  1287. IoStatus field in the Context, with the correct success status and byte
  1288. count which are expected if all of the parallel transfers complete
  1289. successfully. After return this status will be unchanged if all requests
  1290. were, in fact, successful. However, if one or more errors occur, the
  1291. IoStatus will be modified to reflect the error status and byte count
  1292. from the first run (by Vbo) which encountered an error. I/O status
  1293. from all subsequent runs will not be indicated.
  1294. Arguments:
  1295. RunCount - Supplies the number of multiple async requests
  1296. that will be issued against the master irp.
  1297. IoRuns - Supplies an array containing the Offset and ByteCount for the
  1298. separate requests.
  1299. Return Value:
  1300. None.
  1301. --*/
  1302. {
  1303. PIO_COMPLETION_ROUTINE CompletionRoutine;
  1304. PIO_STACK_LOCATION IrpSp;
  1305. PMDL Mdl;
  1306. PIRP Irp;
  1307. PIRP MasterIrp;
  1308. ULONG UnwindRunCount;
  1309. PAGED_CODE();
  1310. //
  1311. // Set up things according to whether this is truely async.
  1312. //
  1313. CompletionRoutine = UdfMultiSyncCompletionRoutine;
  1314. if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  1315. CompletionRoutine = UdfMultiAsyncCompletionRoutine;
  1316. }
  1317. //
  1318. // Initialize some local variables.
  1319. //
  1320. MasterIrp = IrpContext->Irp;
  1321. //
  1322. // Itterate through the runs, doing everything that can fail.
  1323. // We let the cleanup in CdFinishBuffers clean up on error.
  1324. //
  1325. for (UnwindRunCount = 0;
  1326. UnwindRunCount < RunCount;
  1327. UnwindRunCount += 1) {
  1328. //
  1329. // Create an associated IRP, making sure there is one stack entry for
  1330. // us, as well.
  1331. //
  1332. IoRuns[UnwindRunCount].SavedIrp =
  1333. Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) );
  1334. if (Irp == NULL) {
  1335. IrpContext->Irp->IoStatus.Information = 0;
  1336. UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
  1337. }
  1338. //
  1339. // Allocate and build a partial Mdl for the request.
  1340. //
  1341. Mdl = IoAllocateMdl( IoRuns[UnwindRunCount].TransferVirtualAddress,
  1342. IoRuns[UnwindRunCount].DiskByteCount,
  1343. FALSE,
  1344. FALSE,
  1345. Irp );
  1346. if (Mdl == NULL) {
  1347. IrpContext->Irp->IoStatus.Information = 0;
  1348. UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
  1349. }
  1350. IoBuildPartialMdl( IoRuns[UnwindRunCount].TransferMdl,
  1351. Mdl,
  1352. IoRuns[UnwindRunCount].TransferVirtualAddress,
  1353. IoRuns[UnwindRunCount].DiskByteCount );
  1354. //
  1355. // Get the first IRP stack location in the associated Irp
  1356. //
  1357. IoSetNextIrpStackLocation( Irp );
  1358. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1359. //
  1360. // Setup the Stack location to describe our read.
  1361. //
  1362. IrpSp->MajorFunction = IRP_MJ_READ;
  1363. IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
  1364. IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
  1365. //
  1366. // Set up the completion routine address in our stack frame.
  1367. //
  1368. IoSetCompletionRoutine( Irp,
  1369. CompletionRoutine,
  1370. IrpContext->IoContext,
  1371. TRUE,
  1372. TRUE,
  1373. TRUE );
  1374. //
  1375. // Setup the next IRP stack location in the associated Irp for the disk
  1376. // driver beneath us.
  1377. //
  1378. IrpSp = IoGetNextIrpStackLocation( Irp );
  1379. //
  1380. // Setup the Stack location to do a read from the disk driver.
  1381. //
  1382. IrpSp->MajorFunction = IRP_MJ_READ;
  1383. IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
  1384. IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
  1385. }
  1386. //
  1387. // We only need to set the associated IRP count in the master irp to
  1388. // make it a master IRP. But we set the count to one more than our
  1389. // caller requested, because we do not want the I/O system to complete
  1390. // the I/O. We also set our own count.
  1391. //
  1392. IrpContext->IoContext->IrpCount = RunCount;
  1393. IrpContext->IoContext->MasterIrp = MasterIrp;
  1394. //
  1395. // We set the count in the master Irp to 1 since typically we
  1396. // will clean up the associated irps ourselves. Setting this to one
  1397. // means completing the last associated Irp with SUCCESS (in the async
  1398. // case) will complete the master irp.
  1399. //
  1400. MasterIrp->AssociatedIrp.IrpCount = 1;
  1401. //
  1402. // Now that all the dangerous work is done, issue the Io requests
  1403. //
  1404. for (UnwindRunCount = 0;
  1405. UnwindRunCount < RunCount;
  1406. UnwindRunCount++) {
  1407. Irp = IoRuns[UnwindRunCount].SavedIrp;
  1408. IoRuns[UnwindRunCount].SavedIrp = NULL;
  1409. //
  1410. // If IoCallDriver returns an error, it has completed the Irp
  1411. // and the error will be caught by our completion routines
  1412. // and dealt with as a normal IO error.
  1413. //
  1414. (VOID) IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  1415. }
  1416. return;
  1417. }
  1418. //
  1419. // Local support routine
  1420. //
  1421. VOID
  1422. UdfSingleAsync (
  1423. IN PIRP_CONTEXT IrpContext,
  1424. IN LONGLONG ByteOffset,
  1425. IN ULONG ByteCount
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. This routine reads one or more contiguous sectors from a device
  1430. asynchronously, and is used if there is only one read necessary to
  1431. complete the IRP. It implements the read by simply filling
  1432. in the next stack frame in the Irp, and passing it on. The transfer
  1433. occurs to the single buffer originally specified in the user request.
  1434. Arguments:
  1435. ByteOffset - Supplies the starting Logical Byte Offset to begin reading from
  1436. ByteCount - Supplies the number of bytes to read from the device
  1437. Return Value:
  1438. None.
  1439. --*/
  1440. {
  1441. PIO_STACK_LOCATION IrpSp;
  1442. PIO_COMPLETION_ROUTINE CompletionRoutine;
  1443. PAGED_CODE();
  1444. //
  1445. // Set up things according to whether this is truely async.
  1446. //
  1447. if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
  1448. CompletionRoutine = UdfSingleSyncCompletionRoutine;
  1449. } else {
  1450. CompletionRoutine = UdfSingleAsyncCompletionRoutine;
  1451. }
  1452. //
  1453. // Set up the completion routine address in our stack frame.
  1454. //
  1455. IoSetCompletionRoutine( IrpContext->Irp,
  1456. CompletionRoutine,
  1457. IrpContext->IoContext,
  1458. TRUE,
  1459. TRUE,
  1460. TRUE );
  1461. //
  1462. // Setup the next IRP stack location in the associated Irp for the disk
  1463. // driver beneath us.
  1464. //
  1465. IrpSp = IoGetNextIrpStackLocation( IrpContext->Irp );
  1466. //
  1467. // Setup the Stack location to do a read from the disk driver.
  1468. //
  1469. IrpSp->MajorFunction = IrpContext->MajorFunction;
  1470. IrpSp->Parameters.Read.Length = ByteCount;
  1471. IrpSp->Parameters.Read.ByteOffset.QuadPart = ByteOffset;
  1472. //
  1473. // Issue the Io request
  1474. //
  1475. //
  1476. // If IoCallDriver returns an error, it has completed the Irp
  1477. // and the error will be caught by our completion routines
  1478. // and dealt with as a normal IO error.
  1479. //
  1480. (VOID)IoCallDriver( IrpContext->Vcb->TargetDeviceObject, IrpContext->Irp );
  1481. }
  1482. //
  1483. // Local support routine
  1484. //
  1485. VOID
  1486. UdfWaitSync (
  1487. IN PIRP_CONTEXT IrpContext
  1488. )
  1489. /*++
  1490. Routine Description:
  1491. This routine waits for one or more previously started I/O requests
  1492. from the above routines, by simply waiting on the event.
  1493. Arguments:
  1494. Return Value:
  1495. None
  1496. --*/
  1497. {
  1498. PAGED_CODE();
  1499. KeWaitForSingleObject( &IrpContext->IoContext->SyncEvent,
  1500. Executive,
  1501. KernelMode,
  1502. FALSE,
  1503. NULL );
  1504. KeClearEvent( &IrpContext->IoContext->SyncEvent );
  1505. return;
  1506. }
  1507. //
  1508. // Local support routine
  1509. //
  1510. NTSTATUS
  1511. UdfMultiSyncCompletionRoutine (
  1512. IN PDEVICE_OBJECT DeviceObject,
  1513. IN PIRP Irp,
  1514. IN PVOID Context
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. This is the completion routine for all synchronous reads
  1519. started via UdfMultipleAsync.
  1520. The completion routine has has the following responsibilities:
  1521. If the individual request was completed with an error, then
  1522. this completion routine must see if this is the first error
  1523. and remember the error status in the Context.
  1524. If the IrpCount goes to 1, then it sets the event in the Context
  1525. parameter to signal the caller that all of the asynch requests
  1526. are done.
  1527. Arguments:
  1528. DeviceObject - Pointer to the file system device object.
  1529. Irp - Pointer to the associated Irp which is being completed. (This
  1530. Irp will no longer be accessible after this routine returns.)
  1531. Context - The context parameter which was specified for all of
  1532. the multiple asynch I/O requests for this MasterIrp.
  1533. Return Value:
  1534. The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
  1535. immediately complete the Master Irp without being in a race condition
  1536. with the IoCompleteRequest thread trying to decrement the IrpCount in
  1537. the Master Irp.
  1538. --*/
  1539. {
  1540. PUDF_IO_CONTEXT IoContext = Context;
  1541. //
  1542. // If we got an error (or verify required), remember it in the Irp
  1543. //
  1544. if (!NT_SUCCESS( Irp->IoStatus.Status )) {
  1545. InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
  1546. IoContext->MasterIrp->IoStatus.Information = 0;
  1547. }
  1548. //
  1549. // We must do this here since IoCompleteRequest won't get a chance
  1550. // on this associated Irp.
  1551. //
  1552. IoFreeMdl( Irp->MdlAddress );
  1553. IoFreeIrp( Irp );
  1554. if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
  1555. //
  1556. // Update the Master Irp with any error status from the associated Irps.
  1557. //
  1558. IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
  1559. KeSetEvent( &IoContext->SyncEvent, 0, FALSE );
  1560. }
  1561. UNREFERENCED_PARAMETER( DeviceObject );
  1562. return STATUS_MORE_PROCESSING_REQUIRED;
  1563. }
  1564. //
  1565. // Local support routine
  1566. //
  1567. NTSTATUS
  1568. UdfMultiAsyncCompletionRoutine (
  1569. IN PDEVICE_OBJECT DeviceObject,
  1570. IN PIRP Irp,
  1571. IN PVOID Context
  1572. )
  1573. /*++
  1574. Routine Description:
  1575. This is the completion routine for all asynchronous reads
  1576. started via UdfMultipleAsync.
  1577. The completion routine has has the following responsibilities:
  1578. If the individual request was completed with an error, then
  1579. this completion routine must see if this is the first error
  1580. and remember the error status in the Context.
  1581. Arguments:
  1582. DeviceObject - Pointer to the file system device object.
  1583. Irp - Pointer to the associated Irp which is being completed. (This
  1584. Irp will no longer be accessible after this routine returns.)
  1585. Context - The context parameter which was specified for all of
  1586. the multiple asynch I/O requests for this MasterIrp.
  1587. Return Value:
  1588. Currently always returns STATUS_SUCCESS.
  1589. --*/
  1590. {
  1591. PUDF_IO_CONTEXT IoContext = Context;
  1592. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
  1593. //
  1594. // If we got an error (or verify required), remember it in the Irp
  1595. //
  1596. if (!NT_SUCCESS( Irp->IoStatus.Status )) {
  1597. InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
  1598. }
  1599. //
  1600. // Decrement IrpCount and see if it goes to zero.
  1601. //
  1602. if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
  1603. //
  1604. // Mark the master Irp pending
  1605. //
  1606. IoMarkIrpPending( IoContext->MasterIrp );
  1607. //
  1608. // Update the Master Irp with any error status from the associated Irps.
  1609. //
  1610. IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
  1611. //
  1612. // Update the information field with the correct value.
  1613. //
  1614. IoContext->MasterIrp->IoStatus.Information = 0;
  1615. if (NT_SUCCESS( IoContext->MasterIrp->IoStatus.Status )) {
  1616. IoContext->MasterIrp->IoStatus.Information = IoContext->RequestedByteCount;
  1617. }
  1618. //
  1619. // Now release the resource
  1620. //
  1621. ExReleaseResourceForThreadLite( IoContext->Resource,
  1622. IoContext->ResourceThreadId );
  1623. //
  1624. // and finally, free the context record.
  1625. //
  1626. UdfFreeIoContext( IoContext );
  1627. //
  1628. // Return success in this case.
  1629. //
  1630. return STATUS_SUCCESS;
  1631. } else {
  1632. //
  1633. // We need to cleanup the associated Irp and its Mdl.
  1634. //
  1635. IoFreeMdl( Irp->MdlAddress );
  1636. IoFreeIrp( Irp );
  1637. return STATUS_MORE_PROCESSING_REQUIRED;
  1638. }
  1639. UNREFERENCED_PARAMETER( DeviceObject );
  1640. }
  1641. //
  1642. // Local support routine
  1643. //
  1644. NTSTATUS
  1645. UdfSingleSyncCompletionRoutine (
  1646. IN PDEVICE_OBJECT DeviceObject,
  1647. IN PIRP Irp,
  1648. IN PVOID Context
  1649. )
  1650. /*++
  1651. Routine Description:
  1652. This is the completion routine for all reads started via UdfSingleAsync.
  1653. The completion routine has has the following responsibilities:
  1654. It sets the event in the Context parameter to signal the caller
  1655. that all of the asynch requests are done.
  1656. Arguments:
  1657. DeviceObject - Pointer to the file system device object.
  1658. Irp - Pointer to the Irp for this request. (This Irp will no longer
  1659. be accessible after this routine returns.)
  1660. Context - The context parameter which was specified in the call to
  1661. UdfSingleAsynch.
  1662. Return Value:
  1663. The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
  1664. immediately complete the Master Irp without being in a race condition
  1665. with the IoCompleteRequest thread trying to decrement the IrpCount in
  1666. the Master Irp.
  1667. --*/
  1668. {
  1669. //
  1670. // Store the correct information field into the Irp.
  1671. //
  1672. if (!NT_SUCCESS( Irp->IoStatus.Status )) {
  1673. Irp->IoStatus.Information = 0;
  1674. }
  1675. KeSetEvent( &((PUDF_IO_CONTEXT)Context)->SyncEvent, 0, FALSE );
  1676. return STATUS_MORE_PROCESSING_REQUIRED;
  1677. UNREFERENCED_PARAMETER( DeviceObject );
  1678. }
  1679. //
  1680. // Local support routine
  1681. //
  1682. NTSTATUS
  1683. UdfSingleAsyncCompletionRoutine (
  1684. IN PDEVICE_OBJECT DeviceObject,
  1685. IN PIRP Irp,
  1686. IN PVOID Context
  1687. )
  1688. /*++
  1689. Routine Description:
  1690. This is the completion routine for all asynchronous reads
  1691. started via UdfSingleAsynch.
  1692. Arguments:
  1693. DeviceObject - Pointer to the file system device object.
  1694. Irp - Pointer to the Irp for this request. (This Irp will no longer
  1695. be accessible after this routine returns.)
  1696. Context - The context parameter which was specified in the call to
  1697. UdfSingleAsynch.
  1698. Return Value:
  1699. Currently always returns STATUS_SUCCESS.
  1700. --*/
  1701. {
  1702. //
  1703. // Update the information field with the correct value for bytes read.
  1704. //
  1705. Irp->IoStatus.Information = 0;
  1706. if (NT_SUCCESS( Irp->IoStatus.Status )) {
  1707. Irp->IoStatus.Information = ((PUDF_IO_CONTEXT) Context)->RequestedByteCount;
  1708. }
  1709. //
  1710. // Mark the Irp pending
  1711. //
  1712. IoMarkIrpPending( Irp );
  1713. //
  1714. // Now release the resource
  1715. //
  1716. ExReleaseResourceForThreadLite( ((PUDF_IO_CONTEXT) Context)->Resource,
  1717. ((PUDF_IO_CONTEXT) Context)->ResourceThreadId );
  1718. //
  1719. // and finally, free the context record.
  1720. //
  1721. UdfFreeIoContext( (PUDF_IO_CONTEXT) Context );
  1722. return STATUS_SUCCESS;
  1723. UNREFERENCED_PARAMETER( DeviceObject );
  1724. }