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

📄 queue.c

📁 该源码是用DDK编写的WDM驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
//  CharSample_DDKQueueCancelRoutine
//      Cancel routine used for queue IRPs while in the queue
//
//  Arguments:
//      IN  DeviceObject
//              Device object for our device
//
//      IN  Irp
//              IRP to be cancelled
//
//  Return Value:
//      none
//
VOID CharSample_DDKQueueCancelRoutine(
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
{
    KIRQL           oldIrql;
    PCHARSAMPLE_DDK_QUEUE  queue;

    // release the system cancel spinlock
    oldIrql = Irp->CancelIrql;
    IoReleaseCancelSpinLock(DISPATCH_LEVEL);

    // get our queue from the IRP
    queue = (PCHARSAMPLE_DDK_QUEUE)Irp->Tail.Overlay.DriverContext[0];

    ASSERT(queue != NULL);

    // grab the queue protection
    KeAcquireSpinLockAtDpcLevel(&queue->QueueLock);

    // remove our IRP from the queue
    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

    // drop the queue protection
    KeReleaseSpinLock(&queue->QueueLock, oldIrql);

    // cancel the IRP
    Irp->IoStatus.Status = STATUS_CANCELLED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Cancel Safe IRP List
///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKInitializeList
//      Sets up a cancel safe IRP list.
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//      IN  DeviceObject
//              Device object for our driver
//
//  Return Value:
//      none
//
VOID CharSample_DDKInitializeList(
    IN  PCHARSAMPLE_DDK_LIST List,
    IN  PDEVICE_OBJECT  DeviceObject
    )
{
    // save off the user info
    List->DeviceObject = DeviceObject;

    // initialize our queue lock
    KeInitializeSpinLock(&List->ListLock);

    // initialize our IRP list
    InitializeListHead(&List->IrpList);

    List->ErrorStatus = STATUS_SUCCESS;

    return;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKInsertHead
//      Puts Irp entry at head of list
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//      IN  Irp
//              IRP to be put in list
//
//  Return Value:
//      Status
//
NTSTATUS CharSample_DDKInsertHead(
    IN  PCHARSAMPLE_DDK_LIST List,
    IN  PIRP            Irp
    )
{
    NTSTATUS                status;
    KIRQL                   oldIrql;
    PCHARSAMPLE_DDK_DEVICE_EXTENSION   deviceExtension;

    deviceExtension = (PCHARSAMPLE_DDK_DEVICE_EXTENSION)List->DeviceObject->DeviceExtension;

    // Grab the list protection
    KeAcquireSpinLock(&List->ListLock, &oldIrql);

    if (List->ErrorStatus != STATUS_SUCCESS)
    {
        status = List->ErrorStatus;

        // drop the queue protection
        KeReleaseSpinLock(&List->ListLock, oldIrql);

        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }

    // put our list pointer into the IRP
    Irp->Tail.Overlay.DriverContext[0] = List;

    // put the entry at the head of the list
    InsertHeadList(&List->IrpList, &Irp->Tail.Overlay.ListEntry);

    // set cancel routine
    IoSetCancelRoutine(Irp, CharSample_DDKListCancelRoutine);

    // Make sure the IRP was not cancelled before 
    // we inserted our cancel routine
    if (Irp->Cancel)
    {
        // If the IRP was cancelled after we put in our cancel routine we
        // will get back NULL here and we will let the cancel routine handle
        // the IRP.  If NULL is not returned here then we know the IRP was 
        // cancelled before we inserted the cancel routine, and we
        // need to cancel the IRP
        if (IoSetCancelRoutine(Irp, NULL) != NULL)
        {
            RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

            // drop the list protection
            KeReleaseSpinLock(&List->ListLock, oldIrql);

            // cancel the IRP
            status = STATUS_CANCELLED;
            Irp->IoStatus.Status = status;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            return status;
        }
    }

    // mark irp pending since STATUS_PENDING is returned
    IoMarkIrpPending(Irp);
    status = STATUS_PENDING;

    // drop the list protection
    KeReleaseSpinLock(&List->ListLock, oldIrql);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKInsertTail
//      Puts Irp entry at end of list
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//      IN  Irp
//              IRP to be put in list
//
//  Return Value:
//      Status
//
NTSTATUS CharSample_DDKInsertTail(
    IN  PCHARSAMPLE_DDK_LIST   List,
    IN  PIRP            Irp
    )
{
    NTSTATUS                status;
    KIRQL                   oldIrql;
    PCHARSAMPLE_DDK_DEVICE_EXTENSION   deviceExtension;

    deviceExtension = (PCHARSAMPLE_DDK_DEVICE_EXTENSION)List->DeviceObject->DeviceExtension;

    // Grab the list protection
    KeAcquireSpinLock(&List->ListLock, &oldIrql);

    if (List->ErrorStatus != STATUS_SUCCESS)
    {
        status = List->ErrorStatus;

        // drop the queue protection
        KeReleaseSpinLock(&List->ListLock, oldIrql);

        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }

    // put our list pointer into the IRP
    Irp->Tail.Overlay.DriverContext[0] = (PVOID)List;

    // put the entry at the head of the list
    InsertHeadList(&List->IrpList, &Irp->Tail.Overlay.ListEntry);

    // set cancel routine
    IoSetCancelRoutine(Irp, CharSample_DDKListCancelRoutine);

    // Make sure the IRP was not cancelled before 
    // we inserted our cancel routine
    if (Irp->Cancel)
    {
        // If the IRP was cancelled after we put in our cancel routine we
        // will get back NULL here and we will let the cancel routine handle
        // the IRP.  If NULL is not returned here then we know the IRP was 
        // cancelled before we inserted the cancel routine, and we
        // need to cancel the IRP
        if (IoSetCancelRoutine(Irp, NULL) != NULL)
        {
            RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

            // drop the list protection
            KeReleaseSpinLock(&List->ListLock, oldIrql);

            // cancel the IRP
            status = STATUS_CANCELLED;
            Irp->IoStatus.Status = status;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            return status;
        }
    }

    // mark irp pending since STATUS_PENDING is returned
    IoMarkIrpPending(Irp);
    status = STATUS_PENDING;

    // drop the list protection
    KeReleaseSpinLock(&List->ListLock, oldIrql);

    return status;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKRemoveHead
//      Removes an Irp entry from the head of list
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//  Return Value:
//      IRP removed from head of list
//
PIRP CharSample_DDKRemoveHead(
    IN  PCHARSAMPLE_DDK_LIST   List
    )
{
    PLIST_ENTRY entry;
    PIRP        irp;
    KIRQL       oldIrql;

    // Grab the list protection
    KeAcquireSpinLock(&List->ListLock, &oldIrql);

    // Make sure there are entries in the list
    if (IsListEmpty(&List->IrpList))
    {
        // drop the list protection
        KeReleaseSpinLock(&List->ListLock, oldIrql);

        return NULL;
    }

    // get a new IRP from the queue
    for (entry = List->IrpList.Flink; entry != &List->IrpList; entry = entry->Flink)
    {
        // get our IRP from the entry
        irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

        ASSERT(irp->Type == IO_TYPE_IRP);

        // if we found an IRP, pull the queue cancel routine out of it
        // See if the IRP is canceled
        if (IoSetCancelRoutine(irp, NULL) == NULL)
        {
            // cancel routine already has a hold on this IRP, 
            // just go on to the next one
            irp = NULL;
        }
        else
        {
            // Found a usable IRP, pull the entry out of the list
            RemoveEntryList(entry);
            break;
        }
    }

    // drop the list protection
    KeReleaseSpinLock(&List->ListLock, oldIrql);

    return irp;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKRemoveTail
//      Removes an Irp entry from the tail of list
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//  Return Value:
//      IRP removed from end of list
//
PIRP CharSample_DDKRemoveTail(
    IN  PCHARSAMPLE_DDK_LIST   List
    )
{
    PLIST_ENTRY entry;
    PIRP        irp;
    KIRQL       oldIrql;

    // Grab the list protection
    KeAcquireSpinLock(&List->ListLock, &oldIrql);

    // Make sure there are entries in the list
    if (IsListEmpty(&List->IrpList))
    {
        // drop the list protection
        KeReleaseSpinLock(&List->ListLock, oldIrql);

        return NULL;
    }

    // get a new IRP from the queue
    for (entry = List->IrpList.Blink; entry != &List->IrpList; entry = entry->Blink)
    {
        // get our IRP from the entry
        irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

        ASSERT(irp->Type == IO_TYPE_IRP);

        // if we found an IRP, pull the queue cancel routine out of it
        // See if the IRP is canceled
        if (IoSetCancelRoutine(irp, NULL) == NULL)
        {
            // cancel routine already has a hold on this IRP, 
            // just go on to the next one
            irp = NULL;
        }
        else
        {
            // Found a usable IRP, pull the entry out of the list
            RemoveEntryList(entry);
            break;
        }
    }

    // drop the list protection
    KeReleaseSpinLock(&List->ListLock, oldIrql);

    return irp;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKFlushList
//      Cancels all IRPs in the list, or all IRPs in the list related to a 
//      particular open handle.
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//      IN  FileObject
//              If NULL all IRPs in list are cancelled, if non-NULL then all
//              IRPs related to this file object are cancelled.
//
//  Return Value:
//      none
//
VOID CharSample_DDKFlushList(
    IN  PCHARSAMPLE_DDK_LIST   List,
    IN  PFILE_OBJECT        FileObject
    )
{
    PLIST_ENTRY         entry;
    PLIST_ENTRY         nextEntry;
    PIRP                irp;
    PIO_STACK_LOCATION  irpStack;
    KIRQL               oldIrql;
    LIST_ENTRY          cancelList;

    // initialize our cancel list
    InitializeListHead(&cancelList);

    // grab the list protection
    KeAcquireSpinLock(&List->ListLock, &oldIrql);

    // Look at the first entry in the list
    entry = List->IrpList.Flink;
    while (entry != &List->IrpList)
    {
        // get the next list entry
        nextEntry = entry->Flink;

        // Get the IRP from the entry
        irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

        ASSERT(irp->Type == IO_TYPE_IRP);

        // Determine if we need to pull out of list
        if (FileObject != NULL)
        {
            // get the current IRP stack location from the IRP
            irpStack = IoGetCurrentIrpStackLocation(irp);

            if (irpStack->FileObject != FileObject)
            {
                // go to the next entry
                entry = nextEntry;

                // We are not flushing this IRP
                continue;
            }
        }

        // Attempt to cancel the IRP
        if (IoSetCancelRoutine(irp, NULL) == NULL)
        {
            // go to the next entry
            entry = nextEntry;

            // cancel routine already has this IRP,
            // just go on
            continue;
        }

        // pull the IRP from the list
        RemoveEntryList(entry);

        InsertTailList(&cancelList, entry);

        // go to the next entry
        entry = nextEntry;
    }

    // drop the list protection
    KeReleaseSpinLock(&List->ListLock, oldIrql);

    // Now clear out our cancel list
    while (!IsListEmpty(&cancelList))
    {
        // Get the first entry on the list
        entry = RemoveHeadList(&cancelList);

        // Get the IRP for that entry
        irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);

        // Cancel the IRP
        irp->IoStatus.Status = STATUS_CANCELLED;
        irp->IoStatus.Information = 0;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
    }

    return;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKInvalidateList
//      Stops list from receiving anymore IRPs, all IRPs are completed upon
//      receipt
//
//  Arguments:
//      IN  List
//              An instance of our list structure
//
//  Return Value:
//      none
//
VOID CharSample_DDKInvalidateList(
    IN  PCHARSAMPLE_DDK_LIST   List,
    IN  NTSTATUS                ErrorStatus
    )
{
    // indicate the list is shutdown
    List->ErrorStatus = ErrorStatus;

    // flush all requests from the list
    CharSample_DDKFlushList(List, NULL);

    return;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
//  CharSample_DDKListCancelRoutine
//      Cancel routine used for our cancel safe IRP list
//
//  Arguments:
//      IN  DeviceObject
//              Device object for our device
//
//      IN  Irp
//              IRP to be cancelled

⌨️ 快捷键说明

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