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
00815
00816
00817 requestorMode = KeGetPreviousMode();
00818
00819
00820
00821
00822
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
00837
00838
00839 deviceObject =
IoGetRelatedDeviceObject( fileObject );
00840
00841
00842
00843
00844
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
00868
00869
00870
00871
00872
00873
00874
try {
00875
00876
00877
00878
00879
00880
ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine);
00881
00882
00883
00884
00885
00886
00887
00888
00889
if (fileObject->
CompletionContext &&
IopApcRoutinePresent( ApcRoutine )) {
00890
ObDereferenceObject( fileObject );
00891
return STATUS_INVALID_PARAMETER;
00892 }
00893
00894
00895
00896
00897
00898
00899
if (ARGUMENT_PRESENT( ByteOffset )) {
00900
ProbeForRead( ByteOffset,
00901
sizeof( LARGE_INTEGER ),
00902
sizeof( ULONG ) );
00903 fileOffset = *ByteOffset;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
if (fileObject->
Flags &
FO_NO_INTERMEDIATE_BUFFERING) {
00913
00914
00915
00916
00917
00918
00919
00920
if ((deviceObject->
SectorSize &&
00921 (Length & (deviceObject->
SectorSize - 1)))) {
00922
00923
00924
00925
00926
00927
if ((deviceObject->
SectorSize &&
00928 Length % deviceObject->
SectorSize)) {
00929
ObDereferenceObject( fileObject );
00930
return STATUS_INVALID_PARAMETER;
00931 }
00932 }
00933
00934
00935
00936
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
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
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
00985
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
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
01013
01014
01015
01016
if (ARGUMENT_PRESENT( Key )) {
01017 keyValue =
ProbeAndReadUlong( Key );
01018 }
01019
01020 } except(
IopExceptionFilter( GetExceptionInformation(), &exceptionCode )) {
01021
01022
01023
01024
01025
01026
01027
01028
ObDereferenceObject( fileObject );
01029
if (capturedArray !=
NULL) {
01030
ExFreePool( capturedArray );
01031 }
01032
return exceptionCode;
01033
01034 }
01035
01036 }
else {
01037
01038
01039
01040
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
01056
01057
01058
01059
01060
if ((deviceObject->
SectorSize &&
01061 (Length & (deviceObject->
SectorSize - 1)))) {
01062
01063
01064
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
01077
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
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
01111
01112
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
01135
01136
01137 fastIoDispatch = deviceObject->
DriverObject->
FastIoDispatch;
01138
01139
01140
01141
01142
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
01178
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
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
01213
01214
01215
KeClearEvent( &fileObject->
Event );
01216
01217
01218
01219
01220
01221
01222 irp =
IopAllocateIrp( deviceObject->
StackSize, TRUE );
01223
if (!irp) {
01224
01225
01226
01227
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
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
01256
01257
01258
01259
01260
01261
01262
01263
01264 irpSp =
IoGetNextIrpStackLocation( irp );
01265 majorFunction = (PULONG) (&irpSp->
MajorFunction);
01266 *majorFunction =
IRP_MJ_READ;
01267 irpSp->
FileObject = fileObject;
01268
01269
01270
01271
01272
01273
01274
01275
01276 irp->
AssociatedIrp.SystemBuffer = (PVOID)
NULL;
01277 irp->
MdlAddress = (
PMDL)
NULL;
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 irp->
Flags = 0;
01289
01290
if (Length) {
01291
01292
PMDL mdl;
01293
01294
try {
01295
01296
01297
01298
01299
01300
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
01310
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
01324
01325
01326
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
01345
01346
01347
if (capturedArray !=
NULL) {
01348
ExFreePool( capturedArray );
01349 }
01350
01351
01352
01353
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
01364
01365
01366
01367 irpSp->
Parameters.Read.Length = Length;
01368 irpSp->
Parameters.Read.Key = keyValue;
01369 irpSp->
Parameters.Read.ByteOffset = fileOffset;
01370
01371
01372
01373
01374
01375
01376 status =
IopSynchronousServiceTail( deviceObject,
01377 irp,
01378 fileObject,
01379 TRUE,
01380 requestorMode,
01381 synchronousIo,
01382 ReadTransfer );
01383
01384
return status;
01385
01386 }
}