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.

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