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

read.c File Reference

#include "iop.h"

Go to the source code of this file.

Functions

NTSTATUS NtReadFile (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL)
NTSTATUS NtReadFileScatter (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PFILE_SEGMENT_ELEMENT SegmentArray, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL)

Variables

ULONG IopCacheHitIncrement = 0


Function Documentation

NTSTATUS NtReadFile IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  Buffer,
IN ULONG  Length,
IN PLARGE_INTEGER ByteOffset  OPTIONAL,
IN PULONG Key  OPTIONAL
 

Definition at line 36 of file io/read.c.

References _DEVICE_OBJECT::AlignmentRequirement, ASSERT, _IRP::AssociatedIrp, Buffer, _IRP::Cancel, _IRP::CancelRoutine, DO_BUFFERED_IO, DO_DIRECT_IO, _DEVICE_OBJECT::DriverObject, Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExEventObjectType, ExRaiseStatus(), FALSE, _DRIVER_OBJECT::FastIoDispatch, _FAST_IO_DISPATCH::FastIoRead, _IO_STACK_LOCATION::FileObject, _IRP::Flags, _DEVICE_OBJECT::Flags, FO_ALERTABLE_IO, FO_MAILSLOT, FO_NAMED_PIPE, FO_NO_INTERMEDIATE_BUFFERING, FO_SYNCHRONOUS_IO, IoAllocateMdl(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrp, IopAllocateIrpCleanup(), IopApcRoutinePresent, IopCacheHitIncrement, IopExceptionCleanup(), IopExceptionFilter(), IopReleaseFileObjectLock, IopSynchronousServiceTail(), IopUpdateReadOperationCount(), IopUpdateReadTransferCount(), IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_DEFER_IO_COMPLETION, IRP_INPUT_OPERATION, IRP_MJ_READ, IRP_NOCACHE, IRP_READ_OPERATION, KeBoostPriorityThread(), KeClearEvent, KernelMode, KeSetEvent(), Key, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmProbeAndLockPages(), NonPagedPoolCacheAligned, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, PDRIVER_CANCEL, _IRP::PendingReturned, ProbeAndReadUlong, ProbeForRead, ProbeForWrite(), ProbeForWriteIoStatusEx, PsGetCurrentThread, ReadTransfer, _IRP::RequestorMode, _DEVICE_OBJECT::SectorSize, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by CopyStream(), NTFastDOSIO(), RegLoadAsciiFileAsUnicode(), RegReadBinaryFile(), and SepReadPipe().

00050 : 00051 00052 This service reads Length bytes of data from the file associated with 00053 FileHandle starting at ByteOffset and puts the data into the caller's 00054 Buffer. If the end of the file is reached before Length bytes have 00055 been read, then the operation will terminate. The actual length of 00056 the data read from the file will be returned in the second longword 00057 of the IoStatusBlock. 00058 00059 Arguments: 00060 00061 FileHandle - Supplies a handle to the file to be read. 00062 00063 Event - Optionally supplies an event to be signaled when the read operation 00064 is complete. 00065 00066 ApcRoutine - Optionally supplies an APC routine to be executed when the read 00067 operation is complete. 00068 00069 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, if 00070 an ApcRoutine was specified. 00071 00072 IoStatusBlock - Address of the caller's I/O status block. 00073 00074 Buffer - Address of buffer to receive the data read from the file. 00075 00076 Length - Supplies the length, in bytes, of the data to read from the file. 00077 00078 ByteOffset - Optionally specifies the starting byte offset within the file 00079 to begin the read operation. If not specified and the file is open 00080 for synchronous I/O, then the current file position is used. If the 00081 file is not opened for synchronous I/O and the parameter is not 00082 specified, then it is an error. 00083 00084 Key - Optionally specifies a key to be used if there are locks associated 00085 with the file. 00086 00087 Return Value: 00088 00089 The status returned is success if the read operation was properly queued 00090 to the I/O system. Once the read completes the status of the operation 00091 can be determined by examining the Status field of the I/O status block. 00092 00093 --*/ 00094 00095 { 00096 PIRP irp; 00097 NTSTATUS status; 00098 PFILE_OBJECT fileObject; 00099 PDEVICE_OBJECT deviceObject; 00100 PFAST_IO_DISPATCH fastIoDispatch; 00101 KPROCESSOR_MODE requestorMode; 00102 PIO_STACK_LOCATION irpSp; 00103 NTSTATUS exceptionCode; 00104 BOOLEAN synchronousIo; 00105 PKEVENT eventObject = (PKEVENT) NULL; 00106 ULONG keyValue = 0; 00107 LARGE_INTEGER fileOffset = {0,0}; 00108 PULONG majorFunction; 00109 00110 PAGED_CODE(); 00111 00112 // 00113 // Get the previous mode; i.e., the mode of the caller. 00114 // 00115 00116 requestorMode = KeGetPreviousMode(); 00117 00118 // 00119 // Reference the file object so the target device can be found. Note 00120 // that if the caller does not have read access to the file, the operation 00121 // will fail. 00122 // 00123 00124 status = ObReferenceObjectByHandle( FileHandle, 00125 FILE_READ_DATA, 00126 IoFileObjectType, 00127 requestorMode, 00128 (PVOID *) &fileObject, 00129 NULL ); 00130 if (!NT_SUCCESS( status )) { 00131 return status; 00132 } 00133 00134 // 00135 // Get the address of the target device object. 00136 // 00137 00138 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00139 00140 if (requestorMode != KernelMode) { 00141 00142 // 00143 // The caller's access mode is not kernel so probe each of the arguments 00144 // and capture them as necessary. If any failures occur, the condition 00145 // handler will be invoked to handle them. It will simply cleanup and 00146 // return an access violation status code back to the system service 00147 // dispatcher. 00148 // 00149 00150 try { 00151 00152 // 00153 // The IoStatusBlock parameter must be writeable by the caller. 00154 // 00155 00156 ProbeForWriteIoStatusEx(IoStatusBlock , ApcRoutine); 00157 00158 // 00159 // The caller's data buffer must be writable from the caller's 00160 // mode. This check ensures that this is the case. Since the 00161 // buffer address is captured, the caller cannot change it, 00162 // even though he/she can change the protection from another 00163 // thread. This error will be caught by the probe/lock or 00164 // buffer copy operations later. 00165 // 00166 00167 ProbeForWrite( Buffer, Length, sizeof( UCHAR ) ); 00168 00169 // 00170 // If this file has an I/O completion port associated w/it, then 00171 // ensure that the caller did not supply an APC routine, as the 00172 // two are mutually exclusive methods for I/O completion 00173 // notification. 00174 // 00175 00176 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 00177 ObDereferenceObject( fileObject ); 00178 return STATUS_INVALID_PARAMETER; 00179 } 00180 00181 // 00182 // Also ensure that the ByteOffset parameter is readable from 00183 // the caller's mode and capture it if it is present. 00184 // 00185 00186 if (ARGUMENT_PRESENT( ByteOffset )) { 00187 ProbeForRead( ByteOffset, 00188 sizeof( LARGE_INTEGER ), 00189 sizeof( ULONG ) ); 00190 fileOffset = *ByteOffset; 00191 } 00192 00193 // 00194 // Check to see whether the caller has opened the file without 00195 // intermediate buffering. If so, perform the following Buffer 00196 // and ByteOffset parameter checks differently. 00197 // 00198 00199 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 00200 00201 // 00202 // The file was opened without intermediate buffering enabled. 00203 // Check that the Buffer is properly aligned, and that the 00204 // length is an integral number of 512-byte blocks. 00205 // 00206 00207 if ((deviceObject->SectorSize && 00208 (Length & (deviceObject->SectorSize - 1))) || 00209 (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) { 00210 00211 // 00212 // Check for sector sizes that are not a power of two. 00213 // 00214 00215 if ((deviceObject->SectorSize && 00216 Length % deviceObject->SectorSize) || 00217 (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) { 00218 ObDereferenceObject( fileObject ); 00219 return STATUS_INVALID_PARAMETER; 00220 } 00221 } 00222 00223 // 00224 // If a ByteOffset parameter was specified, ensure that it 00225 // is a valid argument. 00226 // 00227 00228 if (ARGUMENT_PRESENT( ByteOffset )) { 00229 if (deviceObject->SectorSize && 00230 (fileOffset.LowPart & (deviceObject->SectorSize - 1))) { 00231 ObDereferenceObject( fileObject ); 00232 return STATUS_INVALID_PARAMETER; 00233 } 00234 } 00235 } 00236 00237 // 00238 // Finally, ensure that if there is a key parameter specified it 00239 // is readable by the caller. 00240 // 00241 00242 if (ARGUMENT_PRESENT( Key )) { 00243 keyValue = ProbeAndReadUlong( Key ); 00244 } 00245 00246 } except(IopExceptionFilter( GetExceptionInformation(), &exceptionCode )) { 00247 00248 // 00249 // An exception was incurred while attempting to probe the 00250 // caller's parameters. Dereference the file object and return 00251 // an appropriate error status code. 00252 // 00253 00254 ObDereferenceObject( fileObject ); 00255 return exceptionCode; 00256 00257 } 00258 00259 } else { 00260 00261 // 00262 // The caller's mode is kernel. Get the same parameters that are 00263 // required from any other mode. 00264 // 00265 00266 if (ARGUMENT_PRESENT( ByteOffset )) { 00267 fileOffset = *ByteOffset; 00268 } 00269 00270 if (ARGUMENT_PRESENT( Key )) { 00271 keyValue = *Key; 00272 } 00273 00274 #if DBG 00275 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 00276 00277 // 00278 // The file was opened without intermediate buffering enabled. 00279 // Check that the Buffer is properly aligned, and that the 00280 // length is an integral number of the block size. 00281 // 00282 00283 if ((deviceObject->SectorSize && 00284 (Length & (deviceObject->SectorSize - 1))) || 00285 (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) { 00286 00287 // 00288 // Check for sector sizes that are not a power of two. 00289 // 00290 00291 if ((deviceObject->SectorSize && 00292 Length % deviceObject->SectorSize) || 00293 (ULONG_PTR) Buffer & deviceObject->AlignmentRequirement) { 00294 ObDereferenceObject( fileObject ); 00295 ASSERT( FALSE ); 00296 return STATUS_INVALID_PARAMETER; 00297 } 00298 } 00299 00300 // 00301 // If a ByteOffset parameter was specified, ensure that it 00302 // is a valid argument. 00303 // 00304 00305 if (ARGUMENT_PRESENT( ByteOffset )) { 00306 if (deviceObject->SectorSize && 00307 (fileOffset.LowPart & (deviceObject->SectorSize - 1))) { 00308 ObDereferenceObject( fileObject ); 00309 ASSERT( FALSE ); 00310 return STATUS_INVALID_PARAMETER; 00311 } 00312 } 00313 } 00314 #endif // DBG 00315 } 00316 00317 // 00318 // Get the address of the event object and set the event to the Not- 00319 // Signaled state, if an one was specified. Note here too, that if 00320 // the handle does not refer to an event, then the reference will fail. 00321 // 00322 00323 if (ARGUMENT_PRESENT( Event )) { 00324 status = ObReferenceObjectByHandle( Event, 00325 EVENT_MODIFY_STATE, 00326 ExEventObjectType, 00327 requestorMode, 00328 (PVOID *) &eventObject, 00329 NULL ); 00330 if (!NT_SUCCESS( status )) { 00331 ObDereferenceObject( fileObject ); 00332 return status; 00333 } else { 00334 KeClearEvent( eventObject ); 00335 } 00336 } 00337 00338 // 00339 // Get the address of the driver object's Fast I/O dispatch structure. 00340 // 00341 00342 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 00343 00344 // 00345 // Make a special check here to determine whether this is a synchronous 00346 // I/O operation. If it is, then wait here until the file is owned by 00347 // the current thread. 00348 // 00349 00350 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00351 00352 BOOLEAN interrupted; 00353 00354 if (!IopAcquireFastLock( fileObject )) { 00355 status = IopAcquireFileObjectLock( fileObject, 00356 requestorMode, 00357 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00358 &interrupted ); 00359 if (interrupted) { 00360 if (eventObject) { 00361 ObDereferenceObject( eventObject ); 00362 } 00363 ObDereferenceObject( fileObject ); 00364 return status; 00365 } 00366 } 00367 00368 if (!ARGUMENT_PRESENT( ByteOffset ) || 00369 (fileOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && 00370 fileOffset.HighPart == -1)) { 00371 fileOffset = fileObject->CurrentByteOffset; 00372 } 00373 00374 // 00375 // Turbo read support. If the file is currently cached on this 00376 // file object, then call the Cache Manager directly via FastIoRead 00377 // and try to successfully complete the request here. Note if 00378 // FastIoRead returns FALSE or we get an I/O error, we simply 00379 // fall through and go the "long way" and create an Irp. 00380 // 00381 00382 if (fileObject->PrivateCacheMap) { 00383 00384 IO_STATUS_BLOCK localIoStatus; 00385 00386 ASSERT(fastIoDispatch && fastIoDispatch->FastIoRead); 00387 00388 // 00389 // Negative file offsets are illegal. 00390 // 00391 00392 if (fileOffset.HighPart < 0) { 00393 if (eventObject) { 00394 ObDereferenceObject( eventObject ); 00395 } 00396 IopReleaseFileObjectLock( fileObject ); 00397 ObDereferenceObject( fileObject ); 00398 return STATUS_INVALID_PARAMETER; 00399 } 00400 00401 if (fastIoDispatch->FastIoRead( fileObject, 00402 &fileOffset, 00403 Length, 00404 TRUE, 00405 keyValue, 00406 Buffer, 00407 &localIoStatus, 00408 deviceObject ) 00409 00410 && 00411 00412 ((localIoStatus.Status == STATUS_SUCCESS) || 00413 (localIoStatus.Status == STATUS_BUFFER_OVERFLOW) || 00414 (localIoStatus.Status == STATUS_END_OF_FILE))) { 00415 00416 // 00417 // Boost the priority of the current thread so that it appears 00418 // as if it just did I/O. This causes background jobs that 00419 // get cache hits to be more responsive in terms of getting 00420 // more CPU time. 00421 // 00422 00423 if (IopCacheHitIncrement) { 00424 KeBoostPriorityThread( &PsGetCurrentThread()->Tcb, 00425 (KPRIORITY) IopCacheHitIncrement ); 00426 } 00427 00428 // 00429 // Carefully return the I/O status. 00430 // 00431 00432 IopUpdateReadOperationCount( ); 00433 IopUpdateReadTransferCount( (ULONG)localIoStatus.Information ); 00434 00435 try { 00436 *IoStatusBlock = localIoStatus; 00437 } except( EXCEPTION_EXECUTE_HANDLER ) { 00438 localIoStatus.Status = GetExceptionCode(); 00439 localIoStatus.Information = 0; 00440 } 00441 00442 // 00443 // If an event was specified, set it. 00444 // 00445 00446 if (ARGUMENT_PRESENT( Event )) { 00447 KeSetEvent( eventObject, 0, FALSE ); 00448 ObDereferenceObject( eventObject ); 00449 } 00450 00451 // 00452 // Note that the file object event need not be set to the 00453 // Signaled state, as it is already set. 00454 // 00455 00456 // 00457 // Cleanup and return. 00458 // 00459 00460 IopReleaseFileObjectLock( fileObject ); 00461 ObDereferenceObject( fileObject ); 00462 00463 return localIoStatus.Status; 00464 } 00465 } 00466 synchronousIo = TRUE; 00467 00468 } else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) { 00469 00470 // 00471 // The file is not open for synchronous I/O operations, but the 00472 // caller did not specify a ByteOffset parameter. 00473 // 00474 00475 if (eventObject) { 00476 ObDereferenceObject( eventObject ); 00477 } 00478 ObDereferenceObject( fileObject ); 00479 return STATUS_INVALID_PARAMETER; 00480 } else { 00481 synchronousIo = FALSE; 00482 } 00483 00484 // 00485 // Negative file offsets are illegal. 00486 // 00487 00488 if (fileOffset.HighPart < 0) { 00489 if (eventObject) { 00490 ObDereferenceObject( eventObject ); 00491 } 00492 if (synchronousIo) { 00493 IopReleaseFileObjectLock( fileObject ); 00494 } 00495 ObDereferenceObject( fileObject ); 00496 return STATUS_INVALID_PARAMETER; 00497 } 00498 00499 // 00500 // Set the file object to the Not-Signaled state. 00501 // 00502 00503 KeClearEvent( &fileObject->Event ); 00504 00505 // 00506 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00507 // The allocation is performed with an exception handler in case the 00508 // caller does not have enough quota to allocate the packet. 00509 00510 irp = IopAllocateIrp( deviceObject->StackSize, TRUE ); 00511 if (!irp) { 00512 00513 // 00514 // An IRP could not be allocated. Cleanup and return an appropriate 00515 // error status code. 00516 // 00517 00518 IopAllocateIrpCleanup( fileObject, eventObject ); 00519 00520 return STATUS_INSUFFICIENT_RESOURCES; 00521 } 00522 irp->Tail.Overlay.OriginalFileObject = fileObject; 00523 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00524 irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL; 00525 irp->RequestorMode = requestorMode; 00526 irp->PendingReturned = FALSE; 00527 irp->Cancel = FALSE; 00528 irp->CancelRoutine = (PDRIVER_CANCEL) NULL; 00529 00530 // 00531 // Fill in the service independent parameters in the IRP. 00532 // 00533 00534 irp->UserEvent = eventObject; 00535 irp->UserIosb = IoStatusBlock; 00536 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 00537 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 00538 00539 // 00540 // Get a pointer to the stack location for the first driver. This will be 00541 // used to pass the original function codes and parameters. Note that 00542 // setting the major function here also sets: 00543 // 00544 // MinorFunction = 0; 00545 // Flags = 0; 00546 // Control = 0; 00547 // 00548 00549 irpSp = IoGetNextIrpStackLocation( irp ); 00550 majorFunction = (PULONG) (&irpSp->MajorFunction); 00551 *majorFunction = IRP_MJ_READ; 00552 irpSp->FileObject = fileObject; 00553 00554 // 00555 // Now determine whether this device expects to have data buffered to it 00556 // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO 00557 // flag in the device object. If the flag is set, then a system buffer is 00558 // allocated and the driver's data will be copied into it. Otherwise, a 00559 // Memory Descriptor List (MDL) is allocated and the caller's buffer is 00560 // locked down using it. 00561 // 00562 00563 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 00564 irp->MdlAddress = (PMDL) NULL; 00565 00566 if (deviceObject->Flags & DO_BUFFERED_IO) { 00567 00568 // 00569 // The device does not support direct I/O. Allocate a system buffer 00570 // and specify that it should be deallocated on completion. Also 00571 // indicate that this is an input operation so the data will be copied 00572 // into the caller's buffer. This is done using an exception handler 00573 // that will perform cleanup if the operation fails. Note that this 00574 // is only done if the operation has a non-zero length. 00575 // 00576 00577 if (Length) { 00578 00579 try { 00580 00581 // 00582 // Allocate the intermediary system buffer from nonpaged pool 00583 // and charge quota for it. 00584 // 00585 00586 irp->AssociatedIrp.SystemBuffer = 00587 ExAllocatePoolWithQuota( NonPagedPoolCacheAligned, Length ); 00588 00589 } except(EXCEPTION_EXECUTE_HANDLER) { 00590 00591 // 00592 // An exception was incurred while either probing the caller's 00593 // buffer or allocating the system buffer. Determine what 00594 // actually happened, clean everything up, and return an 00595 // appropriate error status code. 00596 // 00597 00598 IopExceptionCleanup( fileObject, 00599 irp, 00600 eventObject, 00601 (PKEVENT) NULL ); 00602 00603 return GetExceptionCode(); 00604 00605 } 00606 00607 // 00608 // Remember the address of the caller's buffer so the copy can take 00609 // place during I/O completion. Also, set the flags so that the 00610 // completion code knows to do the copy and to deallocate the buffer. 00611 // 00612 00613 irp->UserBuffer = Buffer; 00614 irp->Flags = IRP_BUFFERED_IO | 00615 IRP_DEALLOCATE_BUFFER | 00616 IRP_INPUT_OPERATION; 00617 00618 } else { 00619 00620 // 00621 // This is a zero-length read. Simply indicate that this is 00622 // buffered I/O, and pass along the request. The buffer will 00623 // not be set to deallocate so the completion path does not 00624 // have to special-case the length. 00625 // 00626 00627 irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; 00628 00629 } 00630 00631 } else if (deviceObject->Flags & DO_DIRECT_IO) { 00632 00633 // 00634 // This is a direct I/O operation. Allocate an MDL and invoke the 00635 // memory management routine to lock the buffer into memory. This 00636 // is done using an exception handler that will perform cleanup if 00637 // the operation fails. Note that no MDL is allocated, nor is any 00638 // memory probed or locked if the length of the request was zero. 00639 // 00640 00641 PMDL mdl; 00642 00643 irp->Flags = 0; 00644 00645 if (Length) { 00646 00647 try { 00648 00649 // 00650 // Allocate an MDL, charging quota for it, and hang it off of 00651 // the IRP. Probe and lock the pages associated with the 00652 // caller's buffer for write access and fill in the MDL with 00653 // the PFNs of those pages. 00654 // 00655 00656 mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp ); 00657 if (mdl == NULL) { 00658 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00659 } 00660 MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess ); 00661 00662 } except(EXCEPTION_EXECUTE_HANDLER) { 00663 00664 // 00665 // An exception was incurred while either probing the caller's 00666 // buffer or allocating the MDL. Determine what actually 00667 // happened, clean everything up, and return an appropriate 00668 // error status code. 00669 // 00670 00671 IopExceptionCleanup( fileObject, 00672 irp, 00673 eventObject, 00674 (PKEVENT) NULL ); 00675 00676 return GetExceptionCode(); 00677 00678 } 00679 00680 } 00681 00682 } else { 00683 00684 // 00685 // Pass the address of the user's buffer so the driver has access to 00686 // it. It is now the driver's responsibility to do everything. 00687 // 00688 00689 irp->Flags = 0; 00690 irp->UserBuffer = Buffer; 00691 } 00692 00693 // 00694 // If this read operation is supposed to be performed with caching disabled 00695 // set the disable flag in the IRP so no caching is performed. 00696 // 00697 00698 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 00699 irp->Flags |= IRP_NOCACHE | IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION; 00700 } else { 00701 irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION; 00702 } 00703 00704 // 00705 // Copy the caller's parameters to the service-specific portion of the 00706 // IRP. 00707 // 00708 00709 irpSp->Parameters.Read.Length = Length; 00710 irpSp->Parameters.Read.Key = keyValue; 00711 irpSp->Parameters.Read.ByteOffset = fileOffset; 00712 00713 // 00714 // Queue the packet, call the driver, and synchronize appopriately with 00715 // I/O completion. 00716 // 00717 00718 status = IopSynchronousServiceTail( deviceObject, 00719 irp, 00720 fileObject, 00721 TRUE, 00722 requestorMode, 00723 synchronousIo, 00724 ReadTransfer ); 00725 00726 return status; 00727 }

NTSTATUS NtReadFileScatter IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PFILE_SEGMENT_ELEMENT  SegmentArray,
IN ULONG  Length,
IN PLARGE_INTEGER ByteOffset  OPTIONAL,
IN PULONG Key  OPTIONAL
 

Definition at line 730 of file io/read.c.

References ASSERT, _IRP::AssociatedIrp, Buffer, BYTES_TO_PAGES, _IRP::Cancel, _IRP::CancelRoutine, _DEVICE_OBJECT::DeviceType, DO_BUFFERED_IO, _DEVICE_OBJECT::DriverObject, Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExEventObjectType, ExFreePool(), ExRaiseStatus(), FALSE, _DRIVER_OBJECT::FastIoDispatch, _IO_STACK_LOCATION::FileObject, _IRP::Flags, _DEVICE_OBJECT::Flags, FO_ALERTABLE_IO, FO_MAILSLOT, FO_NAMED_PIPE, FO_NO_INTERMEDIATE_BUFFERING, FO_SYNCHRONOUS_IO, IoAllocateMdl(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrp, IopAllocateIrpCleanup(), IopApcRoutinePresent, IopExceptionCleanup(), IopExceptionFilter(), IopReleaseFileObjectLock, IopSynchronousServiceTail(), IoWriteAccess, IRP_DEFER_IO_COMPLETION, IRP_MJ_READ, IRP_NOCACHE, IRP_READ_OPERATION, KeClearEvent, KernelMode, Key, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, MmProbeAndLockSelectedPages(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _IRP::Overlay, PAGE_SIZE, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, PDRIVER_CANCEL, _IRP::PendingReturned, ProbeAndReadUlong, ProbeForRead, ProbeForWriteIoStatusEx, PsGetCurrentProcess, PsGetCurrentThread, ReadTransfer, _IRP::RequestorMode, _DEVICE_OBJECT::SectorSize, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

00744 : 00745 00746 This service reads Length bytes of data from the file associated with 00747 FileHandle starting at ByteOffset and puts the data into the caller's 00748 buffer segments. The buffer segments are not virtually contiguous, 00749 but are 8 KB in length and alignment. If the end of the file is reached 00750 before Length bytes have been read, then the operation will terminate. 00751 The actual length of the data read from the file will be returned in 00752 the second longword of the IoStatusBlock. 00753 00754 Arguments: 00755 00756 FileHandle - Supplies a handle to the file to be read. 00757 00758 Event - Unused the I/O must use a completion port. 00759 00760 ApcRoutine - Optionally supplies an APC routine to be executed when the read 00761 operation is complete. 00762 00763 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, if 00764 an ApcRoutine was specified. 00765 00766 IoStatusBlock - Address of the caller's I/O status block. 00767 00768 SegmentArray - An array of buffer segment pointers that specify 00769 where the data should be placed. 00770 00771 Length - Supplies the length, in bytes, of the data to read from the file. 00772 00773 ByteOffset - Optionally specifies the starting byte offset within the file 00774 to begin the read operation. If not specified and the file is open 00775 for synchronous I/O, then the current file position is used. If the 00776 file is not opened for synchronous I/O and the parameter is not 00777 specified, then it is an error. 00778 00779 Key - Unused. 00780 00781 Return Value: 00782 00783 The status returned is success if the read operation was properly queued 00784 to the I/O system. Once the read completes the status of the operation 00785 can be determined by examining the Status field of the I/O status block. 00786 00787 Notes: 00788 00789 This interface is only supported for no buffering and asynchronous I/O. 00790 00791 --*/ 00792 00793 { 00794 PIRP irp; 00795 NTSTATUS status; 00796 PFILE_OBJECT fileObject; 00797 PDEVICE_OBJECT deviceObject; 00798 PFAST_IO_DISPATCH fastIoDispatch; 00799 PFILE_SEGMENT_ELEMENT capturedArray = NULL; 00800 KPROCESSOR_MODE requestorMode; 00801 PIO_STACK_LOCATION irpSp; 00802 NTSTATUS exceptionCode; 00803 PKEVENT eventObject = (PKEVENT) NULL; 00804 ULONG keyValue = 0; 00805 ULONG elementCount; 00806 LARGE_INTEGER fileOffset = {0,0}; 00807 PULONG majorFunction; 00808 ULONG i; 00809 BOOLEAN synchronousIo; 00810 00811 PAGED_CODE(); 00812 00813 // 00814 // Get the previous mode; i.e., the mode of the caller. 00815 // 00816 00817 requestorMode = KeGetPreviousMode(); 00818 00819 // 00820 // Reference the file object so the target device can be found. Note 00821 // that if the caller does not have read access to the file, the operation 00822 // will fail. 00823 // 00824 00825 status = ObReferenceObjectByHandle( FileHandle, 00826 FILE_READ_DATA, 00827 IoFileObjectType, 00828 requestorMode, 00829 (PVOID *) &fileObject, 00830 NULL ); 00831 if (!NT_SUCCESS( status )) { 00832 return status; 00833 } 00834 00835 // 00836 // Get the address of the target device object. 00837 // 00838 00839 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00840 00841 // 00842 // Verify this is a valid scatter read request. In particular it must be 00843 // non cached, asynchronous, use completion ports, non buffer I/O device 00844 // and directed at a file system device. 00845 // 00846 00847 if (!(fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) || 00848 (fileObject->Flags & FO_SYNCHRONOUS_IO) || 00849 deviceObject->Flags & DO_BUFFERED_IO || 00850 (deviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM && 00851 deviceObject->DeviceType != FILE_DEVICE_DFS && 00852 deviceObject->DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM && 00853 deviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM && 00854 deviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM && 00855 deviceObject->DeviceType != FILE_DEVICE_FILE_SYSTEM && 00856 deviceObject->DeviceType != FILE_DEVICE_DFS_VOLUME )) { 00857 00858 ObDereferenceObject( fileObject ); 00859 return STATUS_INVALID_PARAMETER; 00860 } 00861 00862 elementCount = BYTES_TO_PAGES(Length); 00863 00864 if (requestorMode != KernelMode) { 00865 00866 // 00867 // The caller's access mode is not kernel so probe each of the arguments 00868 // and capture them as necessary. If any failures occur, the condition 00869 // handler will be invoked to handle them. It will simply cleanup and 00870 // return an access violation status code back to the system service 00871 // dispatcher. 00872 // 00873 00874 try { 00875 00876 // 00877 // The IoStatusBlock parameter must be writeable by the caller. 00878 // 00879 00880 ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine); 00881 00882 // 00883 // If this file has an I/O completion port associated w/it, then 00884 // ensure that the caller did not supply an APC routine, as the 00885 // two are mutually exclusive methods for I/O completion 00886 // notification. 00887 // 00888 00889 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 00890 ObDereferenceObject( fileObject ); 00891 return STATUS_INVALID_PARAMETER; 00892 } 00893 00894 // 00895 // Also ensure that the ByteOffset parameter is readable from 00896 // the caller's mode and capture it if it is present. 00897 // 00898 00899 if (ARGUMENT_PRESENT( ByteOffset )) { 00900 ProbeForRead( ByteOffset, 00901 sizeof( LARGE_INTEGER ), 00902 sizeof( ULONG ) ); 00903 fileOffset = *ByteOffset; 00904 } 00905 00906 // 00907 // Check to see whether the caller has opened the file without 00908 // intermediate buffering. If so, perform the following ByteOffset 00909 // parameter check differently. 00910 // 00911 00912 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 00913 00914 // 00915 // The file was opened without intermediate buffering enabled. 00916 // Check that the Buffer is properly aligned, and that the 00917 // length is an integral number of 512-byte blocks. 00918 // 00919 00920 if ((deviceObject->SectorSize && 00921 (Length & (deviceObject->SectorSize - 1)))) { 00922 00923 // 00924 // Check for sector sizes that are not a power of two. 00925 // 00926 00927 if ((deviceObject->SectorSize && 00928 Length % deviceObject->SectorSize)) { 00929 ObDereferenceObject( fileObject ); 00930 return STATUS_INVALID_PARAMETER; 00931 } 00932 } 00933 00934 // 00935 // If a ByteOffset parameter was specified, ensure that it 00936 // is a valid argument. 00937 // 00938 00939 if (ARGUMENT_PRESENT( ByteOffset )) { 00940 if (deviceObject->SectorSize && 00941 (fileOffset.LowPart & (deviceObject->SectorSize - 1))) { 00942 ObDereferenceObject( fileObject ); 00943 return STATUS_INVALID_PARAMETER; 00944 } 00945 } 00946 } 00947 00948 // 00949 // The SegmentArray paramter must be accessible. 00950 // 00951 00952 #ifdef _X86_ 00953 ProbeForRead( SegmentArray, 00954 elementCount * sizeof( FILE_SEGMENT_ELEMENT ), 00955 sizeof( ULONG ) 00956 ); 00957 #elif defined(_WIN64) 00958 00959 // 00960 // If we are a wow64 process, follow the X86 rules 00961 // 00962 00963 if (PsGetCurrentProcess()->Wow64Process) { 00964 ProbeForRead( SegmentArray, 00965 elementCount * sizeof( FILE_SEGMENT_ELEMENT ), 00966 sizeof( ULONG ) 00967 ); 00968 } else { 00969 ProbeForRead( SegmentArray, 00970 elementCount * sizeof( FILE_SEGMENT_ELEMENT ), 00971 TYPE_ALIGNMENT( FILE_SEGMENT_ELEMENT ) 00972 ); 00973 } 00974 #else 00975 ProbeForRead( SegmentArray, 00976 elementCount * sizeof( FILE_SEGMENT_ELEMENT ), 00977 TYPE_ALIGNMENT( FILE_SEGMENT_ELEMENT ) 00978 ); 00979 #endif 00980 00981 if (Length != 0) { 00982 00983 // 00984 // Capture the segment array so it cannot be changed after 00985 // it has been looked at. 00986 // 00987 00988 capturedArray = ExAllocatePoolWithQuota( PagedPool, 00989 elementCount * sizeof( FILE_SEGMENT_ELEMENT ) 00990 ); 00991 00992 RtlCopyMemory( capturedArray, 00993 SegmentArray, 00994 elementCount * sizeof( FILE_SEGMENT_ELEMENT ) 00995 ); 00996 00997 SegmentArray = capturedArray; 00998 00999 // 01000 // Verify that all the addresses are page aligned. 01001 // 01002 01003 for (i = 0; i < elementCount; i++) { 01004 01005 if ( SegmentArray[i].Alignment & (PAGE_SIZE - 1)) { 01006 ExRaiseStatus( STATUS_INVALID_PARAMETER ); 01007 } 01008 } 01009 } 01010 01011 // 01012 // Finally, ensure that if there is a key parameter specified it 01013 // is readable by the caller. 01014 // 01015 01016 if (ARGUMENT_PRESENT( Key )) { 01017 keyValue = ProbeAndReadUlong( Key ); 01018 } 01019 01020 } except(IopExceptionFilter( GetExceptionInformation(), &exceptionCode )) { 01021 01022 // 01023 // An exception was incurred while attempting to probe the 01024 // caller's parameters. Dereference the file object and return 01025 // an appropriate error status code. 01026 // 01027 01028 ObDereferenceObject( fileObject ); 01029 if (capturedArray != NULL) { 01030 ExFreePool( capturedArray ); 01031 } 01032 return exceptionCode; 01033 01034 } 01035 01036 } else { 01037 01038 // 01039 // The caller's mode is kernel. Get the same parameters that are 01040 // required from any other mode. 01041 // 01042 01043 if (ARGUMENT_PRESENT( ByteOffset )) { 01044 fileOffset = *ByteOffset; 01045 } 01046 01047 if (ARGUMENT_PRESENT( Key )) { 01048 keyValue = *Key; 01049 } 01050 01051 #if DBG 01052 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 01053 01054 // 01055 // The file was opened without intermediate buffering enabled. 01056 // Check that the the length is an integral number of the block 01057 // size. 01058 // 01059 01060 if ((deviceObject->SectorSize && 01061 (Length & (deviceObject->SectorSize - 1)))) { 01062 01063 // 01064 // Check for sector sizes that are not a power of two. 01065 // 01066 01067 if ((deviceObject->SectorSize && 01068 Length % deviceObject->SectorSize)) { 01069 ObDereferenceObject( fileObject ); 01070 ASSERT( FALSE ); 01071 return STATUS_INVALID_PARAMETER; 01072 } 01073 } 01074 01075 // 01076 // If a ByteOffset parameter was specified, ensure that it 01077 // is a valid argument. 01078 // 01079 01080 if (ARGUMENT_PRESENT( ByteOffset )) { 01081 if (deviceObject->SectorSize && 01082 (fileOffset.LowPart & (deviceObject->SectorSize - 1))) { 01083 ObDereferenceObject( fileObject ); 01084 ASSERT( FALSE ); 01085 return STATUS_INVALID_PARAMETER; 01086 } 01087 } 01088 } 01089 01090 if (Length != 0) { 01091 01092 // 01093 // Verify that all the addresses are page aligned. 01094 // 01095 01096 for (i = 0; i < elementCount; i++) { 01097 01098 if ( SegmentArray[i].Alignment & (PAGE_SIZE - 1)) { 01099 01100 ObDereferenceObject( fileObject ); 01101 ASSERT(FALSE); 01102 return STATUS_INVALID_PARAMETER; 01103 } 01104 } 01105 } 01106 #endif // DBG 01107 } 01108 01109 // 01110 // Get the address of the event object and set the event to the Not- 01111 // Signaled state, if an one was specified. Note here too, that if 01112 // the handle does not refer to an event, then the reference will fail. 01113 // 01114 01115 if (ARGUMENT_PRESENT( Event )) { 01116 status = ObReferenceObjectByHandle( Event, 01117 EVENT_MODIFY_STATE, 01118 ExEventObjectType, 01119 requestorMode, 01120 (PVOID *) &eventObject, 01121 NULL ); 01122 if (!NT_SUCCESS( status )) { 01123 ObDereferenceObject( fileObject ); 01124 if (capturedArray != NULL) { 01125 ExFreePool( capturedArray ); 01126 } 01127 return status; 01128 } else { 01129 KeClearEvent( eventObject ); 01130 } 01131 } 01132 01133 // 01134 // Get the address of the driver object's Fast I/O dispatch structure. 01135 // 01136 01137 fastIoDispatch = deviceObject->DriverObject->FastIoDispatch; 01138 01139 // 01140 // Make a special check here to determine whether this is a synchronous 01141 // I/O operation. If it is, then wait here until the file is owned by 01142 // the current thread. 01143 // 01144 01145 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 01146 01147 BOOLEAN interrupted; 01148 01149 if (!IopAcquireFastLock( fileObject )) { 01150 status = IopAcquireFileObjectLock( fileObject, 01151 requestorMode, 01152 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 01153 &interrupted ); 01154 if (interrupted) { 01155 if (eventObject) { 01156 ObDereferenceObject( eventObject ); 01157 } 01158 ObDereferenceObject( fileObject ); 01159 if (capturedArray != NULL) { 01160 ExFreePool( capturedArray ); 01161 } 01162 return status; 01163 } 01164 } 01165 01166 if (!ARGUMENT_PRESENT( ByteOffset ) || 01167 (fileOffset.LowPart == FILE_USE_FILE_POINTER_POSITION && 01168 fileOffset.HighPart == -1)) { 01169 fileOffset = fileObject->CurrentByteOffset; 01170 } 01171 01172 synchronousIo = TRUE; 01173 01174 } else if (!ARGUMENT_PRESENT( ByteOffset ) && !(fileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) { 01175 01176 // 01177 // The file is not open for synchronous I/O operations, but the 01178 // caller did not specify a ByteOffset parameter. 01179 // 01180 01181 if (eventObject) { 01182 ObDereferenceObject( eventObject ); 01183 } 01184 ObDereferenceObject( fileObject ); 01185 if (capturedArray != NULL) { 01186 ExFreePool( capturedArray ); 01187 } 01188 return STATUS_INVALID_PARAMETER; 01189 } else { 01190 synchronousIo = FALSE; 01191 } 01192 01193 // 01194 // Negative file offsets are illegal. 01195 // 01196 01197 if (fileOffset.HighPart < 0) { 01198 if (eventObject) { 01199 ObDereferenceObject( eventObject ); 01200 } 01201 if (synchronousIo) { 01202 IopReleaseFileObjectLock( fileObject ); 01203 } 01204 ObDereferenceObject( fileObject ); 01205 if (capturedArray != NULL) { 01206 ExFreePool( capturedArray ); 01207 } 01208 return STATUS_INVALID_PARAMETER; 01209 } 01210 01211 // 01212 // Set the file object to the Not-Signaled state. 01213 // 01214 01215 KeClearEvent( &fileObject->Event ); 01216 01217 // 01218 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 01219 // The allocation is performed with an exception handler in case the 01220 // caller does not have enough quota to allocate the packet. 01221 01222 irp = IopAllocateIrp( deviceObject->StackSize, TRUE ); 01223 if (!irp) { 01224 01225 // 01226 // An IRP could not be allocated. Cleanup and return an appropriate 01227 // error status code. 01228 // 01229 01230 IopAllocateIrpCleanup( fileObject, eventObject ); 01231 01232 if (capturedArray != NULL) { 01233 ExFreePool( capturedArray ); 01234 } 01235 return STATUS_INSUFFICIENT_RESOURCES; 01236 } 01237 irp->Tail.Overlay.OriginalFileObject = fileObject; 01238 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01239 irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL; 01240 irp->RequestorMode = requestorMode; 01241 irp->PendingReturned = FALSE; 01242 irp->Cancel = FALSE; 01243 irp->CancelRoutine = (PDRIVER_CANCEL) NULL; 01244 01245 // 01246 // Fill in the service independent parameters in the IRP. 01247 // 01248 01249 irp->UserEvent = eventObject; 01250 irp->UserIosb = IoStatusBlock; 01251 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01252 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01253 01254 // 01255 // Get a pointer to the stack location for the first driver. This will be 01256 // used to pass the original function codes and parameters. Note that 01257 // setting the major function here also sets: 01258 // 01259 // MinorFunction = 0; 01260 // Flags = 0; 01261 // Control = 0; 01262 // 01263 01264 irpSp = IoGetNextIrpStackLocation( irp ); 01265 majorFunction = (PULONG) (&irpSp->MajorFunction); 01266 *majorFunction = IRP_MJ_READ; 01267 irpSp->FileObject = fileObject; 01268 01269 // 01270 // Always allocate a Memory Descriptor List (MDL) and lock down the 01271 // caller's buffer. This way the file system do not have change to 01272 // build a scatter MDL. Note buffered I/O is not supported for this 01273 // routine. 01274 // 01275 01276 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 01277 irp->MdlAddress = (PMDL) NULL; 01278 01279 01280 // 01281 // This is a direct I/O operation. Allocate an MDL and invoke the 01282 // memory management routine to lock the buffer into memory. This 01283 // is done using an exception handler that will perform cleanup if 01284 // the operation fails. Note that no MDL is allocated, nor is any 01285 // memory probed or locked if the length of the request was zero. 01286 // 01287 01288 irp->Flags = 0; 01289 01290 if (Length) { 01291 01292 PMDL mdl; 01293 01294 try { 01295 01296 // 01297 // Allocate an MDL, charging quota for it, and hang it off of 01298 // the IRP. Probe and lock the pages associated with the 01299 // caller's buffer for write access and fill in the MDL with 01300 // the PFNs of those pages. 01301 // 01302 01303 mdl = IoAllocateMdl( (PVOID)(ULONG_PTR) SegmentArray[0].Buffer, Length, FALSE, TRUE, irp ); 01304 if (mdl == NULL) { 01305 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 01306 } 01307 01308 // 01309 // The address of the first file segment is used as a base 01310 // address. 01311 // 01312 01313 MmProbeAndLockSelectedPages( mdl, 01314 SegmentArray, 01315 requestorMode, 01316 IoWriteAccess ); 01317 01318 irp->UserBuffer = (PVOID)(ULONG_PTR) SegmentArray[0].Buffer; 01319 01320 } except(EXCEPTION_EXECUTE_HANDLER) { 01321 01322 // 01323 // An exception was incurred while either probing the caller's 01324 // buffer or allocating the MDL. Determine what actually 01325 // happened, clean everything up, and return an appropriate 01326 // error status code. 01327 // 01328 01329 IopExceptionCleanup( fileObject, 01330 irp, 01331 eventObject, 01332 (PKEVENT) NULL ); 01333 01334 if (capturedArray != NULL) { 01335 ExFreePool( capturedArray ); 01336 } 01337 return GetExceptionCode(); 01338 01339 } 01340 01341 } 01342 01343 // 01344 // We are done with the captured buffer. 01345 // 01346 01347 if (capturedArray != NULL) { 01348 ExFreePool( capturedArray ); 01349 } 01350 01351 // 01352 // If this read operation is supposed to be performed with caching disabled 01353 // set the disable flag in the IRP so no caching is performed. 01354 // 01355 01356 if (fileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) { 01357 irp->Flags |= IRP_NOCACHE | IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION; 01358 } else { 01359 irp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION; 01360 } 01361 01362 // 01363 // Copy the caller's parameters to the service-specific portion of the 01364 // IRP. 01365 // 01366 01367 irpSp->Parameters.Read.Length = Length; 01368 irpSp->Parameters.Read.Key = keyValue; 01369 irpSp->Parameters.Read.ByteOffset = fileOffset; 01370 01371 // 01372 // Queue the packet, call the driver, and synchronize appopriately with 01373 // I/O completion. 01374 // 01375 01376 status = IopSynchronousServiceTail( deviceObject, 01377 irp, 01378 fileObject, 01379 TRUE, 01380 requestorMode, 01381 synchronousIo, 01382 ReadTransfer ); 01383 01384 return status; 01385 01386 } }


Variable Documentation

ULONG IopCacheHitIncrement = 0
 

Definition at line 28 of file io/read.c.

Referenced by NtReadFile().


Generated on Sat May 15 19:45:27 2004 for test by doxygen 1.3.7