00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "UdfProcs.h"
00022
00023
00024
00025
00026
00027 #define BugCheckFileId (UDFS_BUG_CHECK_DEVIOSUP)
00028
00029
00030
00031
00032
00033 #define Dbg (UDFS_DEBUG_LEVEL_DEVIOSUP)
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 typedef struct _IO_RUN {
00045
00046
00047
00048
00049
00050
00051
00052 LONGLONG
DiskOffset;
00053 ULONG
DiskByteCount;
00054
00055
00056
00057
00058
00059
00060 PVOID
UserBuffer;
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 PVOID
TransferBuffer;
00083 ULONG
TransferByteCount;
00084 ULONG
TransferBufferOffset;
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 PMDL TransferMdl;
00096 PVOID
TransferVirtualAddress;
00097
00098
00099
00100
00101
00102 PIRP SavedIrp;
00103
00104 }
IO_RUN;
00105 typedef IO_RUN *
PIO_RUN;
00106
00107 #define MAX_PARALLEL_IOS 5
00108
00109
00110
00111
00112
00113 BOOLEAN
00114
UdfPrepareBuffers (
00115 IN
PIRP_CONTEXT IrpContext,
00116 IN
PIRP Irp,
00117 IN
PFCB Fcb,
00118 IN PVOID UserBuffer,
00119 IN ULONG UserBufferOffset,
00120 IN LONGLONG StartingOffset,
00121 IN ULONG ByteCount,
00122 IN PIO_RUN IoRuns,
00123 IN PULONG RunCount,
00124 IN PULONG ThisByteCount,
00125 OUT PBOOLEAN SparseRuns
00126 );
00127
00128 BOOLEAN
00129
UdfFinishBuffers (
00130 IN
PIRP_CONTEXT IrpContext,
00131 IN PIO_RUN IoRuns,
00132 IN ULONG RunCount,
00133 IN BOOLEAN FinalCleanup
00134 );
00135
00136
VOID
00137
UdfMultipleAsync (
00138 IN
PIRP_CONTEXT IrpContext,
00139 IN ULONG RunCount,
00140 IN PIO_RUN IoRuns
00141 );
00142
00143
VOID
00144
UdfSingleAsync (
00145 IN
PIRP_CONTEXT IrpContext,
00146 IN LONGLONG ByteOffset,
00147 IN ULONG ByteCount
00148 );
00149
00150
VOID
00151
UdfWaitSync (
00152 IN
PIRP_CONTEXT IrpContext
00153 );
00154
00155
NTSTATUS
00156
UdfMultiSyncCompletionRoutine (
00157 IN
PDEVICE_OBJECT DeviceObject,
00158 IN
PIRP Irp,
00159 IN PVOID Context
00160 );
00161
00162
NTSTATUS
00163
UdfMultiAsyncCompletionRoutine (
00164 IN
PDEVICE_OBJECT DeviceObject,
00165 IN
PIRP Irp,
00166 IN PVOID Context
00167 );
00168
00169
NTSTATUS
00170
UdfSingleSyncCompletionRoutine (
00171 IN
PDEVICE_OBJECT DeviceObject,
00172 IN
PIRP Irp,
00173 IN PVOID Context
00174 );
00175
00176
NTSTATUS
00177
UdfSingleAsyncCompletionRoutine (
00178 IN
PDEVICE_OBJECT DeviceObject,
00179 IN
PIRP Irp,
00180 IN PVOID Context
00181 );
00182
00183
#ifdef ALLOC_PRAGMA
00184
#endif
00185
00186
#ifdef ALLOC_PRAGMA
00187
#pragma alloc_text(PAGE, UdfCreateUserMdl)
00188
#pragma alloc_text(PAGE, UdfMultipleAsync)
00189
#pragma alloc_text(PAGE, UdfNonCachedRead)
00190
#pragma alloc_text(PAGE, UdfFinishBuffers)
00191
#pragma alloc_text(PAGE, UdfPrepareBuffers)
00192
#pragma alloc_text(PAGE, UdfSingleAsync)
00193
#pragma alloc_text(PAGE, UdfWaitSync)
00194
#pragma alloc_text(PAGE, UdfPerformDevIoCtrl)
00195
#pragma alloc_text(PAGE, UdfReadSectors)
00196
#endif
00197
00198
00199
00200
NTSTATUS
00201 UdfNonCachedRead (
00202 IN
PIRP_CONTEXT IrpContext,
00203 IN
PFCB Fcb,
00204 IN LONGLONG StartingOffset,
00205 IN ULONG ByteCount
00206 )
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 {
00239
NTSTATUS Status = STATUS_SUCCESS;
00240
00241
IO_RUN IoRuns[
MAX_PARALLEL_IOS];
00242 ULONG RunCount = 0;
00243 ULONG CleanupRunCount = 0;
00244
00245 PVOID UserBuffer;
00246 ULONG UserBufferOffset = 0;
00247 LONGLONG CurrentOffset = StartingOffset;
00248 ULONG RemainingByteCount = ByteCount;
00249 ULONG ThisByteCount;
00250
00251 BOOLEAN Unaligned;
00252 BOOLEAN SparseRuns;
00253 BOOLEAN FlushIoBuffers =
FALSE;
00254 BOOLEAN FirstPass =
TRUE;
00255
00256
PAGED_CODE();
00257
00258
00259
00260
00261
00262
if (IrpContext->Irp->MdlAddress ==
NULL) {
00263
00264
UdfCreateUserMdl( IrpContext, ByteCount,
TRUE );
00265 }
00266
00267
00268
00269
00270
00271
try {
00272
00273
UdfMapUserBuffer( IrpContext, &UserBuffer);
00274
00275
00276
00277
00278
00279
do {
00280
00281
00282
00283
00284
00285
00286
00287 RtlZeroMemory( IoRuns,
sizeof( IoRuns ));
00288
00289 Unaligned =
UdfPrepareBuffers( IrpContext,
00290 IrpContext->Irp,
00291 Fcb,
00292 UserBuffer,
00293 UserBufferOffset,
00294 CurrentOffset,
00295 RemainingByteCount,
00296 IoRuns,
00297 &CleanupRunCount,
00298 &ThisByteCount,
00299 &SparseRuns );
00300
00301
00302 RunCount = CleanupRunCount;
00303
00304
00305
00306
00307
00308
00309
ASSERT( !(SparseRuns &&
FlagOn( Fcb->FcbState,
FCB_STATE_VMCB_MAPPING|
FCB_STATE_EMBEDDED_DATA )));
00310
00311
if (RunCount == 0) {
00312
00313
try_leave(
Status = IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS );
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
if ((ThisByteCount < RemainingByteCount) &&
00324 !
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
00325
00326
UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
if ((RunCount == 1) && !Unaligned && !SparseRuns && FirstPass) {
00338
00339
UdfSingleAsync( IrpContext,
00340 IoRuns[0].DiskOffset,
00341 IoRuns[0].DiskByteCount );
00342
00343
00344
00345
00346
00347 CleanupRunCount = 0;
00348
00349
00350
00351
00352
00353
if (
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
00354
00355
UdfWaitSync( IrpContext );
00356
00357
Status = IrpContext->Irp->IoStatus.Status;
00358
00359
00360
00361
00362
00363
00364 }
else {
00365
00366
ClearFlag( IrpContext->Flags,
IRP_CONTEXT_FLAG_ALLOC_IO );
00367
Status = STATUS_PENDING;
00368 }
00369
00370
try_leave( NOTHING );
00371 }
00372
00373
00374
00375
00376
00377
UdfMultipleAsync( IrpContext, RunCount, IoRuns );
00378
00379
00380
00381
00382
00383 CleanupRunCount = 0;
00384
00385
00386
00387
00388
00389
00390
if (
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
00391
00392
00393
00394
00395
00396
UdfWaitSync( IrpContext );
00397
00398
Status = IrpContext->Irp->IoStatus.Status;
00399
00400
00401
00402
00403
00404
if (!
NT_SUCCESS(
Status )) {
00405
00406
try_leave( NOTHING );
00407 }
00408
00409
00410
00411
00412
00413
00414
if (Unaligned &&
00415
UdfFinishBuffers( IrpContext, IoRuns, RunCount,
FALSE )) {
00416
00417 FlushIoBuffers =
TRUE;
00418 }
00419
00420
00421
00422
00423
00424
00425 RemainingByteCount -= ThisByteCount;
00426 CurrentOffset += ThisByteCount;
00427 UserBuffer =
Add2Ptr( UserBuffer, ThisByteCount, PVOID );
00428 UserBufferOffset += ThisByteCount;
00429
00430
00431
00432
00433
00434
00435 }
else {
00436
00437
ClearFlag( IrpContext->Flags,
IRP_CONTEXT_FLAG_ALLOC_IO );
00438 CleanupRunCount = 0;
00439
try_leave(
Status = STATUS_PENDING );
00440
break;
00441 }
00442
00443 FirstPass =
FALSE;
00444 }
while (RemainingByteCount != 0);
00445
00446
00447
00448
00449
00450
if (FlushIoBuffers) {
00451
00452
KeFlushIoBuffers( IrpContext->Irp->MdlAddress,
TRUE,
FALSE );
00453 }
00454
00455 } finally {
00456
00457
DebugUnwind(
"UdfNonCachedRead" );
00458
00459
00460
00461
00462
00463
if (CleanupRunCount != 0) {
00464
00465
UdfFinishBuffers( IrpContext, IoRuns, CleanupRunCount,
TRUE );
00466 }
00467 }
00468
00469
return Status;
00470 }
00471
00472
00473
NTSTATUS
00474 UdfCreateUserMdl (
00475 IN
PIRP_CONTEXT IrpContext,
00476 IN ULONG BufferLength,
00477 IN BOOLEAN RaiseOnError
00478 )
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 {
00506
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
00507
PMDL Mdl;
00508
00509
PAGED_CODE();
00510
00511
ASSERT_IRP_CONTEXT( IrpContext );
00512
ASSERT_IRP( IrpContext->Irp );
00513
ASSERT( IrpContext->Irp->MdlAddress ==
NULL );
00514
00515
00516
00517
00518
00519 Mdl =
IoAllocateMdl( IrpContext->Irp->UserBuffer,
00520 BufferLength,
00521
FALSE,
00522
FALSE,
00523 IrpContext->Irp );
00524
00525
if (Mdl !=
NULL) {
00526
00527
00528
00529
00530
00531
00532
try {
00533
00534
MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode,
IoWriteAccess );
00535
00536
Status = STATUS_SUCCESS;
00537
00538 } except(
EXCEPTION_EXECUTE_HANDLER) {
00539
00540
Status = GetExceptionCode();
00541
00542
IoFreeMdl( Mdl );
00543 IrpContext->Irp->MdlAddress =
NULL;
00544
00545
if (!
FsRtlIsNtstatusExpected(
Status )) {
00546
00547
Status = STATUS_INVALID_USER_BUFFER;
00548 }
00549 }
00550 }
00551
00552
00553
00554
00555
00556
if (
Status != STATUS_SUCCESS) {
00557
00558
if (RaiseOnError) {
00559
00560
UdfRaiseStatus( IrpContext,
Status );
00561 }
00562 }
00563
00564
00565
00566
00567
00568
return Status;
00569 }
00570
00571
00572
NTSTATUS
00573 UdfPerformDevIoCtrl (
00574 IN
PIRP_CONTEXT IrpContext,
00575 IN ULONG IoControlCode,
00576 IN
PDEVICE_OBJECT Device,
00577 OUT PVOID OutputBuffer OPTIONAL,
00578 IN ULONG OutputBufferLength,
00579 IN BOOLEAN InternalDeviceIoControl,
00580 IN BOOLEAN OverrideVerify,
00581 OUT PIO_STATUS_BLOCK Iosb OPTIONAL
00582 )
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 {
00617
NTSTATUS Status;
00618
PIRP Irp;
00619
KEVENT Event;
00620 IO_STATUS_BLOCK LocalIosb;
00621 PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
00622
00623
PAGED_CODE();
00624
00625
00626
00627
00628
00629
if (ARGUMENT_PRESENT( Iosb )) {
00630
00631 IosbToUse = Iosb;
00632 }
00633
00634 IosbToUse->Status = 0;
00635 IosbToUse->Information = 0;
00636
00637
KeInitializeEvent( &
Event, NotificationEvent,
FALSE );
00638
00639
Irp =
IoBuildDeviceIoControlRequest( IoControlCode,
00640 Device,
00641
NULL,
00642 0,
00643 OutputBuffer,
00644 OutputBufferLength,
00645 InternalDeviceIoControl,
00646 &
Event,
00647 IosbToUse );
00648
00649
if (
Irp ==
NULL) {
00650
00651
return STATUS_INSUFFICIENT_RESOURCES;
00652 }
00653
00654
if (OverrideVerify) {
00655
00656
SetFlag(
IoGetNextIrpStackLocation(
Irp )->Flags,
SL_OVERRIDE_VERIFY_VOLUME );
00657 }
00658
00659
Status =
IoCallDriver( Device,
Irp );
00660
00661
00662
00663
00664
00665
00666
00667
if (
Status == STATUS_PENDING) {
00668
00669 (
VOID)
KeWaitForSingleObject( &
Event,
00670
Executive,
00671
KernelMode,
00672
FALSE,
00673 (PLARGE_INTEGER)
NULL );
00674
00675
Status = IosbToUse->Status;
00676 }
00677
00678
return Status;
00679
00680 UNREFERENCED_PARAMETER( IrpContext );
00681 }
00682
00683
00684
NTSTATUS
00685 UdfReadSectors (
00686 IN
PIRP_CONTEXT IrpContext,
00687 IN LONGLONG StartingOffset,
00688 IN ULONG ByteCount,
00689 IN BOOLEAN ReturnError,
00690 IN OUT PVOID Buffer,
00691 IN
PDEVICE_OBJECT TargetDeviceObject
00692 )
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 {
00732 PLONGLONG UseStartingOffset;
00733 LONGLONG LocalStartingOffset;
00734
NTSTATUS Status;
00735
KEVENT Event;
00736
PIRP Irp;
00737
00738
PAGED_CODE();
00739
00740
DebugTrace(( +1,
Dbg,
00741
"UdfReadSectors, %x%08x +%x -> %08x from DO %08x\n",
00742 ((PLARGE_INTEGER)&StartingOffset)->HighPart,
00743 ((PLARGE_INTEGER)&StartingOffset)->LowPart,
00744 ByteCount,
00745
Buffer,
00746 TargetDeviceObject ));
00747
00748
00749
00750
00751
00752
00753
00754
00755
ASSERT( IrpContext->Vcb ==
NULL || ByteCount ==
SectorSize( IrpContext->Vcb ));
00756
00757
00758
00759
00760
00761
00762
if (IrpContext->Vcb &&
00763 IrpContext->Vcb->Pcb &&
00764 IrpContext->Vcb->Pcb->SparingMcb) {
00765
00766 LONGLONG SparingPsn;
00767
00768
if (
FsRtlLookupLargeMcbEntry( IrpContext->Vcb->Pcb->SparingMcb,
00769
LlSectorsFromBytes( IrpContext->Vcb, StartingOffset ),
00770 &SparingPsn,
00771
NULL,
00772
NULL,
00773
NULL,
00774
NULL ) &&
00775 SparingPsn != -1) {
00776
00777 StartingOffset =
BytesFromSectors( IrpContext->Vcb, (ULONG) SparingPsn );
00778 }
00779 }
00780
00781
00782
00783
00784
00785
KeInitializeEvent( &
Event, NotificationEvent,
FALSE );
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 UseStartingOffset = &StartingOffset;
00797
00798
if (IrpContext->Vcb &&
00799
FlagOn( IrpContext->Vcb->VcbState,
VCB_STATE_METHOD_2_FIXUP )) {
00800
00801 LocalStartingOffset =
UdfMethod2TransformByteOffset( IrpContext->Vcb, StartingOffset );
00802 UseStartingOffset = &LocalStartingOffset;
00803
00804
DebugTrace(( 0,
Dbg,
00805
"UdfReadSectors, Method2 Fixup to %x%08x\n",
00806 ((PLARGE_INTEGER)UseStartingOffset)->HighPart,
00807 ((PLARGE_INTEGER)UseStartingOffset)->LowPart ));
00808 }
00809
00810
00811
00812
00813
00814
00815
Irp =
IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
00816 TargetDeviceObject,
00817
Buffer,
00818 ByteCount,
00819 (PLARGE_INTEGER) UseStartingOffset,
00820 &
Event,
00821 &IrpContext->Irp->IoStatus );
00822
00823
if (
Irp ==
NULL) {
00824
00825
UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
00826 }
00827
00828
00829
00830
00831
00832
SetFlag(
IoGetNextIrpStackLocation(
Irp )->Flags,
SL_OVERRIDE_VERIFY_VOLUME );
00833
00834
00835
00836
00837
00838
00839
Status =
IoCallDriver( TargetDeviceObject,
Irp );
00840
00841
00842
00843
00844
00845
if (
Status == STATUS_PENDING) {
00846
00847
Status =
KeWaitForSingleObject( &
Event,
00848
Executive,
00849
KernelMode,
00850
FALSE,
00851
NULL );
00852
00853
00854
00855
00856
00857
if (
NT_SUCCESS(
Status )) {
00858
00859
Status = IrpContext->Irp->IoStatus.Status;
00860 }
00861 }
00862
00863
DebugTrace(( -1,
Dbg,
"UdfReadSectors -> %08x\n",
Status ));
00864
00865
00866
00867
00868
00869
if (!
NT_SUCCESS(
Status ) && !ReturnError) {
00870
00871
UdfNormalizeAndRaiseStatus( IrpContext,
Status );
00872 }
00873
00874
return Status;
00875 }
00876
00877
00878
00879
00880
00881
00882 BOOLEAN
00883 UdfPrepareBuffers (
00884 IN
PIRP_CONTEXT IrpContext,
00885 IN
PIRP Irp,
00886 IN
PFCB Fcb,
00887 IN PVOID UserBuffer,
00888 IN ULONG UserBufferOffset,
00889 IN LONGLONG StartingOffset,
00890 IN ULONG ByteCount,
00891 IN PIO_RUN IoRuns,
00892 IN PULONG RunCount,
00893 IN PULONG ThisByteCount,
00894 IN PBOOLEAN SparseRuns
00895 )
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 {
00946
PVCB Vcb;
00947
00948 BOOLEAN Recorded;
00949
00950 BOOLEAN FoundUnaligned =
FALSE;
00951
PIO_RUN ThisIoRun = IoRuns;
00952
00953
00954
00955
00956
00957
00958
00959 ULONG RemainingByteCount = ByteCount;
00960 LONGLONG CurrentFileOffset = StartingOffset;
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 PVOID CurrentUserBuffer = UserBuffer;
00971 ULONG CurrentUserBufferOffset = UserBufferOffset;
00972
00973 PVOID ScratchUserBuffer = UserBuffer;
00974 ULONG ScratchUserBufferOffset = UserBufferOffset;
00975
00976
00977
00978
00979
00980
00981 LONGLONG DiskOffset;
00982 ULONG CurrentByteCount;
00983
00984
PAGED_CODE();
00985
00986 Vcb = Fcb->Vcb;
00987
00988
00989
00990
00991
00992 *RunCount = 0;
00993 *ThisByteCount = 0;
00994 *SparseRuns =
FALSE;
00995
00996
00997
00998
00999
01000
01001
while (
TRUE) {
01002
01003 *RunCount += 1;
01004
01005
01006
01007
01008
01009
01010 ThisIoRun->
UserBuffer = CurrentUserBuffer;
01011
01012
01013
01014
01015
01016
01017 Recorded =
UdfLookupAllocation( IrpContext,
01018 Fcb,
01019 CurrentFileOffset,
01020 &DiskOffset,
01021 &CurrentByteCount );
01022
01023
01024
01025
01026
01027
if (CurrentByteCount > RemainingByteCount) {
01028
01029 CurrentByteCount = RemainingByteCount;
01030 }
01031
01032
01033
01034
01035
01036
if (!Recorded) {
01037
01038
01039
01040
01041
01042 *RunCount -= 1;
01043
01044
01045
01046
01047
01048
01049 RtlZeroMemory( CurrentUserBuffer, CurrentByteCount );
01050 *SparseRuns =
TRUE;
01051
01052
01053
01054
01055
01056
01057 ScratchUserBuffer =
Add2Ptr( CurrentUserBuffer,
01058 CurrentByteCount,
01059 PVOID );
01060
01061 ScratchUserBufferOffset += CurrentByteCount;
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 }
else if (
SectorOffset( Vcb, DiskOffset ) ||
01079
SectorOffset( Vcb, CurrentUserBufferOffset ) ||
01080 (
SectorOffset( Vcb, CurrentByteCount ) &&
01081 CurrentByteCount <
SectorSize( Vcb ))) {
01082
01083
01084
01085
01086
01087
if (!
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
01088
01089
UdfRaiseStatus( IrpContext, STATUS_CANT_WAIT );
01090 }
01091
01092
01093
01094
01095
01096
01097
01098
01099 ThisIoRun->
TransferBufferOffset =
SectorOffset( Vcb, DiskOffset );
01100
01101
01102
01103
01104
01105 ThisIoRun->
DiskOffset =
LlSectorTruncate( Vcb, DiskOffset );
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
if ((ScratchUserBufferOffset + ThisIoRun->
TransferBufferOffset < CurrentUserBufferOffset) &&
01122 (ThisIoRun->
TransferBufferOffset + CurrentByteCount >=
SectorSize( Vcb ))) {
01123
01124 ThisIoRun->
DiskByteCount =
SectorTruncate( Vcb, ThisIoRun->
TransferBufferOffset + CurrentByteCount );
01125 CurrentByteCount = ThisIoRun->
DiskByteCount - ThisIoRun->
TransferBufferOffset;
01126 ThisIoRun->
TransferByteCount = CurrentByteCount;
01127
01128
01129
01130
01131
01132 ThisIoRun->
TransferBuffer = ScratchUserBuffer;
01133 ThisIoRun->
TransferMdl =
Irp->
MdlAddress;
01134 ThisIoRun->
TransferVirtualAddress =
Add2Ptr(
Irp->
UserBuffer,
01135 ScratchUserBufferOffset,
01136 PVOID );
01137
01138 ScratchUserBuffer =
Add2Ptr( ScratchUserBuffer,
01139 ThisIoRun->
DiskByteCount,
01140 PVOID );
01141
01142 ScratchUserBufferOffset += ThisIoRun->
DiskByteCount;
01143
01144
01145
01146
01147
01148 }
else {
01149
01150
01151
01152
01153
01154 ThisIoRun->
DiskByteCount =
SectorAlign( Vcb, ThisIoRun->
TransferBufferOffset + CurrentByteCount );
01155
01156
if (ThisIoRun->
DiskByteCount >
PAGE_SIZE) {
01157
01158 ThisIoRun->
DiskByteCount =
PAGE_SIZE;
01159 }
01160
01161
if (ThisIoRun->
TransferBufferOffset + CurrentByteCount > ThisIoRun->
DiskByteCount) {
01162
01163 CurrentByteCount = ThisIoRun->
DiskByteCount - ThisIoRun->
TransferBufferOffset;
01164 }
01165
01166 ThisIoRun->
TransferByteCount = CurrentByteCount;
01167
01168
01169
01170
01171
01172 ThisIoRun->
TransferBuffer =
FsRtlAllocatePoolWithTag(
UdfNonPagedPool,
01173
PAGE_SIZE,
01174
TAG_IO_BUFFER );
01175
01176
01177
01178
01179
01180 ThisIoRun->
TransferMdl =
IoAllocateMdl( ThisIoRun->
TransferBuffer,
01181
PAGE_SIZE,
01182
FALSE,
01183
FALSE,
01184
NULL );
01185
01186 ThisIoRun->
TransferVirtualAddress = ThisIoRun->
TransferBuffer;
01187
01188
if (ThisIoRun->
TransferMdl ==
NULL) {
01189
01190 IrpContext->Irp->IoStatus.Information = 0;
01191
UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
01192 }
01193
01194
MmBuildMdlForNonPagedPool( ThisIoRun->
TransferMdl );
01195 }
01196
01197
01198
01199
01200
01201 FoundUnaligned =
TRUE;
01202
01203
01204
01205
01206
01207 }
else {
01208
01209
01210
01211
01212
01213
01214
01215 CurrentByteCount =
SectorTruncate( Vcb, CurrentByteCount );
01216
01217
01218
01219
01220
01221 ThisIoRun->
DiskOffset = DiskOffset;
01222 ThisIoRun->
DiskByteCount = CurrentByteCount;
01223
01224
01225
01226
01227
01228
01229 ThisIoRun->
TransferBuffer = CurrentUserBuffer;
01230 ThisIoRun->
TransferMdl =
Irp->
MdlAddress;
01231 ThisIoRun->
TransferVirtualAddress =
Add2Ptr(
Irp->
UserBuffer,
01232 CurrentUserBufferOffset,
01233 PVOID );
01234
01235 ScratchUserBuffer =
Add2Ptr( CurrentUserBuffer,
01236 CurrentByteCount,
01237 PVOID );
01238
01239 ScratchUserBufferOffset += CurrentByteCount;
01240 }
01241
01242
01243
01244
01245
01246
01247 RemainingByteCount -= CurrentByteCount;
01248
01249
01250
01251
01252
01253
01254 *ThisByteCount += CurrentByteCount;
01255
01256
if ((RemainingByteCount == 0) || (*RunCount ==
MAX_PARALLEL_IOS)) {
01257
01258
break;
01259 }
01260
01261
01262
01263
01264
01265 ThisIoRun = IoRuns + *RunCount;
01266 CurrentUserBuffer =
Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID );
01267 CurrentUserBufferOffset += CurrentByteCount;
01268 CurrentFileOffset += CurrentByteCount;
01269 }
01270
01271
return FoundUnaligned;
01272 }
01273
01274
01275
01276
01277
01278
01279 BOOLEAN
01280 UdfFinishBuffers (
01281 IN
PIRP_CONTEXT IrpContext,
01282 IN PIO_RUN IoRuns,
01283 IN ULONG RunCount,
01284 IN BOOLEAN FinalCleanup
01285 )
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321 {
01322 BOOLEAN FlushIoBuffers =
FALSE;
01323
01324 ULONG RemainingEntries = RunCount;
01325
PIO_RUN ThisIoRun = &IoRuns[RunCount - 1];
01326
01327
PAGED_CODE();
01328
01329
01330
01331
01332
01333
while (RemainingEntries != 0) {
01334
01335
01336
01337
01338
01339
if (ThisIoRun->
TransferByteCount != 0) {
01340
01341
01342
01343
01344
01345
01346
01347
if (!FinalCleanup) {
01348
01349
01350
01351
01352
01353
01354
if (ThisIoRun->
TransferMdl == IrpContext->Irp->MdlAddress) {
01355
01356 RtlMoveMemory( ThisIoRun->
UserBuffer,
01357
Add2Ptr( ThisIoRun->
TransferBuffer,
01358 ThisIoRun->
TransferBufferOffset,
01359 PVOID ),
01360 ThisIoRun->
TransferByteCount );
01361
01362 }
else {
01363
01364 RtlCopyMemory( ThisIoRun->
UserBuffer,
01365
Add2Ptr( ThisIoRun->
TransferBuffer,
01366 ThisIoRun->
TransferBufferOffset,
01367 PVOID ),
01368 ThisIoRun->
TransferByteCount );
01369 }
01370
01371 FlushIoBuffers =
TRUE;
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
if (ThisIoRun->
TransferMdl != IrpContext->Irp->MdlAddress) {
01381
01382
if (ThisIoRun->
TransferMdl !=
NULL) {
01383
01384
IoFreeMdl( ThisIoRun->
TransferMdl );
01385 }
01386
01387
01388
01389
01390
01391
01392
if (ThisIoRun->
TransferBuffer !=
NULL) {
01393
01394
UdfFreePool( &ThisIoRun->
TransferBuffer );
01395 }
01396 }
01397 }
01398
01399
01400
01401
01402
01403
01404
if (ThisIoRun->
SavedIrp !=
NULL) {
01405
01406
if (ThisIoRun->
SavedIrp->
MdlAddress !=
NULL) {
01407
01408
IoFreeMdl( ThisIoRun->
SavedIrp->
MdlAddress );
01409 }
01410
01411
IoFreeIrp( ThisIoRun->
SavedIrp );
01412 }
01413
01414
01415
01416
01417
01418 ThisIoRun -= 1;
01419 RemainingEntries -= 1;
01420 }
01421
01422
01423
01424
01425
01426
return FlushIoBuffers;
01427 }
01428
01429
01430
01431
01432
01433
01434
VOID
01435 UdfMultipleAsync (
01436 IN
PIRP_CONTEXT IrpContext,
01437 IN ULONG RunCount,
01438 IN PIO_RUN IoRuns
01439 )
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 {
01482
PIO_COMPLETION_ROUTINE CompletionRoutine;
01483
PIO_STACK_LOCATION IrpSp;
01484
PMDL Mdl;
01485
PIRP Irp;
01486
PIRP MasterIrp;
01487 ULONG UnwindRunCount;
01488
01489
PAGED_CODE();
01490
01491
01492
01493
01494
01495 CompletionRoutine =
UdfMultiSyncCompletionRoutine;
01496
01497
if (!
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
01498
01499 CompletionRoutine =
UdfMultiAsyncCompletionRoutine;
01500 }
01501
01502
01503
01504
01505
01506 MasterIrp = IrpContext->Irp;
01507
01508
01509
01510
01511
01512
01513
for (UnwindRunCount = 0;
01514 UnwindRunCount < RunCount;
01515 UnwindRunCount += 1) {
01516
01517
01518
01519
01520
01521
01522 IoRuns[UnwindRunCount].SavedIrp =
01523
Irp =
IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) );
01524
01525
if (
Irp ==
NULL) {
01526
01527 IrpContext->Irp->IoStatus.Information = 0;
01528
UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
01529 }
01530
01531
01532
01533
01534
01535 Mdl =
IoAllocateMdl( IoRuns[UnwindRunCount].TransferVirtualAddress,
01536 IoRuns[UnwindRunCount].DiskByteCount,
01537
FALSE,
01538
FALSE,
01539
Irp );
01540
01541
if (Mdl ==
NULL) {
01542
01543 IrpContext->Irp->IoStatus.Information = 0;
01544
UdfRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
01545 }
01546
01547
IoBuildPartialMdl( IoRuns[UnwindRunCount].TransferMdl,
01548 Mdl,
01549 IoRuns[UnwindRunCount].TransferVirtualAddress,
01550 IoRuns[UnwindRunCount].DiskByteCount );
01551
01552
01553
01554
01555
01556
IoSetNextIrpStackLocation(
Irp );
01557 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01558
01559
01560
01561
01562
01563 IrpSp->
MajorFunction =
IRP_MJ_READ;
01564 IrpSp->
Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
01565 IrpSp->
Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
01566
01567
01568
01569
01570
01571
IoSetCompletionRoutine(
Irp,
01572 CompletionRoutine,
01573 IrpContext->IoContext,
01574
TRUE,
01575
TRUE,
01576
TRUE );
01577
01578
01579
01580
01581
01582
01583 IrpSp =
IoGetNextIrpStackLocation(
Irp );
01584
01585
01586
01587
01588
01589 IrpSp->
MajorFunction =
IRP_MJ_READ;
01590 IrpSp->
Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
01591 IrpSp->
Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
01592 }
01593
01594
01595
01596
01597
01598
01599
01600
01601 IrpContext->IoContext->IrpCount = RunCount;
01602 IrpContext->IoContext->MasterIrp = MasterIrp;
01603
01604
01605
01606
01607
01608
01609
01610
01611 MasterIrp->
AssociatedIrp.IrpCount = 1;
01612
01613
01614
01615
01616
01617
for (UnwindRunCount = 0;
01618 UnwindRunCount < RunCount;
01619 UnwindRunCount++) {
01620
01621
Irp = IoRuns[UnwindRunCount].SavedIrp;
01622 IoRuns[UnwindRunCount].SavedIrp =
NULL;
01623
01624
01625
01626
01627
01628
01629
01630 (
VOID)
IoCallDriver( IrpContext->Vcb->TargetDeviceObject,
Irp );
01631 }
01632
01633
return;
01634 }
01635
01636
01637
01638
01639
01640
01641
VOID
01642 UdfSingleAsync (
01643 IN
PIRP_CONTEXT IrpContext,
01644 IN LONGLONG ByteOffset,
01645 IN ULONG ByteCount
01646 )
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 {
01671
PIO_STACK_LOCATION IrpSp;
01672
PIO_COMPLETION_ROUTINE CompletionRoutine;
01673
01674
PAGED_CODE();
01675
01676
01677
01678
01679
01680
if (
FlagOn( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT )) {
01681
01682 CompletionRoutine =
UdfSingleSyncCompletionRoutine;
01683
01684 }
else {
01685
01686 CompletionRoutine =
UdfSingleAsyncCompletionRoutine;
01687 }
01688
01689
01690
01691
01692
01693
IoSetCompletionRoutine( IrpContext->Irp,
01694 CompletionRoutine,
01695 IrpContext->IoContext,
01696
TRUE,
01697
TRUE,
01698
TRUE );
01699
01700
01701
01702
01703
01704
01705 IrpSp =
IoGetNextIrpStackLocation( IrpContext->Irp );
01706
01707
01708
01709
01710
01711 IrpSp->
MajorFunction =
IRP_MJ_READ;
01712 IrpSp->
Parameters.Read.Length = ByteCount;
01713 IrpSp->
Parameters.Read.ByteOffset.QuadPart = ByteOffset;
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725 (
VOID)
IoCallDriver( IrpContext->Vcb->TargetDeviceObject, IrpContext->Irp );
01726
01727
01728
01729
01730
01731
return;
01732 }
01733
01734
01735
01736
01737
01738
01739
VOID
01740 UdfWaitSync (
01741 IN
PIRP_CONTEXT IrpContext
01742 )
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 {
01760
PAGED_CODE();
01761
01762
KeWaitForSingleObject( &IrpContext->IoContext->SyncEvent,
01763
Executive,
01764
KernelMode,
01765
FALSE,
01766
NULL );
01767
01768
KeClearEvent( &IrpContext->IoContext->SyncEvent );
01769
01770
return;
01771 }
01772
01773
01774
01775
01776
01777
01778
NTSTATUS
01779 UdfMultiSyncCompletionRoutine (
01780 IN
PDEVICE_OBJECT DeviceObject,
01781 IN
PIRP Irp,
01782 IN PVOID Context
01783 )
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821 {
01822
PUDF_IO_CONTEXT IoContext = Context;
01823
01824
01825
01826
01827
01828
if (!
NT_SUCCESS(
Irp->
IoStatus.Status )) {
01829
01830 InterlockedExchange( &IoContext->
Status,
Irp->
IoStatus.Status );
01831 IoContext->
MasterIrp->
IoStatus.Information = 0;
01832 }
01833
01834
01835
01836
01837
01838
01839
IoFreeMdl(
Irp->
MdlAddress );
01840
IoFreeIrp(
Irp );
01841
01842
if (InterlockedDecrement( &IoContext->
IrpCount ) == 0) {
01843
01844
01845
01846
01847
01848 IoContext->
MasterIrp->
IoStatus.Status = IoContext->
Status;
01849
KeSetEvent( &IoContext->
SyncEvent, 0,
FALSE );
01850 }
01851
01852 UNREFERENCED_PARAMETER( DeviceObject );
01853
01854
return STATUS_MORE_PROCESSING_REQUIRED;
01855 }
01856
01857
01858
01859
01860
01861
01862
NTSTATUS
01863 UdfMultiAsyncCompletionRoutine (
01864 IN
PDEVICE_OBJECT DeviceObject,
01865 IN
PIRP Irp,
01866 IN PVOID Context
01867 )
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898 {
01899
PUDF_IO_CONTEXT IoContext = Context;
01900
PIO_STACK_LOCATION IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01901
01902
01903
01904
01905
01906
if (!
NT_SUCCESS(
Irp->
IoStatus.Status )) {
01907
01908 InterlockedExchange( &IoContext->
Status,
Irp->
IoStatus.Status );
01909 }
01910
01911
01912
01913
01914
01915
if (InterlockedDecrement( &IoContext->
IrpCount ) == 0) {
01916
01917
01918
01919
01920
01921
IoMarkIrpPending( IoContext->
MasterIrp );
01922
01923
01924
01925
01926
01927 IoContext->
MasterIrp->
IoStatus.Status = IoContext->
Status;
01928
01929
01930
01931
01932
01933 IoContext->
MasterIrp->
IoStatus.Information = 0;
01934
01935
if (
NT_SUCCESS( IoContext->
MasterIrp->
IoStatus.Status )) {
01936
01937 IoContext->
MasterIrp->
IoStatus.Information = IoContext->
RequestedByteCount;
01938 }
01939
01940
01941
01942
01943
01944
ExReleaseResourceForThread( IoContext->
Resource,
01945 IoContext->
ResourceThreadId );
01946
01947
01948
01949
01950
01951
UdfFreeIoContext( IoContext );
01952
01953
01954
01955
01956
01957
return STATUS_SUCCESS;
01958
01959 }
else {
01960
01961
01962
01963
01964
01965
IoFreeMdl(
Irp->
MdlAddress );
01966
IoFreeIrp(
Irp );
01967
01968
return STATUS_MORE_PROCESSING_REQUIRED;
01969 }
01970
01971 UNREFERENCED_PARAMETER( DeviceObject );
01972 }
01973
01974
01975
01976
01977
01978
01979
NTSTATUS
01980 UdfSingleSyncCompletionRoutine (
01981 IN
PDEVICE_OBJECT DeviceObject,
01982 IN
PIRP Irp,
01983 IN PVOID Context
01984 )
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016 {
02017
02018
02019
02020
02021
if (!
NT_SUCCESS(
Irp->
IoStatus.Status )) {
02022
02023
Irp->
IoStatus.Information = 0;
02024 }
02025
02026
KeSetEvent( &((
PUDF_IO_CONTEXT)Context)->SyncEvent, 0,
FALSE );
02027
02028
return STATUS_MORE_PROCESSING_REQUIRED;
02029
02030 UNREFERENCED_PARAMETER( DeviceObject );
02031 }
02032
02033
02034
02035
02036
02037
02038
NTSTATUS
02039 UdfSingleAsyncCompletionRoutine (
02040 IN
PDEVICE_OBJECT DeviceObject,
02041 IN
PIRP Irp,
02042 IN PVOID Context
02043 )
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068 {
02069
02070
02071
02072
02073
Irp->
IoStatus.Information = 0;
02074
02075
if (
NT_SUCCESS(
Irp->
IoStatus.Status )) {
02076
02077
Irp->
IoStatus.Information = ((
PUDF_IO_CONTEXT) Context)->RequestedByteCount;
02078 }
02079
02080
02081
02082
02083
02084
IoMarkIrpPending(
Irp );
02085
02086
02087
02088
02089
02090
ExReleaseResourceForThread( ((
PUDF_IO_CONTEXT) Context)->
Resource,
02091 ((
PUDF_IO_CONTEXT) Context)->ResourceThreadId );
02092
02093
02094
02095
02096
02097
UdfFreeIoContext( (
PUDF_IO_CONTEXT) Context );
02098
return STATUS_SUCCESS;
02099
02100 UNREFERENCED_PARAMETER( DeviceObject );
02101 }
02102