tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
阅读:3743回复:12

有谁反汇编过iofcompleterequest吗

楼主#
更多 发布于:2004-08-17 10:45
能说一说里面都作了哪些操作吗?鄙人汇编太菜了 :(
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
沙发#
发布于: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;
}
slwqw
驱动大牛
驱动大牛
  • 注册日期2002-07-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望197点
  • 贡献值0点
  • 好评度147点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-08-17 11:02
2000/NT的源代码都出来了,还去反汇编?莫非真是吃饱了撑着没有事干? :D
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-08-17 11:08
只是部分源码吧,有IofCompleteRequest的实现吗
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
地下室#
发布于: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: :( :(
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-08-17 11:21
找到了,谢谢!!我太兴奋了!!赫赫
奇怪,以前我有explorer搜索iofcompleterequest一直没找到,今天改用source insight搜索就找到了,害得我郁闷了好几天
 :D
放分
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2004-08-17 15:00
又郁闷了,看了IofCompleteRequest的实现还是不知道上面的代码哪里错了,

我的本意是这样的,当Irp->CurrentLocation == 1的时候,此时在过滤驱动程序里面io stack就不够用了,这种情况下,通常的解决办法是重新构造一个irp来完成任务,但是这样太麻烦了,所以我就想利用当前的io stack,设置完成例程,在完成例程结束后,恢复上一个io stack的内容,然后继续调用IoCompleteRequest完成Irp。

不知道有没有大虾研究过这个问题??

看了IoCompleteRequest的代码,我觉得这种方案还是可行的。
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
7楼#
发布于:2004-08-17 23:06
把IoCompleteRequest的代码贴出来看看。
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
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 );

        }
    }
}
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
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.
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-09-06 17:36
在irp的标准处理模型中,对一个irp不能调用IoCompleteRequest多次,但是注意我在完成例程中已经返回STATUS_MORE_PROCESSING_REQUIRED,该返回值将打断完成例程的回溯过程,所以此时必须由我再调用IoCompleteRequest,才能继续完成例程的回溯,看看IofCompleteRequest的实现机会很明白。

所以我上面那段代码的问题绝对不是这个原因产生的。至于是什么原因我还不清楚。:)
rayyang2000
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2012-09-13
  • 粉丝3
  • 关注0
  • 积分1036分
  • 威望925点
  • 贡献值3点
  • 好评度823点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-09-22 20:49
在irp的标准处理模型中,对一个irp不能调用IoCompleteRequest多次,但是注意我在完成例程中已经返回STATUS_MORE_PROCESSING_REQUIRED,该返回值将打断完成例程的回溯过程,所以此时必须由我再调用IoCompleteRequest,才能继续完成例程的回溯,看看IofCompleteRequest的实现机会很明白。

所以我上面那段代码的问题绝对不是这个原因产生的。至于是什么原因我还不清楚。:)


poor guy! you don't understand what i said~~~
天天coding-debugging中----超稀饭memory dump file ======================================================== [b]Windows Device Driver Development and Consulting Service[/b] [color=blue][url]http://www.ybwork.com[/url][/color] ========================================================
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
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]

你说的确实挺难让人明白
游客

返回顶部