00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "UdfProcs.h"
00023
00024
00025
00026
00027
00028 #define BugCheckFileId (UDFS_BUG_CHECK_READ)
00029
00030
00031
00032
00033
00034 #define Dbg (UDFS_DEBUG_LEVEL_READ)
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define SafeZeroMemory(IC,AT,BYTE_COUNT) { \
00049
try { \
00050
RtlZeroMemory( (AT), (BYTE_COUNT) ); \
00051
} except( EXCEPTION_EXECUTE_HANDLER ) { \
00052
UdfRaiseStatus( IC, STATUS_INVALID_USER_BUFFER ); \
00053
} \
00054
}
00055
00056
00057
00058
00059
00060 #define READ_AHEAD_GRANULARITY (0x10000)
00061
00062
#ifdef ALLOC_PRAGMA
00063
#pragma alloc_text(PAGE, UdfCommonRead)
00064
#endif
00065
00066
00067
NTSTATUS
00068 UdfCommonRead (
00069 IN
PIRP_CONTEXT IrpContext,
00070 IN
PIRP Irp
00071 )
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
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 }
00572