Ejemplo n.º 1
0
NTSTATUS
NTAPI
PsSuspendProcess(IN PEPROCESS Process)
{
    PETHREAD Thread;
    PAGED_CODE();

    /* Lock the Process */
    if (!ExAcquireRundownProtection(&Process->RundownProtect))
    {
        /* Process is terminating */
        return STATUS_PROCESS_IS_TERMINATING;
    }

    /* Get the first thread */
    Thread = PsGetNextProcessThread(Process, NULL);
    while (Thread)
    {
        /* Resume it */
        PsSuspendThread(Thread, NULL);

        /* Move to the next thread */
        Thread = PsGetNextProcessThread(Process, Thread);
    }

    /* Unlock the process */
    ExReleaseRundownProtection(&Process->RundownProtect);
    return STATUS_SUCCESS;
}
Ejemplo n.º 2
0
Archivo: work.c Proyecto: killvxk/NT_OS
VOID
NTAPI
ExSwapinWorkerThreads(IN BOOLEAN AllowSwap)
{
    KEVENT Event;
    PETHREAD CurrentThread = PsGetCurrentThread(), Thread;
    PEPROCESS Process = PsInitialSystemProcess;
    KAPC Apc;
    PAGED_CODE();

    /* Initialize an event so we know when we're done */
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    /* Lock this routine */
    ExAcquireFastMutex(&ExpWorkerSwapinMutex);

    /* New threads cannot swap anymore */
    ExpWorkersCanSwap = AllowSwap;

    /* Loop all threads in the system process */
    Thread = PsGetNextProcessThread(Process, NULL);
    while (Thread)
    {
        /* Skip threads with explicit permission to do this */
        if (Thread->ExWorkerCanWaitUser) goto Next;

        /* Check if we reached ourselves */
        if (Thread == CurrentThread)
        {
            /* Do it inline */
            KeSetKernelStackSwapEnable(AllowSwap);
        }
        else
        {
            /* Queue an APC */
            KeInitializeApc(&Apc,
                            &Thread->Tcb,
                            InsertApcEnvironment,
                            ExpSetSwappingKernelApc,
                            NULL,
                            NULL,
                            KernelMode,
                            &AllowSwap);
            if (KeInsertQueueApc(&Apc, &Event, NULL, 3))
            {
                /* Wait for the APC to run */
                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
                KeClearEvent(&Event);
            }
        }
        
        /* Next thread */
Next:
        Thread = PsGetNextProcessThread(Process, Thread);
    }

    /* Release the lock */
    ExReleaseFastMutex(&ExpWorkerSwapinMutex);
}
Ejemplo n.º 3
0
NTSTATUS
NTAPI
PspTerminateProcess(IN PEPROCESS Process,
                    IN NTSTATUS ExitStatus)
{
    PETHREAD Thread;
    NTSTATUS Status = STATUS_NOTHING_TO_TERMINATE;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG,
            "Process: %p ExitStatus: %d\n", Process, ExitStatus);
    PSREFTRACE(Process);

    /* Check if this is a Critical Process */
    if (Process->BreakOnTermination)
    {
        /* Break to debugger */
        PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
                              Process,
                              Process->ImageFileName);
    }

    /* Set the delete flag */
    InterlockedOr((PLONG)&Process->Flags, PSF_PROCESS_DELETE_BIT);

    /* Get the first thread */
    Thread = PsGetNextProcessThread(Process, NULL);
    while (Thread)
    {
        /* Kill it */
        PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
        Thread = PsGetNextProcessThread(Process, Thread);

        /* We had at least one thread, so termination is OK */
        Status = STATUS_SUCCESS;
    }

    /* Check if there was nothing to terminate or if we have a debug port */
    if ((Status == STATUS_NOTHING_TO_TERMINATE) || (Process->DebugPort))
    {
        /* Clear the handle table anyway */
        ObClearProcessHandleTable(Process);
    }

    /* Return status */
    return Status;
}
Ejemplo n.º 4
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL,
                   IN NTSTATUS ExitStatus)
{
    NTSTATUS Status;
    PEPROCESS Process, CurrentProcess = PsGetCurrentProcess();
    PETHREAD Thread, CurrentThread = PsGetCurrentThread();
    BOOLEAN KillByHandle;
    PAGED_CODE();
    PSTRACE(PS_KILL_DEBUG,
            "ProcessHandle: %p ExitStatus: %d\n", ProcessHandle, ExitStatus);

    /* Were we passed a process handle? */
    if (ProcessHandle)
    {
        /* Yes we were, use it */
        KillByHandle = TRUE;
    }
    else
    {
        /* We weren't... we assume this is suicide */
        KillByHandle = FALSE;
        ProcessHandle = NtCurrentProcess();
    }

    /* Get the Process Object */
    Status = ObReferenceObjectByHandle(ProcessHandle,
                                       PROCESS_TERMINATE,
                                       PsProcessType,
                                       KeGetPreviousMode(),
                                       (PVOID*)&Process,
                                       NULL);
    if (!NT_SUCCESS(Status)) return(Status);

    /* Check if this is a Critical Process, and Bugcheck */
    if (Process->BreakOnTermination)
    {
        /* Break to debugger */
        PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
                              Process,
                              Process->ImageFileName);
    }

    /* Lock the Process */
    if (!ExAcquireRundownProtection(&Process->RundownProtect))
    {
        /* Failed to lock, fail */
        ObDereferenceObject(Process);
        return STATUS_PROCESS_IS_TERMINATING;
    }

    /* Set the delete flag, unless the process is comitting suicide */
    if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT);

    /* Get the first thread */
    Status = STATUS_NOTHING_TO_TERMINATE;
    Thread = PsGetNextProcessThread(Process, NULL);
    if (Thread)
    {
        /* We know we have at least a thread */
        Status = STATUS_SUCCESS;

        /* Loop and kill the others */
        do
        {
            /* Ensure it's not ours*/
            if (Thread != CurrentThread)
            {
                /* Kill it */
                PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
            }

            /* Move to the next thread */
            Thread = PsGetNextProcessThread(Process, Thread);
        } while (Thread);
    }

    /* Unlock the process */
    ExReleaseRundownProtection(&Process->RundownProtect);

    /* Check if we are killing ourselves */
    if (Process == CurrentProcess)
    {
        /* Also make sure the caller gave us our handle */
        if (KillByHandle)
        {
            /* Dereference the process */
            ObDereferenceObject(Process);

            /* Terminate ourselves */
            PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE);
        }
    }
    else if (ExitStatus == DBG_TERMINATE_PROCESS)
    {
        /* Disable debugging on this process */
        DbgkClearProcessDebugObject(Process, NULL);
    }

    /* Check if there was nothing to terminate, or if we have a Debug Port */
    if ((Status == STATUS_NOTHING_TO_TERMINATE) ||
        ((Process->DebugPort) && (KillByHandle)))
    {
        /* Clear the handle table */
        ObClearProcessHandleTable(Process);

        /* Return status now */
        Status = STATUS_SUCCESS;
    }

    /* Decrease the reference count we added */
    ObDereferenceObject(Process);

    /* Return status */
    return Status;
}
Ejemplo n.º 5
0
VOID
ExSwapinWorkerThreads (
    IN BOOLEAN AllowSwap
    )

/*++

Routine Description:

    Sets the kernel stacks of the delayed worker threads to be swappable
    or pins them into memory.

Arguments:

    AllowSwap - Supplies TRUE if worker kernel stacks should be swappable,
                FALSE if not.

Return Value:

    None.

--*/

{
    PETHREAD         Thread;
    PETHREAD         CurrentThread;
    PEPROCESS        Process;
    KAPC             Apc;
    KEVENT           SwapSetEvent;

    PAGED_CODE();

    CurrentThread = PsGetCurrentThread();

    KeInitializeEvent (&SwapSetEvent,
                       NotificationEvent,
                       FALSE);

    Process = PsInitialSystemProcess;

    //
    // Serialize callers.
    //

    ExAcquireFastMutex (&ExpWorkerSwapinMutex);

    //
    // Stop new threads from swapping.
    //

    ExpWorkersCanSwap = AllowSwap;

    //
    // Stop existing worker threads from swapping.
    //

    for (Thread = PsGetNextProcessThread (Process, NULL);
         Thread != NULL;
         Thread = PsGetNextProcessThread (Process, Thread)) {

        //
        // Skip threads that are not worker threads or worker threads that
        // were permanently marked noswap at creation time.
        //

        if (Thread->ExWorkerCanWaitUser == 0) {
            continue;
        }

        if (Thread == CurrentThread) {

            //
            // No need to use an APC on the current thread.
            //

            KeSetKernelStackSwapEnable (AllowSwap);
        }
        else {

            //
            // Queue an APC to the thread, and wait for it to fire:
            //

            KeInitializeApc (&Apc,
                             &Thread->Tcb,
                             InsertApcEnvironment,
                             ExpSetSwappingKernelApc,
                             NULL,
                             NULL,
                             KernelMode,
                             &AllowSwap);

            if (KeInsertQueueApc (&Apc, &SwapSetEvent, NULL, 3)) {

                KeWaitForSingleObject (&SwapSetEvent,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL);

                KeClearEvent(&SwapSetEvent);
            }
        }
    }

    ExReleaseFastMutex (&ExpWorkerSwapinMutex);
}