⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irp.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
                    return NULL;
                }

                /* Copy into the System Buffer */
                RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
                              InputBuffer,
                              InputBufferLength);

                /* Write the flags */
                Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
            }
            else
            {
                Irp->Flags = 0;
            }

            /* Check if we got an output buffer */
            if (OutputBuffer)
            {
                /* Allocate the System Buffer */
                Irp->MdlAddress = IoAllocateMdl(OutputBuffer,
                                                OutputBufferLength,
                                                FALSE,
                                                FALSE,
                                                Irp);
                if (!Irp->MdlAddress)
                {
                    /* Free the IRP and fail */
                    IoFreeIrp(Irp);
                    return NULL;
                }

                /* Probe and Lock */
                _SEH_TRY
                {
                    /* Do the probe */
                    MmProbeAndLockPages(Irp->MdlAddress,
                                        KernelMode,
                                        IO_METHOD_FROM_CTL_CODE(IoControlCode) ==
                                        METHOD_IN_DIRECT ?
                                        IoReadAccess : IoWriteAccess);
                }
                _SEH_HANDLE
                {
                    /* Free the MDL */
                    IoFreeMdl(Irp->MdlAddress);

                    /* Free the input buffer and IRP */
                    if (InputBuffer) ExFreePool(Irp->AssociatedIrp.SystemBuffer);
                    IoFreeIrp(Irp);
                    Irp = NULL;
                }
                _SEH_END;

                /* This is how we know if probing failed */
                if (!Irp) return NULL;
            }
            break;

        case METHOD_NEITHER:

            /* Just save the Buffer */
            Irp->UserBuffer = OutputBuffer;
            StackPtr->Parameters.DeviceIoControl.Type3InputBuffer = InputBuffer;
    }

    /* Now write the Event and IoSB */
    Irp->UserIosb = IoStatusBlock;
    Irp->UserEvent = Event;

    /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    IoQueueThreadIrp(Irp);

    /* Return the IRP */
    IOTRACE(IO_IRP_DEBUG,
            "%s - Built IRP %p with IOCTL, Buffers, DO %lx %p %p %p\n",
            __FUNCTION__,
            Irp,
            IoControlCode,
            InputBuffer,
            OutputBuffer,
            DeviceObject);
    return Irp;
}

/*
 * @implemented
 */
PIRP
NTAPI
IoBuildSynchronousFsdRequest(IN ULONG MajorFunction,
                             IN PDEVICE_OBJECT DeviceObject,
                             IN PVOID Buffer,
                             IN ULONG Length,
                             IN PLARGE_INTEGER StartingOffset,
                             IN PKEVENT Event,
                             IN PIO_STATUS_BLOCK IoStatusBlock)
{
    PIRP Irp;

    /* Do the big work to set up the IRP */
    Irp = IoBuildAsynchronousFsdRequest(MajorFunction,
                                        DeviceObject,
                                        Buffer,
                                        Length,
                                        StartingOffset,
                                        IoStatusBlock );
    if (!Irp) return NULL;

    /* Set the Event which makes it Syncronous */
    Irp->UserEvent = Event;

    /* Sync IRPs are queued to requestor thread's irp cancel/cleanup list */
    IoQueueThreadIrp(Irp);
    return Irp;
}

/*
 * @implemented
 */
BOOLEAN
NTAPI
IoCancelIrp(IN PIRP Irp)
{
    KIRQL OldIrql;
    PDRIVER_CANCEL CancelRoutine;
    IOTRACE(IO_IRP_DEBUG,
            "%s - Canceling IRP %p\n",
            __FUNCTION__,
            Irp);
    ASSERT(Irp->Type == IO_TYPE_IRP);

    /* Acquire the cancel lock and cancel the IRP */
    IoAcquireCancelSpinLock(&OldIrql);
    Irp->Cancel = TRUE;

    /* Clear the cancel routine and get the old one */
    CancelRoutine = IoSetCancelRoutine(Irp, NULL);
    if (CancelRoutine)
    {
        /* We had a routine, make sure the IRP isn't completed */
        if (Irp->CurrentLocation > (Irp->StackCount + 1))
        {
            /* It is, bugcheck */
            KeBugCheckEx(CANCEL_STATE_IN_COMPLETED_IRP,
                         (ULONG_PTR)Irp,
                         0,
                         0,
                         0);
        }

        /* Set the cancel IRQL And call the routine */
        Irp->CancelIrql = OldIrql;
        CancelRoutine(IoGetCurrentIrpStackLocation(Irp)->DeviceObject, Irp);
        return TRUE;
    }

    /* Otherwise, release the cancel lock and fail */
    IoReleaseCancelSpinLock(OldIrql);
    return FALSE;
}

/*
 * @implemented
 */
VOID
NTAPI
IoCancelThreadIo(IN PETHREAD Thread)
{
    KIRQL OldIrql;
    ULONG Retries = 3000;
    LARGE_INTEGER Interval;
    PLIST_ENTRY ListHead, NextEntry;
    PIRP Irp;
    IOTRACE(IO_IRP_DEBUG,
            "%s - Canceling IRPs for Thread %p\n",
            __FUNCTION__,
            Thread);

    /* Raise to APC to protect the IrpList */
    OldIrql = KfRaiseIrql(APC_LEVEL);

    /* Start by cancelling all the IRPs in the current thread queue. */
    ListHead = &Thread->IrpList;
    NextEntry = ListHead->Flink;
    while (ListHead != NextEntry)
    {
        /* Get the IRP */
        Irp = CONTAINING_RECORD(NextEntry, IRP, ThreadListEntry);

        /* Cancel it */
        IoCancelIrp(Irp);

        /* Move to the next entry */
        NextEntry = NextEntry->Flink;
    }

     /* Wait 100 milliseconds */
    Interval.QuadPart = -1000000;

    /* Wait till all the IRPs are completed or cancelled. */
    while (!IsListEmpty(&Thread->IrpList))
    {
        /* Now we can lower */
        KfLowerIrql(OldIrql);

        /* Wait a short while and then look if all our IRPs were completed. */
        KeDelayExecutionThread(KernelMode, FALSE, &Interval);

        /*
         * Don't stay here forever if some broken driver doesn't complete
         * the IRP.
         */
        if (!(Retries--)) IopRemoveThreadIrp();

        /* Raise the IRQL Again */
        OldIrql = KfRaiseIrql(APC_LEVEL);
    }

    /* We're done, lower the IRQL */
    KfLowerIrql(OldIrql);
}

/*
 * @implemented
 */
NTSTATUS
NTAPI
IoCallDriver(IN PDEVICE_OBJECT DeviceObject,
             IN PIRP Irp)
{
    /* Call fast call */
    return IofCallDriver(DeviceObject, Irp);
}

/*
 * @implemented
 */
VOID
NTAPI
IoCompleteRequest(IN PIRP Irp,
                  IN CCHAR PriorityBoost)
{
    /* Call the fastcall */
    IofCompleteRequest(Irp, PriorityBoost);
}

/*
 * @implemented
 */
VOID
NTAPI
IoEnqueueIrp(IN PIRP Irp)
{
    /* This is the same as calling IoQueueThreadIrp */
    IoQueueThreadIrp(Irp);
}

/*
 * @implemented
 */
NTSTATUS
FASTCALL
IofCallDriver(IN PDEVICE_OBJECT DeviceObject,
              IN PIRP Irp)
{
    PDRIVER_OBJECT DriverObject;
    PIO_STACK_LOCATION Param;

    /* Get the Driver Object */
    DriverObject = DeviceObject->DriverObject;

    /* Decrease the current location and check if */
    Irp->CurrentLocation--;
    if (Irp->CurrentLocation <= 0)
    {
        /* This IRP ran out of stack, bugcheck */
        KeBugCheckEx(NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR)Irp, 0, 0, 0);
    }

    /* Now update the stack location */
    Param = IoGetNextIrpStackLocation(Irp);
    Irp->Tail.Overlay.CurrentStackLocation = Param;

    /* Get the Device Object */
    Param->DeviceObject = DeviceObject;

    /* Call it */
    return DriverObject->MajorFunction[Param->MajorFunction](DeviceObject,
                                                             Irp);
}

FORCEINLINE
VOID
IopClearStackLocation(IN PIO_STACK_LOCATION IoStackLocation)
{
    IoStackLocation->MinorFunction = 0;
    IoStackLocation->Flags = 0;
    IoStackLocation->Control &= SL_ERROR_RETURNED;
    IoStackLocation->Parameters.Others.Argument1 = 0;
    IoStackLocation->Parameters.Others.Argument2 = 0;
    IoStackLocation->Parameters.Others.Argument3 = 0;
    IoStackLocation->FileObject = NULL;
}

/*
 * @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 != 0xFFFFFFFF);

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

    /* Get the Current Stack and skip it */
    StackPtr = IoGetCurrentIrpStackLocation(Irp);
    IoSkipCurrentIrpStackLocation(Irp);

    /* Loop the Stacks and complete the IRPs */
    do
    {
        /* 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 = (PVOID)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);
        }

        /* Move to next stack location and pointer */
        IoSkipCurrentIrpStackLocation(Irp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -