00592 :
00593
00594 The following code
is called
only when doing
IRP tracking. It duplicates code
00595 in iosubs.c.
00596 This routine
is invoked to complete an I/O request. It
is invoked by
the
00597 driver in its DPC routine to perform
the final completion of
the IRP. The
00598
functions performed by
this routine are as follows.
00599
00600 1.
A check
is made to determine whether
the packet's stack locations
00601 have been exhausted. If not, then
the stack location pointer
is set
00602 to
the next location and
if there
is a routine to be invoked, then
00603
it will be invoked. This continues until there are either no more
00604
routines which are interested or
the packet runs
out of stack.
00605
00606 If a routine
is invoked to complete
the packet
for a specific driver
00607 which needs to perform work a lot of work or
the work needs to be
00608 performed in
the context of another process, then
the routine will
00609
return an alternate success code of STATUS_MORE_PROCESSING_REQUIRED.
00610 This indicates that
this completion routine should simply
return to
00611 its caller because
the operation will be
"completed" by
this routine
00612 again sometime in
the future.
00613
00614 2.
A check
is made to determine whether
this IRP is an associated
IRP.
00615 If
it is, then
the count on
the master
IRP is decremented. If
the
00616 count
for the master becomes zero, then
the master
IRP will be
00617 completed according to
the steps below taken
for a normal
IRP being
00618 completed. If
the count
is still non-zero, then
this IRP (the one
00619 being completed) will simply be deallocated.
00620
00621 3. If
this is paging I/O or a close operation, then simply write
the
00622 I/O status block and set
the event to
the signaled state, and
00623 dereference
the event. If
this is paging I/O, deallocate
the IRP
00624 as well.
00625
00626 4.
Unlock the pages,
if any, specified by
the MDL by calling
00627
MmUnlockPages.
00628
00629 5.
A check
is made to determine whether or not completion of
the
00630 request can be deferred until later. If
it can be, then
this
00631 routine simply exits and leaves
it up to
the originator of
the
00632 request to fully complete
the IRP. By not initializing and queueing
00633
the special kernel APC to
the calling thread (which is the current
00634 thread by definition), a lot of interrupt and queueing processing
00635 can be avoided.
00636
00637
00638 6. The
final rundown routine
is invoked to queue
the request packet to
00639
the target (requesting) thread as a special kernel mode APC.
00640
00641 Arguments:
00642
00643 Irp - Pointer to the I/O Request Packet to complete.
00644
00645 PriorityBoost - Supplies the amount of priority boost that is to be given
00646 to the target thread when the special kernel APC is queued.
00647
00648 Return Value:
00649
00650 None.
00651
00652 --*/
00653
00654 #define ZeroAndDopeIrpStackLocation( IrpSp ) { \
00655 (IrpSp)->MinorFunction = 0; \
00656 (IrpSp)->Flags = 0; \
00657 (IrpSp)->Control =
SL_NOTCOPIED; \
00658 (IrpSp)->Parameters.Others.Argument1 = 0; \
00659 (IrpSp)->Parameters.Others.Argument2 = 0; \
00660 (IrpSp)->Parameters.Others.Argument3 = 0; \
00661 (IrpSp)->Parameters.Others.Argument4 = 0; \
00662 (IrpSp)->FileObject = (
PFILE_OBJECT)
NULL; }
00663
00664 {
00665
PIRP masterIrp;
00666
NTSTATUS status;
00667
PIO_STACK_LOCATION stackPointer;
00668
PMDL mdl;
00669
PETHREAD thread;
00670
PFILE_OBJECT fileObject;
00671 KIRQL irql;
00672 PVOID saveAuxiliaryPointer =
NULL;
00673
00674
#ifndef NO_SPECIAL_IRP
00675
PVOID routine ;
00676
IOFCOMPLETEREQUEST_STACKDATA completionPacket;
00677
#endif
00678
00679
if (!
IopVerifierOn) {
00680
IopfCompleteRequest(Irp, PriorityBoost);
00681
return;
00682 }
00683
00684
#if DBG
00685
00686
if (
Irp->
CurrentLocation <= (CCHAR)
Irp->
StackCount) {
00687
00688 stackPointer =
IoGetCurrentIrpStackLocation(Irp);
00689
if (stackPointer->
MajorFunction ==
IRP_MJ_POWER) {
00690
PoPowerTrace(
00691 POWERTRACE_COMPLETE,
00692
IoGetCurrentIrpStackLocation(Irp)->DeviceObject,
00693 Irp,
00694
IoGetCurrentIrpStackLocation(Irp)
00695 );
00696 }
00697 }
00698
00699
#endif
00700
00701
SPECIALIRP_IOF_COMPLETE_1(Irp, PriorityBoost, &completionPacket);
00702
00703
00704
00705
00706
00707
00708
if (
Irp->
CurrentLocation > (CCHAR) (
Irp->
StackCount + 1) ||
00709
Irp->
Type !=
IO_TYPE_IRP) {
00710
KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR) Irp, __LINE__, 0, 0 );
00711 }
00712
00713
00714
00715
00716
00717
if (
Irp->
Type !=
IO_TYPE_IRP) {
00718
00719
KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
00720 IO_CALL_DRIVER_IRP_TYPE_INVALID,
00721 (ULONG_PTR)Irp,
00722 0,
00723 0);
00724 }
00725
00726
00727
00728
00729
00730
00731
if (
Irp->
CancelRoutine) {
00732
00733
ASSERT(
Irp->
CancelRoutine == NULL);
00734
00735
KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
00736 IO_COMPLETE_REQUEST_CANCEL_ROUTINE_SET,
00737 (ULONG_PTR)
Irp->
CancelRoutine,
00738 (ULONG_PTR)Irp,
00739 0);
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
if (
Irp->
IoStatus.Status == STATUS_PENDING) {
00749
00750
00751
KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
00752 IO_COMPLETE_REQUEST_INVALID_STATUS,
00753
Irp->
IoStatus.Status,
00754 (ULONG_PTR)Irp,
00755 0);
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
if (
Irp->
IoStatus.Status == 0xffffffff) {
00765
00766
00767
KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
00768 IO_COMPLETE_REQUEST_INVALID_STATUS,
00769
Irp->
IoStatus.Status,
00770 (ULONG_PTR)Irp,
00771 0);
00772 }
00773
00774
00775
00776
00777
00778
00779
ASSERT( !(
Irp->
Flags & IRP_PAGING_IO &&
Irp->
IoStatus.Status == STATUS_QUOTA_EXCEEDED ) );
00780
00781
#ifndef NO_SPECIAL_IRP
00782
00783
if (!
IovpTrackingFlags) {
00784
00785
IopfCompleteRequest(Irp, PriorityBoost);
00786
return;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
for (stackPointer =
IoGetCurrentIrpStackLocation( Irp ),
00799
Irp->
CurrentLocation++,
00800
Irp->
Tail.Overlay.CurrentStackLocation++;
00801
Irp->
CurrentLocation <= (CCHAR) (
Irp->
StackCount + 1);
00802 stackPointer++,
00803
Irp->
CurrentLocation++,
00804
Irp->
Tail.Overlay.CurrentStackLocation++) {
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
Irp->
PendingReturned = stackPointer->
Control &
SL_PENDING_RETURNED;
00816
00817
SPECIALIRP_IOF_COMPLETE_2(Irp, &completionPacket);
00818
00819
if ( (
NT_SUCCESS(
Irp->
IoStatus.Status ) &&
00820 stackPointer->
Control &
SL_INVOKE_ON_SUCCESS) ||
00821 (!
NT_SUCCESS(
Irp->
IoStatus.Status ) &&
00822 stackPointer->
Control &
SL_INVOKE_ON_ERROR) ||
00823 (
Irp->
Cancel &&
00824 stackPointer->
Control &
SL_INVOKE_ON_CANCEL)
00825 ) {
00826
00827
00828
00829
00830
00831
00832
00833
ZeroAndDopeIrpStackLocation( stackPointer );
00834
00835
#ifndef NO_SPECIAL_IRP
00836
routine = stackPointer->
CompletionRoutine ;
00837
SPECIALIRP_IOF_COMPLETE_3(Irp, routine, &completionPacket);
00838
#endif
00839
00840
PERFINFO_DRIVER_COMPLETIONROUTINE_CALL(Irp, stackPointer);
00841
00842 status = stackPointer->
CompletionRoutine( (
PDEVICE_OBJECT) (
Irp->
CurrentLocation == (CCHAR) (
Irp->
StackCount + 1) ?
00843 (
PDEVICE_OBJECT) NULL :
00844
IoGetCurrentIrpStackLocation( Irp )->DeviceObject),
00845 Irp,
00846 stackPointer->
Context );
00847
00848
PERFINFO_DRIVER_COMPLETIONROUTINE_RETURN(Irp, stackPointer);
00849
00850
SPECIALIRP_IOF_COMPLETE_4(Irp, status, &completionPacket);
00851
00852
if (status == STATUS_MORE_PROCESSING_REQUIRED) {
00853
00854
00855
00856
00857
00858
00859
00860
00861
SPECIALIRP_IOF_COMPLETE_5(Irp, &completionPacket);
00862
return;
00863 }
00864
00865 }
else {
00866
if (
Irp->
PendingReturned &&
Irp->
CurrentLocation <=
Irp->
StackCount) {
00867
IoMarkIrpPending( Irp );
00868 }
00869
ZeroAndDopeIrpStackLocation( stackPointer );
00870 }
00871
00872
SPECIALIRP_IOF_COMPLETE_5(Irp, &completionPacket);
00873 }
00874
00875
00876
00877
00878
00879
00880
00881
if (
Irp->
Flags &
IRP_ASSOCIATED_IRP) {
00882 ULONG count;
00883 masterIrp =
Irp->
AssociatedIrp.MasterIrp;
00884 count =
ExInterlockedAddUlong( (PULONG) &masterIrp->
AssociatedIrp.IrpCount,
00885 0xffffffff,
00886 &IopDatabaseLock );
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
Irp->
Tail.Overlay.Thread = masterIrp->
Tail.Overlay.Thread;
00900
IopFreeIrpAndMdls( Irp );
00901
if (count == 1) {
00902
IoCompleteRequest( masterIrp, PriorityBoost );
00903 }
00904
return;
00905 }
00906
00907
00908
00909
00910
00911
00912
if ((
Irp->
IoStatus.Status == STATUS_REPARSE ) &&
00913 (
Irp->
IoStatus.Information > IO_REPARSE_TAG_RESERVED_RANGE)) {
00914
00915
if (
Irp->
IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) {
00916
00917
00918
00919
00920
00921
00922
ASSERT(
Irp->
Tail.Overlay.AuxiliaryBuffer != NULL );
00923
00924 saveAuxiliaryPointer = (PVOID)
Irp->
Tail.Overlay.AuxiliaryBuffer;
00925
00926
00927
00928
00929
00930
00931
Irp->
Tail.Overlay.AuxiliaryBuffer =
NULL;
00932 }
else {
00933
00934
00935
00936
00937
00938
00939
Irp->
IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED;
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
if (
Irp->
Tail.Overlay.AuxiliaryBuffer) {
00951
ExFreePool(
Irp->
Tail.Overlay.AuxiliaryBuffer );
00952
Irp->
Tail.Overlay.AuxiliaryBuffer =
NULL;
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
if (
Irp->
Flags & (
IRP_PAGING_IO |
IRP_CLOSE_OPERATION)) {
00999
if (
Irp->
Flags & (
IRP_SYNCHRONOUS_PAGING_IO |
IRP_CLOSE_OPERATION)) {
01000 ULONG flags;
01001
01002 flags =
Irp->
Flags &
IRP_SYNCHRONOUS_PAGING_IO;
01003 *
Irp->
UserIosb =
Irp->
IoStatus;
01004 (
VOID)
KeSetEvent(
Irp->
UserEvent, PriorityBoost, FALSE );
01005
if (flags) {
01006
IoFreeIrp( Irp );
01007 }
01008 }
else {
01009 thread =
Irp->
Tail.Overlay.Thread;
01010
KeInitializeApc( &
Irp->
Tail.Apc,
01011 &thread->
Tcb,
01012
Irp->
ApcEnvironment,
01013 IopCompletePageWrite,
01014 (PKRUNDOWN_ROUTINE) NULL,
01015 (PKNORMAL_ROUTINE) NULL,
01016 KernelMode,
01017 (PVOID) NULL );
01018 (
VOID)
KeInsertQueueApc( &
Irp->
Tail.Apc,
01019 (PVOID) NULL,
01020 (PVOID) NULL,
01021 PriorityBoost );
01022 }
01023
return;
01024 }
01025
01026
01027
01028
01029
01030
if (
Irp->
MdlAddress !=
NULL) {
01031
01032
01033
01034
01035
01036 mdl =
Irp->
MdlAddress;
01037
while (mdl !=
NULL) {
01038
MmUnlockPages( mdl );
01039 mdl = mdl->
Next;
01040 }
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
if (
Irp->
Flags &
IRP_DEFER_IO_COMPLETION && !
Irp->
PendingReturned) {
01051
01052
if ((
Irp->
IoStatus.Status == STATUS_REPARSE ) &&
01053 (
Irp->
IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)) {
01054
01055
01056
01057
01058
01059
01060
Irp->
Tail.Overlay.AuxiliaryBuffer = saveAuxiliaryPointer;
01061 }
01062
01063
return;
01064 }
01065
01066
01067
01068
01069
01070
01071 thread =
Irp->
Tail.Overlay.Thread;
01072 fileObject =
Irp->
Tail.Overlay.OriginalFileObject;
01073
01074
if (!
Irp->
Cancel) {
01075
01076
KeInitializeApc( &
Irp->
Tail.Apc,
01077 &thread->
Tcb,
01078
Irp->
ApcEnvironment,
01079 IopCompleteRequest,
01080 IopAbortRequest,
01081 (PKNORMAL_ROUTINE) NULL,
01082 KernelMode,
01083 (PVOID) NULL );
01084
01085 (
VOID)
KeInsertQueueApc( &
Irp->
Tail.Apc,
01086 fileObject,
01087 (PVOID) saveAuxiliaryPointer,
01088 PriorityBoost );
01089 }
else {
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 ExAcquireSpinLock( &IopCompletionLock, &irql );
01106
01107 thread =
Irp->
Tail.Overlay.Thread;
01108
01109
if (thread) {
01110
01111
KeInitializeApc( &
Irp->
Tail.Apc,
01112 &thread->
Tcb,
01113
Irp->
ApcEnvironment,
01114 IopCompleteRequest,
01115 IopAbortRequest,
01116 (PKNORMAL_ROUTINE) NULL,
01117 KernelMode,
01118 (PVOID) NULL );
01119
01120 (
VOID)
KeInsertQueueApc( &
Irp->
Tail.Apc,
01121 fileObject,
01122 (PVOID) saveAuxiliaryPointer,
01123 PriorityBoost );
01124
01125 ExReleaseSpinLock( &IopCompletionLock, irql );
01126
01127 }
else {
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 ExReleaseSpinLock( &IopCompletionLock, irql );
01138
01139
ASSERT(
Irp->
Cancel );
01140
01141
01142
01143
01144
01145
IopDropIrp( Irp, fileObject );
01146
01147 }
01148 }
01149
#else
01150
01151
IopfCompleteRequest(Irp, PriorityBoost);
01152
return;
01153
01154
#endif
01155
}