mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 20:25:39 +00:00
Alex Ionescu <ionucu@videotron.ca>
- Removed ke/alert.c and moved its functions where they belong. - Commented and organized KeInitializeThread. - Began switch to true KOBJECT enumeration used in NT. - Implemented KeAlertResumeThread and NtAlertResumeThread. - Harmonized Formatting in ke/kthread.c svn path=/trunk/; revision=13974
This commit is contained in:
parent
a8f6850b9f
commit
b2a42182ef
10 changed files with 643 additions and 499 deletions
|
@ -58,7 +58,7 @@ static ULONG gNumberOfControllers = 0;
|
|||
|
||||
/* Queue thread management */
|
||||
static KEVENT QueueThreadTerminate;
|
||||
static PVOID ThreadObject;
|
||||
static PVOID QueueThreadObject;
|
||||
|
||||
|
||||
static VOID NTAPI MotorStopDpcFunc(PKDPC UnusedDpc,
|
||||
|
@ -378,8 +378,8 @@ static VOID NTAPI Unload(PDRIVER_OBJECT DriverObject)
|
|||
KdPrint(("floppy: unloading\n"));
|
||||
|
||||
KeSetEvent(&QueueThreadTerminate, 0, FALSE);
|
||||
KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, 0);
|
||||
ObDereferenceObject(ThreadObject);
|
||||
KeWaitForSingleObject(QueueThreadObject, Executive, KernelMode, FALSE, 0);
|
||||
ObDereferenceObject(QueueThreadObject);
|
||||
|
||||
for(i = 0; i < gNumberOfControllers; i++)
|
||||
{
|
||||
|
@ -1152,7 +1152,7 @@ NTSTATUS NTAPI DriverEntry(PDRIVER_OBJECT DriverObject,
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ThreadObject, NULL) != STATUS_SUCCESS)
|
||||
if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, NULL, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
|
||||
{
|
||||
KdPrint(("floppy: Unable to reference returned thread handle; failing init\n"));
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
|
|
@ -36,23 +36,34 @@ typedef VOID STDCALL_FUNC
|
|||
|
||||
struct _DISPATCHER_HEADER;
|
||||
|
||||
typedef enum _KERNEL_OBJECTS {
|
||||
KNotificationEvent = 0,
|
||||
KSynchronizationEvent = 1,
|
||||
KMutant = 2,
|
||||
KProcess = 3,
|
||||
KQueue = 4,
|
||||
KSemaphore = 5,
|
||||
KThread = 6,
|
||||
KNotificationTimer = 8,
|
||||
KSynchronizationTimer = 9,
|
||||
KApc = 18,
|
||||
KDpc = 19,
|
||||
KDeviceQueue = 20,
|
||||
KEventPair = 21,
|
||||
KInterrupt = 22,
|
||||
KProfile = 23
|
||||
} KERNEL_OBJECTS;
|
||||
typedef enum _KOBJECTS {
|
||||
EventNotificationObject = 0,
|
||||
EventSynchronizationObject = 1,
|
||||
MutantObject = 2,
|
||||
ProcessObject = 3,
|
||||
QueueObject = 4,
|
||||
SemaphoreObject = 5,
|
||||
ThreadObject = 6,
|
||||
GateObject = 7,
|
||||
TimerNotificationObject = 8,
|
||||
TimerSynchronizationObject = 9,
|
||||
Spare2Object = 10,
|
||||
Spare3Object = 11,
|
||||
Spare4Object = 12,
|
||||
Spare5Object = 13,
|
||||
Spare6Object = 14,
|
||||
Spare7Object = 15,
|
||||
Spare8Object = 16,
|
||||
Spare9Object = 17,
|
||||
ApcObject = 18,
|
||||
DpcObject = 19,
|
||||
DeviceQueueObject = 20,
|
||||
EventPairObject = 21,
|
||||
InterruptObject = 22,
|
||||
ProfileObject = 23,
|
||||
ThreadedDpcObject = 24,
|
||||
MaximumKernelObject = 25
|
||||
} KOBJECTS;
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
|
|
|
@ -113,8 +113,7 @@ OBJECTS_KE = \
|
|||
ke/sem.o \
|
||||
ke/spinlock.o \
|
||||
ke/timer.o \
|
||||
ke/wait.o \
|
||||
ke/alert.o
|
||||
ke/wait.o
|
||||
|
||||
# Memory Manager (Mm)
|
||||
OBJECTS_MM = \
|
||||
|
|
|
@ -498,7 +498,7 @@ VOID STDCALL PsExitSpecialApc(PKAPC Apc,
|
|||
#define PROCESS_PRIO_RT 18
|
||||
|
||||
|
||||
VOID
|
||||
VOID STDCALL
|
||||
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First);
|
||||
NTSTATUS KeReleaseThread(PKTHREAD Thread);
|
||||
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
/* $Id:$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/alert.c
|
||||
* PURPOSE: Alerts
|
||||
*
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||
/*
|
||||
* FUNCTION: Tests whether there are any pending APCs for the current thread
|
||||
* and if so the APCs will be delivered on exit from kernel mode
|
||||
*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
BOOLEAN OldState;
|
||||
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
OldState = Thread->Alerted[AlertMode];
|
||||
|
||||
/* If the Thread is Alerted, Clear it */
|
||||
if (OldState) {
|
||||
Thread->Alerted[AlertMode] = FALSE;
|
||||
} else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
|
||||
/* If the mode is User and the Queue isn't empty, set Pending */
|
||||
Thread->ApcState.UserApcPending = TRUE;
|
||||
}
|
||||
|
||||
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return OldState;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
KeAlertThread(PKTHREAD Thread, KPROCESSOR_MODE AlertMode)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
|
||||
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
|
||||
/* Return if thread is already alerted. */
|
||||
if (Thread->Alerted[AlertMode] == FALSE)
|
||||
{
|
||||
if (Thread->State == THREAD_STATE_BLOCKED &&
|
||||
(AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
|
||||
Thread->Alertable)
|
||||
{
|
||||
KiAbortWaitThread(Thread, STATUS_ALERTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->Alerted[AlertMode] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtAlertResumeThread(IN HANDLE ThreadHandle,
|
||||
OUT PULONG SuspendCount)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* EXPORTED
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtAlertThread (IN HANDLE ThreadHandle)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SUSPEND_RESUME,
|
||||
PsThreadType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* do an alert depending on the processor mode. If some kmode code wants to
|
||||
enforce a umode alert it should call KeAlertThread() directly. If kmode
|
||||
code wants to do a kmode alert it's sufficient to call it with Zw or just
|
||||
use KeAlertThread() directly */
|
||||
|
||||
KeAlertThread(&Thread->Tcb, PreviousMode);
|
||||
|
||||
ObDereferenceObject(Thread);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtTestAlert(VOID)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* Check and Alert Thread if needed */
|
||||
|
||||
return KeTestAlertThread(PreviousMode) ? STATUS_ALERTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ KeInitializeApc(
|
|||
|
||||
/* Set up the basic APC Structure Data */
|
||||
RtlZeroMemory(Apc, sizeof(KAPC));
|
||||
Apc->Type = KApc;
|
||||
Apc->Type = ApcObject;
|
||||
Apc->Size = sizeof(KAPC);
|
||||
|
||||
/* Set the Environment */
|
||||
|
|
|
@ -88,7 +88,7 @@ KeInitializeDpc (PKDPC Dpc,
|
|||
*/
|
||||
{
|
||||
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
|
||||
Dpc->Type = KDpc;
|
||||
Dpc->Type = DpcObject;
|
||||
Dpc->Number= 0;
|
||||
Dpc->Importance= MediumImportance;
|
||||
Dpc->DeferredRoutine = DeferredRoutine;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/kthread.c
|
||||
* PURPOSE: Microkernel thread support
|
||||
*
|
||||
* PROGRAMMERS: David Welch (welch@cwcom.net)
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Commented, reorganized some stuff, fixed/implemented some functions.
|
||||
* David Welch (welch@cwcom.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
@ -16,48 +16,325 @@
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
KiServiceCheck (VOID)
|
||||
ULONG
|
||||
STDCALL
|
||||
KeAlertResumeThread(IN PKTHREAD Thread)
|
||||
{
|
||||
PETHREAD Thread;
|
||||
ULONG PreviousCount;
|
||||
KIRQL OldIrql;
|
||||
|
||||
Thread = PsGetCurrentThread();
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow)
|
||||
{
|
||||
PsInitWin32Thread (Thread);
|
||||
/* Lock the Dispatcher Database and the APC Queue */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
|
||||
/* Return if Thread is already alerted. */
|
||||
if (Thread->Alerted[KernelMode] == FALSE) {
|
||||
|
||||
/* If it's Blocked, unblock if it we should */
|
||||
if (Thread->State == THREAD_STATE_BLOCKED && Thread->Alertable) {
|
||||
|
||||
DPRINT("Aborting Wait\n");
|
||||
KiAbortWaitThread(Thread, STATUS_ALERTED);
|
||||
|
||||
} else {
|
||||
|
||||
/* If not, simply Alert it */
|
||||
Thread->Alerted[KernelMode] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the old Suspend Count */
|
||||
PreviousCount = Thread->SuspendCount;
|
||||
|
||||
/* If the thread is suspended, decrease one of the suspend counts */
|
||||
if (PreviousCount) {
|
||||
|
||||
/* Decrease count. If we are now zero, unwait it completely */
|
||||
if (--Thread->SuspendCount) {
|
||||
|
||||
/* Signal and satisfy */
|
||||
Thread->SuspendSemaphore.Header.SignalState++;
|
||||
KiDispatcherObjectWake(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Release Locks and return the Old State */
|
||||
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return PreviousCount;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeAlertThread(PKTHREAD Thread,
|
||||
KPROCESSOR_MODE AlertMode)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
BOOLEAN PreviousState;
|
||||
|
||||
/* Acquire the Dispatcher Database Lock */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Save the Previous State */
|
||||
PreviousState = Thread->Alerted[AlertMode];
|
||||
|
||||
/* Return if Thread is already alerted. */
|
||||
if (PreviousState == FALSE) {
|
||||
|
||||
/* If it's Blocked, unblock if it we should */
|
||||
if (Thread->State == THREAD_STATE_BLOCKED &&
|
||||
(AlertMode == KernelMode || Thread->WaitMode == AlertMode) &&
|
||||
Thread->Alertable) {
|
||||
|
||||
DPRINT("Aborting Wait\n");
|
||||
KiAbortWaitThread(Thread, STATUS_ALERTED);
|
||||
|
||||
} else {
|
||||
|
||||
/* If not, simply Alert it */
|
||||
Thread->Alerted[AlertMode] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the Dispatcher Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
/* Return the old state */
|
||||
return PreviousState;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
KeCapturePersistentThreadState(
|
||||
IN PVOID CurrentThread,
|
||||
KeCapturePersistentThreadState(IN PVOID CurrentThread,
|
||||
IN ULONG Setting1,
|
||||
IN ULONG Setting2,
|
||||
IN ULONG Setting3,
|
||||
IN ULONG Setting4,
|
||||
IN ULONG Setting5,
|
||||
IN PVOID ThreadState
|
||||
)
|
||||
IN PVOID ThreadState)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Initialize the microkernel state of the thread
|
||||
*/
|
||||
VOID
|
||||
KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
|
||||
STDCALL
|
||||
KeInitializeThread(PKPROCESS Process,
|
||||
PKTHREAD Thread,
|
||||
BOOLEAN First)
|
||||
{
|
||||
ASSERT(SwapEntry == 0);
|
||||
if (Page != 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
||||
PVOID KernelStack;
|
||||
NTSTATUS Status;
|
||||
extern unsigned int init_stack_top;
|
||||
extern unsigned int init_stack;
|
||||
PMEMORY_AREA StackArea;
|
||||
ULONG i;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
|
||||
/* Initialize the Boundary Address */
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
|
||||
/* Initalize the Dispatcher Header */
|
||||
KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
|
||||
ThreadObject,
|
||||
sizeof(KTHREAD),
|
||||
FALSE);
|
||||
InitializeListHead(&Thread->MutantListHead);
|
||||
|
||||
/* If this is isn't the first thread, allocate the Kernel Stack */
|
||||
if (!First) {
|
||||
|
||||
PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
|
||||
KernelStack = NULL;
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_KERNEL_STACK,
|
||||
&KernelStack,
|
||||
MM_STACK_SIZE,
|
||||
0,
|
||||
&StackArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
/* Check for Success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
DPRINT1("Failed to create thread stack\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
/* Mark the Stack */
|
||||
for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++) {
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a Virtual Mapping for it */
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
KernelStack,
|
||||
PAGE_READWRITE,
|
||||
Page,
|
||||
MM_STACK_SIZE / PAGE_SIZE);
|
||||
|
||||
/* Check for success */
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
|
||||
/* Set the Kernel Stack */
|
||||
Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
Thread->StackLimit = (ULONG_PTR)KernelStack;
|
||||
Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
|
||||
} else {
|
||||
|
||||
/* Use the Initial Stack */
|
||||
Thread->InitialStack = (PCHAR)init_stack_top;
|
||||
Thread->StackBase = (PCHAR)init_stack_top;
|
||||
Thread->StackLimit = (ULONG_PTR)init_stack;
|
||||
Thread->KernelStack = (PCHAR)init_stack_top;
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish the pde's for the new stack and the thread structure within the
|
||||
* address space of the new process. They are accessed while taskswitching or
|
||||
* while handling page faults. At this point it isn't possible to call the
|
||||
* page fault handler for the missing pde's.
|
||||
*/
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
||||
|
||||
/* Set the Thread to initalized */
|
||||
Thread->State = THREAD_STATE_INITIALIZED;
|
||||
|
||||
/* The Native API function will initialize the TEB field later */
|
||||
Thread->Teb = NULL;
|
||||
|
||||
/* Initialize stuff to zero */
|
||||
Thread->TlsArray = NULL;
|
||||
Thread->DebugActive = 0;
|
||||
Thread->Alerted[0] = 0;
|
||||
Thread->Alerted[1] = 0;
|
||||
Thread->Iopl = 0;
|
||||
|
||||
/* Set up FPU/NPX Stuff */
|
||||
Thread->NpxState = NPX_STATE_INVALID;
|
||||
Thread->NpxIrql = 0;
|
||||
|
||||
/* Setup APC Fields */
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[0]);
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[1]);
|
||||
Thread->ApcState.Process = Process;
|
||||
Thread->ApcState.KernelApcInProgress = 0;
|
||||
Thread->ApcState.KernelApcPending = 0;
|
||||
Thread->ApcState.UserApcPending = 0;
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||
Thread->ApcQueueable = TRUE;
|
||||
RtlZeroMemory(&Thread->SavedApcState, sizeof(KAPC_STATE));
|
||||
KeInitializeSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
/* Setup Wait Fields */
|
||||
Thread->WaitStatus = STATUS_SUCCESS;
|
||||
Thread->WaitIrql = PASSIVE_LEVEL;
|
||||
Thread->WaitMode = 0;
|
||||
Thread->WaitNext = FALSE;
|
||||
Thread->WaitListEntry.Flink = NULL;
|
||||
Thread->WaitListEntry.Blink = NULL;
|
||||
Thread->WaitTime = 0;
|
||||
Thread->WaitBlockList = NULL;
|
||||
RtlZeroMemory(Thread->WaitBlock, sizeof(KWAIT_BLOCK) * 4);
|
||||
RtlZeroMemory(&Thread->Timer, sizeof(KTIMER));
|
||||
KeInitializeTimer(&Thread->Timer);
|
||||
|
||||
/* Setup scheduler Fields */
|
||||
Thread->BasePriority = Process->BasePriority;
|
||||
Thread->DecrementCount = 0;
|
||||
Thread->PriorityDecrement = 0;
|
||||
Thread->Quantum = Process->ThreadQuantum;
|
||||
Thread->Saturation = 0;
|
||||
Thread->Priority = Process->BasePriority;
|
||||
Thread->UserAffinity = Process->Affinity;
|
||||
Thread->SystemAffinityActive = 0;
|
||||
Thread->Affinity = Process->Affinity;
|
||||
Thread->Preempted = 0;
|
||||
Thread->ProcessReadyQueue = 0;
|
||||
Thread->KernelStackResident = 1;
|
||||
Thread->NextProcessor = 0;
|
||||
Thread->ContextSwitches = 0;
|
||||
|
||||
/* Setup Queue Fields */
|
||||
Thread->Queue = NULL;
|
||||
Thread->QueueListEntry.Flink = NULL;
|
||||
Thread->QueueListEntry.Blink = NULL;
|
||||
|
||||
/* Setup Misc Fields */
|
||||
Thread->LegoData = 0;
|
||||
Thread->PowerState = 0;
|
||||
Thread->ServiceTable = KeServiceDescriptorTable;
|
||||
Thread->CallbackStack = NULL;
|
||||
Thread->Win32Thread = NULL;
|
||||
Thread->TrapFrame = NULL;
|
||||
Thread->EnableStackSwap = 0;
|
||||
Thread->LargeStack = 0;
|
||||
Thread->ResourceIndex = 0;
|
||||
Thread->PreviousMode = KernelMode;
|
||||
Thread->KernelTime = 0;
|
||||
Thread->UserTime = 0;
|
||||
Thread->AutoAlignment = Process->AutoAlignment;
|
||||
|
||||
/* FIXME OPTIMIZATION OF DOOM. DO NOT ENABLE FIXME */
|
||||
#if 0
|
||||
Thread->WaitBlock[3].Object = (PVOID)&Thread->Timer;
|
||||
Thread->WaitBlock[3].Thread = Thread;
|
||||
Thread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
|
||||
Thread->WaitBlock[3].WaitType = WaitAny;
|
||||
Thread->WaitBlock[3].NextWaitBlock = NULL;
|
||||
InsertTailList(&Thread->Timer.Header.WaitListHead,
|
||||
&Thread->WaitBlock[3].WaitListEntry);
|
||||
#endif
|
||||
|
||||
/* Initialize the Suspend APC */
|
||||
KeInitializeApc(&Thread->SuspendApc,
|
||||
Thread,
|
||||
OriginalApcEnvironment,
|
||||
PiSuspendThreadKernelRoutine,
|
||||
PiSuspendThreadRundownRoutine,
|
||||
PiSuspendThreadNormalRoutine,
|
||||
KernelMode,
|
||||
NULL);
|
||||
|
||||
/* Initialize the Suspend Semaphore */
|
||||
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
|
||||
|
||||
/* Insert the Thread into the Process's Thread List */
|
||||
InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
|
||||
|
||||
/* Set up the Suspend Counts */
|
||||
Thread->FreezeCount = 0;
|
||||
Thread->SuspendCount = 0;
|
||||
|
||||
/* Do x86 specific part */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -65,9 +342,7 @@ KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
|||
*/
|
||||
KPRIORITY
|
||||
STDCALL
|
||||
KeQueryPriorityThread (
|
||||
IN PKTHREAD Thread
|
||||
)
|
||||
KeQueryPriorityThread (IN PKTHREAD Thread)
|
||||
{
|
||||
return Thread->Priority;
|
||||
}
|
||||
|
@ -77,10 +352,8 @@ KeQueryPriorityThread (
|
|||
*/
|
||||
ULONG
|
||||
STDCALL
|
||||
KeQueryRuntimeThread(
|
||||
IN PKTHREAD Thread,
|
||||
OUT PULONG UserTime
|
||||
)
|
||||
KeQueryRuntimeThread(IN PKTHREAD Thread,
|
||||
OUT PULONG UserTime)
|
||||
{
|
||||
/* Return the User Time */
|
||||
*UserTime = Thread->UserTime;
|
||||
|
@ -89,6 +362,18 @@ KeQueryRuntimeThread(
|
|||
return Thread->KernelTime;
|
||||
}
|
||||
|
||||
VOID
|
||||
KeFreeStackPage(PVOID Context,
|
||||
MEMORY_AREA* MemoryArea,
|
||||
PVOID Address,
|
||||
PFN_TYPE Page,
|
||||
SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty)
|
||||
{
|
||||
ASSERT(SwapEntry == 0);
|
||||
if (Page) MmReleasePageMemoryConsumer(MC_NPPOOL, Page);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KeReleaseThread(PKTHREAD Thread)
|
||||
/*
|
||||
|
@ -123,14 +408,14 @@ KeReleaseThread(PKTHREAD Thread)
|
|||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeSetKernelStackSwapEnable(
|
||||
IN BOOLEAN Enable
|
||||
)
|
||||
KeSetKernelStackSwapEnable(IN BOOLEAN Enable)
|
||||
{
|
||||
PKTHREAD Thread;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
BOOLEAN PreviousState;
|
||||
KIRQL OldIrql;
|
||||
|
||||
Thread = KeGetCurrentThread();
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Save Old State */
|
||||
PreviousState = Thread->EnableStackSwap;
|
||||
|
@ -138,182 +423,13 @@ KeSetKernelStackSwapEnable(
|
|||
/* Set New State */
|
||||
Thread->EnableStackSwap = Enable;
|
||||
|
||||
/* No, Release Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
/* Return Old State */
|
||||
return PreviousState;
|
||||
}
|
||||
|
||||
VOID
|
||||
KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
|
||||
/*
|
||||
* FUNCTION: Initialize the microkernel state of the thread
|
||||
*/
|
||||
{
|
||||
PVOID KernelStack;
|
||||
NTSTATUS Status;
|
||||
extern unsigned int init_stack_top;
|
||||
extern unsigned int init_stack;
|
||||
PMEMORY_AREA StackArea;
|
||||
ULONG i;
|
||||
PHYSICAL_ADDRESS BoundaryAddressMultiple;
|
||||
|
||||
BoundaryAddressMultiple.QuadPart = 0;
|
||||
|
||||
KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
|
||||
InternalThreadType,
|
||||
sizeof(ETHREAD),
|
||||
FALSE);
|
||||
InitializeListHead(&Thread->MutantListHead);
|
||||
if (!First)
|
||||
{
|
||||
PFN_TYPE Page[MM_STACK_SIZE / PAGE_SIZE];
|
||||
KernelStack = NULL;
|
||||
|
||||
MmLockAddressSpace(MmGetKernelAddressSpace());
|
||||
Status = MmCreateMemoryArea(NULL,
|
||||
MmGetKernelAddressSpace(),
|
||||
MEMORY_AREA_KERNEL_STACK,
|
||||
&KernelStack,
|
||||
MM_STACK_SIZE,
|
||||
0,
|
||||
&StackArea,
|
||||
FALSE,
|
||||
FALSE,
|
||||
BoundaryAddressMultiple);
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Failed to create thread stack\n");
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
for (i = 0; i < (MM_STACK_SIZE / PAGE_SIZE); i++)
|
||||
{
|
||||
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Page[i]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
}
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
KernelStack,
|
||||
PAGE_READWRITE,
|
||||
Page,
|
||||
MM_STACK_SIZE / PAGE_SIZE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
KEBUGCHECK(0);
|
||||
}
|
||||
Thread->InitialStack = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
Thread->StackBase = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
Thread->StackLimit = (ULONG_PTR)KernelStack;
|
||||
Thread->KernelStack = (PCHAR)KernelStack + MM_STACK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->InitialStack = (PCHAR)init_stack_top;
|
||||
Thread->StackBase = (PCHAR)init_stack_top;
|
||||
Thread->StackLimit = (ULONG_PTR)init_stack;
|
||||
Thread->KernelStack = (PCHAR)init_stack_top;
|
||||
}
|
||||
|
||||
/*
|
||||
* Establish the pde's for the new stack and the thread structure within the
|
||||
* address space of the new process. They are accessed while taskswitching or
|
||||
* while handling page faults. At this point it isn't possible to call the
|
||||
* page fault handler for the missing pde's.
|
||||
*/
|
||||
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread->StackLimit, MM_STACK_SIZE);
|
||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
||||
|
||||
/*
|
||||
* The Native API function will initialize the TEB field later
|
||||
*/
|
||||
Thread->Teb = NULL;
|
||||
Thread->TlsArray = NULL;
|
||||
Thread->DebugActive = 0;
|
||||
Thread->State = THREAD_STATE_INITIALIZED;
|
||||
Thread->Alerted[0] = 0;
|
||||
Thread->Alerted[1] = 0;
|
||||
Thread->Iopl = 0;
|
||||
Thread->NpxState = NPX_STATE_INVALID;
|
||||
|
||||
Thread->Saturation = 0;
|
||||
Thread->Priority = Process->BasePriority;
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[0]);
|
||||
InitializeListHead(&Thread->ApcState.ApcListHead[1]);
|
||||
Thread->ApcState.Process = Process;
|
||||
Thread->ApcState.KernelApcInProgress = 0;
|
||||
Thread->ApcState.KernelApcPending = 0;
|
||||
Thread->ApcState.UserApcPending = 0;
|
||||
Thread->ContextSwitches = 0;
|
||||
Thread->WaitStatus = STATUS_SUCCESS;
|
||||
Thread->WaitIrql = PASSIVE_LEVEL;
|
||||
Thread->WaitMode = 0;
|
||||
Thread->WaitNext = FALSE;
|
||||
Thread->WaitBlockList = NULL;
|
||||
Thread->WaitListEntry.Flink = NULL;
|
||||
Thread->WaitListEntry.Blink = NULL;
|
||||
Thread->WaitTime = 0;
|
||||
Thread->BasePriority = Process->BasePriority;
|
||||
Thread->DecrementCount = 0;
|
||||
Thread->PriorityDecrement = 0;
|
||||
Thread->Quantum = Process->ThreadQuantum;
|
||||
RtlZeroMemory(Thread->WaitBlock, sizeof(KWAIT_BLOCK)*4);
|
||||
Thread->LegoData = 0;
|
||||
Thread->UserAffinity = Process->Affinity;
|
||||
Thread->SystemAffinityActive = 0;
|
||||
Thread->PowerState = 0;
|
||||
Thread->NpxIrql = 0;
|
||||
Thread->ServiceTable = KeServiceDescriptorTable;
|
||||
Thread->Queue = NULL;
|
||||
KeInitializeSpinLock(&Thread->ApcQueueLock);
|
||||
RtlZeroMemory(&Thread->Timer, sizeof(KTIMER));
|
||||
KeInitializeTimer(&Thread->Timer);
|
||||
Thread->QueueListEntry.Flink = NULL;
|
||||
Thread->QueueListEntry.Blink = NULL;
|
||||
Thread->Affinity = Process->Affinity;
|
||||
Thread->Preempted = 0;
|
||||
Thread->ProcessReadyQueue = 0;
|
||||
Thread->KernelStackResident = 1;
|
||||
Thread->NextProcessor = 0;
|
||||
Thread->CallbackStack = NULL;
|
||||
Thread->Win32Thread = NULL;
|
||||
Thread->TrapFrame = NULL;
|
||||
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
|
||||
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
|
||||
Thread->EnableStackSwap = 0;
|
||||
Thread->LargeStack = 0;
|
||||
Thread->ResourceIndex = 0;
|
||||
Thread->PreviousMode = KernelMode;
|
||||
Thread->KernelTime = 0;
|
||||
Thread->UserTime = 0;
|
||||
RtlZeroMemory(&Thread->SavedApcState, sizeof(KAPC_STATE));
|
||||
|
||||
Thread->ApcStateIndex = OriginalApcEnvironment;
|
||||
Thread->ApcQueueable = TRUE;
|
||||
Thread->AutoAlignment = Process->AutoAlignment;
|
||||
|
||||
KeInitializeApc(&Thread->SuspendApc,
|
||||
Thread,
|
||||
OriginalApcEnvironment,
|
||||
PiSuspendThreadKernelRoutine,
|
||||
PiSuspendThreadRundownRoutine,
|
||||
PiSuspendThreadNormalRoutine,
|
||||
KernelMode,
|
||||
NULL);
|
||||
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
|
||||
|
||||
InsertTailList(&Process->ThreadListHead,
|
||||
&Thread->ThreadListEntry);
|
||||
Thread->FreezeCount = 0;
|
||||
Thread->SuspendCount = 0;
|
||||
|
||||
/*
|
||||
* Do x86 specific part
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -321,33 +437,33 @@ VOID
|
|||
STDCALL
|
||||
KeRevertToUserAffinityThread(VOID)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
PKTHREAD CurrentThread;
|
||||
KIRQL oldIrql;
|
||||
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
KIRQL OldIrql;
|
||||
|
||||
ASSERT(CurrentThread->SystemAffinityActive != FALSE);
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Return to User Affinity */
|
||||
CurrentThread->Affinity = CurrentThread->UserAffinity;
|
||||
|
||||
/* Disable System Affinity */
|
||||
CurrentThread->SystemAffinityActive = FALSE;
|
||||
|
||||
if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber()))
|
||||
{
|
||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentThread->WaitIrql = oldIrql;
|
||||
/* Check if we need to Dispatch a New thread */
|
||||
if (CurrentThread->Affinity & (1 << KeGetCurrentProcessorNumber())) {
|
||||
|
||||
/* No, just release */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
} else {
|
||||
|
||||
/* We need to dispatch a new thread */
|
||||
CurrentThread->WaitIrql = OldIrql;
|
||||
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
||||
KeLowerIrql(oldIrql);
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -355,11 +471,14 @@ KeRevertToUserAffinityThread(VOID)
|
|||
*/
|
||||
CCHAR
|
||||
STDCALL
|
||||
KeSetIdealProcessorThread (
|
||||
IN PKTHREAD Thread,
|
||||
KeSetIdealProcessorThread(IN PKTHREAD Thread,
|
||||
IN CCHAR Processor)
|
||||
{
|
||||
CCHAR PreviousIdealProcessor;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Save Old Ideal Processor */
|
||||
PreviousIdealProcessor = Thread->IdealProcessor;
|
||||
|
@ -367,6 +486,9 @@ KeSetIdealProcessorThread (
|
|||
/* Set New Ideal Processor */
|
||||
Thread->IdealProcessor = Processor;
|
||||
|
||||
/* Release Lock */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
/* Return Old Ideal Processor */
|
||||
return PreviousIdealProcessor;
|
||||
}
|
||||
|
@ -378,86 +500,237 @@ VOID
|
|||
STDCALL
|
||||
KeSetSystemAffinityThread(IN KAFFINITY Affinity)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
PKTHREAD CurrentThread;
|
||||
KIRQL oldIrql;
|
||||
|
||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
KIRQL OldIrql;
|
||||
|
||||
ASSERT(Affinity & ((1 << KeNumberProcessors) - 1));
|
||||
|
||||
/* Lock the Dispatcher Database */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
|
||||
/* Set the System Affinity Specified */
|
||||
CurrentThread->Affinity = Affinity;
|
||||
|
||||
/* Enable System Affinity */
|
||||
CurrentThread->SystemAffinityActive = TRUE;
|
||||
|
||||
if (Affinity & (1 << KeGetCurrentProcessorNumber()))
|
||||
{
|
||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentThread->WaitIrql = oldIrql;
|
||||
/* Check if we need to Dispatch a New thread */
|
||||
if (Affinity & (1 << KeGetCurrentProcessorNumber())) {
|
||||
|
||||
/* No, just release */
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
|
||||
} else {
|
||||
|
||||
/* We need to dispatch a new thread */
|
||||
CurrentThread->WaitIrql = OldIrql;
|
||||
PsDispatchThreadNoLock(THREAD_STATE_READY);
|
||||
KeLowerIrql(oldIrql);
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
/* The Increment Argument seems to be ignored by NT and always 0 when called */
|
||||
VOID
|
||||
STDCALL
|
||||
KeTerminateThread(IN KPRIORITY Increment)
|
||||
{
|
||||
/* The Increment Argument seems to be ignored by NT and always 0 when called */
|
||||
|
||||
/* Call our own internal routine */
|
||||
PsTerminateCurrentThread(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* FUNCTION: Tests whether there are any pending APCs for the current thread
|
||||
* and if so the APCs will be delivered on exit from kernel mode
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
BOOLEAN OldState;
|
||||
|
||||
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
|
||||
|
||||
/* Lock the Dispatcher Database and the APC Queue */
|
||||
OldIrql = KeAcquireDispatcherDatabaseLock();
|
||||
KiAcquireSpinLock(&Thread->ApcQueueLock);
|
||||
|
||||
/* Save the old State */
|
||||
OldState = Thread->Alerted[AlertMode];
|
||||
|
||||
/* If the Thread is Alerted, Clear it */
|
||||
if (OldState) {
|
||||
|
||||
Thread->Alerted[AlertMode] = FALSE;
|
||||
|
||||
} else if ((AlertMode == UserMode) && (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode]))) {
|
||||
|
||||
/* If the mode is User and the Queue isn't empty, set Pending */
|
||||
Thread->ApcState.UserApcPending = TRUE;
|
||||
}
|
||||
|
||||
/* Release Locks and return the Old State */
|
||||
KiReleaseSpinLock(&Thread->ApcQueueLock);
|
||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||
return OldState;
|
||||
}
|
||||
|
||||
VOID
|
||||
KiServiceCheck (VOID)
|
||||
{
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
/* Check if we need to inialize Win32 for this Thread */
|
||||
if (Thread->ServiceTable != KeServiceDescriptorTableShadow) {
|
||||
|
||||
/* We do. Initialize it and save the new table */
|
||||
PsInitWin32Thread((PETHREAD)Thread);
|
||||
Thread->ServiceTable = KeServiceDescriptorTableShadow;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtAlertResumeThread(IN HANDLE ThreadHandle,
|
||||
OUT PULONG SuspendCount)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
ULONG PreviousState;
|
||||
|
||||
/* Check if parameters are valid */
|
||||
if(PreviousMode != KernelMode) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
ProbeForWrite(SuspendCount,
|
||||
sizeof(HANDLE),
|
||||
sizeof(ULONG));
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
|
||||
/* Reference the Object */
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SUSPEND_RESUME,
|
||||
PsThreadType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
|
||||
/* Check for Success */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/* Call the Kernel Function */
|
||||
PreviousState = KeAlertResumeThread(&Thread->Tcb);
|
||||
|
||||
/* Dereference Object */
|
||||
ObDereferenceObject(Thread);
|
||||
|
||||
if (SuspendCount) {
|
||||
|
||||
_SEH_TRY {
|
||||
|
||||
*SuspendCount = PreviousState;
|
||||
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
|
||||
} _SEH_END;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* EXPORTED
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtAlertThread (IN HANDLE ThreadHandle)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
PETHREAD Thread;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Reference the Object */
|
||||
Status = ObReferenceObjectByHandle(ThreadHandle,
|
||||
THREAD_SUSPEND_RESUME,
|
||||
PsThreadType,
|
||||
PreviousMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
|
||||
/* Check for Success */
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
/*
|
||||
* Do an alert depending on the processor mode. If some kmode code wants to
|
||||
* enforce a umode alert it should call KeAlertThread() directly. If kmode
|
||||
* code wants to do a kmode alert it's sufficient to call it with Zw or just
|
||||
* use KeAlertThread() directly
|
||||
*/
|
||||
KeAlertThread(&Thread->Tcb, PreviousMode);
|
||||
|
||||
/* Dereference Object */
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
NtDelayExecution(IN BOOLEAN Alertable,
|
||||
IN PLARGE_INTEGER DelayInterval)
|
||||
{
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
LARGE_INTEGER SafeInterval;
|
||||
NTSTATUS Status;
|
||||
|
||||
PreviousMode = ExGetPreviousMode();
|
||||
/* Check if parameters are valid */
|
||||
if(PreviousMode != KernelMode) {
|
||||
|
||||
if(PreviousMode != KernelMode)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
_SEH_TRY {
|
||||
|
||||
_SEH_TRY
|
||||
{
|
||||
ProbeForRead(DelayInterval,
|
||||
sizeof(LARGE_INTEGER),
|
||||
sizeof(ULONG));
|
||||
|
||||
/* make a copy on the kernel stack and let DelayInterval point to it so
|
||||
we don't need to wrap KeDelayExecutionThread in SEH! */
|
||||
SafeInterval = *DelayInterval;
|
||||
DelayInterval = &SafeInterval;
|
||||
}
|
||||
_SEH_HANDLE
|
||||
{
|
||||
Status = _SEH_GetExceptionCode();
|
||||
}
|
||||
_SEH_END;
|
||||
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
} _SEH_HANDLE {
|
||||
|
||||
Status = _SEH_GetExceptionCode();
|
||||
} _SEH_END;
|
||||
}
|
||||
|
||||
/* Call the Kernel Function */
|
||||
Status = KeDelayExecutionThread(PreviousMode,
|
||||
Alertable,
|
||||
&SafeInterval);
|
||||
|
||||
/* Return Status */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return KeDelayExecutionThread(PreviousMode,
|
||||
Alertable,
|
||||
DelayInterval);
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
|
|||
case InternalProcessType:
|
||||
break;
|
||||
|
||||
case InternalThreadType:
|
||||
case ThreadObject:
|
||||
break;
|
||||
|
||||
case InternalNotificationEvent:
|
||||
|
@ -386,7 +386,7 @@ BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr, KPRIORITY increment)
|
|||
case InternalProcessType:
|
||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||
|
||||
case InternalThreadType:
|
||||
case ThreadObject:
|
||||
return(KeDispatcherObjectWakeAll(hdr, increment));
|
||||
|
||||
case InternalMutexType:
|
||||
|
|
|
@ -1055,6 +1055,17 @@ NtYieldExecution(VOID)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOT EXPORTED
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
NtTestAlert(VOID)
|
||||
{
|
||||
/* Check and Alert Thread if needed */
|
||||
return KeTestAlertThread(ExGetPreviousMode()) ? STATUS_ALERTED : STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue