test: ioverifier.h File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# ioverifier.h File Reference

`#include "ioassert.h"`
`#include "trackirp.h"`
`#include "flunkirp.h"`
`#include "hashirp.h"`
`#include "sessnirp.h"`

Go to the source code of this file.

## Classes

struct | _IOV_INIT_DATA

## Defines

#define | IOVP_COMPLETE_REQUEST(Apc, Sa1, Sa2)
#define | IOV_INITIALIZE_IRP(Irp, PacketSize, StackSize)
#define | IOV_DELETE_DEVICE(DeviceObject)
#define | IOV_DETACH_DEVICE(DeviceObject)
#define | IOV_ATTACH_DEVICE_TO_DEVICE_STACK(SourceDeviceObject, TargetDeviceObject)
#define | IOV_CANCEL_IRP(Irp, ReturnValue) IovCancelIrp((Irp), (ReturnValue))

## Typedefs

typedef _IOV_INIT_DATA | IOV_INIT_DATA
typedef _IOV_INIT_DATA * | PIOV_INIT_DATA

## Functions

NTSTATUS FASTCALL | IovSpecialIrpCallDriver (IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
VOID FASTCALL | IovSpecialIrpCompleteRequest (IN PIRP Irp, IN CCHAR PriorityBoost)
VOID | IovpSpecialIrpVerifierInitWorker (IN PVOID Parameter)
VOID | IovpCompleteRequest (IN PKAPC Apc, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID | IovInitializeIrp (PIRP Irp, USHORT PacketSize, CCHAR StackSize)
VOID | IovAttachDeviceToDeviceStack (PDEVICE_OBJECT SourceDevice, PDEVICE_OBJECT TargetDevice)
VOID | IovDeleteDevice (PDEVICE_OBJECT DeleteDevice)
VOID | IovDetachDevice (PDEVICE_OBJECT TargetDevice)
BOOLEAN | IovCancelIrp (PIRP Irp, BOOLEAN *returnValue)

## Define Documentation

#define IOV_ATTACH_DEVICE_TO_DEVICE_STACK | ( | SourceDeviceObject,
|  | TargetDeviceObject |  | ) |

Value:

    {   \
            if (IopVerifierOn) \
                IovAttachDeviceToDeviceStack((SourceDeviceObject), (TargetDeviceObject));   \
        }

Definition at line 63 of file ioverifier.h.

Referenced by IoAttachDeviceToDeviceStack().

#define IOV_CANCEL_IRP | ( | Irp,
|  | ReturnValue |  | ) | IovCancelIrp((Irp), (ReturnValue))

| Definition at line 69 of file ioverifier.h. Referenced by IoCancelIrp().

#define IOV_DELETE_DEVICE | ( | DeviceObject |  | ) |

Value:

    {   \
            if (IopVerifierOn) \
                IovDeleteDevice(DeviceObject);   \
        }

Definition at line 51 of file ioverifier.h.

Referenced by IoDeleteDevice().

#define IOV_DETACH_DEVICE | ( | DeviceObject |  | ) |

Value:

    {   \
            if (IopVerifierOn) \
                IovDetachDevice(DeviceObject);   \
        }

Definition at line 57 of file ioverifier.h.

Referenced by IoDetachDevice().

#define IOV_INITIALIZE_IRP | ( | Irp,
|  | PacketSize,
|  | StackSize |  | ) |

Value:

    {   \
            if (IopVerifierOn) \
                IovInitializeIrp((Irp), (PacketSize), (StackSize));   \
        }

Definition at line 45 of file ioverifier.h.

Referenced by IoInitializeIrp().

#define IOVP_COMPLETE_REQUEST | ( | Apc,
|  | Sa1,
|  | Sa2 |  | ) |

Value:

    {   \
            if (IopVerifierOn) \
                IovpCompleteRequest((Apc), (Sa1), (Sa2));   \
        }

Definition at line 39 of file ioverifier.h.

Referenced by IopCompleteRequest().

## Typedef Documentation

typedef struct _IOV_INIT_DATA IOV_INIT_DATA

typedef struct _IOV_INIT_DATA * PIOV_INIT_DATA

## Function Documentation

VOID IovAttachDeviceToDeviceStack | ( | PDEVICE_OBJECT | SourceDevice,
|  | PDEVICE_OBJECT | TargetDevice
| ) |

Definition at line 1296 of file ioverifier.c.

References IovpVerifierLevel, SPECIALIRP_IO_ATTACH_DEVICE_TO_DEVICE_STACK, and VOID().

    01300 {
    01301     if (IovpVerifierLevel < 2) {
    01302         return;
    01303     }
    01304
    01305     SPECIALIRP_IO_ATTACH_DEVICE_TO_DEVICE_STACK(SourceDevice, TargetDevice);
    01306 }

BOOLEAN IovCancelIrp | ( | PIRP | Irp,
|  | BOOLEAN * | returnValue
| ) |

Definition at line 1332 of file ioverifier.c.

References FALSE, Irp, SPECIALIRP_IO_CANCEL_IRP, and TRUE.

    01336 {
    01337 #ifndef NO_SPECIAL_IRP
    01338     BOOLEAN cancelHandled ;
    01339
    01340     SPECIALIRP_IO_CANCEL_IRP(Irp, &cancelHandled, returnValue) ;
    01341
    01342     if (cancelHandled) {
    01343
    01344        return TRUE ;
    01345     }
    01346 #endif
    01347     return FALSE;
    01348 }

VOID IovDeleteDevice | ( | PDEVICE_OBJECT | DeleteDevice | ) |

Definition at line 1309 of file ioverifier.c.

References IovpVerifierLevel, SPECIALIRP_IO_DELETE_DEVICE, and VOID().

    01312 {
    01313     if (IovpVerifierLevel < 2) {
    01314         return;
    01315     }
    01316
    01317     SPECIALIRP_IO_DELETE_DEVICE(DeleteDevice);
    01318 }

VOID IovDetachDevice | ( | PDEVICE_OBJECT | TargetDevice | ) |

Definition at line 1321 of file ioverifier.c.

References IovpVerifierLevel, SPECIALIRP_IO_DETACH_DEVICE, and VOID().

    01324 {
    01325     if (IovpVerifierLevel < 2) {
    01326         return;
    01327     }
    01328     SPECIALIRP_IO_DETACH_DEVICE(TargetDevice);
    01329 }

VOID IovInitializeIrp | ( | PIRP | Irp,
|  | USHORT | PacketSize,
|  | CCHAR | StackSize
| ) |

Definition at line 1279 of file ioverifier.c.

References IovpVerifierLevel, Irp, SPECIALIRP_IO_INITIALIZE_IRP, and VOID().

    01284 {
    01285     BOOLEAN initializeHandled ;
    01286
    01287     if (IovpVerifierLevel < 2) {
    01288         return;
    01289     }
    01290
    01291     SPECIALIRP_IO_INITIALIZE_IRP(Irp, PacketSize, StackSize, &initializeHandled) ;
    01292
    01293 }

VOID IovpCompleteRequest | ( | IN PKAPC | Apc,
|  | IN PVOID * | SystemArgument1,
|  | IN PVOID * | SystemArgument2
| ) |

Definition at line 542 of file ioverifier.c.

References IO_INVALID_STACK_EVENT, IO_INVALID_STACK_IOSB, KeBugCheckEx(), KeGetCurrentThread, _IRP::UserEvent, _IRP::UserIosb, and VOID().

    00547 {
    00548     PIRP    irp;
    00549     PUCHAR addr;
    00550     ULONG   BestStackOffset;
    00551
    00552     irp = CONTAINING_RECORD( Apc, IRP, Tail.Apc );
    00553
    00554 #if defined(_X86_)
    00555
    00556
    00557     addr = (PUCHAR)irp->UserIosb;
    00558     if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
    00559         (addr <= (PUCHAR)&BestStackOffset)) {
    00560         KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
    00561                      IO_INVALID_STACK_IOSB,
    00562                      (ULONG_PTR)addr,
    00563                      0,
    00564                      0);
    00565
    00566     }
    00567
    00568     addr = (PUCHAR)irp->UserEvent;
    00569     if ((addr > (PUCHAR)KeGetCurrentThread()->StackLimit) &&
    00570         (addr <= (PUCHAR)&BestStackOffset)) {
    00571         KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
    00572                      IO_INVALID_STACK_EVENT,
    00573                      (ULONG_PTR)addr,
    00574                      0,
    00575                      0);
    00576
    00577     }
    00578 #endif
    00579 }

VOID IovpSpecialIrpVerifierInitWorker | ( | IN PVOID | Parameter | ) |

NTSTATUS FASTCALL IovSpecialIrpCallDriver | ( | IN PDEVICE_OBJECT | DeviceObject,
|  | IN OUT PIRP | Irp
| ) |

Definition at line 1159 of file ioverifier.c.

References ASSERT, _IRP::CurrentLocation, DbgPrint, _IO_STACK_LOCATION::DeviceObject, FASTCALL, IO_CALL_DRIVER_INVALID_DEVICE_OBJECT, IO_CALL_DRIVER_IRP_TYPE_INVALID, IO_CALL_DRIVER_IRQL_NOT_EQUAL, IO_TYPE_IRP, IOFCALLDRIVER_STACKDATA, IoGetNextIrpStackLocation, IopfCallDriver(), IopVerifierOn, IovpValidateDeviceObject(), Irp, KeBugCheckEx(), _IO_STACK_LOCATION::MajorFunction, _DRIVER_OBJECT::MajorFunction, NTSTATUS(), PDRIVER_DISPATCH, PERFINFO_DRIVER_MAJORFUNCTION_CALL, PERFINFO_DRIVER_MAJORFUNCTION_RETURN, SPECIALIRP_IOF_CALL_1, SPECIALIRP_IOF_CALL_2, _IRP::Tail, and _IRP::Type.

Referenced by IovCallDriver(), and IoVerifierInit().

    01165                    :
    01166
    01167     This routine is invoked to pass an I/O Request Packet (IRP) to another
    01168     driver at its dispatch routine. This routine is called only for IRP tracking
    01169     It duplicates the code in iosubs.c.
    01170
    01171 Arguments:
    01172
    01173     DeviceObject - Pointer to device object to which the IRP should be passed.
    01174
    01175     Irp - Pointer to IRP for request.
    01176
    01177 Return Value:
    01178
    01179     Return status from driver's dispatch routine.
    01180
    01181 --*/
    01182
    01183 {
    01184     PIO_STACK_LOCATION irpSp;
    01185     PDRIVER_OBJECT driverObject;
    01186     NTSTATUS status;
    01187     KIRQL saveIrql;
    01188     PDRIVER_DISPATCH dispatchRoutine;
    01189     IOFCALLDRIVER_STACKDATA iofCallDriverStackData ;
    01190
    01191     if (!IopVerifierOn) {
    01192         status = IopfCallDriver(DeviceObject, Irp);
    01193         return status;
    01194     }
    01195
    01196     //
    01197     // Ensure that this is really an I/O Request Packet.
    01198     //
    01199
    01200     if (Irp->Type != IO_TYPE_IRP) {
    01201
    01202         ASSERT(Irp->Type == IO_TYPE_IRP);
    01203         KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
    01204                      IO_CALL_DRIVER_IRP_TYPE_INVALID,
    01205                      (ULONG_PTR)Irp,
    01206                      0,
    01207                      0);
    01208     }
    01209
    01210     if (!IovpValidateDeviceObject(DeviceObject)) {
    01211         KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
    01212                      IO_CALL_DRIVER_INVALID_DEVICE_OBJECT,
    01213                      (ULONG_PTR)DeviceObject,
    01214                      0,
    01215                      0);
    01216     }
    01217
    01218     SPECIALIRP_IOF_CALL_1(&Irp, DeviceObject, &iofCallDriverStackData) ;
    01219
    01220     //
    01221     // Update the IRP stack to point to the next location.
    01222     //
    01223     Irp->CurrentLocation--;
    01224
    01225     if (Irp->CurrentLocation <= 0) {
    01226         KeBugCheckEx( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0, 0 );
    01227     }
    01228
    01229     irpSp = IoGetNextIrpStackLocation( Irp );
    01230     Irp->Tail.Overlay.CurrentStackLocation = irpSp;
    01231
    01232     //
    01233     // Save a pointer to the device object for this request so that it can
    01234     // be used later in completion.
    01235     //
    01236
    01237     irpSp->DeviceObject = DeviceObject;
    01238
    01239     //
    01240     // Invoke the driver at its dispatch routine entry point.
    01241     //
    01242
    01243     driverObject = DeviceObject->DriverObject;
    01244
    01245     dispatchRoutine = driverObject->MajorFunction[irpSp->MajorFunction] ;
    01246
    01247     saveIrql = KeGetCurrentIrql();
    01248
    01249     PERFINFO_DRIVER_MAJORFUNCTION_CALL(Irp, irpSp, driverObject);
    01250
    01251     status = dispatchRoutine( DeviceObject, Irp );
    01252
    01253     PERFINFO_DRIVER_MAJORFUNCTION_RETURN(Irp, irpSp, driverObject);
    01254
    01255     if (saveIrql != KeGetCurrentIrql()) {
    01256
    01257         DbgPrint( "IO: IoCallDriver( Driver object: %p  Device object: %p  Irp: %p )\n",
    01258                   driverObject,
    01259                   DeviceObject,
    01260                   Irp
    01261                 );
    01262         DbgPrint( "    Irql before: %x  != After: %x\n", saveIrql, KeGetCurrentIrql() );
    01263
    01264         ASSERT(saveIrql == KeGetCurrentIrql());
    01265
    01266         KeBugCheckEx(DRIVER_VERIFIER_IOMANAGER_VIOLATION,
    01267                      IO_CALL_DRIVER_IRQL_NOT_EQUAL,
    01268                      saveIrql,
    01269                      KeGetCurrentIrql(),
    01270                      0);
    01271     }
    01272
    01273     SPECIALIRP_IOF_CALL_2(Irp, DeviceObject, dispatchRoutine, &status, &iofCallDriverStackData) ;
    01274
    01275     return status;
    01276 }

VOID FASTCALL IovSpecialIrpCompleteRequest | ( | IN PIRP | Irp,
|  | IN CCHAR | PriorityBoost
| ) |

Definition at line 586 of file ioverifier.c.

References FASTCALL, NULL, SL_NOTCOPIED, and ZeroAndDopeIrpStackLocation.

Referenced by IovCompleteRequest(), and IoVerifierInit().

    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     // Begin by ensuring that this packet has not already been completed
    00705     // by someone.
    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     // Ensure that the packet being completed really is still an IRP.
    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     // Ensure that no one believes that this request is still in a cancellable
    00728     // state.
    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     // Ensure that the packet is not being completed with a thoroughly
    00744     // confusing status code.  Actually completing a packet with a pending
    00745     // status probably means that someone forgot to set the real status in
    00746     // the packet.
    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     // Ensure that the packet is not being completed with a minus one.  This is
    00760     // apparently a common problem in some drivers, and has no meaning as a
    00761     // status code.
    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     // Ensure that if this is a paging I/O operation, and it failed, that the
    00776     // reason for the failure isn't because quota was exceeded.
    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     // Now check to see whether this is the last driver that needs to be
    00791     // invoked for this packet.  If not, then bump the stack and check to
    00792     // see whether the driver wishes to see the completion.  As each stack
    00793     // location is examined, invoke any routine which needs to be invoked.
    00794     // If the routine returns STATUS_MORE_PROCESSING_REQUIRED, then stop the
    00795     // processing of this packet.
    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         // A stack location was located.  Check to see whether or not it
    00808         // has a completion routine and if so, whether or not it should be
    00809         // invoked.
    00810         //
    00811         // Begin by saving the pending returned flag in the current stack
    00812         // location in the fixed part of the IRP.
    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             // This driver has specified a completion routine.  Invoke the
    00829             // routine passing it a pointer to its device object and the
    00830             // IRP that is being completed.
    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                 // Note:  Notice that if the driver has returned the above
    00856                 //        status value, it may have already DEALLOCATED the
    00857                 //        packet!  Therefore, do NOT touch any part of the
    00858                 //        IRP in the following code.
    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     // Check to see whether this is an associated IRP.  If so, then decrement
    00877     // the count in the master IRP.  If the count is decremented to zero,
    00878     // then complete the master packet as well.
    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         // Deallocate this packet and any MDLs that are associated with it
    00890         // by either doing direct deallocations if they were allocated from
    00891         // a zone or by queueing the packet to a thread to perform the
    00892         // deallocation.
    00893         //
    00894         // Also, check the count of the master IRP to determine whether or not
    00895         // the count has gone to zero.  If not, then simply get out of here.
    00896         // Otherwise, complete the master packet.
    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     // Check to see if we have a name junction. If so set the stage to
    00909     // transmogrify the reparse point data in IopCompleteRequest.
    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             // For name junctions, we save the pointer to the auxiliary
    00919             // buffer and use it below.
    00920             //
    00921
    00922             ASSERT( Irp->Tail.Overlay.AuxiliaryBuffer != NULL );
    00923
    00924             saveAuxiliaryPointer = (PVOID) Irp->Tail.Overlay.AuxiliaryBuffer;
    00925
    00926             //
    00927             // We NULL the entry to avoid its de-allocation at this time.
    00928             // This buffer get deallocated in IopDoNameTransmogrify
    00929             //
    00930
    00931             Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
    00932         } else {
    00933
    00934             //
    00935             // Fail the request. A driver needed to act on this IRP prior
    00936             // to getting to this point.
    00937             //
    00938
    00939             Irp->IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED;
    00940         }
    00941     }
    00942
    00943     //
    00944     // Check the auxiliary buffer pointer in the packet and if a buffer was
    00945     // allocated, deallocate it now.  Note that this buffer must be freed
    00946     // here since the pointer is overlayed with the APC that will be used
    00947     // to get to the requesting thread's context.
    00948     //
    00949
    00950     if (Irp->Tail.Overlay.AuxiliaryBuffer) {
    00951         ExFreePool( Irp->Tail.Overlay.AuxiliaryBuffer );
    00952         Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
    00953     }
    00954
    00955     //
    00956     // Check to see if this is paging I/O or a close operation.  If either,
    00957     // then special processing must be performed.  The reasons that special
    00958     // processing must be performed is different based on the type of
    00959     // operation being performed.  The biggest reasons for special processing
    00960     // on paging operations are that using a special kernel APC for an in-
    00961     // page operation cannot work since the special kernel APC can incur
    00962     // another pagefault.  Likewise, all paging I/O uses MDLs that belong
    00963     // to the memory manager, not the I/O system.
    00964     //
    00965     // Close operations are special because the close may have been invoked
    00966     // because of a special kernel APC (some IRP was completed which caused
    00967     // the reference count on the object to become zero while in the I/O
    00968     // system's special kernel APC routine).  Therefore, a special kernel APC
    00969     // cannot be used since it cannot execute until the close APC finishes.
    00970     //
    00971     // The special steps are as follows for a synchronous paging operation
    00972     // and close are:
    00973     //
    00974     //     1.  Copy the I/O status block (it is in SVAS, nonpaged).
    00975     //     2.  Signal the event
    00976     //     3.  If paging I/O, deallocate the IRP
    00977     //
    00978     // The special steps taken for asynchronous paging operations (out-pages)
    00979     // are as follows:
    00980     //
    00981     //     1.  Initialize a special kernel APC just for page writes.
    00982     //     1.  Queue the special kernel APC.
    00983     //
    00984     // It should also be noted that the logic for completing a Mount request
    00985     // operation is exactly the same as a Page Read.  No assumptions should be
    00986     // made here about this being a Page Read operation w/o carefully checking
    00987     // to ensure that they are also true for a Mount.  That is:
    00988     //
    00989     //     IRP_PAGING_IO  and  IRP_MOUNT_COMPLETION
    00990     //
    00991     // are the same flag in the IRP.
    00992     //
    00993     // Also note that the last time the IRP is touched for a close operation
    00994     // must be just before the event is set to the signaled state.  Once this
    00995     // occurs, the IRP can be deallocated by the thread waiting for the event.
    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     // Check to see whether any pages need to be unlocked.
    01028     //
    01029
    01030     if (Irp->MdlAddress != NULL) {
    01031
    01032         //
    01033         // Unlock any pages that may be described by MDLs.
    01034         //
    01035
    01036         mdl = Irp->MdlAddress;
    01037         while (mdl != NULL) {
    01038             MmUnlockPages( mdl );
    01039             mdl = mdl->Next;
    01040         }
    01041     }
    01042
    01043     //
    01044     // Make a final check here to determine whether or not this is a
    01045     // synchronous I/O operation that is being completed in the context
    01046     // of the original requestor.  If so, then an optimal path through
    01047     // I/O completion can be taken.
    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             // For name junctions we reinstate the address of the appropriate
    01057             // buffer. It is freed in parse.c
    01058             //
    01059
    01060             Irp->Tail.Overlay.AuxiliaryBuffer = saveAuxiliaryPointer;
    01061         }
    01062
    01063         return;
    01064     }
    01065
    01066     //
    01067     // Finally, initialize the IRP as an APC structure and queue the special
    01068     // kernel APC to the target thread.
    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         // This request has been cancelled.  Ensure that access to the thread
    01093         // is synchronized, otherwise it may go away while attempting to get
    01094         // through the remainder of completion for this request.  This happens
    01095         // when the thread times out waiting for the request to be completed
    01096         // once it has been cancelled.
    01097         //
    01098         // Note that it is safe to capture the thread pointer above, w/o having
    01099         // the lock because the cancel flag was not set at that point, and
    01100         // the code that disassociates IRPs must set the flag before looking to
    01101         // see whether or not the packet has been completed, and this packet
    01102         // will appear to be completed because it no longer belongs to a driver.
    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             // This request has been aborted from completing in the caller's
    01131             // thread.  This can only occur if the packet was cancelled, and
    01132             // the driver did not complete the request, so it was timed out.
    01133             // Attempt to drop things on the floor, since the originating thread
    01134             // has probably exited at this point.
    01135             //
    01136
    01137             ExReleaseSpinLock( &IopCompletionLock, irql );
    01138
    01139             ASSERT( Irp->Cancel );
    01140
    01141             //
    01142             // Drop the IRP on the floor.
    01143             //
    01144
    01145             IopDropIrp( Irp, fileObject );
    01146
    01147         }
    01148     }
    01149 #else
    01150
    01151     IopfCompleteRequest(Irp, PriorityBoost);
    01152     return;
    01153
    01154 #endif
    01155 }