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

📄 iocomp.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * PROJECT:         ReactOS Kernel
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            ntoskrnl/io/iocomp.c
 * PURPOSE:         I/O Wrappers (called Completion Ports) for Kernel Queues
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 *                  Thomas Weidenmueller (w3seek@reactos.org)
 */

/* INCLUDES *****************************************************************/

#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>

POBJECT_TYPE IoCompletionType;

NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;

GENERIC_MAPPING IopCompletionMapping =
{
    STANDARD_RIGHTS_READ    | IO_COMPLETION_QUERY_STATE,
    STANDARD_RIGHTS_WRITE   | IO_COMPLETION_MODIFY_STATE,
    STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | IO_COMPLETION_QUERY_STATE,
    IO_COMPLETION_ALL_ACCESS
};

static const INFORMATION_CLASS_INFO IoCompletionInfoClass[] =
{
     /* IoCompletionBasicInformation */
    ICI_SQ_SAME(sizeof(IO_COMPLETION_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
};

/* PRIVATE FUNCTIONS *********************************************************/

NTSTATUS
NTAPI
IopUnloadSafeCompletion(IN PDEVICE_OBJECT DeviceObject,
                        IN PIRP Irp,
                        IN PVOID Context)
{
    NTSTATUS Status;
    PIO_UNLOAD_SAFE_COMPLETION_CONTEXT UnsafeContext =
        (PIO_UNLOAD_SAFE_COMPLETION_CONTEXT)Context;

    /* Reference the device object */
    ObReferenceObject(UnsafeContext->DeviceObject);

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

    /* Dereference the device object */
    ObDereferenceObject(UnsafeContext->DeviceObject);

    /* Free our context */
    ExFreePool(UnsafeContext);
    return Status;
}

VOID
NTAPI
IopFreeIoCompletionPacket(PIO_COMPLETION_PACKET Packet)
{
    PKPRCB Prcb = KeGetCurrentPrcb();
    PNPAGED_LOOKASIDE_LIST List;

    /* Use the P List */
    List = (PNPAGED_LOOKASIDE_LIST)Prcb->
            PPLookasideList[LookasideCompletionList].P;
    List->L.TotalFrees++;

    /* Check if the Free was within the Depth or not */
    if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
    {
        /* Let the balancer know */
        List->L.FreeMisses++;

        /* Use the L List */
        List = (PNPAGED_LOOKASIDE_LIST)Prcb->
                PPLookasideList[LookasideCompletionList].L;
        List->L.TotalFrees++;

        /* Check if the Free was within the Depth or not */
        if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth)
        {
            /* All lists failed, use the pool */
            List->L.FreeMisses++;
            ExFreePool(Packet);
        }
    }

    /* The free was within dhe Depth */
    InterlockedPushEntrySList(&List->L.ListHead, (PSINGLE_LIST_ENTRY)Packet);
}

VOID
NTAPI
IopDeleteIoCompletion(PVOID ObjectBody)
{
    PKQUEUE Queue = ObjectBody;
    PLIST_ENTRY FirstEntry;
    PLIST_ENTRY CurrentEntry;
    PIRP Irp;
    PIO_COMPLETION_PACKET Packet;

    /* Rundown the Queue */
    FirstEntry = KeRundownQueue(Queue);
    if (FirstEntry)
    {
        /* Loop the packets */
        CurrentEntry = FirstEntry;
        do
        {
            /* Get the Packet */
            Packet = CONTAINING_RECORD(CurrentEntry,
                                       IO_COMPLETION_PACKET,
                                       ListEntry);

            /* Go to next Entry */
            CurrentEntry = CurrentEntry->Flink;

            /* Check if it's part of an IRP, or a separate packet */
            if (Packet->PacketType == IrpCompletionPacket)
            {
                /* Get the IRP and free it */
                Irp = CONTAINING_RECORD(Packet, IRP, Tail.Overlay.ListEntry);
                IoFreeIrp(Irp);
            }
            else
            {
                /* Use common routine */
                IopFreeIoCompletionPacket(Packet);
            }
        } while (FirstEntry != CurrentEntry);
    }
}

/* PUBLIC FUNCTIONS **********************************************************/

/*
 * @implemented
 */
NTSTATUS
NTAPI
IoSetIoCompletion(IN PVOID IoCompletion,
                  IN PVOID KeyContext,
                  IN PVOID ApcContext,
                  IN NTSTATUS IoStatus,
                  IN ULONG_PTR IoStatusInformation,
                  IN BOOLEAN Quota)
{
    PKQUEUE Queue = (PKQUEUE)IoCompletion;
    PNPAGED_LOOKASIDE_LIST List;
    PKPRCB Prcb = KeGetCurrentPrcb();
    PIO_COMPLETION_PACKET Packet;

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

    /* Try to allocate the Packet */
    List->L.TotalAllocates++;
    Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);

    /* Check if that failed, use the L list if it did */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Get L List */
        List = (PNPAGED_LOOKASIDE_LIST)Prcb->
                PPLookasideList[LookasideCompletionList].L;

        /* Try to allocate the Packet */
        List->L.TotalAllocates++;
        Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
    }

    /* Still failed, use pool */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Allocate from Nonpaged Pool */
        Packet = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Packet), IOC_TAG);
    }

    /* Make sure we have one by now... */
    if (Packet)
    {
        /* Set up the Packet */
        Packet->PacketType = IrpMiniCompletionPacket;
        Packet->Key = KeyContext;
        Packet->Context = ApcContext;
        Packet->IoStatus.Status = IoStatus;
        Packet->IoStatus.Information = IoStatusInformation;

        /* Insert the Queue */
        KeInsertQueue(Queue, &Packet->ListEntry);
    }
    else
    {
        /* Out of memory, fail */
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Return Success */
    return STATUS_SUCCESS;
}

/*
 * @implemented
 */
NTSTATUS
NTAPI
IoSetCompletionRoutineEx(IN PDEVICE_OBJECT DeviceObject,
                         IN PIRP Irp,
                         IN PIO_COMPLETION_ROUTINE CompletionRoutine,
                         IN PVOID Context,
                         IN BOOLEAN InvokeOnSuccess,
                         IN BOOLEAN InvokeOnError,
                         IN BOOLEAN InvokeOnCancel)
{
    PIO_UNLOAD_SAFE_COMPLETION_CONTEXT UnloadContext;

    /* Allocate the context */
    UnloadContext = ExAllocatePoolWithTag(NonPagedPool,
                                          sizeof(*UnloadContext),
                                          TAG('I', 'o', 'U', 's'));
    if (!UnloadContext) return STATUS_INSUFFICIENT_RESOURCES;

    /* Set up the context */
    UnloadContext->DeviceObject = DeviceObject;
    UnloadContext->Context = Context;
    UnloadContext->CompletionRoutine = CompletionRoutine;

    /* Now set the completion routine */
    IoSetCompletionRoutine(Irp,
                           IopUnloadSafeCompletion,
                           UnloadContext,
                           InvokeOnSuccess,
                           InvokeOnError,
                           InvokeOnCancel);
    return STATUS_SUCCESS;
}

NTSTATUS
NTAPI
NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
                     IN ACCESS_MASK DesiredAccess,
                     IN POBJECT_ATTRIBUTES ObjectAttributes,
                     IN ULONG NumberOfConcurrentThreads)
{
    PKQUEUE Queue;
    HANDLE hIoCompletionHandle;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status = STATUS_SUCCESS;
    PAGED_CODE();

    /* Check if this was a user-mode call */
    if (PreviousMode != KernelMode)
    {
        /* Wrap probing in SEH */
        _SEH_TRY
        {
            /* Probe the handle */
            ProbeForWriteHandle(IoCompletionHandle);
        }
        _SEH_HANDLE
        {
            /* Get the exception code */
            Status = _SEH_GetExceptionCode();
        }
        _SEH_END;

        /* Fail on exception */
        if (!NT_SUCCESS(Status)) return Status;
    }

    /* Create the Object */
    Status = ObCreateObject(PreviousMode,
                            IoCompletionType,
                            ObjectAttributes,
                            PreviousMode,
                            NULL,
                            sizeof(KQUEUE),
                            0,
                            0,
                            (PVOID*)&Queue);
    if (NT_SUCCESS(Status))
    {
        /* Initialize the Queue */
        KeInitializeQueue(Queue, NumberOfConcurrentThreads);

        /* Insert it */
        Status = ObInsertObject(Queue,
                                NULL,
                                DesiredAccess,
                                0,
                                NULL,
                                &hIoCompletionHandle);

⌨️ 快捷键说明

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