mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Remove ps/create.c, it did not fit with the current model of abstraction. Major cleanup of ps/process.c, created ps/notify.c and ps/quota.c. Implemented NtOpenProcess, PsRemoveLoadImageNotifyRoutine, PsGetCurrentProcessSessionId
svn path=/trunk/; revision=14662
This commit is contained in:
parent
781c6b374f
commit
f4d2ac0b1e
12 changed files with 1712 additions and 1726 deletions
|
@ -222,7 +222,6 @@ OBJECTS_OB = \
|
||||||
# Process Manager (Ps)
|
# Process Manager (Ps)
|
||||||
OBJECTS_PS = \
|
OBJECTS_PS = \
|
||||||
ps/cid.o \
|
ps/cid.o \
|
||||||
ps/create.o \
|
|
||||||
ps/debug.o \
|
ps/debug.o \
|
||||||
ps/idle.o \
|
ps/idle.o \
|
||||||
ps/job.o \
|
ps/job.o \
|
||||||
|
@ -230,6 +229,8 @@ OBJECTS_PS = \
|
||||||
ps/locale.o \
|
ps/locale.o \
|
||||||
ps/process.o \
|
ps/process.o \
|
||||||
ps/psmgr.o \
|
ps/psmgr.o \
|
||||||
|
ps/notify.o \
|
||||||
|
ps/quota.o \
|
||||||
ps/query.o \
|
ps/query.o \
|
||||||
ps/security.o \
|
ps/security.o \
|
||||||
ps/suspend.o \
|
ps/suspend.o \
|
||||||
|
|
|
@ -97,6 +97,10 @@ STDCALL
|
||||||
KiUnblockThread(PKTHREAD Thread,
|
KiUnblockThread(PKTHREAD Thread,
|
||||||
PNTSTATUS WaitStatus,
|
PNTSTATUS WaitStatus,
|
||||||
KPRIORITY Increment);
|
KPRIORITY Increment);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
KeSuspendThread(PKTHREAD Thread);
|
||||||
|
|
||||||
/* gmutex.c ********************************************************************/
|
/* gmutex.c ********************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -533,6 +533,12 @@ PspExitThread(NTSTATUS ExitStatus);
|
||||||
extern LIST_ENTRY PspReaperListHead;
|
extern LIST_ENTRY PspReaperListHead;
|
||||||
extern WORK_QUEUE_ITEM PspReaperWorkItem;
|
extern WORK_QUEUE_ITEM PspReaperWorkItem;
|
||||||
extern BOOLEAN PspReaping;
|
extern BOOLEAN PspReaping;
|
||||||
|
extern PEPROCESS PsInitialSystemProcess;
|
||||||
|
extern PEPROCESS PsIdleProcess;
|
||||||
|
extern POBJECT_TYPE PsProcessType;
|
||||||
|
extern LIST_ENTRY PsActiveProcessHead;
|
||||||
|
extern FAST_MUTEX PspActiveProcessMutex;
|
||||||
|
extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
|
@ -544,7 +550,7 @@ VOID PsFreezeOtherThread(PETHREAD Thread);
|
||||||
VOID PsFreezeProcessThreads(PEPROCESS Process);
|
VOID PsFreezeProcessThreads(PEPROCESS Process);
|
||||||
VOID PsUnfreezeProcessThreads(PEPROCESS Process);
|
VOID PsUnfreezeProcessThreads(PEPROCESS Process);
|
||||||
ULONG PsEnumThreadsByProcess(PEPROCESS Process);
|
ULONG PsEnumThreadsByProcess(PEPROCESS Process);
|
||||||
PEPROCESS PsGetNextProcess(PEPROCESS OldProcess);
|
PEPROCESS STDCALL PsGetNextProcess(PEPROCESS OldProcess);
|
||||||
VOID
|
VOID
|
||||||
PsApplicationProcessorInit(VOID);
|
PsApplicationProcessorInit(VOID);
|
||||||
VOID
|
VOID
|
||||||
|
@ -679,6 +685,9 @@ VOID PsUnlockProcess(PEPROCESS Process);
|
||||||
#define EPROCESS_TO_KPROCESS(pEProcess) (&(pEProcess)->Pcb)
|
#define EPROCESS_TO_KPROCESS(pEProcess) (&(pEProcess)->Pcb)
|
||||||
#define KPROCESS_TO_EPROCESS(pKProcess) (CONTAINING_RECORD((pKProcess), EPROCESS, Pcb))
|
#define KPROCESS_TO_EPROCESS(pKProcess) (CONTAINING_RECORD((pKProcess), EPROCESS, Pcb))
|
||||||
|
|
||||||
|
#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8
|
||||||
|
#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8
|
||||||
|
|
||||||
#endif /* ASSEMBLER */
|
#endif /* ASSEMBLER */
|
||||||
|
|
||||||
#endif /* __INCLUDE_INTERNAL_PS_H */
|
#endif /* __INCLUDE_INTERNAL_PS_H */
|
||||||
|
|
|
@ -53,6 +53,16 @@ UpdatePageDirs(PKTHREAD Thread, PKPROCESS Process)
|
||||||
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FUNCTION: Returns a pointer to the current process
|
||||||
|
*/
|
||||||
|
PKPROCESS
|
||||||
|
STDCALL
|
||||||
|
KeGetCurrentProcess(VOID)
|
||||||
|
{
|
||||||
|
return(&(PsGetCurrentProcess()->Pcb));
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
KeInitializeProcess(PKPROCESS Process,
|
KeInitializeProcess(PKPROCESS Process,
|
||||||
|
|
|
@ -1,642 +0,0 @@
|
||||||
/* $Id$
|
|
||||||
*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS kernel
|
|
||||||
* FILE: ntoskrnl/ps/create.c
|
|
||||||
* PURPOSE: Thread managment
|
|
||||||
*
|
|
||||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
|
||||||
* Phillip Susi
|
|
||||||
* Skywing
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE:
|
|
||||||
*
|
|
||||||
* All of the routines that manipulate the thread queue synchronize on
|
|
||||||
* a single spinlock
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
|
||||||
|
|
||||||
#include <ntoskrnl.h>
|
|
||||||
#define NDEBUG
|
|
||||||
#include <internal/debug.h>
|
|
||||||
|
|
||||||
/* GLOBAL *******************************************************************/
|
|
||||||
|
|
||||||
#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8
|
|
||||||
#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
|
|
||||||
|
|
||||||
static ULONG PiThreadNotifyRoutineCount = 0;
|
|
||||||
static PCREATE_THREAD_NOTIFY_ROUTINE
|
|
||||||
PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
STDCALL
|
|
||||||
KeSuspendThread(PKTHREAD Thread);
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
|
||||||
|
|
||||||
VOID
|
|
||||||
PiBeforeBeginThread(CONTEXT c)
|
|
||||||
{
|
|
||||||
KeLowerIrql(PASSIVE_LEVEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
PsInitializeThread (
|
|
||||||
PEPROCESS Process,
|
|
||||||
PETHREAD* ThreadPtr,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
KPROCESSOR_MODE AccessMode,
|
|
||||||
BOOLEAN First )
|
|
||||||
{
|
|
||||||
PETHREAD Thread;
|
|
||||||
NTSTATUS Status;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
if (Process == NULL)
|
|
||||||
{
|
|
||||||
Process = PsInitialSystemProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create and initialize thread
|
|
||||||
*/
|
|
||||||
Status = ObCreateObject(AccessMode,
|
|
||||||
PsThreadType,
|
|
||||||
ObjectAttributes,
|
|
||||||
KernelMode,
|
|
||||||
NULL,
|
|
||||||
sizeof(ETHREAD),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
(PVOID*)&Thread);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reference process
|
|
||||||
*/
|
|
||||||
ObReferenceObjectByPointer(Process,
|
|
||||||
PROCESS_CREATE_THREAD,
|
|
||||||
PsProcessType,
|
|
||||||
KernelMode);
|
|
||||||
|
|
||||||
Thread->ThreadsProcess = Process;
|
|
||||||
Thread->Cid.UniqueThread = NULL;
|
|
||||||
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
|
|
||||||
|
|
||||||
DPRINT("Thread = %x\n",Thread);
|
|
||||||
|
|
||||||
KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
|
|
||||||
InitializeListHead(&Thread->ActiveTimerListHead);
|
|
||||||
KeInitializeSpinLock(&Thread->ActiveTimerListLock);
|
|
||||||
InitializeListHead(&Thread->IrpList);
|
|
||||||
Thread->DeadThread = FALSE;
|
|
||||||
Thread->HasTerminated = FALSE;
|
|
||||||
Thread->Tcb.Win32Thread = NULL;
|
|
||||||
DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
|
|
||||||
|
|
||||||
|
|
||||||
Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority;
|
|
||||||
Thread->Tcb.Priority = Thread->Tcb.BasePriority;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local Procedure Call facility (LPC)
|
|
||||||
*/
|
|
||||||
KeInitializeSemaphore (& Thread->LpcReplySemaphore, 0, LONG_MAX);
|
|
||||||
Thread->LpcReplyMessage = NULL;
|
|
||||||
Thread->LpcReplyMessageId = 0; /* not valid */
|
|
||||||
/* Thread->LpcReceiveMessageId = 0; */
|
|
||||||
Thread->LpcExitThreadCalled = FALSE;
|
|
||||||
Thread->LpcReceivedMsgIdValid = FALSE;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireDispatcherDatabaseLock();
|
|
||||||
InsertTailList(&Process->ThreadListHead,
|
|
||||||
&Thread->ThreadListEntry);
|
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
|
||||||
|
|
||||||
*ThreadPtr = Thread;
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS
|
|
||||||
PsCreateTeb (
|
|
||||||
HANDLE ProcessHandle,
|
|
||||||
PTEB *TebPtr,
|
|
||||||
PETHREAD Thread,
|
|
||||||
PINITIAL_TEB InitialTeb )
|
|
||||||
{
|
|
||||||
PEPROCESS Process;
|
|
||||||
NTSTATUS Status;
|
|
||||||
ULONG ByteCount;
|
|
||||||
ULONG RegionSize;
|
|
||||||
ULONG TebSize;
|
|
||||||
PVOID TebBase;
|
|
||||||
TEB Teb;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
TebSize = PAGE_SIZE;
|
|
||||||
|
|
||||||
if (NULL == Thread->ThreadsProcess)
|
|
||||||
{
|
|
||||||
/* We'll be allocating a 64k block here and only use 4k of it, but this
|
|
||||||
path should almost never be taken. Actually, I never saw it was taken,
|
|
||||||
so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and
|
|
||||||
move on */
|
|
||||||
TebBase = NULL;
|
|
||||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&TebBase,
|
|
||||||
0,
|
|
||||||
&TebSize,
|
|
||||||
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (! NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to allocate virtual memory for TEB\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Process = Thread->ThreadsProcess;
|
|
||||||
PsLockProcess(Process, FALSE);
|
|
||||||
if (NULL == Process->TebBlock ||
|
|
||||||
Process->TebBlock == Process->TebLastAllocated)
|
|
||||||
{
|
|
||||||
Process->TebBlock = NULL;
|
|
||||||
RegionSize = MM_VIRTMEM_GRANULARITY;
|
|
||||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&Process->TebBlock,
|
|
||||||
0,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RESERVE | MEM_TOP_DOWN,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (! NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
PsUnlockProcess(Process);
|
|
||||||
DPRINT1("Failed to reserve virtual memory for TEB\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize);
|
|
||||||
}
|
|
||||||
TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE);
|
|
||||||
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
|
||||||
&TebBase,
|
|
||||||
0,
|
|
||||||
&TebSize,
|
|
||||||
MEM_COMMIT,
|
|
||||||
PAGE_READWRITE);
|
|
||||||
if (! NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("Failed to commit virtual memory for TEB\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
Process->TebLastAllocated = TebBase;
|
|
||||||
PsUnlockProcess(Process);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
|
|
||||||
ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize);
|
|
||||||
|
|
||||||
RtlZeroMemory(&Teb, sizeof(TEB));
|
|
||||||
/* set all pointers to and from the TEB */
|
|
||||||
Teb.Tib.Self = TebBase;
|
|
||||||
if (Thread->ThreadsProcess)
|
|
||||||
{
|
|
||||||
Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
|
|
||||||
}
|
|
||||||
DPRINT("Teb.Peb %x\n", Teb.Peb);
|
|
||||||
|
|
||||||
/* store stack information from InitialTeb */
|
|
||||||
if(InitialTeb != NULL)
|
|
||||||
{
|
|
||||||
/* fixed-size stack */
|
|
||||||
if(InitialTeb->StackBase && InitialTeb->StackLimit)
|
|
||||||
{
|
|
||||||
Teb.Tib.StackBase = InitialTeb->StackBase;
|
|
||||||
Teb.Tib.StackLimit = InitialTeb->StackLimit;
|
|
||||||
Teb.DeallocationStack = InitialTeb->StackLimit;
|
|
||||||
}
|
|
||||||
/* expandable stack */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Teb.Tib.StackBase = InitialTeb->StackCommit;
|
|
||||||
Teb.Tib.StackLimit = InitialTeb->StackCommitMax;
|
|
||||||
Teb.DeallocationStack = InitialTeb->StackReserved;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* more initialization */
|
|
||||||
Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
|
|
||||||
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
|
|
||||||
Teb.CurrentLocale = PsDefaultThreadLocaleId;
|
|
||||||
|
|
||||||
/* Terminate the exception handler list */
|
|
||||||
Teb.Tib.ExceptionList = (PVOID)-1;
|
|
||||||
|
|
||||||
DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
|
|
||||||
|
|
||||||
/* write TEB data into teb page */
|
|
||||||
Status = NtWriteVirtualMemory(ProcessHandle,
|
|
||||||
TebBase,
|
|
||||||
&Teb,
|
|
||||||
sizeof(TEB),
|
|
||||||
&ByteCount);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
/* free TEB */
|
|
||||||
DPRINT1 ("Writing TEB failed!\n");
|
|
||||||
|
|
||||||
RegionSize = 0;
|
|
||||||
NtFreeVirtualMemory(ProcessHandle,
|
|
||||||
TebBase,
|
|
||||||
&RegionSize,
|
|
||||||
MEM_RELEASE);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TebPtr != NULL)
|
|
||||||
{
|
|
||||||
*TebPtr = (PTEB)TebBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("TEB allocated at %p\n", TebBase);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
LdrInitApcRundownRoutine ( PKAPC Apc )
|
|
||||||
{
|
|
||||||
ExFreePool(Apc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
LdrInitApcKernelRoutine (
|
|
||||||
PKAPC Apc,
|
|
||||||
PKNORMAL_ROUTINE* NormalRoutine,
|
|
||||||
PVOID* NormalContext,
|
|
||||||
PVOID* SystemArgument1,
|
|
||||||
PVOID* SystemArgument2)
|
|
||||||
{
|
|
||||||
ExFreePool(Apc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
NtCreateThread (
|
|
||||||
OUT PHANDLE ThreadHandle,
|
|
||||||
IN ACCESS_MASK DesiredAccess,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
||||||
IN HANDLE ProcessHandle,
|
|
||||||
OUT PCLIENT_ID ClientId,
|
|
||||||
IN PCONTEXT ThreadContext,
|
|
||||||
IN PINITIAL_TEB InitialTeb,
|
|
||||||
IN BOOLEAN CreateSuspended )
|
|
||||||
{
|
|
||||||
HANDLE hThread;
|
|
||||||
CONTEXT SafeContext;
|
|
||||||
INITIAL_TEB SafeInitialTeb;
|
|
||||||
PEPROCESS Process;
|
|
||||||
PETHREAD Thread;
|
|
||||||
PTEB TebBase;
|
|
||||||
PKAPC LdrInitApc;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
KPROCESSOR_MODE PreviousMode;
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
if(ThreadContext == NULL)
|
|
||||||
{
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
PreviousMode = ExGetPreviousMode();
|
|
||||||
|
|
||||||
if(PreviousMode != KernelMode)
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
ProbeForWrite(ThreadHandle,
|
|
||||||
sizeof(HANDLE),
|
|
||||||
sizeof(ULONG));
|
|
||||||
if(ClientId != NULL)
|
|
||||||
{
|
|
||||||
ProbeForWrite(ClientId,
|
|
||||||
sizeof(CLIENT_ID),
|
|
||||||
sizeof(ULONG));
|
|
||||||
}
|
|
||||||
ProbeForRead(ThreadContext,
|
|
||||||
sizeof(CONTEXT),
|
|
||||||
sizeof(ULONG));
|
|
||||||
SafeContext = *ThreadContext;
|
|
||||||
ThreadContext = &SafeContext;
|
|
||||||
ProbeForRead(InitialTeb,
|
|
||||||
sizeof(INITIAL_TEB),
|
|
||||||
sizeof(ULONG));
|
|
||||||
SafeInitialTeb = *InitialTeb;
|
|
||||||
InitialTeb = &SafeInitialTeb;
|
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
|
|
||||||
ThreadHandle,ThreadContext);
|
|
||||||
|
|
||||||
Status = ObReferenceObjectByHandle(
|
|
||||||
ProcessHandle,
|
|
||||||
PROCESS_CREATE_THREAD,
|
|
||||||
PsProcessType,
|
|
||||||
PreviousMode,
|
|
||||||
(PVOID*)&Process,
|
|
||||||
NULL);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = PsLockProcess(Process, FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Process->ExitTime.QuadPart != 0)
|
|
||||||
{
|
|
||||||
PsUnlockProcess(Process);
|
|
||||||
return STATUS_PROCESS_IS_TERMINATING;
|
|
||||||
}
|
|
||||||
|
|
||||||
PsUnlockProcess(Process);
|
|
||||||
|
|
||||||
Status = PsInitializeThread(Process,
|
|
||||||
&Thread,
|
|
||||||
ObjectAttributes,
|
|
||||||
PreviousMode,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
ObDereferenceObject(Process);
|
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create a client id handle */
|
|
||||||
Status = PsCreateCidHandle (
|
|
||||||
Thread, PsThreadType, &Thread->Cid.UniqueThread);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = PsCreateTeb(ProcessHandle,
|
|
||||||
&TebBase,
|
|
||||||
Thread,
|
|
||||||
InitialTeb);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
Thread->Tcb.Teb = TebBase;
|
|
||||||
|
|
||||||
Thread->StartAddress = NULL;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Maybe send a message to the process's debugger
|
|
||||||
*/
|
|
||||||
DbgkCreateThread((PVOID)ThreadContext->Eip);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* First, force the thread to be non-alertable for user-mode alerts.
|
|
||||||
*/
|
|
||||||
Thread->Tcb.Alertable = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the thread is to be created suspended then queue an APC to
|
|
||||||
* do the suspend before we run any userspace code.
|
|
||||||
*/
|
|
||||||
if (CreateSuspended)
|
|
||||||
{
|
|
||||||
KeSuspendThread(&Thread->Tcb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Queue an APC to the thread that will execute the ntdll startup
|
|
||||||
* routine.
|
|
||||||
*/
|
|
||||||
LdrInitApc = ExAllocatePoolWithTag (
|
|
||||||
NonPagedPool, sizeof(KAPC), TAG_KAPC );
|
|
||||||
KeInitializeApc (
|
|
||||||
LdrInitApc,
|
|
||||||
&Thread->Tcb,
|
|
||||||
OriginalApcEnvironment,
|
|
||||||
LdrInitApcKernelRoutine,
|
|
||||||
LdrInitApcRundownRoutine,
|
|
||||||
LdrpGetSystemDllEntryPoint(),
|
|
||||||
UserMode,
|
|
||||||
NULL );
|
|
||||||
KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT);
|
|
||||||
/*
|
|
||||||
* The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE.
|
|
||||||
* We must do this manually. Do NOT attempt to set the Thread to Alertable before the call,
|
|
||||||
* doing so is a blatant and erronous hack.
|
|
||||||
*/
|
|
||||||
Thread->Tcb.ApcState.UserApcPending = TRUE;
|
|
||||||
Thread->Tcb.Alerted[KernelMode] = TRUE;
|
|
||||||
|
|
||||||
oldIrql = KeAcquireDispatcherDatabaseLock ();
|
|
||||||
KiUnblockThread(&Thread->Tcb, NULL, 0);
|
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
|
||||||
|
|
||||||
Status = ObInsertObject((PVOID)Thread,
|
|
||||||
NULL,
|
|
||||||
DesiredAccess,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
&hThread);
|
|
||||||
if(NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
_SEH_TRY
|
|
||||||
{
|
|
||||||
if(ClientId != NULL)
|
|
||||||
{
|
|
||||||
*ClientId = Thread->Cid;
|
|
||||||
}
|
|
||||||
*ThreadHandle = hThread;
|
|
||||||
}
|
|
||||||
_SEH_HANDLE
|
|
||||||
{
|
|
||||||
Status = _SEH_GetExceptionCode();
|
|
||||||
}
|
|
||||||
_SEH_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
PsCreateSystemThread (
|
|
||||||
PHANDLE ThreadHandle,
|
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
HANDLE ProcessHandle,
|
|
||||||
PCLIENT_ID ClientId,
|
|
||||||
PKSTART_ROUTINE StartRoutine,
|
|
||||||
PVOID StartContext )
|
|
||||||
/*
|
|
||||||
* FUNCTION: Creates a thread which executes in kernel mode
|
|
||||||
* ARGUMENTS:
|
|
||||||
* ThreadHandle (OUT) = Caller supplied storage for the returned thread
|
|
||||||
* handle
|
|
||||||
* DesiredAccess = Requested access to the thread
|
|
||||||
* ObjectAttributes = Object attributes (optional)
|
|
||||||
* ProcessHandle = Handle of process thread will run in
|
|
||||||
* NULL to use system process
|
|
||||||
* ClientId (OUT) = Caller supplied storage for the returned client id
|
|
||||||
* of the thread (optional)
|
|
||||||
* StartRoutine = Entry point for the thread
|
|
||||||
* StartContext = Argument supplied to the thread when it begins
|
|
||||||
* execution
|
|
||||||
* RETURNS: Success or failure status
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
PETHREAD Thread;
|
|
||||||
NTSTATUS Status;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
PAGED_CODE();
|
|
||||||
|
|
||||||
DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
|
|
||||||
ThreadHandle,ProcessHandle);
|
|
||||||
|
|
||||||
Status = PsInitializeThread(
|
|
||||||
NULL,
|
|
||||||
&Thread,
|
|
||||||
ObjectAttributes,
|
|
||||||
KernelMode,
|
|
||||||
FALSE);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the thread as a system thread */
|
|
||||||
Thread->SystemThread = TRUE;
|
|
||||||
|
|
||||||
Status = PsCreateCidHandle(Thread,
|
|
||||||
PsThreadType,
|
|
||||||
&Thread->Cid.UniqueThread);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread->StartAddress = StartRoutine;
|
|
||||||
Status = KiArchInitThread (
|
|
||||||
&Thread->Tcb, StartRoutine, StartContext);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
ObDereferenceObject(Thread);
|
|
||||||
return(Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ClientId != NULL)
|
|
||||||
{
|
|
||||||
*ClientId=Thread->Cid;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldIrql = KeAcquireDispatcherDatabaseLock ();
|
|
||||||
KiUnblockThread(&Thread->Tcb, NULL, 0);
|
|
||||||
KeReleaseDispatcherDatabaseLock(oldIrql);
|
|
||||||
|
|
||||||
Status = ObInsertObject(
|
|
||||||
(PVOID)Thread,
|
|
||||||
NULL,
|
|
||||||
DesiredAccess,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
ThreadHandle);
|
|
||||||
|
|
||||||
/* don't dereference the thread, the initial reference serves as the keep-alive
|
|
||||||
reference which will be removed by the thread reaper */
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
PspRunCreateThreadNotifyRoutines (
|
|
||||||
PETHREAD CurrentThread,
|
|
||||||
BOOLEAN Create )
|
|
||||||
{
|
|
||||||
ULONG i;
|
|
||||||
CLIENT_ID Cid = CurrentThread->Cid;
|
|
||||||
|
|
||||||
for (i = 0; i < PiThreadNotifyRoutineCount; i++)
|
|
||||||
{
|
|
||||||
PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @implemented
|
|
||||||
*/
|
|
||||||
NTSTATUS STDCALL
|
|
||||||
PsSetCreateThreadNotifyRoutine (
|
|
||||||
IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
|
|
||||||
{
|
|
||||||
if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
|
|
||||||
{
|
|
||||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
||||||
}
|
|
||||||
|
|
||||||
PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
|
|
||||||
PiThreadNotifyRoutineCount++;
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
|
|
@ -79,6 +79,35 @@ PspReapRoutine(PVOID Context)
|
||||||
KeReleaseDispatcherDatabaseLock(OldIrql);
|
KeReleaseDispatcherDatabaseLock(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PspKillMostProcesses(VOID)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY current_entry;
|
||||||
|
PEPROCESS current;
|
||||||
|
|
||||||
|
/* Acquire the Active Process Lock */
|
||||||
|
ExAcquireFastMutex(&PspActiveProcessMutex);
|
||||||
|
|
||||||
|
/* Loop all processes on the list */
|
||||||
|
current_entry = PsActiveProcessHead.Flink;
|
||||||
|
while (current_entry != &PsActiveProcessHead)
|
||||||
|
{
|
||||||
|
current = CONTAINING_RECORD(current_entry, EPROCESS, ProcessListEntry);
|
||||||
|
current_entry = current_entry->Flink;
|
||||||
|
|
||||||
|
if (current->UniqueProcessId != PsInitialSystemProcess->UniqueProcessId &&
|
||||||
|
current->UniqueProcessId != PsGetCurrentProcessId())
|
||||||
|
{
|
||||||
|
/* Terminate all the Threads in this Process */
|
||||||
|
PspTerminateProcessThreads(current, STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the lock */
|
||||||
|
ExReleaseFastMutex(&PspActiveProcessMutex);
|
||||||
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
PspTerminateProcessThreads(PEPROCESS Process,
|
PspTerminateProcessThreads(PEPROCESS Process,
|
||||||
|
|
194
reactos/ntoskrnl/ps/notify.c
Normal file
194
reactos/ntoskrnl/ps/notify.c
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/ps/notify.c
|
||||||
|
* PURPOSE: Notifications
|
||||||
|
*
|
||||||
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES ****************************************************************/
|
||||||
|
|
||||||
|
#include <ntoskrnl.h>
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* GLOBAL *******************************************************************/
|
||||||
|
|
||||||
|
#define MAX_THREAD_NOTIFY_ROUTINE_COUNT 8
|
||||||
|
#define TAG_KAPC TAG('k','p','a','p') /* kpap - kernel ps apc */
|
||||||
|
|
||||||
|
static ULONG PiThreadNotifyRoutineCount = 0;
|
||||||
|
static PCREATE_THREAD_NOTIFY_ROUTINE
|
||||||
|
PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
|
||||||
|
|
||||||
|
static PCREATE_PROCESS_NOTIFY_ROUTINE
|
||||||
|
PspProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT];
|
||||||
|
|
||||||
|
static PLOAD_IMAGE_NOTIFY_ROUTINE
|
||||||
|
PspLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT];
|
||||||
|
|
||||||
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
|
||||||
|
IN BOOLEAN Remove)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Check if it's a removal or addition */
|
||||||
|
if (Remove)
|
||||||
|
{
|
||||||
|
/* Loop the routines */
|
||||||
|
for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
|
||||||
|
{
|
||||||
|
/* Check for a match */
|
||||||
|
if ((PVOID)PspProcessNotifyRoutine[i] == (PVOID)NotifyRoutine)
|
||||||
|
{
|
||||||
|
/* Remove and return */
|
||||||
|
PspProcessNotifyRoutine[i] = NULL;
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Loop the routines */
|
||||||
|
for(i=0;i<MAX_PROCESS_NOTIFY_ROUTINE_COUNT;i++)
|
||||||
|
{
|
||||||
|
/* Find an empty one */
|
||||||
|
if (PspProcessNotifyRoutine[i] == NULL)
|
||||||
|
{
|
||||||
|
/* Add it */
|
||||||
|
PspProcessNotifyRoutine[i] = NotifyRoutine;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing found */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsRemoveLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Loop the routines */
|
||||||
|
for(i=0;i<MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT;i++)
|
||||||
|
{
|
||||||
|
/* Check for a match */
|
||||||
|
if ((PVOID)PspLoadImageNotifyRoutine[i] == (PVOID)NotifyRoutine)
|
||||||
|
{
|
||||||
|
/* Remove and return */
|
||||||
|
PspLoadImageNotifyRoutine[i] = NULL;
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing found */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsSetLoadImageNotifyRoutine(IN PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
/* Loop the routines */
|
||||||
|
for (i = 0; i < MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT; i++)
|
||||||
|
{
|
||||||
|
/* Find an empty one */
|
||||||
|
if (PspLoadImageNotifyRoutine[i] == NULL)
|
||||||
|
{
|
||||||
|
/* Add it */
|
||||||
|
PspLoadImageNotifyRoutine[i] = NotifyRoutine;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing found */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
PspRunCreateThreadNotifyRoutines (
|
||||||
|
PETHREAD CurrentThread,
|
||||||
|
BOOLEAN Create )
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
CLIENT_ID Cid = CurrentThread->Cid;
|
||||||
|
|
||||||
|
for (i = 0; i < PiThreadNotifyRoutineCount; i++)
|
||||||
|
{
|
||||||
|
PiThreadNotifyRoutine[i](Cid.UniqueProcess, Cid.UniqueThread, Create);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PspRunCreateProcessNotifyRoutines(PEPROCESS CurrentProcess,
|
||||||
|
BOOLEAN Create)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
HANDLE ProcessId = (HANDLE)CurrentProcess->UniqueProcessId;
|
||||||
|
HANDLE ParentId = CurrentProcess->InheritedFromUniqueProcessId;
|
||||||
|
|
||||||
|
for(i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
if(PspProcessNotifyRoutine[i])
|
||||||
|
{
|
||||||
|
PspProcessNotifyRoutine[i](ParentId, ProcessId, Create);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PspRunLoadImageNotifyRoutines(PUNICODE_STRING FullImageName,
|
||||||
|
HANDLE ProcessId,
|
||||||
|
PIMAGE_INFO ImageInfo)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_PROCESS_NOTIFY_ROUTINE_COUNT; ++ i)
|
||||||
|
{
|
||||||
|
if (PspLoadImageNotifyRoutine[i])
|
||||||
|
{
|
||||||
|
PspLoadImageNotifyRoutine[i](FullImageName, ProcessId, ImageInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
PsSetCreateThreadNotifyRoutine (
|
||||||
|
IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine )
|
||||||
|
{
|
||||||
|
if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
|
||||||
|
{
|
||||||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
|
||||||
|
PiThreadNotifyRoutineCount++;
|
||||||
|
|
||||||
|
return(STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
File diff suppressed because it is too large
Load diff
|
@ -14,13 +14,28 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
extern LARGE_INTEGER ShortPsLockDelay, PsLockTimeout;
|
||||||
|
|
||||||
|
static GENERIC_MAPPING PiProcessMapping = {
|
||||||
|
STANDARD_RIGHTS_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||||
|
STANDARD_RIGHTS_WRITE | PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD |
|
||||||
|
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_DUP_HANDLE |
|
||||||
|
PROCESS_TERMINATE | PROCESS_SET_QUOTA | PROCESS_SET_INFORMATION | PROCESS_SET_PORT,
|
||||||
|
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
|
||||||
|
PROCESS_ALL_ACCESS};
|
||||||
|
|
||||||
|
VOID
|
||||||
|
INIT_FUNCTION
|
||||||
|
PsInitClientIDManagment(VOID);
|
||||||
|
|
||||||
|
VOID STDCALL PspKillMostProcesses();
|
||||||
/* FUNCTIONS ***************************************************************/
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
VOID PiShutdownProcessManager(VOID)
|
VOID PiShutdownProcessManager(VOID)
|
||||||
{
|
{
|
||||||
DPRINT("PiShutdownProcessManager()\n");
|
DPRINT("PiShutdownProcessManager()\n");
|
||||||
|
|
||||||
PiKillMostProcesses();
|
PspKillMostProcesses();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
|
@ -33,7 +48,177 @@ PiInitProcessManager(VOID)
|
||||||
PsInitialiseW32Call();
|
PsInitialiseW32Call();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
INIT_FUNCTION
|
||||||
|
PsInitProcessManagment(VOID)
|
||||||
|
{
|
||||||
|
PKPROCESS KProcess;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
ShortPsLockDelay.QuadPart = -100LL;
|
||||||
|
PsLockTimeout.QuadPart = -10000000LL; /* one second */
|
||||||
|
/*
|
||||||
|
* Register the process object type
|
||||||
|
*/
|
||||||
|
|
||||||
|
PsProcessType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
|
||||||
|
PsProcessType->Tag = TAG('P', 'R', 'O', 'C');
|
||||||
|
PsProcessType->TotalObjects = 0;
|
||||||
|
PsProcessType->TotalHandles = 0;
|
||||||
|
PsProcessType->PeakObjects = 0;
|
||||||
|
PsProcessType->PeakHandles = 0;
|
||||||
|
PsProcessType->PagedPoolCharge = 0;
|
||||||
|
PsProcessType->NonpagedPoolCharge = sizeof(EPROCESS);
|
||||||
|
PsProcessType->Mapping = &PiProcessMapping;
|
||||||
|
PsProcessType->Dump = NULL;
|
||||||
|
PsProcessType->Open = NULL;
|
||||||
|
PsProcessType->Close = NULL;
|
||||||
|
PsProcessType->Delete = PspDeleteProcess;
|
||||||
|
PsProcessType->Parse = NULL;
|
||||||
|
PsProcessType->Security = NULL;
|
||||||
|
PsProcessType->QueryName = NULL;
|
||||||
|
PsProcessType->OkayToClose = NULL;
|
||||||
|
PsProcessType->Create = NULL;
|
||||||
|
PsProcessType->DuplicationNotify = NULL;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&PsProcessType->TypeName, L"Process");
|
||||||
|
|
||||||
|
ObpCreateTypeObject(PsProcessType);
|
||||||
|
|
||||||
|
InitializeListHead(&PsActiveProcessHead);
|
||||||
|
ExInitializeFastMutex(&PspActiveProcessMutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the idle process
|
||||||
|
*/
|
||||||
|
Status = ObCreateObject(KernelMode,
|
||||||
|
PsProcessType,
|
||||||
|
NULL,
|
||||||
|
KernelMode,
|
||||||
|
NULL,
|
||||||
|
sizeof(EPROCESS),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(PVOID*)&PsIdleProcess);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create the idle process object, Status: 0x%x\n", Status);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(PsIdleProcess, sizeof(EPROCESS));
|
||||||
|
|
||||||
|
PsIdleProcess->Pcb.Affinity = 0xFFFFFFFF;
|
||||||
|
PsIdleProcess->Pcb.IopmOffset = 0xffff;
|
||||||
|
PsIdleProcess->Pcb.LdtDescriptor[0] = 0;
|
||||||
|
PsIdleProcess->Pcb.LdtDescriptor[1] = 0;
|
||||||
|
PsIdleProcess->Pcb.BasePriority = PROCESS_PRIO_IDLE;
|
||||||
|
PsIdleProcess->Pcb.ThreadQuantum = 6;
|
||||||
|
InitializeListHead(&PsIdleProcess->Pcb.ThreadListHead);
|
||||||
|
InitializeListHead(&PsIdleProcess->ThreadListHead);
|
||||||
|
InitializeListHead(&PsIdleProcess->ProcessListEntry);
|
||||||
|
KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.DispatcherHeader,
|
||||||
|
ProcessObject,
|
||||||
|
sizeof(EPROCESS),
|
||||||
|
FALSE);
|
||||||
|
PsIdleProcess->Pcb.DirectoryTableBase =
|
||||||
|
(LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
|
||||||
|
strcpy(PsIdleProcess->ImageFileName, "Idle");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the system process
|
||||||
|
*/
|
||||||
|
Status = ObCreateObject(KernelMode,
|
||||||
|
PsProcessType,
|
||||||
|
NULL,
|
||||||
|
KernelMode,
|
||||||
|
NULL,
|
||||||
|
sizeof(EPROCESS),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(PVOID*)&PsInitialSystemProcess);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create the system process object, Status: 0x%x\n", Status);
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* System threads may run on any processor. */
|
||||||
|
PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF;
|
||||||
|
PsInitialSystemProcess->Pcb.IopmOffset = 0xffff;
|
||||||
|
PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0;
|
||||||
|
PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0;
|
||||||
|
PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL;
|
||||||
|
PsInitialSystemProcess->Pcb.ThreadQuantum = 6;
|
||||||
|
InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
|
||||||
|
KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader,
|
||||||
|
ProcessObject,
|
||||||
|
sizeof(EPROCESS),
|
||||||
|
FALSE);
|
||||||
|
KProcess = &PsInitialSystemProcess->Pcb;
|
||||||
|
|
||||||
|
MmInitializeAddressSpace(PsInitialSystemProcess,
|
||||||
|
&PsInitialSystemProcess->AddressSpace);
|
||||||
|
|
||||||
|
KeInitializeEvent(&PsInitialSystemProcess->LockEvent, SynchronizationEvent, FALSE);
|
||||||
|
PsInitialSystemProcess->LockCount = 0;
|
||||||
|
PsInitialSystemProcess->LockOwner = NULL;
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
KProcess->DirectoryTableBase =
|
||||||
|
(LARGE_INTEGER)(LONGLONG)(ULONG)MmGetPageDirectory();
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
LARGE_INTEGER dummy;
|
||||||
|
dummy.QuadPart = (LONGLONG)(ULONG)MmGetPageDirectory();
|
||||||
|
KProcess->DirectoryTableBase = dummy;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
strcpy(PsInitialSystemProcess->ImageFileName, "System");
|
||||||
|
|
||||||
|
PsInitialSystemProcess->Win32WindowStation = (HANDLE)0;
|
||||||
|
|
||||||
|
InsertHeadList(&PsActiveProcessHead,
|
||||||
|
&PsInitialSystemProcess->ProcessListEntry);
|
||||||
|
InitializeListHead(&PsInitialSystemProcess->ThreadListHead);
|
||||||
|
|
||||||
|
#ifndef SCHED_REWRITE
|
||||||
|
PTOKEN BootToken;
|
||||||
|
|
||||||
|
/* No parent, this is the Initial System Process. Assign Boot Token */
|
||||||
|
BootToken = SepCreateSystemProcessToken();
|
||||||
|
BootToken->TokenInUse = TRUE;
|
||||||
|
PsInitialSystemProcess->Token = BootToken;
|
||||||
|
ObReferenceObject(BootToken);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PspPostInitSystemProcess(VOID)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* this routine is called directly after the exectuive handle tables were
|
||||||
|
initialized. We'll set up the Client ID handle table and assign the system
|
||||||
|
process a PID */
|
||||||
|
PsInitClientIDManagment();
|
||||||
|
|
||||||
|
ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess);
|
||||||
|
ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable;
|
||||||
|
|
||||||
|
Status = PsCreateCidHandle(PsInitialSystemProcess,
|
||||||
|
PsProcessType,
|
||||||
|
&PsInitialSystemProcess->UniqueProcessId);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create CID handle (unique process id) for the system process!\n");
|
||||||
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* NAME EXPORTED
|
* NAME EXPORTED
|
||||||
* PsGetVersion
|
* PsGetVersion
|
||||||
|
|
151
reactos/ntoskrnl/ps/quota.c
Normal file
151
reactos/ntoskrnl/ps/quota.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS kernel
|
||||||
|
* FILE: ntoskrnl/ps/quota.c
|
||||||
|
* PURPOSE: Process Pool Quotas
|
||||||
|
*
|
||||||
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* INCLUDES **************************************************************/
|
||||||
|
|
||||||
|
#include <ntoskrnl.h>
|
||||||
|
#define NDEBUG
|
||||||
|
#include <internal/debug.h>
|
||||||
|
|
||||||
|
/* FUNCTIONS ***************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PsChargePoolQuota(IN PEPROCESS Process,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Charge the usage */
|
||||||
|
Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
|
||||||
|
|
||||||
|
/* Raise Exception */
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ExRaiseStatus(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
/* Call the general function */
|
||||||
|
return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsChargeProcessPagedPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
/* Call the general function */
|
||||||
|
return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
STDCALL
|
||||||
|
PsChargeProcessPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
PEPROCESS_QUOTA_BLOCK QuotaBlock;
|
||||||
|
ULONG NewUsageSize;
|
||||||
|
ULONG NewMaxQuota;
|
||||||
|
|
||||||
|
/* Get current Quota Block */
|
||||||
|
QuotaBlock = Process->QuotaBlock;
|
||||||
|
|
||||||
|
/* Quota Operations are not to be done on the SYSTEM Process */
|
||||||
|
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/* New Size in use */
|
||||||
|
NewUsageSize = QuotaBlock->QuotaEntry[PoolType].Usage + Amount;
|
||||||
|
|
||||||
|
/* Does this size respect the quota? */
|
||||||
|
if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Limit)
|
||||||
|
{
|
||||||
|
/* It doesn't, so keep raising the Quota */
|
||||||
|
while (MiRaisePoolQuota(PoolType,
|
||||||
|
QuotaBlock->QuotaEntry[PoolType].Limit,
|
||||||
|
&NewMaxQuota))
|
||||||
|
{
|
||||||
|
/* Save new Maximum Quota */
|
||||||
|
QuotaBlock->QuotaEntry[PoolType].Limit = NewMaxQuota;
|
||||||
|
|
||||||
|
/* See if the new Maximum Quota fulfills our need */
|
||||||
|
if (NewUsageSize <= NewMaxQuota) goto QuotaChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_QUOTA_EXCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
QuotaChanged:
|
||||||
|
/* Save new Usage */
|
||||||
|
QuotaBlock->QuotaEntry[PoolType].Usage = NewUsageSize;
|
||||||
|
|
||||||
|
/* Is this a new peak? */
|
||||||
|
if (NewUsageSize > QuotaBlock->QuotaEntry[PoolType].Peak)
|
||||||
|
{
|
||||||
|
QuotaBlock->QuotaEntry[PoolType].Peak = NewUsageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All went well */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PsReturnPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
STDCALL
|
||||||
|
PsReturnProcessPagedPoolQuota(IN PEPROCESS Process,
|
||||||
|
IN ULONG_PTR Amount)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
|
@ -18,9 +18,6 @@ ULONG
|
||||||
STDCALL
|
STDCALL
|
||||||
KeResumeThread(PKTHREAD Thread);
|
KeResumeThread(PKTHREAD Thread);
|
||||||
|
|
||||||
ULONG
|
|
||||||
STDCALL
|
|
||||||
KeSuspendThread(PKTHREAD Thread);
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -428,6 +428,573 @@ PsPrepareForApplicationProcessorInit(ULONG Id)
|
||||||
Id, IdleThread->Cid.UniqueThread);
|
Id, IdleThread->Cid.UniqueThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PiBeforeBeginThread(CONTEXT c)
|
||||||
|
{
|
||||||
|
KeLowerIrql(PASSIVE_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
PsInitializeThread (
|
||||||
|
PEPROCESS Process,
|
||||||
|
PETHREAD* ThreadPtr,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
KPROCESSOR_MODE AccessMode,
|
||||||
|
BOOLEAN First )
|
||||||
|
{
|
||||||
|
PETHREAD Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if (Process == NULL)
|
||||||
|
{
|
||||||
|
Process = PsInitialSystemProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create and initialize thread
|
||||||
|
*/
|
||||||
|
Status = ObCreateObject(AccessMode,
|
||||||
|
PsThreadType,
|
||||||
|
ObjectAttributes,
|
||||||
|
KernelMode,
|
||||||
|
NULL,
|
||||||
|
sizeof(ETHREAD),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(PVOID*)&Thread);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reference process
|
||||||
|
*/
|
||||||
|
ObReferenceObjectByPointer(Process,
|
||||||
|
PROCESS_CREATE_THREAD,
|
||||||
|
PsProcessType,
|
||||||
|
KernelMode);
|
||||||
|
|
||||||
|
Thread->ThreadsProcess = Process;
|
||||||
|
Thread->Cid.UniqueThread = NULL;
|
||||||
|
Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
|
||||||
|
|
||||||
|
DPRINT("Thread = %x\n",Thread);
|
||||||
|
|
||||||
|
KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
|
||||||
|
InitializeListHead(&Thread->ActiveTimerListHead);
|
||||||
|
KeInitializeSpinLock(&Thread->ActiveTimerListLock);
|
||||||
|
InitializeListHead(&Thread->IrpList);
|
||||||
|
Thread->DeadThread = FALSE;
|
||||||
|
Thread->HasTerminated = FALSE;
|
||||||
|
Thread->Tcb.Win32Thread = NULL;
|
||||||
|
DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
|
||||||
|
|
||||||
|
|
||||||
|
Thread->Tcb.BasePriority = (CHAR)Process->Pcb.BasePriority;
|
||||||
|
Thread->Tcb.Priority = Thread->Tcb.BasePriority;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local Procedure Call facility (LPC)
|
||||||
|
*/
|
||||||
|
KeInitializeSemaphore (& Thread->LpcReplySemaphore, 0, LONG_MAX);
|
||||||
|
Thread->LpcReplyMessage = NULL;
|
||||||
|
Thread->LpcReplyMessageId = 0; /* not valid */
|
||||||
|
/* Thread->LpcReceiveMessageId = 0; */
|
||||||
|
Thread->LpcExitThreadCalled = FALSE;
|
||||||
|
Thread->LpcReceivedMsgIdValid = FALSE;
|
||||||
|
|
||||||
|
oldIrql = KeAcquireDispatcherDatabaseLock();
|
||||||
|
InsertTailList(&Process->ThreadListHead,
|
||||||
|
&Thread->ThreadListEntry);
|
||||||
|
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||||
|
|
||||||
|
*ThreadPtr = Thread;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
PsCreateTeb (
|
||||||
|
HANDLE ProcessHandle,
|
||||||
|
PTEB *TebPtr,
|
||||||
|
PETHREAD Thread,
|
||||||
|
PINITIAL_TEB InitialTeb )
|
||||||
|
{
|
||||||
|
PEPROCESS Process;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ULONG ByteCount;
|
||||||
|
ULONG RegionSize;
|
||||||
|
ULONG TebSize;
|
||||||
|
PVOID TebBase;
|
||||||
|
TEB Teb;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
TebSize = PAGE_SIZE;
|
||||||
|
|
||||||
|
if (NULL == Thread->ThreadsProcess)
|
||||||
|
{
|
||||||
|
/* We'll be allocating a 64k block here and only use 4k of it, but this
|
||||||
|
path should almost never be taken. Actually, I never saw it was taken,
|
||||||
|
so maybe we should just ASSERT(NULL != Thread->ThreadsProcess) and
|
||||||
|
move on */
|
||||||
|
TebBase = NULL;
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&TebBase,
|
||||||
|
0,
|
||||||
|
&TebSize,
|
||||||
|
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate virtual memory for TEB\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Process = Thread->ThreadsProcess;
|
||||||
|
PsLockProcess(Process, FALSE);
|
||||||
|
if (NULL == Process->TebBlock ||
|
||||||
|
Process->TebBlock == Process->TebLastAllocated)
|
||||||
|
{
|
||||||
|
Process->TebBlock = NULL;
|
||||||
|
RegionSize = MM_VIRTMEM_GRANULARITY;
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&Process->TebBlock,
|
||||||
|
0,
|
||||||
|
&RegionSize,
|
||||||
|
MEM_RESERVE | MEM_TOP_DOWN,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PsUnlockProcess(Process);
|
||||||
|
DPRINT1("Failed to reserve virtual memory for TEB\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
Process->TebLastAllocated = (PVOID) ((char *) Process->TebBlock + RegionSize);
|
||||||
|
}
|
||||||
|
TebBase = (PVOID) ((char *) Process->TebLastAllocated - PAGE_SIZE);
|
||||||
|
Status = ZwAllocateVirtualMemory(ProcessHandle,
|
||||||
|
&TebBase,
|
||||||
|
0,
|
||||||
|
&TebSize,
|
||||||
|
MEM_COMMIT,
|
||||||
|
PAGE_READWRITE);
|
||||||
|
if (! NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to commit virtual memory for TEB\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
Process->TebLastAllocated = TebBase;
|
||||||
|
PsUnlockProcess(Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
|
||||||
|
ASSERT(NULL != TebBase && PAGE_SIZE <= TebSize);
|
||||||
|
|
||||||
|
RtlZeroMemory(&Teb, sizeof(TEB));
|
||||||
|
/* set all pointers to and from the TEB */
|
||||||
|
Teb.Tib.Self = TebBase;
|
||||||
|
if (Thread->ThreadsProcess)
|
||||||
|
{
|
||||||
|
Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
|
||||||
|
}
|
||||||
|
DPRINT("Teb.Peb %x\n", Teb.Peb);
|
||||||
|
|
||||||
|
/* store stack information from InitialTeb */
|
||||||
|
if(InitialTeb != NULL)
|
||||||
|
{
|
||||||
|
/* fixed-size stack */
|
||||||
|
if(InitialTeb->StackBase && InitialTeb->StackLimit)
|
||||||
|
{
|
||||||
|
Teb.Tib.StackBase = InitialTeb->StackBase;
|
||||||
|
Teb.Tib.StackLimit = InitialTeb->StackLimit;
|
||||||
|
Teb.DeallocationStack = InitialTeb->StackLimit;
|
||||||
|
}
|
||||||
|
/* expandable stack */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Teb.Tib.StackBase = InitialTeb->StackCommit;
|
||||||
|
Teb.Tib.StackLimit = InitialTeb->StackCommitMax;
|
||||||
|
Teb.DeallocationStack = InitialTeb->StackReserved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* more initialization */
|
||||||
|
Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
|
||||||
|
Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
|
||||||
|
Teb.CurrentLocale = PsDefaultThreadLocaleId;
|
||||||
|
|
||||||
|
/* Terminate the exception handler list */
|
||||||
|
Teb.Tib.ExceptionList = (PVOID)-1;
|
||||||
|
|
||||||
|
DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
|
||||||
|
|
||||||
|
/* write TEB data into teb page */
|
||||||
|
Status = NtWriteVirtualMemory(ProcessHandle,
|
||||||
|
TebBase,
|
||||||
|
&Teb,
|
||||||
|
sizeof(TEB),
|
||||||
|
&ByteCount);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* free TEB */
|
||||||
|
DPRINT1 ("Writing TEB failed!\n");
|
||||||
|
|
||||||
|
RegionSize = 0;
|
||||||
|
NtFreeVirtualMemory(ProcessHandle,
|
||||||
|
TebBase,
|
||||||
|
&RegionSize,
|
||||||
|
MEM_RELEASE);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TebPtr != NULL)
|
||||||
|
{
|
||||||
|
*TebPtr = (PTEB)TebBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("TEB allocated at %p\n", TebBase);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
LdrInitApcRundownRoutine ( PKAPC Apc )
|
||||||
|
{
|
||||||
|
ExFreePool(Apc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID STDCALL
|
||||||
|
LdrInitApcKernelRoutine (
|
||||||
|
PKAPC Apc,
|
||||||
|
PKNORMAL_ROUTINE* NormalRoutine,
|
||||||
|
PVOID* NormalContext,
|
||||||
|
PVOID* SystemArgument1,
|
||||||
|
PVOID* SystemArgument2)
|
||||||
|
{
|
||||||
|
ExFreePool(Apc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
NtCreateThread (
|
||||||
|
OUT PHANDLE ThreadHandle,
|
||||||
|
IN ACCESS_MASK DesiredAccess,
|
||||||
|
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||||
|
IN HANDLE ProcessHandle,
|
||||||
|
OUT PCLIENT_ID ClientId,
|
||||||
|
IN PCONTEXT ThreadContext,
|
||||||
|
IN PINITIAL_TEB InitialTeb,
|
||||||
|
IN BOOLEAN CreateSuspended )
|
||||||
|
{
|
||||||
|
HANDLE hThread;
|
||||||
|
CONTEXT SafeContext;
|
||||||
|
INITIAL_TEB SafeInitialTeb;
|
||||||
|
PEPROCESS Process;
|
||||||
|
PETHREAD Thread;
|
||||||
|
PTEB TebBase;
|
||||||
|
PKAPC LdrInitApc;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
KPROCESSOR_MODE PreviousMode;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
if(ThreadContext == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviousMode = ExGetPreviousMode();
|
||||||
|
|
||||||
|
if(PreviousMode != KernelMode)
|
||||||
|
{
|
||||||
|
_SEH_TRY
|
||||||
|
{
|
||||||
|
ProbeForWrite(ThreadHandle,
|
||||||
|
sizeof(HANDLE),
|
||||||
|
sizeof(ULONG));
|
||||||
|
if(ClientId != NULL)
|
||||||
|
{
|
||||||
|
ProbeForWrite(ClientId,
|
||||||
|
sizeof(CLIENT_ID),
|
||||||
|
sizeof(ULONG));
|
||||||
|
}
|
||||||
|
ProbeForRead(ThreadContext,
|
||||||
|
sizeof(CONTEXT),
|
||||||
|
sizeof(ULONG));
|
||||||
|
SafeContext = *ThreadContext;
|
||||||
|
ThreadContext = &SafeContext;
|
||||||
|
ProbeForRead(InitialTeb,
|
||||||
|
sizeof(INITIAL_TEB),
|
||||||
|
sizeof(ULONG));
|
||||||
|
SafeInitialTeb = *InitialTeb;
|
||||||
|
InitialTeb = &SafeInitialTeb;
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
|
||||||
|
ThreadHandle,ThreadContext);
|
||||||
|
|
||||||
|
Status = ObReferenceObjectByHandle(
|
||||||
|
ProcessHandle,
|
||||||
|
PROCESS_CREATE_THREAD,
|
||||||
|
PsProcessType,
|
||||||
|
PreviousMode,
|
||||||
|
(PVOID*)&Process,
|
||||||
|
NULL);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PsLockProcess(Process, FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Process->ExitTime.QuadPart != 0)
|
||||||
|
{
|
||||||
|
PsUnlockProcess(Process);
|
||||||
|
return STATUS_PROCESS_IS_TERMINATING;
|
||||||
|
}
|
||||||
|
|
||||||
|
PsUnlockProcess(Process);
|
||||||
|
|
||||||
|
Status = PsInitializeThread(Process,
|
||||||
|
&Thread,
|
||||||
|
ObjectAttributes,
|
||||||
|
PreviousMode,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
ObDereferenceObject(Process);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a client id handle */
|
||||||
|
Status = PsCreateCidHandle (
|
||||||
|
Thread, PsThreadType, &Thread->Cid.UniqueThread);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = KiArchInitThreadWithContext(&Thread->Tcb, ThreadContext);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = PsCreateTeb(ProcessHandle,
|
||||||
|
&TebBase,
|
||||||
|
Thread,
|
||||||
|
InitialTeb);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
PsDeleteCidHandle(Thread->Cid.UniqueThread, PsThreadType);
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
Thread->Tcb.Teb = TebBase;
|
||||||
|
|
||||||
|
Thread->StartAddress = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maybe send a message to the process's debugger
|
||||||
|
*/
|
||||||
|
DbgkCreateThread((PVOID)ThreadContext->Eip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, force the thread to be non-alertable for user-mode alerts.
|
||||||
|
*/
|
||||||
|
Thread->Tcb.Alertable = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the thread is to be created suspended then queue an APC to
|
||||||
|
* do the suspend before we run any userspace code.
|
||||||
|
*/
|
||||||
|
if (CreateSuspended)
|
||||||
|
{
|
||||||
|
KeSuspendThread(&Thread->Tcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue an APC to the thread that will execute the ntdll startup
|
||||||
|
* routine.
|
||||||
|
*/
|
||||||
|
LdrInitApc = ExAllocatePoolWithTag (
|
||||||
|
NonPagedPool, sizeof(KAPC), TAG('K', 'a', 'p', 'c'));
|
||||||
|
KeInitializeApc (
|
||||||
|
LdrInitApc,
|
||||||
|
&Thread->Tcb,
|
||||||
|
OriginalApcEnvironment,
|
||||||
|
LdrInitApcKernelRoutine,
|
||||||
|
LdrInitApcRundownRoutine,
|
||||||
|
LdrpGetSystemDllEntryPoint(),
|
||||||
|
UserMode,
|
||||||
|
NULL );
|
||||||
|
KeInsertQueueApc(LdrInitApc, NULL, NULL, IO_NO_INCREMENT);
|
||||||
|
/*
|
||||||
|
* The thread is non-alertable, so the APC we added did not set UserApcPending to TRUE.
|
||||||
|
* We must do this manually. Do NOT attempt to set the Thread to Alertable before the call,
|
||||||
|
* doing so is a blatant and erronous hack.
|
||||||
|
*/
|
||||||
|
Thread->Tcb.ApcState.UserApcPending = TRUE;
|
||||||
|
Thread->Tcb.Alerted[KernelMode] = TRUE;
|
||||||
|
|
||||||
|
oldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
|
KiUnblockThread(&Thread->Tcb, NULL, 0);
|
||||||
|
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||||
|
|
||||||
|
Status = ObInsertObject((PVOID)Thread,
|
||||||
|
NULL,
|
||||||
|
DesiredAccess,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
&hThread);
|
||||||
|
if(NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
_SEH_TRY
|
||||||
|
{
|
||||||
|
if(ClientId != NULL)
|
||||||
|
{
|
||||||
|
*ClientId = Thread->Cid;
|
||||||
|
}
|
||||||
|
*ThreadHandle = hThread;
|
||||||
|
}
|
||||||
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
|
Status = _SEH_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS STDCALL
|
||||||
|
PsCreateSystemThread (
|
||||||
|
PHANDLE ThreadHandle,
|
||||||
|
ACCESS_MASK DesiredAccess,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||||
|
HANDLE ProcessHandle,
|
||||||
|
PCLIENT_ID ClientId,
|
||||||
|
PKSTART_ROUTINE StartRoutine,
|
||||||
|
PVOID StartContext )
|
||||||
|
/*
|
||||||
|
* FUNCTION: Creates a thread which executes in kernel mode
|
||||||
|
* ARGUMENTS:
|
||||||
|
* ThreadHandle (OUT) = Caller supplied storage for the returned thread
|
||||||
|
* handle
|
||||||
|
* DesiredAccess = Requested access to the thread
|
||||||
|
* ObjectAttributes = Object attributes (optional)
|
||||||
|
* ProcessHandle = Handle of process thread will run in
|
||||||
|
* NULL to use system process
|
||||||
|
* ClientId (OUT) = Caller supplied storage for the returned client id
|
||||||
|
* of the thread (optional)
|
||||||
|
* StartRoutine = Entry point for the thread
|
||||||
|
* StartContext = Argument supplied to the thread when it begins
|
||||||
|
* execution
|
||||||
|
* RETURNS: Success or failure status
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
PETHREAD Thread;
|
||||||
|
NTSTATUS Status;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
|
||||||
|
ThreadHandle,ProcessHandle);
|
||||||
|
|
||||||
|
Status = PsInitializeThread(
|
||||||
|
NULL,
|
||||||
|
&Thread,
|
||||||
|
ObjectAttributes,
|
||||||
|
KernelMode,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the thread as a system thread */
|
||||||
|
Thread->SystemThread = TRUE;
|
||||||
|
|
||||||
|
Status = PsCreateCidHandle(Thread,
|
||||||
|
PsThreadType,
|
||||||
|
&Thread->Cid.UniqueThread);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread->StartAddress = StartRoutine;
|
||||||
|
Status = KiArchInitThread (
|
||||||
|
&Thread->Tcb, StartRoutine, StartContext);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ObDereferenceObject(Thread);
|
||||||
|
return(Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClientId != NULL)
|
||||||
|
{
|
||||||
|
*ClientId=Thread->Cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
oldIrql = KeAcquireDispatcherDatabaseLock ();
|
||||||
|
KiUnblockThread(&Thread->Tcb, NULL, 0);
|
||||||
|
KeReleaseDispatcherDatabaseLock(oldIrql);
|
||||||
|
|
||||||
|
Status = ObInsertObject(
|
||||||
|
(PVOID)Thread,
|
||||||
|
NULL,
|
||||||
|
DesiredAccess,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
ThreadHandle);
|
||||||
|
|
||||||
|
/* don't dereference the thread, the initial reference serves as the keep-alive
|
||||||
|
reference which will be removed by the thread reaper */
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
PsInitThreadManagment(VOID)
|
PsInitThreadManagment(VOID)
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue