阅读:3962回复:12
有谁反汇编过iofcompleterequest吗
能说一说里面都作了哪些操作吗?鄙人汇编太菜了 :(
|
|
沙发#
发布于:2004-08-17 10:51
或者谁能告诉我这段代码的错误在哪,谢谢!
/*******************************************************/ NTSTATUS DefaultCompletion( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { UNREFERENCED_PARAMETER(DeviceObject); if (Irp->PendingReturned) { KeSetEvent((PRKEVENT) Context, IO_NO_INCREMENT, FALSE); } return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS DefaultDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = NULL; KEVENT Event; NTSTATUS Status; IO_STACK_LOCATION SavedIrpSp; pdx = DeviceObject->DeviceExtension; SavedIrpSp = *IrpSp; IoSkipCurrentIrpStackLocation(Irp); IoSetCompletionRoutine( Irp, DefaultCompletion, &Event, TRUE, TRUE, TRUE ); KeInitializeEvent(&Event, NotificationEvent, FALSE); Status = IoCallDriver(pdx->AttachedDeviceObject, Irp); if (STATUS_PENDING == Status) { KeWaitForSingleObject(&Event, Executive, KernelMode, TRUE, NULL); Status = Irp->IoStatus.Status; } IoSetNextIrpStackLocation(Irp); *IrpSp = SavedIrpSp; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } |
|
板凳#
发布于:2004-08-17 11:02
2000/NT的源代码都出来了,还去反汇编?莫非真是吃饱了撑着没有事干? :D
|
|
地板#
发布于:2004-08-17 11:08
只是部分源码吧,有IofCompleteRequest的实现吗
|
|
地下室#
发布于:2004-08-17 11:14
晕,2000的实现:
VOID FASTCALL IofCompleteRequest( IN PIRP Irp, IN CCHAR PriorityBoost ) { // // This routine will either jump immediately to IopfCompleteRequest, or // rather IovCompleteRequest. // pIofCompleteRequest(Irp, PriorityBoost); } :mad: :( :( |
|
5楼#
发布于:2004-08-17 11:21
找到了,谢谢!!我太兴奋了!!赫赫
奇怪,以前我有explorer搜索iofcompleterequest一直没找到,今天改用source insight搜索就找到了,害得我郁闷了好几天 :D 放分 |
|
6楼#
发布于:2004-08-17 15:00
又郁闷了,看了IofCompleteRequest的实现还是不知道上面的代码哪里错了,
我的本意是这样的,当Irp->CurrentLocation == 1的时候,此时在过滤驱动程序里面io stack就不够用了,这种情况下,通常的解决办法是重新构造一个irp来完成任务,但是这样太麻烦了,所以我就想利用当前的io stack,设置完成例程,在完成例程结束后,恢复上一个io stack的内容,然后继续调用IoCompleteRequest完成Irp。 不知道有没有大虾研究过这个问题?? 看了IoCompleteRequest的代码,我觉得这种方案还是可行的。 |
|
7楼#
发布于:2004-08-17 23:06
把IoCompleteRequest的代码贴出来看看。
|
|
|
8楼#
发布于:2004-08-18 10:32
VOID
FASTCALL IofCompleteRequest( IN PIRP Irp, IN CCHAR PriorityBoost ) { // // This routine will either jump immediately to IopfCompleteRequest, or // rather IovCompleteRequest. // pIofCompleteRequest(Irp, PriorityBoost); } VOID FASTCALL IopfCompleteRequest( IN PIRP Irp, IN CCHAR PriorityBoost ) /*++ Routine Description: This routine is invoked to complete an I/O request. It is invoked by the driver in its DPC routine to perform the final completion of the IRP. The functions performed by this routine are as follows. 1. A check is made to determine whether the packet's stack locations have been exhausted. If not, then the stack location pointer is set to the next location and if there is a routine to be invoked, then it will be invoked. This continues until there are either no more routines which are interested or the packet runs out of stack. If a routine is invoked to complete the packet for a specific driver which needs to perform work a lot of work or the work needs to be performed in the context of another process, then the routine will return an alternate success code of STATUS_MORE_PROCESSING_REQUIRED. This indicates that this completion routine should simply return to its caller because the operation will be "completed" by this routine again sometime in the future. 2. A check is made to determine whether this IRP is an associated IRP. If it is, then the count on the master IRP is decremented. If the count for the master becomes zero, then the master IRP will be completed according to the steps below taken for a normal IRP being completed. If the count is still non-zero, then this IRP (the one being completed) will simply be deallocated. 3. If this is paging I/O or a close operation, then simply write the I/O status block and set the event to the signaled state, and dereference the event. If this is paging I/O, deallocate the IRP as well. 4. Unlock the pages, if any, specified by the MDL by calling MmUnlockPages. 5. A check is made to determine whether or not completion of the request can be deferred until later. If it can be, then this routine simply exits and leaves it up to the originator of the request to fully complete the IRP. By not initializing and queueing the special kernel APC to the calling thread (which is the current thread by definition), a lot of interrupt and queueing processing can be avoided. 6. The final rundown routine is invoked to queue the request packet to the target (requesting) thread as a special kernel mode APC. Arguments: Irp - Pointer to the I/O Request Packet to complete. PriorityBoost - Supplies the amount of priority boost that is to be given to the target thread when the special kernel APC is queued. Return Value: None. --*/ #define ZeroIrpStackLocation( IrpSp ) { (IrpSp)->MinorFunction = 0; (IrpSp)->Flags = 0; (IrpSp)->Control = 0 ; (IrpSp)->Parameters.Others.Argument1 = 0; (IrpSp)->Parameters.Others.Argument2 = 0; (IrpSp)->Parameters.Others.Argument3 = 0; (IrpSp)->Parameters.Others.Argument4 = 0; (IrpSp)->FileObject = (PFILE_OBJECT) NULL; } { PIRP masterIrp; NTSTATUS status; PIO_STACK_LOCATION stackPointer; PMDL mdl; PETHREAD thread; PFILE_OBJECT fileObject; KIRQL irql; PVOID saveAuxiliaryPointer = NULL; // // Begin by ensuring that this packet has not already been completed // by someone. // if (Irp->CurrentLocation > (CCHAR) (Irp->StackCount + 1) || Irp->Type != IO_TYPE_IRP) { KeBugCheckEx( MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR) Irp, __LINE__, 0, 0 ); } // // Ensure that the packet being completed really is still an IRP. // ASSERT( Irp->Type == IO_TYPE_IRP ); // // Ensure that no one believes that this request is still in a cancelable // state. // ASSERT( !Irp->CancelRoutine ); // // Ensure that the packet is not being completed with a thoroughly // confusing status code. Actually completing a packet with a pending // status probably means that someone forgot to set the real status in // the packet. // ASSERT( Irp->IoStatus.Status != STATUS_PENDING ); // // Ensure that the packet is not being completed with a minus one. This // is apparently a common problem in some drivers, and has no meaning // as a status code. // ASSERT( Irp->IoStatus.Status != 0xffffffff ); // // Ensure that if this is a paging I/O operation, and it failed, that the // reason for the failure isn't because quota was exceeded. // ASSERT( !(Irp->Flags & IRP_PAGING_IO && Irp->IoStatus.Status == STATUS_QUOTA_EXCEEDED ) ); // // Now check to see whether this is the last driver that needs to be // invoked for this packet. If not, then bump the stack and check to // see whether the driver wishes to see the completion. As each stack // location is examined, invoke any routine which needs to be invoked. // If the routine returns STATUS_MORE_PROCESSING_REQUIRED, then stop the // processing of this packet. // for (stackPointer = IoGetCurrentIrpStackLocation( Irp ), Irp->CurrentLocation++, Irp->Tail.Overlay.CurrentStackLocation++; Irp->CurrentLocation <= (CCHAR) (Irp->StackCount + 1); stackPointer++, Irp->CurrentLocation++, Irp->Tail.Overlay.CurrentStackLocation++) { // // A stack location was located. Check to see whether or not it // has a completion routine and if so, whether or not it should be // invoked. // // Begin by saving the pending returned flag in the current stack // location in the fixed part of the IRP. // Irp->PendingReturned = stackPointer->Control & SL_PENDING_RETURNED; if ( (NT_SUCCESS( Irp->IoStatus.Status ) && stackPointer->Control & SL_INVOKE_ON_SUCCESS) || (!NT_SUCCESS( Irp->IoStatus.Status ) && stackPointer->Control & SL_INVOKE_ON_ERROR) || (Irp->Cancel && stackPointer->Control & SL_INVOKE_ON_CANCEL) ) { // // This driver has specified a completion routine. Invoke the // routine passing it a pointer to its device object and the // IRP that is being completed. // ZeroIrpStackLocation( stackPointer ); PERFINFO_DRIVER_COMPLETIONROUTINE_CALL(Irp, stackPointer); status = stackPointer->CompletionRoutine( (PDEVICE_OBJECT) (Irp->CurrentLocation == (CCHAR) (Irp->StackCount + 1) ? (PDEVICE_OBJECT) NULL : IoGetCurrentIrpStackLocation( Irp )->DeviceObject), Irp, stackPointer->Context ); PERFINFO_DRIVER_COMPLETIONROUTINE_RETURN(Irp, stackPointer); if (status == STATUS_MORE_PROCESSING_REQUIRED) { // // Note: Notice that if the driver has returned the above // status value, it may have already DEALLOCATED the // packet! Therefore, do NOT touch any part of the // IRP in the following code. // return; } } else { if (Irp->PendingReturned && Irp->CurrentLocation <= Irp->StackCount) { IoMarkIrpPending( Irp ); } ZeroIrpStackLocation( stackPointer ); } } // // Check to see whether this is an associated IRP. If so, then decrement // the count in the master IRP. If the count is decremented to zero, // then complete the master packet as well. // if (Irp->Flags & IRP_ASSOCIATED_IRP) { ULONG count; masterIrp = Irp->AssociatedIrp.MasterIrp; count = ExInterlockedAddUlong( (PULONG) &masterIrp->AssociatedIrp.IrpCount, 0xffffffff, &IopDatabaseLock ); // // Deallocate this packet and any MDLs that are associated with it // by either doing direct deallocations if they were allocated from // a zone or by queueing the packet to a thread to perform the // deallocation. // // Also, check the count of the master IRP to determine whether or not // the count has gone to zero. If not, then simply get out of here. // Otherwise, complete the master packet. // Irp->Tail.Overlay.Thread = masterIrp->Tail.Overlay.Thread; IopFreeIrpAndMdls( Irp ); if (count == 1) { IoCompleteRequest( masterIrp, PriorityBoost ); } return; } // // Check to see if we have a name junction. If so set the stage to // transmogrify the reparse point data in IopCompleteRequest. // if ((Irp->IoStatus.Status == STATUS_REPARSE ) && (Irp->IoStatus.Information > IO_REPARSE_TAG_RESERVED_RANGE)) { if (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) { // // For name junctions, we save the pointer to the auxiliary // buffer and use it below. // ASSERT( Irp->Tail.Overlay.AuxiliaryBuffer != NULL ); saveAuxiliaryPointer = (PVOID) Irp->Tail.Overlay.AuxiliaryBuffer; // // We NULL the entry to avoid its de-allocation at this time. // This buffer get deallocated in IopDoNameTransmogrify // Irp->Tail.Overlay.AuxiliaryBuffer = NULL; } else { // // Fail the request. A driver needed to act on this IRP prior // to getting to this point. // Irp->IoStatus.Status = STATUS_IO_REPARSE_TAG_NOT_HANDLED; } } // // Check the auxiliary buffer pointer in the packet and if a buffer was // allocated, deallocate it now. Note that this buffer must be freed // here since the pointer is overlayed with the APC that will be used // to get to the requesting thread's context. // if (Irp->Tail.Overlay.AuxiliaryBuffer) { ExFreePool( Irp->Tail.Overlay.AuxiliaryBuffer ); Irp->Tail.Overlay.AuxiliaryBuffer = NULL; } // // Check to see if this is paging I/O or a close operation. If either, // then special processing must be performed. The reasons that special // processing must be performed is different based on the type of // operation being performed. The biggest reasons for special processing // on paging operations are that using a special kernel APC for an in- // page operation cannot work since the special kernel APC can incur // another pagefault. Likewise, all paging I/O uses MDLs that belong // to the memory manager, not the I/O system. // // Close operations are special because the close may have been invoked // because of a special kernel APC (some IRP was completed which caused // the reference count on the object to become zero while in the I/O // system's special kernel APC routine). Therefore, a special kernel APC // cannot be used since it cannot execute until the close APC finishes. // // The special steps are as follows for a synchronous paging operation // and close are: // // 1. Copy the I/O status block (it is in SVAS, nonpaged). // 2. Signal the event // 3. If paging I/O, deallocate the IRP // // The special steps taken for asynchronous paging operations (out-pages) // are as follows: // // 1. Initialize a special kernel APC just for page writes. // 1. Queue the special kernel APC. // // It should also be noted that the logic for completing a Mount request // operation is exactly the same as a Page Read. No assumptions should be // made here about this being a Page Read operation w/o carefully checking // to ensure that they are also true for a Mount. That is: // // IRP_PAGING_IO and IRP_MOUNT_COMPLETION // // are the same flag in the IRP. // // Also note that the last time the IRP is touched for a close operation // must be just before the event is set to the signaled state. Once this // occurs, the IRP can be deallocated by the thread waiting for the event. // if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION)) { if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION)) { ULONG flags; flags = Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO; *Irp->UserIosb = Irp->IoStatus; (VOID) KeSetEvent( Irp->UserEvent, PriorityBoost, FALSE ); if (flags) { IoFreeIrp( Irp ); } } else { thread = Irp->Tail.Overlay.Thread; KeInitializeApc( &Irp->Tail.Apc, &thread->Tcb, Irp->ApcEnvironment, IopCompletePageWrite, (PKRUNDOWN_ROUTINE) NULL, (PKNORMAL_ROUTINE) NULL, KernelMode, (PVOID) NULL ); (VOID) KeInsertQueueApc( &Irp->Tail.Apc, (PVOID) NULL, (PVOID) NULL, PriorityBoost ); } return; } // // Check to see whether any pages need to be unlocked. // if (Irp->MdlAddress != NULL) { // // Unlock any pages that may be described by MDLs. // mdl = Irp->MdlAddress; while (mdl != NULL) { MmUnlockPages( mdl ); mdl = mdl->Next; } } // // Make a final check here to determine whether or not this is a // synchronous I/O operation that is being completed in the context // of the original requestor. If so, then an optimal path through // I/O completion can be taken. // if (Irp->Flags & IRP_DEFER_IO_COMPLETION && !Irp->PendingReturned) { if ((Irp->IoStatus.Status == STATUS_REPARSE ) && (Irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)) { // // For name junctions we reinstate the address of the appropriate // buffer. It is freed in parse.c // Irp->Tail.Overlay.AuxiliaryBuffer = saveAuxiliaryPointer; } return; } // // Finally, initialize the IRP as an APC structure and queue the special // kernel APC to the target thread. // thread = Irp->Tail.Overlay.Thread; fileObject = Irp->Tail.Overlay.OriginalFileObject; if (!Irp->Cancel) { KeInitializeApc( &Irp->Tail.Apc, &thread->Tcb, Irp->ApcEnvironment, IopCompleteRequest, IopAbortRequest, (PKNORMAL_ROUTINE) NULL, KernelMode, (PVOID) NULL ); (VOID) KeInsertQueueApc( &Irp->Tail.Apc, fileObject, (PVOID) saveAuxiliaryPointer, PriorityBoost ); } else { // // This request has been cancelled. Ensure that access to the thread // is synchronized, otherwise it may go away while attempting to get // through the remainder of completion for this request. This happens // when the thread times out waiting for the request to be completed // once it has been cancelled. // // Note that it is safe to capture the thread pointer above, w/o having // the lock because the cancel flag was not set at that point, and // the code that disassociates IRPs must set the flag before looking to // see whether or not the packet has been completed, and this packet // will appear to be completed because it no longer belongs to a driver. // ExAcquireSpinLock( &IopCompletionLock, &irql ); thread = Irp->Tail.Overlay.Thread; if (thread) { KeInitializeApc( &Irp->Tail.Apc, &thread->Tcb, Irp->ApcEnvironment, IopCompleteRequest, IopAbortRequest, (PKNORMAL_ROUTINE) NULL, KernelMode, (PVOID) NULL ); (VOID) KeInsertQueueApc( &Irp->Tail.Apc, fileObject, (PVOID) saveAuxiliaryPointer, PriorityBoost ); ExReleaseSpinLock( &IopCompletionLock, irql ); } else { // // This request has been aborted from completing in the caller's // thread. This can only occur if the packet was cancelled, and // the driver did not complete the request, so it was timed out. // Attempt to drop things on the floor, since the originating thread // has probably exited at this point. // ExReleaseSpinLock( &IopCompletionLock, irql ); ASSERT( Irp->Cancel ); // // Drop the IRP on the floor. // IopDropIrp( Irp, fileObject ); } } } |
|
9楼#
发布于:2004-09-02 17:42
the answer is very simple!
IoCallDriver sends the IRP to the lower driver. That lower driver has completed this IRP. But, when this IRP returns to your driver, you complete this IRP *again*! So, the solution is very simple: remove IoCompleteRequest from your driver. Always remember: only the lowest driver of this IRP *can* call IoCompleteRequest. Any others call this API again will cause a bug check. |
|
|
10楼#
发布于:2004-09-06 17:36
在irp的标准处理模型中,对一个irp不能调用IoCompleteRequest多次,但是注意我在完成例程中已经返回STATUS_MORE_PROCESSING_REQUIRED,该返回值将打断完成例程的回溯过程,所以此时必须由我再调用IoCompleteRequest,才能继续完成例程的回溯,看看IofCompleteRequest的实现机会很明白。
所以我上面那段代码的问题绝对不是这个原因产生的。至于是什么原因我还不清楚。:) |
|
11楼#
发布于:2004-09-22 20:49
在irp的标准处理模型中,对一个irp不能调用IoCompleteRequest多次,但是注意我在完成例程中已经返回STATUS_MORE_PROCESSING_REQUIRED,该返回值将打断完成例程的回溯过程,所以此时必须由我再调用IoCompleteRequest,才能继续完成例程的回溯,看看IofCompleteRequest的实现机会很明白。 poor guy! you don't understand what i said~~~ |
|
|
12楼#
发布于:2004-09-23 09:27
[quote]在irp的标准处理模型中,对一个irp不能调用IoCompleteRequest多次,但是注意我在完成例程中已经返回STATUS_MORE_PROCESSING_REQUIRED,该返回值将打断完成例程的回溯过程,所以此时必须由我再调用IoCompleteRequest,才能继续完成例程的回溯,看看IofCompleteRequest的实现机会很明白。 poor guy! you don't understand what i said~~~ [/quote] 你说的确实挺难让人明白 |
|