Source code of Windows XP (NT5)
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.

1392 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. read.c
  5. Abstract:
  6. This module contains the code to implement the NtReadFile system service.
  7. Author:
  8. Darryl E. Havens (darrylh) 14-Apr-1989
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "iomgr.h"
  14. #ifdef ALLOC_DATA_PRAGMA
  15. #pragma const_seg("PAGECONST")
  16. #endif // ALLOC_DATA_PRAGMA
  17. const KPRIORITY IopCacheHitIncrement = IO_NO_INCREMENT;
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, NtReadFile)
  20. #pragma alloc_text(PAGE, NtReadFileScatter)
  21. #endif
  22. NTSTATUS
  23. NtReadFile(
  24. IN HANDLE FileHandle,
  25. IN HANDLE Event OPTIONAL,
  26. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  27. IN PVOID ApcContext OPTIONAL,
  28. OUT PIO_STATUS_BLOCK IoStatusBlock,
  29. OUT PVOID Buffer,
  30. IN ULONG Length,
  31. IN PLARGE_INTEGER ByteOffset OPTIONAL,
  32. IN PULONG Key OPTIONAL
  33. )
  34. /*++
  35. Routine Description:
  36. This service reads Length bytes of data from the file associated with
  37. FileHandle starting at ByteOffset and puts the data into the caller's
  38. Buffer. If the end of the file is reached before Length bytes have
  39. been read, then the operation will terminate. The actual length of
  40. the data read from the file will be returned in the second longword
  41. of the IoStatusBlock.
  42. Arguments:
  43. FileHandle - Supplies a handle to the file to be read.
  44. Event - Optionally supplies an event to be signaled when the read operation
  45. is complete.
  46. ApcRoutine - Optionally supplies an APC routine to be executed when the read
  47. operation is complete.
  48. ApcContext - Supplies a context parameter to be passed to the ApcRoutine, if
  49. an ApcRoutine was specified.
  50. IoStatusBlock - Address of the caller's I/O status block.
  51. Buffer - Address of buffer to receive the data read from the file.
  52. Length - Supplies the length, in bytes, of the data to read from the file.
  53. ByteOffset - Optionally specifies the starting byte offset within the file
  54. to begin the read operation. If not specified and the file is open
  55. for synchronous I/O, then the current file position is used. If the
  56. file is not opened for synchronous I/O and the parameter is not
  57. specified, then it is an error.
  58. Key - Optionally specifies a key to be used if there are locks associated
  59. with the file.
  60. Return Value:
  61. The status returned is success if the read operation was properly queued
  62. to the I/O system. Once the read completes the status of the operation
  63. can be determined by examining the Status field of the I/O status block.
  64. --*/
  65. {
  66. PIRP irp;
  67. NTSTATUS status;
  68. PFILE_OBJECT fileObject;
  69. PDEVICE_OBJECT deviceObject;
  70. PFAST_IO_DISPATCH fastIoDispatch;
  71. KPROCESSOR_MODE requestorMode;
  72. PIO_STACK_LOCATION irpSp;
  73. NTSTATUS exceptionCode;
  74. BOOLEAN synchronousIo;
  75. PKEVENT eventObject = (PKEVENT) NULL;
  76. ULONG keyValue = 0;
  77. LARGE_INTEGER fileOffset = {0,0};
  78. PULONG majorFunction;
  79. PETHREAD CurrentThread;
  80. PAGED_CODE();
  81. //
  82. // Get the previous mode; i.e., the mode of the caller.
  83. //
  84. CurrentThread = PsGetCurrentThread ();
  85. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  86. //
  87. // Reference the file object so the target device can be found. Note
  88. // that if the caller does not have read access to the file, the operation
  89. // will fail.
  90. //
  91. status = ObReferenceObjectByHandle( FileHandle,
  92. FILE_READ_DATA,
  93. IoFileObjectType,
  94. requestorMode,
  95. (PVOID *) &fileObject,
  96. NULL );
  97. if (!NT_SUCCESS( status )) {
  98. return status;
  99. }
  100. //
  101. // Get the address of the target device object.
  102. //
  103. deviceObject = IoGetRelatedDeviceObject( fileObject );
  104. if (requestorMode != KernelMode) {
  105. //
  106. // The caller's access mode is not kernel so probe each of the arguments
  107. // and capture them as necessary. If any failures occur, the condition
  108. // handler will be invoked to handle them. It will simply cleanup and
  109. // return an access violation status code back to the system service
  110. // dispatcher.
  111. //
  112. try {
  113. //
  114. // The IoStatusBlock parameter must be writeable by the caller.
  115. //
  116. ProbeForWriteIoStatusEx(IoStatusBlock , ApcRoutine);
  117. //
  118. // The caller's data buffer must be writable from the caller's
  119. // mode. This check ensures that this is the case. Since the
  120. // buffer address is captured, the caller cannot change it,
  121. // even though he/she can change the protection from another
  122. // thread. This error will be caught by the probe/lock or
  123. // buffer copy operations later.
  124. //
  125. ProbeForWrite( Buffer, Length, sizeof( UCHAR ) );
  126. //
  127. // If this file has an I/O completion port associated w/it, then
  128. // ensure that the caller did not supply an APC routine, as the
  129. // two are mutually exclusive methods for I/O completion
  130. // notification.
  131. //
  132. if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
  133. ObDereferenceObject( fileObject );
  134. return STATUS_INVALID_PARAMETER;
  135. }
  136. //
  137. // Also ensure that the ByteOffset parameter is readable from
  138. // the caller's mode and capture it if it is present.
  139. //
  140. if (ARGUMENT_PRESENT( ByteOffset )) {
  141. ProbeForReadSmallStructure( ByteOffset,
  142. sizeof( LARGE_INTEGER ),
  143. sizeof( ULONG ) );
  144. fileOffset = *ByteOffset;
  145. }
  146. //
  147. // Check to see whether the caller has opened the file without
  148. // intermediate buffering. If so, perform the following Buffer
  149. // and ByteOffset parameter checks differently.
  150. //
  151. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  152. //
  153. // The file was opened without intermediate buffering enabled.
  154. // Check that the Buffer is properly aligned, and that the
  155. // length is an integral number of 512-byte blocks.
  156. //
  157. if ((deviceObject->SectorSize &&
  158. (Length & (deviceObject->SectorSize - 1))) ||
  159. (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) {
  160. //
  161. // Check for sector sizes that are not a power of two.
  162. //
  163. if ((deviceObject->SectorSize &&
  164. Length % deviceObject->SectorSize) ||
  165. (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) {
  166. ObDereferenceObject( fileObject );
  167. return STATUS_INVALID_PARAMETER;
  168. }
  169. }
  170. //
  171. // If a ByteOffset parameter was specified, ensure that it
  172. // is a valid argument.
  173. //
  174. if (ARGUMENT_PRESENT( ByteOffset )) {
  175. if (deviceObject->SectorSize &&
  176. (fileOffset.LowPart & (deviceObject->SectorSize - 1))) {
  177. ObDereferenceObject( fileObject );
  178. return STATUS_INVALID_PARAMETER;
  179. }
  180. }
  181. }
  182. //
  183. // Finally, ensure that if there is a key parameter specified it
  184. // is readable by the caller.
  185. //
  186. if (ARGUMENT_PRESENT( Key )) {
  187. keyValue = ProbeAndReadUlong( Key );
  188. }
  189. } except(IopExceptionFilter( GetExceptionInformation(), &exceptionCode )) {
  190. //
  191. // An exception was incurred while attempting to probe the
  192. // caller's parameters. Dereference the file object and return
  193. // an appropriate error status code.
  194. //
  195. ObDereferenceObject( fileObject );
  196. return exceptionCode;
  197. }
  198. } else {
  199. //
  200. // The caller's mode is kernel. Get the same parameters that are
  201. // required from any other mode.
  202. //
  203. if (ARGUMENT_PRESENT( ByteOffset )) {
  204. fileOffset = *ByteOffset;
  205. }
  206. if (ARGUMENT_PRESENT( Key )) {
  207. keyValue = *Key;
  208. }
  209. #if DBG
  210. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  211. //
  212. // The file was opened without intermediate buffering enabled.
  213. // Check that the Buffer is properly aligned, and that the
  214. // length is an integral number of the block size.
  215. //
  216. if ((deviceObject->SectorSize &&
  217. (Length & (deviceObject->SectorSize - 1))) ||
  218. (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) {
  219. //
  220. // Check for sector sizes that are not a power of two.
  221. //
  222. if ((deviceObject->SectorSize &&
  223. Length % deviceObject->SectorSize) ||
  224. (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) {
  225. ObDereferenceObject( fileObject );
  226. ASSERT( FALSE );
  227. return STATUS_INVALID_PARAMETER;
  228. }
  229. }
  230. //
  231. // If a ByteOffset parameter was specified, ensure that it
  232. // is a valid argument.
  233. //
  234. if (ARGUMENT_PRESENT( ByteOffset )) {
  235. if (deviceObject->SectorSize &&
  236. (fileOffset.LowPart & (deviceObject->SectorSize - 1))) {
  237. ObDereferenceObject( fileObject );
  238. ASSERT( FALSE );
  239. return STATUS_INVALID_PARAMETER;
  240. }
  241. }
  242. }
  243. #endif // DBG
  244. }
  245. //
  246. // Get the address of the event object and set the event to the Not-
  247. // Signaled state, if an one was specified. Note here too, that if
  248. // the handle does not refer to an event, then the reference will fail.
  249. //
  250. if (ARGUMENT_PRESENT( Event )) {
  251. status = ObReferenceObjectByHandle( Event,
  252. EVENT_MODIFY_STATE,
  253. ExEventObjectType,
  254. requestorMode,
  255. (PVOID *) &eventObject,
  256. NULL );
  257. if (!NT_SUCCESS( status )) {
  258. ObDereferenceObject( fileObject );
  259. return status;
  260. } else {
  261. KeClearEvent( eventObject );
  262. }
  263. }
  264. //
  265. // Get the address of the driver object's Fast I/O dispatch structure.
  266. //
  267. fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  268. //
  269. // Make a special check here to determine whether this is a synchronous
  270. // I/O operation. If it is, then wait here until the file is owned by
  271. // the current thread.
  272. //
  273. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  274. BOOLEAN interrupted;
  275. if (!IopAcquireFastLock( fileObject )) {
  276. status = IopAcquireFileObjectLock( fileObject,
  277. requestorMode,
  278. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  279. &interrupted );
  280. if (interrupted) {
  281. if (eventObject) {
  282. ObDereferenceObject( eventObject );
  283. }
  284. ObDereferenceObject( fileObject );
  285. return status;
  286. }
  287. }
  288. if (!ARGUMENT_PRESENT( ByteOffset ) ||
  289. (fileOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
  290. fileOffset.HighPart == -1)) {
  291. fileOffset = fileObject->CurrentByteOffset;
  292. }
  293. //
  294. // Turbo read support. If the file is currently cached on this
  295. // file object, then call the Cache Manager directly via FastIoRead
  296. // and try to successfully complete the request here. Note if
  297. // FastIoRead returns FALSE or we get an I/O error, we simply
  298. // fall through and go the "long way" and create an Irp.
  299. //
  300. if (fileObject->PrivateCacheMap) {
  301. IO_STATUS_BLOCK localIoStatus;
  302. ASSERT(fastIoDispatch && fastIoDispatch->FastIoRead);
  303. //
  304. // Negative file offsets are illegal.
  305. //
  306. if (fileOffset.HighPart < 0) {
  307. if (eventObject) {
  308. ObDereferenceObject( eventObject );
  309. }
  310. IopReleaseFileObjectLock( fileObject );
  311. ObDereferenceObject( fileObject );
  312. return STATUS_INVALID_PARAMETER;
  313. }
  314. if (fastIoDispatch->FastIoRead( fileObject,
  315. &fileOffset,
  316. Length,
  317. TRUE,
  318. keyValue,
  319. Buffer,
  320. &localIoStatus,
  321. deviceObject )
  322. &&
  323. ((localIoStatus.Status == STATUS_SUCCESS) ||
  324. (localIoStatus.Status == STATUS_BUFFER_OVERFLOW) ||
  325. (localIoStatus.Status == STATUS_END_OF_FILE))) {
  326. //
  327. // Boost the priority of the current thread so that it appears
  328. // as if it just did I/O. This causes background jobs that
  329. // get cache hits to be more responsive in terms of getting
  330. // more CPU time.
  331. //
  332. if (IopCacheHitIncrement) {
  333. KeBoostPriorityThread( &CurrentThread->Tcb,
  334. IopCacheHitIncrement );
  335. }
  336. //
  337. // Carefully return the I/O status.
  338. //
  339. IopUpdateReadOperationCount( );
  340. IopUpdateReadTransferCount( (ULONG)localIoStatus.Information );
  341. try {
  342. *IoStatusBlock = localIoStatus;
  343. } except( EXCEPTION_EXECUTE_HANDLER ) {
  344. localIoStatus.Status = GetExceptionCode();
  345. localIoStatus.Information = 0;
  346. }
  347. //
  348. // If an event was specified, set it.
  349. //
  350. if (ARGUMENT_PRESENT( Event )) {
  351. KeSetEvent( eventObject, 0, FALSE );
  352. ObDereferenceObject( eventObject );
  353. }
  354. //
  355. // Note that the file object event need not be set to the
  356. // Signaled state, as it is already set.
  357. //
  358. //
  359. // Cleanup and return.
  360. //
  361. IopReleaseFileObjectLock( fileObject );
  362. ObDereferenceObject( fileObject );
  363. return localIoStatus.Status;
  364. }
  365. }
  366. synchronousIo = TRUE;
  367. } else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) {
  368. //
  369. // The file is not open for synchronous I/O operations, but the
  370. // caller did not specify a ByteOffset parameter.
  371. //
  372. if (eventObject) {
  373. ObDereferenceObject( eventObject );
  374. }
  375. ObDereferenceObject( fileObject );
  376. return STATUS_INVALID_PARAMETER;
  377. } else {
  378. synchronousIo = FALSE;
  379. }
  380. //
  381. // Negative file offsets are illegal.
  382. //
  383. if (fileOffset.HighPart < 0) {
  384. if (eventObject) {
  385. ObDereferenceObject( eventObject );
  386. }
  387. if (synchronousIo) {
  388. IopReleaseFileObjectLock( fileObject );
  389. }
  390. ObDereferenceObject( fileObject );
  391. return STATUS_INVALID_PARAMETER;
  392. }
  393. //
  394. // Set the file object to the Not-Signaled state.
  395. //
  396. KeClearEvent( &fileObject->Event );
  397. //
  398. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  399. // The allocation is performed with an exception handler in case the
  400. // caller does not have enough quota to allocate the packet.
  401. irp = IopAllocateIrp( deviceObject->StackSize, TRUE );
  402. if (!irp) {
  403. //
  404. // An IRP could not be allocated. Cleanup and return an appropriate
  405. // error status code.
  406. //
  407. IopAllocateIrpCleanup( fileObject, eventObject );
  408. return STATUS_INSUFFICIENT_RESOURCES;
  409. }
  410. irp->Tail.Overlay.OriginalFileObject = fileObject;
  411. irp->Tail.Overlay.Thread = CurrentThread;
  412. irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL;
  413. irp->RequestorMode = requestorMode;
  414. irp->PendingReturned = FALSE;
  415. irp->Cancel = FALSE;
  416. irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
  417. //
  418. // Fill in the service independent parameters in the IRP.
  419. //
  420. irp->UserEvent = eventObject;
  421. irp->UserIosb = IoStatusBlock;
  422. irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
  423. irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
  424. //
  425. // Get a pointer to the stack location for the first driver. This will be
  426. // used to pass the original function codes and parameters. Note that
  427. // setting the major function here also sets:
  428. //
  429. // MinorFunction = 0;
  430. // Flags = 0;
  431. // Control = 0;
  432. //
  433. irpSp = IoGetNextIrpStackLocation( irp );
  434. majorFunction = (PULONG) (&irpSp->MajorFunction);
  435. *majorFunction = IRP_MJ_READ;
  436. irpSp->FileObject = fileObject;
  437. //
  438. // Now determine whether this device expects to have data buffered to it
  439. // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO
  440. // flag in the device object. If the flag is set, then a system buffer is
  441. // allocated and the driver's data will be copied into it. Otherwise, a
  442. // Memory Descriptor List (MDL) is allocated and the caller's buffer is
  443. // locked down using it.
  444. //
  445. irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
  446. irp->MdlAddress = (PMDL) NULL;
  447. if (deviceObject->Flags & DO_BUFFERED_IO) {
  448. //
  449. // The device does not support direct I/O. Allocate a system buffer
  450. // and specify that it should be deallocated on completion. Also
  451. // indicate that this is an input operation so the data will be copied
  452. // into the caller's buffer. This is done using an exception handler
  453. // that will perform cleanup if the operation fails. Note that this
  454. // is only done if the operation has a non-zero length.
  455. //
  456. if (Length) {
  457. try {
  458. //
  459. // Allocate the intermediary system buffer from nonpaged pool
  460. // and charge quota for it.
  461. //
  462. irp->AssociatedIrp.SystemBuffer =
  463. ExAllocatePoolWithQuota( NonPagedPoolCacheAligned, Length );
  464. } except(EXCEPTION_EXECUTE_HANDLER) {
  465. //
  466. // An exception was incurred while either probing the caller's
  467. // buffer or allocating the system buffer. Determine what
  468. // actually happened, clean everything up, and return an
  469. // appropriate error status code.
  470. //
  471. IopExceptionCleanup( fileObject,
  472. irp,
  473. eventObject,
  474. (PKEVENT) NULL );
  475. return GetExceptionCode();
  476. }
  477. //
  478. // Remember the address of the caller's buffer so the copy can take
  479. // place during I/O completion. Also, set the flags so that the
  480. // completion code knows to do the copy and to deallocate the buffer.
  481. //
  482. irp->UserBuffer = Buffer;
  483. irp->Flags = IRP_BUFFERED_IO |
  484. IRP_DEALLOCATE_BUFFER |
  485. IRP_INPUT_OPERATION;
  486. } else {
  487. //
  488. // This is a zero-length read. Simply indicate that this is
  489. // buffered I/O, and pass along the request. The buffer will
  490. // not be set to deallocate so the completion path does not
  491. // have to special-case the length.
  492. //
  493. irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
  494. }
  495. } else if (deviceObject->Flags & DO_DIRECT_IO) {
  496. //
  497. // This is a direct I/O operation. Allocate an MDL and invoke the
  498. // memory management routine to lock the buffer into memory. This
  499. // is done using an exception handler that will perform cleanup if
  500. // the operation fails. Note that no MDL is allocated, nor is any
  501. // memory probed or locked if the length of the request was zero.
  502. //
  503. PMDL mdl;
  504. irp->Flags = 0;
  505. if (Length) {
  506. try {
  507. //
  508. // Allocate an MDL, charging quota for it, and hang it off of
  509. // the IRP. Probe and lock the pages associated with the
  510. // caller's buffer for write access and fill in the MDL with
  511. // the PFNs of those pages.
  512. //
  513. mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp );
  514. if (mdl == NULL) {
  515. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  516. }
  517. MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess );
  518. } except(EXCEPTION_EXECUTE_HANDLER) {
  519. //
  520. // An exception was incurred while either probing the caller's
  521. // buffer or allocating the MDL. Determine what actually
  522. // happened, clean everything up, and return an appropriate
  523. // error status code.
  524. //
  525. IopExceptionCleanup( fileObject,
  526. irp,
  527. eventObject,
  528. (PKEVENT) NULL );
  529. return GetExceptionCode();
  530. }
  531. }
  532. } else {
  533. //
  534. // Pass the address of the user's buffer so the driver has access to
  535. // it. It is now the driver's responsibility to do everything.
  536. //
  537. irp->Flags = 0;
  538. irp->UserBuffer = Buffer;
  539. }
  540. //
  541. // If this read operation is supposed to be performed with caching disabled
  542. // set the disable flag in the IRP so no caching is performed.
  543. //
  544. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  545. irp->Flags |= IRP_NOCACHE | IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
  546. } else {
  547. irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
  548. }
  549. //
  550. // Copy the caller's parameters to the service-specific portion of the
  551. // IRP.
  552. //
  553. irpSp->Parameters.Read.Length = Length;
  554. irpSp->Parameters.Read.Key = keyValue;
  555. irpSp->Parameters.Read.ByteOffset = fileOffset;
  556. //
  557. // Queue the packet, call the driver, and synchronize appopriately with
  558. // I/O completion.
  559. //
  560. status = IopSynchronousServiceTail( deviceObject,
  561. irp,
  562. fileObject,
  563. TRUE,
  564. requestorMode,
  565. synchronousIo,
  566. ReadTransfer );
  567. return status;
  568. }
  569. NTSTATUS
  570. NtReadFileScatter(
  571. IN HANDLE FileHandle,
  572. IN HANDLE Event OPTIONAL,
  573. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  574. IN PVOID ApcContext OPTIONAL,
  575. OUT PIO_STATUS_BLOCK IoStatusBlock,
  576. IN PFILE_SEGMENT_ELEMENT SegmentArray,
  577. IN ULONG Length,
  578. IN PLARGE_INTEGER ByteOffset OPTIONAL,
  579. IN PULONG Key OPTIONAL
  580. )
  581. /*++
  582. Routine Description:
  583. This service reads Length bytes of data from the file associated with
  584. FileHandle starting at ByteOffset and puts the data into the caller's
  585. buffer segments. The buffer segments are not virtually contiguous,
  586. but are 8 KB in length and alignment. If the end of the file is reached
  587. before Length bytes have been read, then the operation will terminate.
  588. The actual length of the data read from the file will be returned in
  589. the second longword of the IoStatusBlock.
  590. Arguments:
  591. FileHandle - Supplies a handle to the file to be read.
  592. Event - Unused the I/O must use a completion port.
  593. ApcRoutine - Optionally supplies an APC routine to be executed when the read
  594. operation is complete.
  595. ApcContext - Supplies a context parameter to be passed to the ApcRoutine, if
  596. an ApcRoutine was specified.
  597. IoStatusBlock - Address of the caller's I/O status block.
  598. SegmentArray - An array of buffer segment pointers that specify
  599. where the data should be placed.
  600. Length - Supplies the length, in bytes, of the data to read from the file.
  601. ByteOffset - Optionally specifies the starting byte offset within the file
  602. to begin the read operation. If not specified and the file is open
  603. for synchronous I/O, then the current file position is used. If the
  604. file is not opened for synchronous I/O and the parameter is not
  605. specified, then it is an error.
  606. Key - Unused.
  607. Return Value:
  608. The status returned is success if the read operation was properly queued
  609. to the I/O system. Once the read completes the status of the operation
  610. can be determined by examining the Status field of the I/O status block.
  611. Notes:
  612. This interface is only supported for no buffering and asynchronous I/O.
  613. --*/
  614. {
  615. PIRP irp;
  616. NTSTATUS status;
  617. PFILE_OBJECT fileObject;
  618. PDEVICE_OBJECT deviceObject;
  619. PFAST_IO_DISPATCH fastIoDispatch;
  620. PFILE_SEGMENT_ELEMENT capturedArray = NULL;
  621. KPROCESSOR_MODE requestorMode;
  622. PIO_STACK_LOCATION irpSp;
  623. NTSTATUS exceptionCode;
  624. PKEVENT eventObject = (PKEVENT) NULL;
  625. ULONG keyValue = 0;
  626. ULONG elementCount;
  627. LARGE_INTEGER fileOffset = {0,0};
  628. PULONG majorFunction;
  629. ULONG i;
  630. BOOLEAN synchronousIo;
  631. PETHREAD CurrentThread;
  632. PAGED_CODE();
  633. //
  634. // Get the previous mode; i.e., the mode of the caller.
  635. //
  636. CurrentThread = PsGetCurrentThread ();
  637. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  638. //
  639. // Reference the file object so the target device can be found. Note
  640. // that if the caller does not have read access to the file, the operation
  641. // will fail.
  642. //
  643. status = ObReferenceObjectByHandle( FileHandle,
  644. FILE_READ_DATA,
  645. IoFileObjectType,
  646. requestorMode,
  647. (PVOID *) &fileObject,
  648. NULL );
  649. if (!NT_SUCCESS( status )) {
  650. return status;
  651. }
  652. //
  653. // Get the address of the target device object.
  654. //
  655. deviceObject = IoGetRelatedDeviceObject( fileObject );
  656. //
  657. // Verify this is a valid scatter read request. In particular it must be
  658. // non cached, asynchronous, use completion ports, non buffer I/O device
  659. // and directed at a file system device.
  660. //
  661. if (!(fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) ||
  662. (fileObject->Flags & FO_SYNCHRONOUS_IO) ||
  663. deviceObject->Flags & DO_BUFFERED_IO ||
  664. (deviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
  665. deviceObject->DeviceType != FILE_DEVICE_DFS &&
  666. deviceObject->DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM &&
  667. deviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
  668. deviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM &&
  669. deviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM &&
  670. deviceObject->DeviceType != FILE_DEVICE_DFS_VOLUME )) {
  671. ObDereferenceObject( fileObject );
  672. return STATUS_INVALID_PARAMETER;
  673. }
  674. elementCount = BYTES_TO_PAGES(Length);
  675. if (requestorMode != KernelMode) {
  676. //
  677. // The caller's access mode is not kernel so probe each of the arguments
  678. // and capture them as necessary. If any failures occur, the condition
  679. // handler will be invoked to handle them. It will simply cleanup and
  680. // return an access violation status code back to the system service
  681. // dispatcher.
  682. //
  683. try {
  684. //
  685. // The IoStatusBlock parameter must be writeable by the caller.
  686. //
  687. ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine);
  688. //
  689. // If this file has an I/O completion port associated w/it, then
  690. // ensure that the caller did not supply an APC routine, as the
  691. // two are mutually exclusive methods for I/O completion
  692. // notification.
  693. //
  694. if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
  695. ObDereferenceObject( fileObject );
  696. return STATUS_INVALID_PARAMETER;
  697. }
  698. //
  699. // Also ensure that the ByteOffset parameter is readable from
  700. // the caller's mode and capture it if it is present.
  701. //
  702. if (ARGUMENT_PRESENT( ByteOffset )) {
  703. ProbeForReadSmallStructure( ByteOffset,
  704. sizeof( LARGE_INTEGER ),
  705. sizeof( ULONG ) );
  706. fileOffset = *ByteOffset;
  707. }
  708. //
  709. // Check to see whether the caller has opened the file without
  710. // intermediate buffering. If so, perform the following ByteOffset
  711. // parameter check differently.
  712. //
  713. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  714. //
  715. // The file was opened without intermediate buffering enabled.
  716. // Check that the Buffer is properly aligned, and that the
  717. // length is an integral number of 512-byte blocks.
  718. //
  719. if ((deviceObject->SectorSize &&
  720. (Length & (deviceObject->SectorSize - 1)))) {
  721. //
  722. // Check for sector sizes that are not a power of two.
  723. //
  724. if ((deviceObject->SectorSize &&
  725. Length % deviceObject->SectorSize)) {
  726. ObDereferenceObject( fileObject );
  727. return STATUS_INVALID_PARAMETER;
  728. }
  729. }
  730. //
  731. // If a ByteOffset parameter was specified, ensure that it
  732. // is a valid argument.
  733. //
  734. if (ARGUMENT_PRESENT( ByteOffset )) {
  735. if (deviceObject->SectorSize &&
  736. (fileOffset.LowPart & (deviceObject->SectorSize - 1))) {
  737. ObDereferenceObject( fileObject );
  738. return STATUS_INVALID_PARAMETER;
  739. }
  740. }
  741. }
  742. //
  743. // The SegmentArray paramter must be accessible.
  744. //
  745. #ifdef _X86_
  746. ProbeForRead( SegmentArray,
  747. elementCount * sizeof( FILE_SEGMENT_ELEMENT ),
  748. sizeof( ULONG )
  749. );
  750. #elif defined(_WIN64)
  751. //
  752. // If we are a wow64 process, follow the X86 rules
  753. //
  754. if (PsGetCurrentProcess()->Wow64Process) {
  755. ProbeForRead( SegmentArray,
  756. elementCount * sizeof( FILE_SEGMENT_ELEMENT ),
  757. sizeof( ULONG )
  758. );
  759. } else {
  760. ProbeForRead( SegmentArray,
  761. elementCount * sizeof( FILE_SEGMENT_ELEMENT ),
  762. TYPE_ALIGNMENT( FILE_SEGMENT_ELEMENT )
  763. );
  764. }
  765. #else
  766. ProbeForRead( SegmentArray,
  767. elementCount * sizeof( FILE_SEGMENT_ELEMENT ),
  768. TYPE_ALIGNMENT( FILE_SEGMENT_ELEMENT )
  769. );
  770. #endif
  771. if (Length != 0) {
  772. //
  773. // Capture the segment array so it cannot be changed after
  774. // it has been looked at.
  775. //
  776. capturedArray = ExAllocatePoolWithQuota( PagedPool,
  777. elementCount * sizeof( FILE_SEGMENT_ELEMENT )
  778. );
  779. RtlCopyMemory( capturedArray,
  780. SegmentArray,
  781. elementCount * sizeof( FILE_SEGMENT_ELEMENT )
  782. );
  783. SegmentArray = capturedArray;
  784. //
  785. // Verify that all the addresses are page aligned.
  786. //
  787. for (i = 0; i < elementCount; i++) {
  788. if ( SegmentArray[i].Alignment & (PAGE_SIZE - 1)) {
  789. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  790. }
  791. }
  792. }
  793. //
  794. // Finally, ensure that if there is a key parameter specified it
  795. // is readable by the caller.
  796. //
  797. if (ARGUMENT_PRESENT( Key )) {
  798. keyValue = ProbeAndReadUlong( Key );
  799. }
  800. } except(IopExceptionFilter( GetExceptionInformation(), &exceptionCode )) {
  801. //
  802. // An exception was incurred while attempting to probe the
  803. // caller's parameters. Dereference the file object and return
  804. // an appropriate error status code.
  805. //
  806. ObDereferenceObject( fileObject );
  807. if (capturedArray != NULL) {
  808. ExFreePool( capturedArray );
  809. }
  810. return exceptionCode;
  811. }
  812. } else {
  813. //
  814. // The caller's mode is kernel. Get the same parameters that are
  815. // required from any other mode.
  816. //
  817. if (ARGUMENT_PRESENT( ByteOffset )) {
  818. fileOffset = *ByteOffset;
  819. }
  820. if (ARGUMENT_PRESENT( Key )) {
  821. keyValue = *Key;
  822. }
  823. #if DBG
  824. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  825. //
  826. // The file was opened without intermediate buffering enabled.
  827. // Check that the the length is an integral number of the block
  828. // size.
  829. //
  830. if ((deviceObject->SectorSize &&
  831. (Length & (deviceObject->SectorSize - 1)))) {
  832. //
  833. // Check for sector sizes that are not a power of two.
  834. //
  835. if ((deviceObject->SectorSize &&
  836. Length % deviceObject->SectorSize)) {
  837. ObDereferenceObject( fileObject );
  838. ASSERT( FALSE );
  839. return STATUS_INVALID_PARAMETER;
  840. }
  841. }
  842. //
  843. // If a ByteOffset parameter was specified, ensure that it
  844. // is a valid argument.
  845. //
  846. if (ARGUMENT_PRESENT( ByteOffset )) {
  847. if (deviceObject->SectorSize &&
  848. (fileOffset.LowPart & (deviceObject->SectorSize - 1))) {
  849. ObDereferenceObject( fileObject );
  850. ASSERT( FALSE );
  851. return STATUS_INVALID_PARAMETER;
  852. }
  853. }
  854. }
  855. if (Length != 0) {
  856. //
  857. // Verify that all the addresses are page aligned.
  858. //
  859. for (i = 0; i < elementCount; i++) {
  860. if ( SegmentArray[i].Alignment & (PAGE_SIZE - 1)) {
  861. ObDereferenceObject( fileObject );
  862. ASSERT(FALSE);
  863. return STATUS_INVALID_PARAMETER;
  864. }
  865. }
  866. }
  867. #endif // DBG
  868. }
  869. //
  870. // Get the address of the event object and set the event to the Not-
  871. // Signaled state, if an one was specified. Note here too, that if
  872. // the handle does not refer to an event, then the reference will fail.
  873. //
  874. if (ARGUMENT_PRESENT( Event )) {
  875. status = ObReferenceObjectByHandle( Event,
  876. EVENT_MODIFY_STATE,
  877. ExEventObjectType,
  878. requestorMode,
  879. (PVOID *) &eventObject,
  880. NULL );
  881. if (!NT_SUCCESS( status )) {
  882. ObDereferenceObject( fileObject );
  883. if (capturedArray != NULL) {
  884. ExFreePool( capturedArray );
  885. }
  886. return status;
  887. } else {
  888. KeClearEvent( eventObject );
  889. }
  890. }
  891. //
  892. // Get the address of the driver object's Fast I/O dispatch structure.
  893. //
  894. fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  895. //
  896. // Make a special check here to determine whether this is a synchronous
  897. // I/O operation. If it is, then wait here until the file is owned by
  898. // the current thread.
  899. //
  900. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  901. BOOLEAN interrupted;
  902. if (!IopAcquireFastLock( fileObject )) {
  903. status = IopAcquireFileObjectLock( fileObject,
  904. requestorMode,
  905. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  906. &interrupted );
  907. if (interrupted) {
  908. if (eventObject) {
  909. ObDereferenceObject( eventObject );
  910. }
  911. ObDereferenceObject( fileObject );
  912. if (capturedArray != NULL) {
  913. ExFreePool( capturedArray );
  914. }
  915. return status;
  916. }
  917. }
  918. if (!ARGUMENT_PRESENT( ByteOffset ) ||
  919. (fileOffset.LowPart == FILE_USE_FILE_POINTER_POSITION &&
  920. fileOffset.HighPart == -1)) {
  921. fileOffset = fileObject->CurrentByteOffset;
  922. }
  923. synchronousIo = TRUE;
  924. } else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) {
  925. //
  926. // The file is not open for synchronous I/O operations, but the
  927. // caller did not specify a ByteOffset parameter.
  928. //
  929. if (eventObject) {
  930. ObDereferenceObject( eventObject );
  931. }
  932. ObDereferenceObject( fileObject );
  933. if (capturedArray != NULL) {
  934. ExFreePool( capturedArray );
  935. }
  936. return STATUS_INVALID_PARAMETER;
  937. } else {
  938. synchronousIo = FALSE;
  939. }
  940. //
  941. // Negative file offsets are illegal.
  942. //
  943. if (fileOffset.HighPart < 0) {
  944. if (eventObject) {
  945. ObDereferenceObject( eventObject );
  946. }
  947. if (synchronousIo) {
  948. IopReleaseFileObjectLock( fileObject );
  949. }
  950. ObDereferenceObject( fileObject );
  951. if (capturedArray != NULL) {
  952. ExFreePool( capturedArray );
  953. }
  954. return STATUS_INVALID_PARAMETER;
  955. }
  956. //
  957. // Set the file object to the Not-Signaled state.
  958. //
  959. KeClearEvent( &fileObject->Event );
  960. //
  961. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  962. // The allocation is performed with an exception handler in case the
  963. // caller does not have enough quota to allocate the packet.
  964. irp = IopAllocateIrp( deviceObject->StackSize, TRUE );
  965. if (!irp) {
  966. //
  967. // An IRP could not be allocated. Cleanup and return an appropriate
  968. // error status code.
  969. //
  970. IopAllocateIrpCleanup( fileObject, eventObject );
  971. if (capturedArray != NULL) {
  972. ExFreePool( capturedArray );
  973. }
  974. return STATUS_INSUFFICIENT_RESOURCES;
  975. }
  976. irp->Tail.Overlay.OriginalFileObject = fileObject;
  977. irp->Tail.Overlay.Thread = CurrentThread;
  978. irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL;
  979. irp->RequestorMode = requestorMode;
  980. irp->PendingReturned = FALSE;
  981. irp->Cancel = FALSE;
  982. irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
  983. //
  984. // Fill in the service independent parameters in the IRP.
  985. //
  986. irp->UserEvent = eventObject;
  987. irp->UserIosb = IoStatusBlock;
  988. irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
  989. irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
  990. //
  991. // Get a pointer to the stack location for the first driver. This will be
  992. // used to pass the original function codes and parameters. Note that
  993. // setting the major function here also sets:
  994. //
  995. // MinorFunction = 0;
  996. // Flags = 0;
  997. // Control = 0;
  998. //
  999. irpSp = IoGetNextIrpStackLocation( irp );
  1000. majorFunction = (PULONG) (&irpSp->MajorFunction);
  1001. *majorFunction = IRP_MJ_READ;
  1002. irpSp->FileObject = fileObject;
  1003. //
  1004. // Always allocate a Memory Descriptor List (MDL) and lock down the
  1005. // caller's buffer. This way the file system do not have change to
  1006. // build a scatter MDL. Note buffered I/O is not supported for this
  1007. // routine.
  1008. //
  1009. irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
  1010. irp->MdlAddress = (PMDL) NULL;
  1011. //
  1012. // This is a direct I/O operation. Allocate an MDL and invoke the
  1013. // memory management routine to lock the buffer into memory. This
  1014. // is done using an exception handler that will perform cleanup if
  1015. // the operation fails. Note that no MDL is allocated, nor is any
  1016. // memory probed or locked if the length of the request was zero.
  1017. //
  1018. irp->Flags = 0;
  1019. if (Length) {
  1020. PMDL mdl;
  1021. try {
  1022. //
  1023. // Allocate an MDL, charging quota for it, and hang it off of
  1024. // the IRP. Probe and lock the pages associated with the
  1025. // caller's buffer for write access and fill in the MDL with
  1026. // the PFNs of those pages.
  1027. //
  1028. mdl = IoAllocateMdl( (PVOID)(ULONG_PTR) SegmentArray[0].Buffer, Length, FALSE, TRUE, irp );
  1029. if (mdl == NULL) {
  1030. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  1031. }
  1032. //
  1033. // The address of the first file segment is used as a base
  1034. // address.
  1035. //
  1036. MmProbeAndLockSelectedPages( mdl,
  1037. SegmentArray,
  1038. requestorMode,
  1039. IoWriteAccess );
  1040. irp->UserBuffer = (PVOID)(ULONG_PTR) SegmentArray[0].Buffer;
  1041. } except(EXCEPTION_EXECUTE_HANDLER) {
  1042. //
  1043. // An exception was incurred while either probing the caller's
  1044. // buffer or allocating the MDL. Determine what actually
  1045. // happened, clean everything up, and return an appropriate
  1046. // error status code.
  1047. //
  1048. IopExceptionCleanup( fileObject,
  1049. irp,
  1050. eventObject,
  1051. (PKEVENT) NULL );
  1052. if (capturedArray != NULL) {
  1053. ExFreePool( capturedArray );
  1054. }
  1055. return GetExceptionCode();
  1056. }
  1057. }
  1058. //
  1059. // We are done with the captured buffer.
  1060. //
  1061. if (capturedArray != NULL) {
  1062. ExFreePool( capturedArray );
  1063. }
  1064. //
  1065. // If this read operation is supposed to be performed with caching disabled
  1066. // set the disable flag in the IRP so no caching is performed.
  1067. //
  1068. if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) {
  1069. irp->Flags |= IRP_NOCACHE | IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
  1070. } else {
  1071. irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION;
  1072. }
  1073. //
  1074. // Copy the caller's parameters to the service-specific portion of the
  1075. // IRP.
  1076. //
  1077. irpSp->Parameters.Read.Length = Length;
  1078. irpSp->Parameters.Read.Key = keyValue;
  1079. irpSp->Parameters.Read.ByteOffset = fileOffset;
  1080. //
  1081. // Queue the packet, call the driver, and synchronize appopriately with
  1082. // I/O completion.
  1083. //
  1084. status = IopSynchronousServiceTail( deviceObject,
  1085. irp,
  1086. fileObject,
  1087. TRUE,
  1088. requestorMode,
  1089. synchronousIo,
  1090. ReadTransfer );
  1091. return status;
  1092. }