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_DATAPIOV_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 }


Generated on Sat May 15 19:44:23 2004 for test by doxygen 1.3.7