00075 :
00076
00077 This
is the common entry point
for NtReadFile calls. For synchronous requests,
00078 CommonRead will complete
the request in
the current thread. If not
00079 synchronous
the request will be passed to
the Fsp
if there
is a need to
00080 block.
00081
00082 Arguments:
00083
00084
Irp - Supplies
the Irp to process
00085
00086 Return Value:
00087
00088
NTSTATUS - The result of
this operation.
00089
00090 --*/
00091
00092 {
00093
NTSTATUS Status;
00094
PIO_STACK_LOCATION IrpSp =
IoGetCurrentIrpStackLocation( Irp );
00095
00096
TYPE_OF_OPEN TypeOfOpen;
00097
PFCB Fcb;
00098
PCCB Ccb;
00099
PVCB Vcb;
00100
00101 BOOLEAN Wait;
00102 ULONG PagingIo;
00103 ULONG
SynchronousIo;
00104 ULONG NonCachedIo;
00105
00106 LONGLONG StartingOffset;
00107 LONGLONG ByteRange;
00108 ULONG ByteCount;
00109 ULONG ReadByteCount;
00110 ULONG OriginalByteCount;
00111
00112 PVOID SystemBuffer, UserBuffer;
00113
00114 BOOLEAN ReleaseFile =
TRUE;
00115
00116
PFILE_OBJECT MappingFileObject;
00117
00118
UDF_IO_CONTEXT LocalIoContext;
00119
00120
PAGED_CODE();
00121
00122
00123
00124
00125
00126
if (IrpSp->
Parameters.Read.Length == 0) {
00127
00128
UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
00129
return STATUS_SUCCESS;
00130 }
00131
00132
00133
00134
00135
00136
00137 TypeOfOpen =
UdfDecodeFileObject( IrpSp->
FileObject, &Fcb, &Ccb );
00138
00139 Vcb = Fcb->
Vcb;
00140
00141
if ((TypeOfOpen ==
UnopenedFileObject) || (TypeOfOpen ==
UserDirectoryOpen)) {
00142
00143
UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
00144
return STATUS_INVALID_DEVICE_REQUEST;
00145 }
00146
00147
00148
00149
00150
00151
00152 Wait =
BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
00153 PagingIo =
FlagOn(
Irp->
Flags, IRP_PAGING_IO );
00154 NonCachedIo =
FlagOn(
Irp->
Flags, IRP_NOCACHE );
00155
SynchronousIo =
FlagOn( IrpSp->
FileObject->
Flags, FO_SYNCHRONOUS_IO );
00156
00157
00158
00159
00160
00161 StartingOffset = IrpSp->
Parameters.Read.ByteOffset.QuadPart;
00162 OriginalByteCount = ByteCount = IrpSp->
Parameters.Read.Length;
00163
00164 ByteRange = StartingOffset + ByteCount;
00165
00166
00167
00168
00169
00170
if (TypeOfOpen ==
UserVolumeOpen) {
00171
00172 NonCachedIo =
TRUE;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
if (PagingIo) {
00184
00185
UdfAcquireFileSharedStarveExclusive( IrpContext, Fcb );
00186
00187 }
else {
00188
00189
UdfAcquireFileShared( IrpContext, Fcb );
00190 }
00191
00192
00193
00194
00195
00196
try {
00197
00198
00199
00200
00201
00202
UdfVerifyFcbOperation( IrpContext, Fcb );
00203
00204
00205
00206
00207
00208
if (TypeOfOpen ==
UserFileOpen) {
00209
00210
00211
00212
00213
00214
00215
Status =
FsRtlCheckOplock( &Fcb->Oplock,
00216 Irp,
00217 IrpContext,
00218 UdfOplockComplete,
00219 UdfPrePostIrp );
00220
00221
00222
00223
00224
00225
00226
if (
Status != STATUS_SUCCESS) {
00227
00228
Irp =
NULL;
00229 IrpContext =
NULL;
00230
00231
try_leave( Status );
00232 }
00233
00234
if (!PagingIo &&
00235 (Fcb->FileLock !=
NULL) &&
00236 !
FsRtlCheckLockForReadAccess( Fcb->FileLock, Irp )) {
00237
00238
try_leave( Status = STATUS_FILE_LOCK_CONFLICT );
00239 }
00240 }
00241
00242
00243
00244
00245
00246
if (StartingOffset >= Fcb->FileSize.QuadPart) {
00247
00248
try_leave( Status = STATUS_END_OF_FILE );
00249 }
00250
00251
00252
00253
00254
00255
if (ByteRange > Fcb->FileSize.QuadPart) {
00256
00257 ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset);
00258 ByteRange = Fcb->FileSize.QuadPart;
00259 }
00260
00261
00262
00263
00264
00265
00266
if (
FlagOn( Fcb->
FcbState, FCB_STATE_EMBEDDED_DATA )) {
00267
00268
00269
00270
00271
00272
ASSERT( Vcb->
MetadataFcb->FileObject != NULL );
00273
00274
00275
00276
00277
00278
00279
00280 StartingOffset += (
BytesFromSectors( Vcb, Fcb->
EmbeddedVsn ) + Fcb->
EmbeddedOffset);
00281 MappingFileObject = Vcb->
MetadataFcb->FileObject;
00282 NonCachedIo =
FALSE;
00283
00284
00285
00286
00287
00288 }
else {
00289
00290 MappingFileObject = IrpSp->
FileObject;
00291 }
00292
00293
00294
00295
00296
00297
if (NonCachedIo) {
00298
00299
00300
00301
00302
00303
00304
00305
00306 ReadByteCount =
SectorAlign( Vcb, ByteCount );
00307
00308
if (
SectorOffset( Vcb, StartingOffset ) ||
00309 (ReadByteCount > OriginalByteCount)) {
00310
00311
if (!Wait) {
00312
00313
UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
00314 }
00315
00316
00317
00318
00319
00320 ReadByteCount = ByteCount;
00321 }
00322
00323
00324
00325
00326
00327
00328
00329
if (IrpContext->IoContext ==
NULL ||
00330 !
FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {
00331
00332
00333
00334
00335
00336
00337
if (Wait) {
00338
00339 IrpContext->IoContext = &LocalIoContext;
00340
ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
00341
00342 }
else {
00343
00344 IrpContext->IoContext =
UdfAllocateIoContext();
00345
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
00346 }
00347 }
00348
00349 RtlZeroMemory( IrpContext->IoContext,
sizeof(
UDF_IO_CONTEXT ));
00350
00351
00352
00353
00354
00355
00356 IrpContext->IoContext->AllocatedContext =
00357
BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
00358
00359
if (Wait) {
00360
00361
KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
00362 NotificationEvent,
00363 FALSE );
00364
00365 }
else {
00366
00367 IrpContext->IoContext->ResourceThreadId =
ExGetCurrentResourceThread();
00368 IrpContext->IoContext->Resource = Fcb->Resource;
00369 IrpContext->IoContext->RequestedByteCount = ByteCount;
00370 }
00371
00372
Irp->
IoStatus.Information = ReadByteCount;
00373
00374
00375
00376
00377
00378
Status =
UdfNonCachedRead( IrpContext, Fcb, StartingOffset, ReadByteCount );
00379
00380
00381
00382
00383
00384
if (
Status == STATUS_PENDING) {
00385
00386
Irp =
NULL;
00387 ReleaseFile =
FALSE;
00388
00389
00390
00391
00392
00393
00394 }
else {
00395
00396
00397
00398
00399
00400
if (!
NT_SUCCESS( Status )) {
00401
00402
00403
00404
00405
00406
Irp->
IoStatus.Information = 0;
00407
00408
00409
00410
00411
00412
if (
IoIsErrorUserInduced( Status )) {
00413
00414
UdfRaiseStatus( IrpContext, Status );
00415 }
00416
00417
Status =
FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR );
00418
00419
00420
00421
00422
00423 }
else if (ReadByteCount != ByteCount) {
00424
00425
UdfMapUserBuffer( IrpContext, &UserBuffer );
00426
00427
SafeZeroMemory( IrpContext,
00428
Add2Ptr( UserBuffer,
00429 ByteCount,
00430 PVOID ),
00431 ReadByteCount - ByteCount );
00432
00433
Irp->
IoStatus.Information = ByteCount;
00434 }
00435
00436
00437
00438
00439
00440
if (
SynchronousIo && !PagingIo &&
NT_SUCCESS( Status )) {
00441
00442 IrpSp->
FileObject->
CurrentByteOffset.QuadPart = ByteRange;
00443 }
00444 }
00445
00446
try_leave( NOTHING );
00447 }
00448
00449
00450
00451
00452
00453
00454
if (MappingFileObject->
PrivateCacheMap ==
NULL) {
00455
00456
00457
00458
00459
00460
00461
ASSERT( MappingFileObject != Vcb->
MetadataFcb->FileObject );
00462
00463
00464
00465
00466
00467
CcInitializeCacheMap( IrpSp->
FileObject,
00468 (
PCC_FILE_SIZES) &Fcb->AllocationSize,
00469 FALSE,
00470 &
UdfData.
CacheManagerCallbacks,
00471 Fcb );
00472
00473
CcSetReadAheadGranularity( IrpSp->
FileObject, READ_AHEAD_GRANULARITY );
00474 }
00475
00476
00477
00478
00479
00480
if (!
FlagOn( IrpContext->MinorFunction, IRP_MN_MDL )) {
00481
00482
00483
00484
00485
00486
00487
00488
UdfMapUserBuffer( IrpContext, &SystemBuffer);
00489
00490
00491
00492
00493
00494
if (!
CcCopyRead( MappingFileObject,
00495 (PLARGE_INTEGER) &StartingOffset,
00496 ByteCount,
00497 Wait,
00498 SystemBuffer,
00499 &
Irp->
IoStatus )) {
00500
00501
try_leave( Status = STATUS_CANT_WAIT );
00502 }
00503
00504
00505
00506
00507
00508
if (!
NT_SUCCESS(
Irp->
IoStatus.Status )) {
00509
00510
UdfNormalizeAndRaiseStatus( IrpContext,
Irp->
IoStatus.Status );
00511 }
00512
00513
Status =
Irp->
IoStatus.Status;
00514
00515
00516
00517
00518
00519 }
else {
00520
00521
CcMdlRead( MappingFileObject,
00522 (PLARGE_INTEGER) &StartingOffset,
00523 ByteCount,
00524 &
Irp->
MdlAddress,
00525 &
Irp->
IoStatus );
00526
00527
Status =
Irp->
IoStatus.Status;
00528 }
00529
00530
00531
00532
00533
00534
if (
SynchronousIo && !PagingIo &&
NT_SUCCESS( Status )) {
00535
00536 IrpSp->
FileObject->
CurrentByteOffset.QuadPart = ByteRange;
00537 }
00538
00539 } finally {
00540
00541
DebugUnwind(
"UdfCommonRead" );
00542
00543
00544
00545
00546
00547
if (ReleaseFile) {
00548
00549
UdfReleaseFile( IrpContext, Fcb );
00550 }
00551 }
00552
00553
00554
00555
00556
00557
if (
Status == STATUS_CANT_WAIT) {
00558
00559
Status =
UdfFsdPostRequest( IrpContext, Irp );
00560
00561
00562
00563
00564
00565 }
else {
00566
00567
UdfCompleteRequest( IrpContext, Irp, Status );
00568 }
00569
00570
return Status;
00571 }