zoukankan      html  css  js  c++  java
  • [转]IoCompleteRequest函数源码

    /*
     * @implemented
     */
    VOID
    FASTCALL
    IofCompleteRequest(IN PIRP Irp,
                       IN CCHAR PriorityBoost)
    {
        PIO_STACK_LOCATION StackPtr, LastStackPtr;
        PDEVICE_OBJECT DeviceObject;
        PFILE_OBJECT FileObject;
        PETHREAD Thread;
        NTSTATUS Status;
        PMDL Mdl, NextMdl;
        ULONG MasterCount;
        PIRP MasterIrp;
        ULONG Flags;
        NTSTATUS ErrorCode = STATUS_SUCCESS;
        IOTRACE(IO_IRP_DEBUG,
                "%s - Completing IRP %p\n",
                __FUNCTION__,
                Irp);

        /* Make sure this IRP isn't getting completed twice or is invalid */
        if ((Irp->CurrentLocation) > (Irp->StackCount + 1))
        {
            /* Bugcheck */
            KeBugCheckEx(MULTIPLE_IRP_COMPLETE_REQUESTS, (ULONG_PTR)Irp, 0, 0, 0);
        }

        /* Some sanity checks */
        ASSERT(Irp->Type == IO_TYPE_IRP);
        ASSERT(!Irp->CancelRoutine);
        ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
        ASSERT(Irp->IoStatus.Status != (NTSTATUS)0xFFFFFFFF);

        /* Get the last stack */
        LastStackPtr = (PIO_STACK_LOCATION)(Irp + 1);//这里
        if (LastStackPtr->Control & SL_ERROR_RETURNED)
        {
            /* Get the error code */
            ErrorCode = PtrToUlong(LastStackPtr->Parameters.Others.Argument4);
        }

        /*
         * Start the loop with the current stack and point the IRP to the next stack
         * and then keep incrementing the stack as we loop through. The IRP should
         * always point to the next stack location w.r.t the one currently being
         * analyzed, so completion routine code will see the appropriate value.
         * Because of this, we must loop until the current stack location is +1 of
         * the stack count, because when StackPtr is at the end, CurrentLocation is +1.
         */
        for (StackPtr = IoGetCurrentIrpStackLocation(Irp),
             Irp->CurrentLocation++,
             Irp->Tail.Overlay.CurrentStackLocation++;
             Irp->CurrentLocation <= (Irp->StackCount + 1);
             StackPtr++,
             Irp->CurrentLocation++,
             Irp->Tail.Overlay.CurrentStackLocation++)
        {
            /* Set Pending Returned */
            Irp->PendingReturned = StackPtr->Control & SL_PENDING_RETURNED;

            /* Check if we failed */
            if (!NT_SUCCESS(Irp->IoStatus.Status))
            {
                /* Check if it was changed by a completion routine */
                if (Irp->IoStatus.Status != ErrorCode)
                {
                    /* Update the error for the current stack */
                    ErrorCode = Irp->IoStatus.Status;
                    StackPtr->Control |= SL_ERROR_RETURNED;
                    LastStackPtr->Parameters.Others.Argument4 = UlongToPtr(ErrorCode);
                    LastStackPtr->Control |= SL_ERROR_RETURNED;
                }
            }

            /* Check if there is a Completion Routine to Call */
            if ((NT_SUCCESS(Irp->IoStatus.Status) &&
                 (StackPtr->Control & SL_INVOKE_ON_SUCCESS)) ||
                (!NT_SUCCESS(Irp->IoStatus.Status) &&
                 (StackPtr->Control & SL_INVOKE_ON_ERROR)) ||
                (Irp->Cancel &&
                 (StackPtr->Control & SL_INVOKE_ON_CANCEL)))
            {
                /* Clear the stack location */
                IopClearStackLocation(StackPtr);

                /* Check for highest-level device completion routines */
                if (Irp->CurrentLocation == (Irp->StackCount + 1))
                {
                    /* Clear the DO, since the current stack location is invalid */
                    DeviceObject = NULL;
                }
                else
                {
                    /* Otherwise, return the real one */
                    DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
                }

                /* Call the completion routine */
                Status = StackPtr->CompletionRoutine(DeviceObject,
                                                     Irp,
                                                     StackPtr->Context);

                /* Don't touch the Packet in this case, since it might be gone! */
                if (Status == STATUS_MORE_PROCESSING_REQUIRED) return;
            }
            else
            {
                /* Otherwise, check if this is a completed IRP */
                if ((Irp->CurrentLocation <= Irp->StackCount) &&
                    (Irp->PendingReturned))
                {
                    /* Mark it as pending */
                    IoMarkIrpPending(Irp);
                }

                /* Clear the stack location */
                IopClearStackLocation(StackPtr);
            }
        }

        /* Check if the IRP is an associated IRP */
        if (Irp->Flags & IRP_ASSOCIATED_IRP)
        {
            /* Get the master IRP and count */
            MasterIrp = Irp->AssociatedIrp.MasterIrp;
            MasterCount = InterlockedDecrement(&MasterIrp->AssociatedIrp.IrpCount);

            /* Free the MDLs */
            for (Mdl = Irp->MdlAddress; Mdl; Mdl = NextMdl)
            {
                /* Go to the next one */
                NextMdl = Mdl->Next;
                IoFreeMdl(Mdl);
            }

            /* Free the IRP itself */
            IoFreeIrp(Irp);

            /* Complete the Master IRP */
            if (!MasterCount) IofCompleteRequest(MasterIrp, PriorityBoost);
            return;
        }

        /* We don't support this yet */
        ASSERT(Irp->IoStatus.Status != STATUS_REPARSE);

        /* Check if we have an auxiliary buffer */
        if (Irp->Tail.Overlay.AuxiliaryBuffer)
        {
            /* Free it */
            ExFreePool(Irp->Tail.Overlay.AuxiliaryBuffer);
            Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
        }

        /* Check if this is a Paging I/O or Close Operation */
        if (Irp->Flags & (IRP_PAGING_IO | IRP_CLOSE_OPERATION))
        {
            /* Handle a Close Operation or Sync Paging I/O */
            if (Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_CLOSE_OPERATION))
            {
                /* Set the I/O Status and Signal the Event */
                Flags = Irp->Flags & (IRP_SYNCHRONOUS_PAGING_IO | IRP_PAGING_IO);
                *Irp->UserIosb = Irp->IoStatus;
                KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE);

                /* Free the IRP for a Paging I/O Only, Close is handled by us */
                if (Flags) IoFreeIrp(Irp);
            }
            else
            {
    #if 0
                /* Page 166 */
                KeInitializeApc(&Irp->Tail.Apc
                                &Irp->Tail.Overlay.Thread->Tcb,
                                Irp->ApcEnvironment,
                                IopCompletePageWrite,
                                NULL,
                                NULL,
                                KernelMode,
                                NULL);
                KeInsertQueueApc(&Irp->Tail.Apc,
                                 NULL,
                                 NULL,
                                 PriorityBoost);
    #else
                /* Not implemented yet. */
                DPRINT1("Not supported!\n");
                while (TRUE);
    #endif
            }

            /* Get out of here */
            return;
        }

        /* Unlock MDL Pages, page 167. */
        Mdl = Irp->MdlAddress;
        while (Mdl)
        {
        MmUnlockPages(Mdl);
            Mdl = Mdl->Next;
        }

        /* Check if we should exit because of a Deferred I/O (page 168) */
        if ((Irp->Flags & IRP_DEFER_IO_COMPLETION) && !(Irp->PendingReturned))
        {
            /*
             * Return without queuing the completion APC, since the caller will
             * take care of doing its own optimized completion at PASSIVE_LEVEL.
             */
            return;
        }

        /* Get the thread and file object */
        Thread = Irp->Tail.Overlay.Thread;
        FileObject = Irp->Tail.Overlay.OriginalFileObject;

        /* Make sure the IRP isn't canceled */
        if (!Irp->Cancel)
        {
            /* Initialize the APC */
            KeInitializeApc(&Irp->Tail.Apc,
                            &Thread->Tcb,
                            Irp->ApcEnvironment,
                            IopCompleteRequest,
                            NULL,
                            NULL,
                            KernelMode,
                            NULL);

            /* Queue it */
            KeInsertQueueApc(&Irp->Tail.Apc,
                             FileObject,
                             NULL, /* This is used for REPARSE stuff */
                             PriorityBoost);
        }
        else
        {
            /* The IRP just got canceled... does a thread still own it? */
            if (Thread)
            {
                /* Yes! There is still hope! Initialize the APC */
                KeInitializeApc(&Irp->Tail.Apc,
                                &Thread->Tcb,
                                Irp->ApcEnvironment,
                                IopCompleteRequest,
                                NULL,
                                NULL,
                                KernelMode,
                                NULL);

                /* Queue it */
                KeInsertQueueApc(&Irp->Tail.Apc,
                                 FileObject,
                                 NULL, /* This is used for REPARSE stuff */
                                 PriorityBoost);
            }
            else
            {
                /* Nothing left for us to do, kill it */
                ASSERT(Irp->Cancel);
                IopCleanupIrp(Irp, FileObject);
            }
        }
    }

  • 相关阅读:
    Dapper数据库字段和model属性映射
    SQLServer性能调优之缓存
    python&django 实现页面中关联查询小功能(基础篇)
    pythonのdjango select_related 和 prefetch_related()
    pythonのdjango 在控制台用log打印操作日志
    pythonのdjango Form简单应用。
    pythonのdjango 信号
    pythonのdjango 缓存
    pythonのdjango CSRF简单使用
    pythonのdjango Session体验
  • 原文地址:https://www.cnblogs.com/adylee/p/2575582.html
Copyright © 2011-2022 走看看