C++ (Cpp) KeBugCheckEx Examples

C++ (Cpp) KeBugCheckEx - 7 examples found. These are the top rated real world C++ (Cpp) examples of KeBugCheckEx extracted from open source projects. You can rate examples to help us improve the quality of examples.
Example #1
0
VOID
ExpCheckForWorker (
    IN PVOID p,
    IN SIZE_T Size
)

{
    KIRQL OldIrql;
    PLIST_ENTRY Entry;
    PCHAR BeginBlock;
    PCHAR EndBlock;
    WORK_QUEUE_TYPE wqt;

    BeginBlock = (PCHAR)p;
    EndBlock = (PCHAR)p + Size;

    KiLockDispatcherDatabase (&OldIrql);

    for (wqt = CriticalWorkQueue; wqt < MaximumWorkQueue; wqt += 1) {
        for (Entry = (PLIST_ENTRY) ExWorkerQueue[wqt].WorkerQueue.EntryListHead.Flink;
                Entry && (Entry != (PLIST_ENTRY) &ExWorkerQueue[wqt].WorkerQueue.EntryListHead);
                Entry = Entry->Flink) {
            if (((PCHAR) Entry >= BeginBlock) && ((PCHAR) Entry < EndBlock)) {
                KeBugCheckEx(WORKER_INVALID,
                             0x0,
                             (ULONG_PTR)Entry,
                             (ULONG_PTR)BeginBlock,
                             (ULONG_PTR)EndBlock);

            }
        }
    }
    KiUnlockDispatcherDatabase (OldIrql);
}
Example #2
0
VOID
ExpWorkerThread (
    IN PVOID StartContext
)
{
    PLIST_ENTRY Entry;
    WORK_QUEUE_TYPE QueueType;
    PWORK_QUEUE_ITEM WorkItem;
    KPROCESSOR_MODE WaitMode;
    LARGE_INTEGER TimeoutValue;
    PLARGE_INTEGER Timeout;
    PETHREAD Thread;
    PEX_WORK_QUEUE WorkerQueue;
    PWORKER_THREAD_ROUTINE WorkerRoutine;
    PVOID Parameter;
    EX_QUEUE_WORKER_INFO OldWorkerInfo;
    EX_QUEUE_WORKER_INFO NewWorkerInfo;
    ULONG CountForQueueEmpty;

    //
    // Set timeout value etc according to whether we are static or dynamic.
    //

    if (((ULONG_PTR)StartContext & DYNAMIC_WORKER_THREAD) == 0) {

        //
        // We are being created as a static thread.  As such it will not
        // terminate, so there is no point in timing out waiting for a work
        // item.
        //

        Timeout = NULL;
    }
    else {

        //
        // This is a dynamic worker thread.  It has a non-infinite timeout
        // so that it can eventually terminate.
        //

        TimeoutValue.QuadPart = -DYNAMIC_THREAD_TIMEOUT;
        Timeout = &TimeoutValue;
    }

    Thread = PsGetCurrentThread ();

    //
    // If the thread is a critical worker thread, then set the thread
    // priority to the lowest realtime level. Otherwise, set the base
    // thread priority to time critical.
    //

    QueueType = (WORK_QUEUE_TYPE)
                ((ULONG_PTR)StartContext & ~DYNAMIC_WORKER_THREAD);

    WorkerQueue = &ExWorkerQueue[QueueType];

    WaitMode = (KPROCESSOR_MODE) WorkerQueue->Info.WaitMode;

    ASSERT (Thread->ExWorkerCanWaitUser == 0);

    if (WaitMode == UserMode) {
        Thread->ExWorkerCanWaitUser = 1;
    }

#if defined(REMOTE_BOOT)
    //
    // In diskless NT scenarios ensure that the kernel stack of the worker
    // threads will not be swapped out.
    //

    if (IoRemoteBootClient) {
        KeSetKernelStackSwapEnable (FALSE);
    }
#endif // defined(REMOTE_BOOT)

    //
    // Register as a worker, exiting if the queue's going down and
    // there aren't any workers in the queue to hand us the shutdown
    // work item if we enter the queue (we want to be able to enter a
    // queue even if the queue's shutting down, in case there's a
    // backlog of work items that the balance manager thread's decided
    // we should be helping to process).
    //

    if (PO_SHUTDOWN_QUEUE == QueueType) {
        CountForQueueEmpty = 1;
    }
    else {
        CountForQueueEmpty = 0;
    }

    if (ExpWorkersCanSwap == FALSE) {
        KeSetKernelStackSwapEnable (FALSE);
    }

    do {

        OldWorkerInfo.QueueWorkerInfo = ReadForWriteAccess (&WorkerQueue->Info.QueueWorkerInfo);

        if (OldWorkerInfo.QueueDisabled &&
                OldWorkerInfo.WorkerCount <= CountForQueueEmpty) {

            //
            // The queue is disabled and empty so just exit.
            //

            KeSetKernelStackSwapEnable (TRUE);
            PsTerminateSystemThread (STATUS_SYSTEM_SHUTDOWN);
        }

        NewWorkerInfo.QueueWorkerInfo = OldWorkerInfo.QueueWorkerInfo;
        NewWorkerInfo.WorkerCount += 1;

    } while (OldWorkerInfo.QueueWorkerInfo !=

             InterlockedCompareExchange (&WorkerQueue->Info.QueueWorkerInfo,
                                         NewWorkerInfo.QueueWorkerInfo,
                                         OldWorkerInfo.QueueWorkerInfo));

    //
    // As of this point, we must only exit if we decrement the worker
    // count without the queue disabled flag being set.  (Unless we
    // exit due to the shutdown work item, which also decrements the
    // worker count).
    //

    Thread->ActiveExWorker = 1;

    //
    // Loop forever waiting for a work queue item, calling the processing
    // routine, and then waiting for another work queue item.
    //

    do {

        //
        // Wait until something is put in the queue or until we time out.
        //
        // By specifying a wait mode of UserMode, the thread's kernel
        // stack is swappable.
        //

        Entry = KeRemoveQueue (&WorkerQueue->WorkerQueue,
                               WaitMode,
                               Timeout);

        if ((ULONG_PTR)Entry != STATUS_TIMEOUT) {

            //
            // This is a real work item, process it.
            //
            // Update the total number of work items processed.
            //

            InterlockedIncrement ((PLONG)&WorkerQueue->WorkItemsProcessed);

            WorkItem = CONTAINING_RECORD(Entry, WORK_QUEUE_ITEM, List);
            WorkerRoutine = WorkItem->WorkerRoutine;
            Parameter = WorkItem->Parameter;

            //
            // Catch worker routines referencing a user mode address.
            //

            ASSERT ((ULONG_PTR)WorkerRoutine > MmUserProbeAddress);

            //
            // Execute the specified routine.
            //

            ((PWORKER_THREAD_ROUTINE)WorkerRoutine) (Parameter);

#if DBG
            if (IsListEmpty (&Thread->IrpList)) {
                //
                // See if a worker just returned while holding a resource
                //
                ExCheckIfResourceOwned ();
            }
#endif
            //
            // Catch worker routines that forget to leave a critial/guarded
            // region. In the debug case execute a breakpoint. In the free
            // case zero the flag so that  APCs can continue to fire to this
            // thread.
            //

            if (Thread->Tcb.CombinedApcDisable != 0) {
                DbgPrint ((char*)ExpWorkerApcDisabledMessage,
                          WorkerRoutine,
                          Parameter,
                          WorkItem);

                ASSERT (FALSE);

                Thread->Tcb.CombinedApcDisable = 0;
            }

            if (KeGetCurrentIrql () != PASSIVE_LEVEL) {
                KeBugCheckEx (WORKER_THREAD_RETURNED_AT_BAD_IRQL,
                              (ULONG_PTR)WorkerRoutine,
                              (ULONG_PTR)KeGetCurrentIrql(),
                              (ULONG_PTR)Parameter,
                              (ULONG_PTR)WorkItem);
            }

            if (PS_IS_THREAD_IMPERSONATING (Thread)) {
                KeBugCheckEx (IMPERSONATING_WORKER_THREAD,
                              (ULONG_PTR)WorkerRoutine,
                              (ULONG_PTR)Parameter,
                              (ULONG_PTR)WorkItem,
                              0);
            }

            continue;
        }

        //
        // These things are known:
        //
        // - Static worker threads do not time out, so this is a dynamic
        //   worker thread.
        //
        // - This thread has been waiting for a long time with nothing
        //   to do.
        //

        if (IsListEmpty (&Thread->IrpList) == FALSE) {

            //
            // There is still I/O pending, can't terminate yet.
            //

            continue;
        }

        //
        // Get out of the queue, if we can
        //

        do {
            OldWorkerInfo.QueueWorkerInfo = ReadForWriteAccess (&WorkerQueue->Info.QueueWorkerInfo);

            if (OldWorkerInfo.QueueDisabled) {

                //
                // We're exiting via the queue disable work item;
                // there's no point in expiring here.
                //

                break;
            }

            NewWorkerInfo.QueueWorkerInfo = OldWorkerInfo.QueueWorkerInfo;
            NewWorkerInfo.WorkerCount -= 1;

        } while (OldWorkerInfo.QueueWorkerInfo
                 != InterlockedCompareExchange(&WorkerQueue->Info.QueueWorkerInfo,
                                               NewWorkerInfo.QueueWorkerInfo,
                                               OldWorkerInfo.QueueWorkerInfo));

        if (OldWorkerInfo.QueueDisabled) {

            //
            // We're exiting via the queue disable work item
            //

            continue;
        }

        //
        // This dynamic thread can be terminated.
        //

        break;

    } while (TRUE);

    //
    // Terminate this dynamic thread.
    //

    InterlockedDecrement ((PLONG)&WorkerQueue->DynamicThreadCount);

    //
    // Carefully clear this before marking the thread stack as swap enabled
    // so that an incoming APC won't inadvertently disable the stack swap
    // afterwards.
    //

    Thread->ActiveExWorker = 0;

    //
    // We will bugcheck if we terminate a thread with stack swapping
    // disabled.
    //

    KeSetKernelStackSwapEnable (TRUE);

    return;
}
Example #3
0
VOID
ExQueueWorkItem (
    __inout PWORK_QUEUE_ITEM WorkItem,
    __in WORK_QUEUE_TYPE QueueType
)

/*++

Routine Description:

    This function inserts a work item into a work queue that is processed
    by a worker thread of the corresponding type.

Arguments:

    WorkItem - Supplies a pointer to the work item to add the the queue.
        This structure must be located in NonPagedPool. The work item
        structure contains a doubly linked list entry, the address of a
        routine to call and a parameter to pass to that routine.

    QueueType - Specifies the type of work queue that the work item
        should be placed in.

Return Value:

    None.

--*/

{
    PEX_WORK_QUEUE Queue;

    ASSERT (QueueType < MaximumWorkQueue);
    ASSERT (WorkItem->List.Flink == NULL);

    //
    // Perform a rudimentary validation on the worker routine.
    //

    if ((ULONG64)WorkItem->WorkerRoutine <= MmUserProbeAddress) {

        KeBugCheckEx (WORKER_INVALID,
                      0x1,
                      (ULONG_PTR)WorkItem,
                      (ULONG_PTR)WorkItem->WorkerRoutine,
                      0);
    }

    Queue = &ExWorkerQueue[QueueType];

    //
    // Insert the work item in the appropriate queue object.
    //

    KeInsertQueue (&Queue->WorkerQueue, &WorkItem->List);

    //
    // We check the queue's shutdown state after we insert the work
    // item to avoid the race condition when the queue's marked
    // between checking the queue and inserting the item.  It's
    // possible for the queue to be marked for shutdown between the
    // insert and this assert (so the insert would've barely sneaked
    // in), but it's not worth guarding against this -- barely
    // sneaking in is not a good design strategy, and at this point in
    // the shutdown sequence, the caller simply should not be trying
    // to insert new queue items.
    //

    ASSERT (!Queue->Info.QueueDisabled);

    //
    // Determine whether another thread should be created, and signal the
    // thread set balance manager if so.
    //

    if (ExpNewThreadNecessary (Queue) != FALSE) {
        KeSetEvent (&ExpThreadSetManagerEvent, 0, FALSE);
    }

    return;
}
Example #4
0
VOID
KeStackAttachProcess (
    __inout PRKPROCESS Process,
    __out PRKAPC_STATE ApcState
)

/*++

Routine Description:

    This function attaches a thread to a target process' address space
    and returns information about a previous attached process.

Arguments:

    Process - Supplies a pointer to a dispatcher object of type process.

Return Value:

    None.

--*/

{

    KLOCK_QUEUE_HANDLE LockHandle;
    PRKTHREAD Thread;

    ASSERT_PROCESS(Process);
    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

    //
    // If the current thread is executing a DPC, then bugcheck.
    //

    Thread = KeGetCurrentThread();
    if (KeIsExecutingDpc() != FALSE) {
        KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
                     (ULONG_PTR)Process,
                     (ULONG_PTR)Thread->ApcState.Process,
                     (ULONG)Thread->ApcStateIndex,
                     (ULONG)KeIsExecutingDpc());
    }

    //
    // If the target process is not the current process, then attach the
    // target process. Otherwise, return a distinguished process value to
    // indicate that an attach was not performed.
    //

    if (Thread->ApcState.Process == Process) {
        ApcState->Process = (PRKPROCESS)1;

    } else {

        //
        // Raise IRQL to SYNCH_LEVEL, acquire the thread APC queue lock, and
        // acquire the dispatcher database lock.
        //

        KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock,
                &LockHandle);

        KiLockDispatcherDatabaseAtSynchLevel();

        //
        // If the current thread is attached to a process, then save the
        // current APC state in the callers APC state structure. Otherwise,
        // save the current APC state in the saved APC state structure, and
        // return a NULL process pointer.
        //
        // N.B. All lock are released by the internal attach routine.
        //

        if (Thread->ApcStateIndex != 0) {
            KiAttachProcess(Thread, Process, &LockHandle, ApcState);

        } else {
            KiAttachProcess(Thread, Process, &LockHandle, &Thread->SavedApcState);
            ApcState->Process = NULL;
        }
    }

    return;
}
Example #5
0
LOGICAL
KeForceAttachProcess (
    __inout PRKPROCESS Process
)

/*++

Routine Description:

    This function forces an attach of a thread to a target process' address
    space if the process is not current being swapped into or out of memory.

    N.B. This function is for use by memory management ONLY.

Arguments:

    Process - Supplies a pointer to a dispatcher object of type process.

Return Value:

    None.

--*/

{

    KLOCK_QUEUE_HANDLE LockHandle;
    PRKTHREAD Thread;

    ASSERT_PROCESS(Process);
    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

    //
    // If the current thread is already attached or executing a DPC, then
    // bugcheck.
    //

    Thread = KeGetCurrentThread();
    if ((Thread->ApcStateIndex != 0) ||
            (KeIsExecutingDpc() != FALSE)) {

        KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
                     (ULONG_PTR)Process,
                     (ULONG_PTR)Thread->ApcState.Process,
                     (ULONG)Thread->ApcStateIndex,
                     (ULONG)KeIsExecutingDpc());
    }

    //
    // If the target process is not the current process, then attach the
    // target process if the process is not currently being swapped in or
    // out of memory.
    //

    if (Thread->ApcState.Process != Process) {

        //
        // Raise IRQL to SYNCH_LEVEL, acquire the thread APC queue lock, and
        // acquire the dispatcher database lock.
        //

        KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock,
                &LockHandle);

        KiLockDispatcherDatabaseAtSynchLevel();

        //
        // If the target process is currently being swapped into or out of
        // memory, then return a value of FALSE. Otherwise, force the process
        // to be inswapped.
        //

        if ((Process->State == ProcessInSwap) ||
                (Process->State == ProcessInTransition) ||
                (Process->State == ProcessOutTransition) ||
                (Process->State == ProcessOutSwap)) {
            KiUnlockDispatcherDatabaseFromSynchLevel();
            KeReleaseInStackQueuedSpinLock(&LockHandle);
            return FALSE;

        } else {

            //
            // Force the process state to in memory and attach the target process.
            //
            // N.B. All lock are released by the internal attach routine.
            //

            Process->State = ProcessInMemory;
            KiAttachProcess(Thread, Process, &LockHandle, &Thread->SavedApcState);
        }
    }

    return TRUE;
}
Example #6
0
VOID
KeAttachProcess (
    __inout PRKPROCESS Process
)

/*++

Routine Description:

    This function attaches a thread to a target process' address space
    if, and only if, there is not already a process attached.

Arguments:

    Process - Supplies a pointer to a dispatcher object of type process.

Return Value:

    None.

--*/

{

    KLOCK_QUEUE_HANDLE LockHandle;
    PRKTHREAD Thread;

    ASSERT_PROCESS(Process);
    ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

    //
    // If the target process is not the current process, then attach the
    // target process.
    //

    Thread = KeGetCurrentThread();
    if (Thread->ApcState.Process != Process) {

        //
        // If the current thread is already attached or executing a DPC, then
        // bugcheck.
        //

        if ((Thread->ApcStateIndex != 0) ||
                (KeIsExecutingDpc() != FALSE)) {

            KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
                         (ULONG_PTR)Process,
                         (ULONG_PTR)Thread->ApcState.Process,
                         (ULONG)Thread->ApcStateIndex,
                         (ULONG)KeIsExecutingDpc());
        }

        //
        // Raise IRQL to SYNCH_LEVEL, acquire the thread APC queue lock,
        // acquire the dispatcher database lock, and attach to the specified
        // process.
        //
        // N.B. All lock are released by the internal attach routine.
        //

        KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock,
                &LockHandle);

        KiLockDispatcherDatabaseAtSynchLevel();
        KiAttachProcess(Thread, Process, &LockHandle, &Thread->SavedApcState);
    }

    return;
}