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

📄 irp.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 4 页
字号:
            /* Queue it */
            KeInsertQueueApc(&Irp->Tail.Apc, Irp->UserIosb, NULL, 2);
        }
        else if ((Port) &&
                 (Irp->Overlay.AsynchronousParameters.UserApcContext))
        {
            /* We have an I/O Completion setup... create the special Overlay */
            Irp->Tail.CompletionKey = Key;
            Irp->Tail.Overlay.PacketType = IrpCompletionPacket;
            KeInsertQueue(Port, &Irp->Tail.Overlay.ListEntry);
        }
        else
        {
            /* Free the IRP since we don't need it anymore */
            IoFreeIrp(Irp);
        }

        /* Check if we have a file object that wasn't part of a create */
        if ((FileObject) && !(SignaledCreateRequest))
        {
            /* Dereference it, since it's not needed anymore either */
            ObDereferenceObjectDeferDelete(FileObject);
        }
    }
    else
    {
        /*
         * Either we didn't return from the request, or we did return but this
         * request was synchronous.
         */
        if ((Irp->PendingReturned) && (FileObject))
        {
            /* So we did return with a synch operation, was it the IRP? */
            if (Irp->Flags & IRP_SYNCHRONOUS_API)
            {
                /* Yes, this IRP was synchronous, so return the I/O Status */
                *Irp->UserIosb = Irp->IoStatus;

                /* Now check if the user gave an event */
                if (Irp->UserEvent)
                {
                    /* Signal it */
                    KeSetEvent(Irp->UserEvent, 0, FALSE);
                }
                else
                {
                    /* No event was given, so signal the FO instead */
                    KeSetEvent(&FileObject->Event, 0, FALSE);
                }
            }
            else
            {
                /*
                 * It's not the IRP that was synchronous, it was the FO
                 * that was opened this way. Signal its event.
                 */
                FileObject->FinalStatus = Irp->IoStatus.Status;
                KeSetEvent(&FileObject->Event, 0, FALSE);
            }
        }

        /* Now that we got here, we do this for incomplete I/Os as well */
        if ((FileObject) && !(Irp->Flags & IRP_CREATE_OPERATION))
        {
            /* Dereference the File Object unless this was a create */
            ObDereferenceObjectDeferDelete(FileObject);
        }

        /*
         * Check if this was an Executive Event (remember that we know this
         * by checking if the IRP is synchronous)
         */
        if ((Irp->UserEvent) &&
            (FileObject) &&
            !(Irp->Flags & IRP_SYNCHRONOUS_API))
        {
            /* This isn't a PKEVENT, so dereference it */
            ObDereferenceObject(Irp->UserEvent);
        }

        /* Now that we've signaled the events, de-associate the IRP */
        IopUnQueueIrpFromThread(Irp);

        /* Free the IRP as well */
        IoFreeIrp(Irp);
    }
}

/* FUNCTIONS *****************************************************************/

/*
 * @implemented
 */
PIRP
NTAPI
IoAllocateIrp(IN CCHAR StackSize,
              IN BOOLEAN ChargeQuota)
{
    PIRP Irp = NULL;
    USHORT Size = IoSizeOfIrp(StackSize);
    PKPRCB Prcb;
    UCHAR Flags = 0;
    PNPAGED_LOOKASIDE_LIST List = NULL;
    PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList;

    /* Figure out which Lookaside List to use */
    if ((StackSize <= 8) && (ChargeQuota == FALSE))
    {
        /* Set Fixed Size Flag */
        Flags = IRP_ALLOCATED_FIXED_SIZE;

        /* See if we should use big list */
        if (StackSize != 1)
        {
            Size = IoSizeOfIrp(8);
            ListType = LookasideLargeIrpList;
        }

        /* Get the PRCB */
        Prcb = KeGetCurrentPrcb();

        /* Get the P List First */
        List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P;

        /* Attempt allocation */
        List->L.TotalAllocates++;
        Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);

        /* Check if the P List failed */
        if (!Irp)
        {
            /* Let the balancer know */
            List->L.AllocateMisses++;

            /* Try the L List */
            List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L;
            List->L.TotalAllocates++;
            Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);
        }
    }

    /* Check if we have to use the pool */
    if (!Irp)
    {
        /* Did we try lookaside and fail? */
        if (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses++;

        /* Check if we should charge quota */
        if (ChargeQuota)
        {
            /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
            /* FIXME */
            Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
        }
        else
        {
            /* Allocate the IRP With no Quota charge */
            Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
        }

        /* Make sure it was sucessful */
        if (!Irp) return(NULL);
    }
    else
    {
        /* We have an IRP from Lookaside */
        Flags |= IRP_LOOKASIDE_ALLOCATION;
    }

    /* Set Flag */
    if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;

    /* Now Initialize it */
    IoInitializeIrp(Irp, Size, StackSize);

    /* Set the Allocation Flags */
    Irp->AllocationFlags = Flags;

    /* Return it */
    IOTRACE(IO_IRP_DEBUG,
            "%s - Allocated IRP %p with allocation flags %lx\n",
            __FUNCTION__,
            Irp,
            Flags);
    return Irp;
}

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

    /* Allocate IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (!Irp) return Irp;

    /* Get the Stack */
    StackPtr = IoGetNextIrpStackLocation(Irp);

    /* Write the Major function and then deal with it */
    StackPtr->MajorFunction = (UCHAR)MajorFunction;

    /* Do not handle the following here */
    if ((MajorFunction != IRP_MJ_FLUSH_BUFFERS) &&
        (MajorFunction != IRP_MJ_SHUTDOWN) &&
        (MajorFunction != IRP_MJ_PNP) &&
        (MajorFunction != IRP_MJ_POWER))
    {
        /* Check if this is Buffered IO */
        if (DeviceObject->Flags & DO_BUFFERED_IO)
        {
            /* Allocate the System Buffer */
            Irp->AssociatedIrp.SystemBuffer =
                ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYS_BUF);
            if (!Irp->AssociatedIrp.SystemBuffer)
            {
                /* Free the IRP and fail */
                IoFreeIrp(Irp);
                return NULL;
            }

            /* Set flags */
            Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;

            /* Handle special IRP_MJ_WRITE Case */
            if (MajorFunction == IRP_MJ_WRITE)
            {
                /* Copy the buffer data */
                RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length);
            }
            else
            {
                /* Set the Input Operation flag and set this as a User Buffer */
                Irp->Flags |= IRP_INPUT_OPERATION;
                Irp->UserBuffer = Buffer;
            }
        }
        else if (DeviceObject->Flags & DO_DIRECT_IO)
        {
            /* Use an MDL for Direct I/O */
            Irp->MdlAddress = IoAllocateMdl(Buffer,
                                            Length,
                                            FALSE,
                                            FALSE,
                                            NULL);
            if (!Irp->MdlAddress)
            {
                /* Free the IRP and fail */
                IoFreeIrp(Irp);
                return NULL;
            }

            /* Probe and Lock */
            _SEH_TRY
            {
                /* Do the probe */
                MmProbeAndLockPages(Irp->MdlAddress,
                                    KernelMode,
                                    MajorFunction == IRP_MJ_READ ?
                                    IoWriteAccess : IoReadAccess);
            }
            _SEH_HANDLE
            {
                /* Free the IRP and its MDL */
                IoFreeMdl(Irp->MdlAddress);
                IoFreeIrp(Irp);
                Irp = NULL;
            }
            _SEH_END;

            /* This is how we know if we failed during the probe */
            if (!Irp) return NULL;
        }
        else
        {
            /* Neither, use the buffer */
            Irp->UserBuffer = Buffer;
        }

        /* Check if this is a read */
        if (MajorFunction == IRP_MJ_READ)
        {
            /* Set the parameters for a read */
            StackPtr->Parameters.Read.Length = Length;
            StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
        }
        else if (MajorFunction == IRP_MJ_WRITE)
        {
            /* Otherwise, set write parameters */
            StackPtr->Parameters.Write.Length = Length;
            StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
        }
    }

    /* Set the Current Thread and IOSB */
    Irp->UserIosb = IoStatusBlock;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();

    /* Set the Status Block after all is done */
    IOTRACE(IO_IRP_DEBUG,
            "%s - Built IRP %p with Major, Buffer, DO %lx %p %p\n",
            __FUNCTION__,
            Irp,
            MajorFunction,
            Buffer,
            DeviceObject);
    return Irp;
}

/*
 * @implemented
 */
PIRP
NTAPI
IoBuildDeviceIoControlRequest(IN ULONG IoControlCode,
                              IN PDEVICE_OBJECT DeviceObject,
                              IN PVOID InputBuffer,
                              IN ULONG InputBufferLength,
                              IN PVOID OutputBuffer,
                              IN ULONG OutputBufferLength,
                              IN BOOLEAN InternalDeviceIoControl,
                              IN PKEVENT Event,
                              IN PIO_STATUS_BLOCK IoStatusBlock)
{
    PIRP Irp;
    PIO_STACK_LOCATION StackPtr;
    ULONG BufferLength;

    /* Allocate IRP */
    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
    if (!Irp) return Irp;

    /* Get the Stack */
    StackPtr = IoGetNextIrpStackLocation(Irp);

    /* Set the DevCtl Type */
    StackPtr->MajorFunction = InternalDeviceIoControl ?
                              IRP_MJ_INTERNAL_DEVICE_CONTROL :
                              IRP_MJ_DEVICE_CONTROL;

    /* Set the IOCTL Data */
    StackPtr->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
    StackPtr->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
    StackPtr->Parameters.DeviceIoControl.OutputBufferLength =
        OutputBufferLength;

    /* Handle the Methods */
    switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
    {
        /* Buffered I/O */
        case METHOD_BUFFERED:

            /* Select the right Buffer Length */
            BufferLength = InputBufferLength > OutputBufferLength ?
                           InputBufferLength : OutputBufferLength;

            /* Make sure there is one */
            if (BufferLength)
            {
                /* Allocate the System Buffer */
                Irp->AssociatedIrp.SystemBuffer =
                    ExAllocatePoolWithTag(NonPagedPool,
                                          BufferLength,
                                          TAG_SYS_BUF);
                if (!Irp->AssociatedIrp.SystemBuffer)
                {
                    /* Free the IRP and fail */
                    IoFreeIrp(Irp);
                    return NULL;
                }

                /* Check if we got a buffer */
                if (InputBuffer)
                {
                    /* Copy into the System Buffer */
                    RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
                                  InputBuffer,
                                  InputBufferLength);
                }

                /* Write the flags */
                Irp->Flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER;
                if (OutputBuffer) Irp->Flags |= IRP_INPUT_OPERATION;

                /* Save the Buffer */
                Irp->UserBuffer = OutputBuffer;
            }
            else
            {
                /* Clear the Flags and Buffer */
                Irp->Flags = 0;
                Irp->UserBuffer = NULL;
            }
            break;

        /* Direct I/O */
        case METHOD_IN_DIRECT:
        case METHOD_OUT_DIRECT:

            /* Check if we got an input buffer */
            if (InputBuffer)
            {
                /* Allocate the System Buffer */
                Irp->AssociatedIrp.SystemBuffer =
                    ExAllocatePoolWithTag(NonPagedPool,
                                          InputBufferLength,
                                          TAG_SYS_BUF);
                if (!Irp->AssociatedIrp.SystemBuffer)
                {
                    /* Free the IRP and fail */
                    IoFreeIrp(Irp);

⌨️ 快捷键说明

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