From f4d2ac0b1eebe4989bc7b811df79c25777bd553f Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 18 Apr 2005 02:12:30 +0000 Subject: [PATCH] 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 --- reactos/ntoskrnl/Makefile | 3 +- reactos/ntoskrnl/include/internal/ke.h | 4 + reactos/ntoskrnl/include/internal/ps.h | 11 +- reactos/ntoskrnl/ke/process.c | 10 + reactos/ntoskrnl/ps/create.c | 642 ---------- reactos/ntoskrnl/ps/kill.c | 29 + reactos/ntoskrnl/ps/notify.c | 194 +++ reactos/ntoskrnl/ps/process.c | 1637 ++++++++---------------- reactos/ntoskrnl/ps/psmgr.c | 187 ++- reactos/ntoskrnl/ps/quota.c | 151 +++ reactos/ntoskrnl/ps/suspend.c | 3 - reactos/ntoskrnl/ps/thread.c | 567 ++++++++ 12 files changed, 1712 insertions(+), 1726 deletions(-) delete mode 100644 reactos/ntoskrnl/ps/create.c create mode 100644 reactos/ntoskrnl/ps/notify.c create mode 100644 reactos/ntoskrnl/ps/quota.c diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 3bbc69224a2..1cfda91d8c6 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -222,7 +222,6 @@ OBJECTS_OB = \ # Process Manager (Ps) OBJECTS_PS = \ ps/cid.o \ - ps/create.o \ ps/debug.o \ ps/idle.o \ ps/job.o \ @@ -230,6 +229,8 @@ OBJECTS_PS = \ ps/locale.o \ ps/process.o \ ps/psmgr.o \ + ps/notify.o \ + ps/quota.o \ ps/query.o \ ps/security.o \ ps/suspend.o \ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 059af38ff6f..6446c91f679 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -97,6 +97,10 @@ STDCALL KiUnblockThread(PKTHREAD Thread, PNTSTATUS WaitStatus, KPRIORITY Increment); + +NTSTATUS +STDCALL +KeSuspendThread(PKTHREAD Thread); /* gmutex.c ********************************************************************/ diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 65adcd4292a..7c52b79451b 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -533,6 +533,12 @@ PspExitThread(NTSTATUS ExitStatus); extern LIST_ENTRY PspReaperListHead; extern WORK_QUEUE_ITEM PspReaperWorkItem; 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 STDCALL @@ -544,7 +550,7 @@ VOID PsFreezeOtherThread(PETHREAD Thread); VOID PsFreezeProcessThreads(PEPROCESS Process); VOID PsUnfreezeProcessThreads(PEPROCESS Process); ULONG PsEnumThreadsByProcess(PEPROCESS Process); -PEPROCESS PsGetNextProcess(PEPROCESS OldProcess); +PEPROCESS STDCALL PsGetNextProcess(PEPROCESS OldProcess); VOID PsApplicationProcessorInit(VOID); VOID @@ -679,6 +685,9 @@ VOID PsUnlockProcess(PEPROCESS Process); #define EPROCESS_TO_KPROCESS(pEProcess) (&(pEProcess)->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 /* __INCLUDE_INTERNAL_PS_H */ diff --git a/reactos/ntoskrnl/ke/process.c b/reactos/ntoskrnl/ke/process.c index ff6f664cc08..a03f271fda0 100644 --- a/reactos/ntoskrnl/ke/process.c +++ b/reactos/ntoskrnl/ke/process.c @@ -53,6 +53,16 @@ UpdatePageDirs(PKTHREAD Thread, PKPROCESS Process) MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD)); } +/* + * FUNCTION: Returns a pointer to the current process + */ +PKPROCESS +STDCALL +KeGetCurrentProcess(VOID) +{ + return(&(PsGetCurrentProcess()->Pcb)); +} + VOID STDCALL KeInitializeProcess(PKPROCESS Process, diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c deleted file mode 100644 index 68f3b87dca6..00000000000 --- a/reactos/ntoskrnl/ps/create.c +++ /dev/null @@ -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 -#define NDEBUG -#include - -/* 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 */ diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index cda7b57c0ce..37b1c405b21 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -79,6 +79,35 @@ PspReapRoutine(PVOID Context) 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 STDCALL PspTerminateProcessThreads(PEPROCESS Process, diff --git a/reactos/ntoskrnl/ps/notify.c b/reactos/ntoskrnl/ps/notify.c new file mode 100644 index 00000000000..2bccc23ab75 --- /dev/null +++ b/reactos/ntoskrnl/ps/notify.c @@ -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 +#define NDEBUG +#include + +/* 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;iCid; + + 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 */ diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 2a1c42ceee8..e12a8e8fd17 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,11 +1,11 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ps/process.c * PURPOSE: Process managment * - * PROGRAMMERS: David Welch (welch@cwcom.net) + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * David Welch (welch@cwcom.net) */ /* INCLUDES ******************************************************************/ @@ -16,345 +16,154 @@ /* GLOBALS ******************************************************************/ -VOID INIT_FUNCTION PsInitClientIDManagment(VOID); - PEPROCESS EXPORTED PsInitialSystemProcess = NULL; PEPROCESS PsIdleProcess = NULL; - POBJECT_TYPE EXPORTED PsProcessType = NULL; LIST_ENTRY PsActiveProcessHead; FAST_MUTEX PspActiveProcessMutex; -static 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}; - -#define MAX_PROCESS_NOTIFY_ROUTINE_COUNT 8 -#define MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT 8 - -static PCREATE_PROCESS_NOTIFY_ROUTINE -PiProcessNotifyRoutine[MAX_PROCESS_NOTIFY_ROUTINE_COUNT]; -static PLOAD_IMAGE_NOTIFY_ROUTINE -PiLoadImageNotifyRoutine[MAX_LOAD_IMAGE_NOTIFY_ROUTINE_COUNT]; +LARGE_INTEGER ShortPsLockDelay, PsLockTimeout; -/* FUNCTIONS *****************************************************************/ +/* INTERNAL FUNCTIONS *****************************************************************/ -PEPROCESS -PsGetNextProcess(PEPROCESS OldProcess) +NTSTATUS +PsLockProcess(PEPROCESS Process, BOOLEAN Timeout) { - PEPROCESS NextProcess; - NTSTATUS Status; - - if (OldProcess == NULL) - { - Status = ObReferenceObjectByPointer(PsIdleProcess, - PROCESS_ALL_ACCESS, - PsProcessType, - KernelMode); - if (!NT_SUCCESS(Status)) - { - CPRINT("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n"); - KEBUGCHECK(0); - } - return PsIdleProcess; - } - - ExAcquireFastMutex(&PspActiveProcessMutex); - NextProcess = OldProcess; - while (1) - { - PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink : - NextProcess->ProcessListEntry.Flink); - if (Flink != &PsActiveProcessHead) - { - NextProcess = CONTAINING_RECORD(Flink, - EPROCESS, - ProcessListEntry); - } - else - { - NextProcess = NULL; - break; - } + ULONG Attempts = 0; + PKTHREAD PrevLockOwner; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL); + PKTHREAD CallingThread = KeGetCurrentThread(); + + PAGED_CODE(); + + KeEnterCriticalRegion(); + + for(;;) + { + PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer( + &Process->LockOwner, CallingThread, NULL); + if(PrevLockOwner == NULL || PrevLockOwner == CallingThread) + { + /* we got the lock or already locked it */ + if(InterlockedIncrementUL(&Process->LockCount) == 1) + { + KeClearEvent(&Process->LockEvent); + } - Status = ObReferenceObjectByPointer(NextProcess, - PROCESS_ALL_ACCESS, - PsProcessType, - KernelMode); - if (NT_SUCCESS(Status)) - { - break; - } - else if (Status == STATUS_PROCESS_IS_TERMINATING) - { - continue; - } - else if (!NT_SUCCESS(Status)) - { - continue; - } - } - - ExReleaseFastMutex(&PspActiveProcessMutex); - ObDereferenceObject(OldProcess); - - return(NextProcess); -} - -VOID -PiKillMostProcesses(VOID) -{ - PLIST_ENTRY current_entry; - PEPROCESS current; - - ExAcquireFastMutex(&PspActiveProcessMutex); - 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()) - { - PspTerminateProcessThreads(current, STATUS_SUCCESS); - } - } - - ExReleaseFastMutex(&PspActiveProcessMutex); -} - -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); - - RtlZeroMemory(PiProcessNotifyRoutine, sizeof(PiProcessNotifyRoutine)); - RtlZeroMemory(PiLoadImageNotifyRoutine, sizeof(PiLoadImageNotifyRoutine)); - - /* - * 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); + return STATUS_SUCCESS; + } + else + { + if(++Attempts > 2) + { + Status = KeWaitForSingleObject(&Process->LockEvent, + Executive, + KernelMode, + FALSE, + Delay); + if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT) + { +#ifndef NDEBUG + if(Status == STATUS_TIMEOUT) + { + DPRINT1("PsLockProcess(0x%x) timed out!\n", Process); + } #endif + KeLeaveCriticalRegion(); + break; + } + } + else + { + KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay); + } + } + } + + return Status; } VOID -PspPostInitSystemProcess(VOID) +PsUnlockProcess(PEPROCESS Process) { - NTSTATUS Status; + PAGED_CODE(); - /* 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(); + ASSERT(Process->LockOwner == KeGetCurrentThread()); - ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess); - ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable; - - Status = PsCreateCidHandle(PsInitialSystemProcess, - PsProcessType, - &PsInitialSystemProcess->UniqueProcessId); - if(!NT_SUCCESS(Status)) + if(InterlockedDecrementUL(&Process->LockCount) == 0) { - DPRINT1("Failed to create CID handle (unique process id) for the system process!\n"); - KEBUGCHECK(0); + InterlockedExchangePointer(&Process->LockOwner, NULL); + KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE); } + + KeLeaveCriticalRegion(); } -PKPROCESS -KeGetCurrentProcess(VOID) -/* - * FUNCTION: Returns a pointer to the current process - */ -{ - return(&(PsGetCurrentProcess()->Pcb)); -} - -/* - * Warning: Even though it returns HANDLE, it's not a real HANDLE but really a - * ULONG ProcessId! (Skywing) - */ -/* - * @implemented - */ -HANDLE STDCALL -PsGetCurrentProcessId(VOID) -{ - return((HANDLE)PsGetCurrentProcess()->UniqueProcessId); -} - -/* - * @unimplemented - */ -ULONG +PEPROCESS STDCALL -PsGetCurrentProcessSessionId ( - VOID - ) +PsGetNextProcess(PEPROCESS OldProcess) { - return PsGetCurrentProcess()->SessionId; -} + PEPROCESS NextProcess; + NTSTATUS Status; + + /* Check if we have a previous process */ + if (OldProcess == NULL) + { + /* We don't, start with the Idle Process */ + Status = ObReferenceObjectByPointer(PsIdleProcess, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode); + if (!NT_SUCCESS(Status)) + { + DPRINT1("PsGetNextProcess(): ObReferenceObjectByPointer failed for PsIdleProcess\n"); + KEBUGCHECK(0); + } + + return PsIdleProcess; + } + + /* Acquire the Active Process Lock */ + ExAcquireFastMutex(&PspActiveProcessMutex); + + /* Start at the previous process */ + NextProcess = OldProcess; + + /* Loop until we fail */ + while (1) + { + /* Get the Process Link */ + PLIST_ENTRY Flink = (NextProcess == PsIdleProcess ? PsActiveProcessHead.Flink : + NextProcess->ProcessListEntry.Flink); + + /* Move to the next Process if we're not back at the beginning */ + if (Flink != &PsActiveProcessHead) + { + NextProcess = CONTAINING_RECORD(Flink, EPROCESS, ProcessListEntry); + } + else + { + NextProcess = NULL; + break; + } -/* - * FUNCTION: Returns a pointer to the current process - * - * @implemented - */ -PEPROCESS STDCALL -IoGetCurrentProcess(VOID) -{ - if (PsGetCurrentThread() == NULL || - PsGetCurrentThread()->Tcb.ApcState.Process == NULL) - { - return(PsInitialSystemProcess); - } - else - { - return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process); - } + /* Reference the Process */ + Status = ObReferenceObjectByPointer(NextProcess, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode); + + /* Exit the loop if the reference worked, keep going if there's an error */ + if (NT_SUCCESS(Status)) break; + } + + /* Release the lock */ + ExReleaseFastMutex(&PspActiveProcessMutex); + + /* Reference the Process we had referenced earlier */ + ObDereferenceObject(OldProcess); + return(NextProcess); } NTSTATUS @@ -630,38 +439,309 @@ exitdereferenceobjects: return Status; } +/* PUBLIC FUNCTIONS *****************************************************************/ /* * @implemented */ -NTSTATUS STDCALL +NTSTATUS +STDCALL PsCreateSystemProcess(PHANDLE ProcessHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes) + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes) { - return PspCreateProcess(ProcessHandle, - DesiredAccess, - ObjectAttributes, - NULL, /* no parent process */ - FALSE, - NULL, - NULL, - NULL); + return PspCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + NULL, /* no parent process */ + FALSE, + NULL, + NULL, + NULL); } +/* + * @implemented + */ +NTSTATUS +STDCALL +PsLookupProcessByProcessId(IN HANDLE ProcessId, + OUT PEPROCESS *Process) +{ + PHANDLE_TABLE_ENTRY CidEntry; + PEPROCESS FoundProcess; + + PAGED_CODE(); + + ASSERT(Process); + + CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess); + if(CidEntry != NULL) + { + ObReferenceObject(FoundProcess); + + PsUnlockCidHandle(CidEntry); + + *Process = FoundProcess; + return STATUS_SUCCESS; + } + + return STATUS_INVALID_PARAMETER; +} + +/* + * FUNCTION: Returns a pointer to the current process + * + * @implemented + */ +PEPROCESS STDCALL +IoGetCurrentProcess(VOID) +{ + if (PsGetCurrentThread() == NULL || + PsGetCurrentThread()->Tcb.ApcState.Process == NULL) + { + return(PsInitialSystemProcess); + } + else + { + return(PEPROCESS)(PsGetCurrentThread()->Tcb.ApcState.Process); + } +} /* * @implemented */ -NTSTATUS STDCALL -NtCreateProcess(OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, - IN HANDLE ParentProcess, - IN BOOLEAN InheritObjectTable, - IN HANDLE SectionHandle OPTIONAL, - IN HANDLE DebugPort OPTIONAL, - IN HANDLE ExceptionPort OPTIONAL) +LARGE_INTEGER STDCALL +PsGetProcessExitTime(VOID) +{ + LARGE_INTEGER Li; + Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart; + return Li; +} + +/* + * @implemented + */ +LONGLONG +STDCALL +PsGetProcessCreateTimeQuadPart(PEPROCESS Process) +{ + return Process->CreateTime.QuadPart; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetProcessDebugPort(PEPROCESS Process) +{ + return Process->DebugPort; +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsGetProcessExitProcessCalled(PEPROCESS Process) +{ + return Process->ExitProcessCalled; +} + +/* + * @implemented + */ +NTSTATUS +STDCALL +PsGetProcessExitStatus(PEPROCESS Process) +{ + return Process->ExitStatus; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetProcessId(PEPROCESS Process) +{ + return (HANDLE)Process->UniqueProcessId; +} + +/* + * @implemented + */ +LPSTR +STDCALL +PsGetProcessImageFileName(PEPROCESS Process) +{ + return (LPSTR)Process->ImageFileName; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetProcessInheritedFromUniqueProcessId(PEPROCESS Process) +{ + return Process->InheritedFromUniqueProcessId; +} + +/* + * @implemented + */ +PEJOB +STDCALL +PsGetProcessJob(PEPROCESS Process) +{ + return Process->Job; +} + +/* + * @implemented + */ +PPEB +STDCALL +PsGetProcessPeb(PEPROCESS Process) +{ + return Process->Peb; +} + +/* + * @implemented + */ +ULONG +STDCALL +PsGetProcessPriorityClass(PEPROCESS Process) +{ + return Process->PriorityClass; +} + +/* + * @implemented + */ +HANDLE STDCALL +PsGetCurrentProcessId(VOID) +{ + return((HANDLE)PsGetCurrentProcess()->UniqueProcessId); +} + +/* + * @implemented + */ +ULONG +STDCALL +PsGetCurrentProcessSessionId(VOID) +{ + return PsGetCurrentProcess()->SessionId; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetProcessSectionBaseAddress(PEPROCESS Process) +{ + return Process->SectionBaseAddress; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetProcessSecurityPort(PEPROCESS Process) +{ + return Process->SecurityPort; +} + +/* + * @implemented + */ +HANDLE +STDCALL +PsGetProcessSessionId(PEPROCESS Process) +{ + return (HANDLE)Process->SessionId; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetProcessWin32Process(PEPROCESS Process) +{ + return Process->Win32Process; +} + +/* + * @implemented + */ +PVOID +STDCALL +PsGetProcessWin32WindowStation(PEPROCESS Process) +{ + return Process->Win32WindowStation; +} + +/* + * @implemented + */ +BOOLEAN +STDCALL +PsIsProcessBeingDebugged(PEPROCESS Process) +{ + return FALSE; //Process->IsProcessBeingDebugged; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetProcessPriorityClass(PEPROCESS Process, + ULONG PriorityClass) +{ + Process->PriorityClass = PriorityClass; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetProcessSecurityPort(PEPROCESS Process, + PVOID SecurityPort) +{ + Process->SecurityPort = SecurityPort; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetProcessWin32Process(PEPROCESS Process, + PVOID Win32Process) +{ + Process->Win32Process = Win32Process; +} + +/* + * @implemented + */ +VOID +STDCALL +PsSetProcessWin32WindowStation(PEPROCESS Process, + PVOID WindowStation) +{ + Process->Win32WindowStation = WindowStation; +} + /* * FUNCTION: Creates a process. * ARGUMENTS: @@ -682,757 +762,158 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, * REMARKS: * This function maps to the win32 CreateProcess. * RETURNS: Status + * + * @implemented */ +NTSTATUS +STDCALL +NtCreateProcess(OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, + IN HANDLE ParentProcess, + IN BOOLEAN InheritObjectTable, + IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, + IN HANDLE ExceptionPort OPTIONAL) { - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_SUCCESS; - PAGED_CODE(); - - PreviousMode = ExGetPreviousMode(); - - if(PreviousMode != KernelMode) - { - _SEH_TRY - { - ProbeForWrite(ProcessHandle, - sizeof(HANDLE), - sizeof(ULONG)); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if(!NT_SUCCESS(Status)) - { - return Status; - } - } - - if(ParentProcess == NULL) - { - Status = STATUS_INVALID_PARAMETER; - } - else - { - Status = PspCreateProcess(ProcessHandle, - DesiredAccess, - ObjectAttributes, - ParentProcess, - InheritObjectTable, - SectionHandle, - DebugPort, - ExceptionPort); - } - - return Status; -} - - -/* - * @unimplemented - */ -NTSTATUS STDCALL -NtOpenProcess(OUT PHANDLE ProcessHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN PCLIENT_ID ClientId) -{ - DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, " - "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n", - ProcessHandle, DesiredAccess, ObjectAttributes, ClientId, - ClientId->UniqueProcess, ClientId->UniqueThread); - - PAGED_CODE(); - - /* - * Not sure of the exact semantics - */ - if (ObjectAttributes != NULL && ObjectAttributes->ObjectName != NULL && - ObjectAttributes->ObjectName->Buffer != NULL) - { - NTSTATUS Status; - PEPROCESS Process; - - Status = ObReferenceObjectByName(ObjectAttributes->ObjectName, - ObjectAttributes->Attributes, - NULL, - DesiredAccess, - PsProcessType, - UserMode, - NULL, - (PVOID*)&Process); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - Status = ObCreateHandle(PsGetCurrentProcess(), - Process, - DesiredAccess, - FALSE, - ProcessHandle); - ObDereferenceObject(Process); - - return(Status); - } - else - { - PLIST_ENTRY current_entry; - PEPROCESS current; - NTSTATUS Status; - - ExAcquireFastMutex(&PspActiveProcessMutex); - current_entry = PsActiveProcessHead.Flink; - while (current_entry != &PsActiveProcessHead) - { - current = CONTAINING_RECORD(current_entry, EPROCESS, - ProcessListEntry); - if (current->UniqueProcessId == ClientId->UniqueProcess) - { - if (current->Pcb.State == PROCESS_STATE_TERMINATED) - { - Status = STATUS_PROCESS_IS_TERMINATING; - } - else - { - Status = ObReferenceObjectByPointer(current, - DesiredAccess, - PsProcessType, - UserMode); - } - ExReleaseFastMutex(&PspActiveProcessMutex); - if (NT_SUCCESS(Status)) - { - Status = ObCreateHandle(PsGetCurrentProcess(), - current, - DesiredAccess, - FALSE, - ProcessHandle); - ObDereferenceObject(current); - DPRINT("*ProcessHandle %x\n", ProcessHandle); - DPRINT("NtOpenProcess() = %x\n", Status); - } - return(Status); - } - current_entry = current_entry->Flink; - } - ExReleaseFastMutex(&PspActiveProcessMutex); - DPRINT("NtOpenProcess() = STATUS_UNSUCCESSFUL\n"); - return(STATUS_UNSUCCESSFUL); - } -} - -/* - * @implemented - */ -LARGE_INTEGER STDCALL -PsGetProcessExitTime(VOID) -{ - LARGE_INTEGER Li; - Li.QuadPart = PsGetCurrentProcess()->ExitTime.QuadPart; - return Li; -} - -/* - * @implemented - */ -LONGLONG -STDCALL -PsGetProcessCreateTimeQuadPart( - PEPROCESS Process - ) -{ - return Process->CreateTime.QuadPart; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetProcessDebugPort( - PEPROCESS Process - ) -{ - return Process->DebugPort; -} - -/* - * @implemented - */ -BOOLEAN -STDCALL -PsGetProcessExitProcessCalled( - PEPROCESS Process - ) -{ - return Process->ExitProcessCalled; -} - -/* - * @implemented - */ -NTSTATUS -STDCALL -PsGetProcessExitStatus( - PEPROCESS Process - ) -{ - return Process->ExitStatus; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetProcessId( - PEPROCESS Process - ) -{ - return (HANDLE)Process->UniqueProcessId; -} - -/* - * @implemented - */ -LPSTR -STDCALL -PsGetProcessImageFileName( - PEPROCESS Process - ) -{ - return (LPSTR)Process->ImageFileName; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetProcessInheritedFromUniqueProcessId( - PEPROCESS Process - ) -{ - return Process->InheritedFromUniqueProcessId; -} - -/* - * @implemented - */ -PEJOB -STDCALL -PsGetProcessJob( - PEPROCESS Process - ) -{ - return Process->Job; -} - -/* - * @implemented - */ -PPEB -STDCALL -PsGetProcessPeb( - PEPROCESS Process - ) -{ - return Process->Peb; -} - -/* - * @implemented - */ -ULONG -STDCALL -PsGetProcessPriorityClass( - PEPROCESS Process - ) -{ - return Process->PriorityClass; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetProcessSectionBaseAddress( - PEPROCESS Process - ) -{ - return Process->SectionBaseAddress; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetProcessSecurityPort( - PEPROCESS Process - ) -{ - return Process->SecurityPort; -} - -/* - * @implemented - */ -HANDLE -STDCALL -PsGetProcessSessionId( - PEPROCESS Process - ) -{ - return (HANDLE)Process->SessionId; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetProcessWin32Process( - PEPROCESS Process - ) -{ - return Process->Win32Process; -} - -/* - * @implemented - */ -PVOID -STDCALL -PsGetProcessWin32WindowStation( - PEPROCESS Process - ) -{ - return Process->Win32WindowStation; -} - -/* - * @implemented - */ -BOOLEAN -STDCALL -PsIsProcessBeingDebugged( - PEPROCESS Process - ) -{ - return FALSE/*Process->IsProcessBeingDebugged*/; -} - - -/* - * @implemented - */ -NTSTATUS STDCALL -PsLookupProcessByProcessId(IN HANDLE ProcessId, - OUT PEPROCESS *Process) -{ - PHANDLE_TABLE_ENTRY CidEntry; - PEPROCESS FoundProcess; - - PAGED_CODE(); - - ASSERT(Process); - - CidEntry = PsLookupCidHandle(ProcessId, PsProcessType, (PVOID*)&FoundProcess); - if(CidEntry != NULL) - { - ObReferenceObject(FoundProcess); - - PsUnlockCidHandle(CidEntry); - - *Process = FoundProcess; - return STATUS_SUCCESS; - } - - return STATUS_INVALID_PARAMETER; -} - -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(PiProcessNotifyRoutine[i]) - PiProcessNotifyRoutine[i](ParentId, ProcessId, Create); -} - -/* - * @implemented - */ -NTSTATUS STDCALL -PsSetCreateProcessNotifyRoutine(IN PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine, - IN BOOLEAN Remove) -{ - ULONG i; - - if (Remove) - { - for(i=0;iPriorityClass = PriorityClass; -} - -/* - * @implemented - */ -VOID -STDCALL -PsSetProcessSecurityPort( - PEPROCESS Process, - PVOID SecurityPort - ) -{ - Process->SecurityPort = SecurityPort; -} - -/* - * @implemented - */ -VOID -STDCALL -PsSetProcessWin32Process( - PEPROCESS Process, - PVOID Win32Process - ) -{ - Process->Win32Process = Win32Process; -} - -/* - * @implemented - */ -VOID -STDCALL -PsSetProcessWin32WindowStation( - PEPROCESS Process, - PVOID WindowStation - ) -{ - Process->Win32WindowStation = WindowStation; -} - -/* Pool Quotas */ -/* - * @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; -} - -NTSTATUS -PsLockProcess(PEPROCESS Process, BOOLEAN Timeout) -{ - ULONG Attempts = 0; - PKTHREAD PrevLockOwner; - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PLARGE_INTEGER Delay = (Timeout ? &PsLockTimeout : NULL); - PKTHREAD CallingThread = KeGetCurrentThread(); - - PAGED_CODE(); - - KeEnterCriticalRegion(); - - for(;;) - { - PrevLockOwner = (PKTHREAD)InterlockedCompareExchangePointer( - &Process->LockOwner, CallingThread, NULL); - if(PrevLockOwner == NULL || PrevLockOwner == CallingThread) + PAGED_CODE(); + + /* Check parameters */ + if(PreviousMode != KernelMode) { - /* we got the lock or already locked it */ - if(InterlockedIncrementUL(&Process->LockCount) == 1) - { - KeClearEvent(&Process->LockEvent); - } + _SEH_TRY + { + ProbeForWrite(ProcessHandle, + sizeof(HANDLE), + sizeof(ULONG)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; - return STATUS_SUCCESS; + if(!NT_SUCCESS(Status)) return Status; + } + + /* Make sure there's a parent process */ + if(ParentProcess == NULL) + { + /* Can't create System Processes like this */ + Status = STATUS_INVALID_PARAMETER; } else { - if(++Attempts > 2) - { - Status = KeWaitForSingleObject(&Process->LockEvent, - Executive, - KernelMode, - FALSE, - Delay); - if(!NT_SUCCESS(Status) || Status == STATUS_TIMEOUT) - { -#ifndef NDEBUG - if(Status == STATUS_TIMEOUT) - { - DPRINT1("PsLockProcess(0x%x) timed out!\n", Process); - } -#endif - KeLeaveCriticalRegion(); - break; - } - } - else - { - KeDelayExecutionThread(KernelMode, FALSE, &ShortPsLockDelay); - } + /* Create a user Process */ + Status = PspCreateProcess(ProcessHandle, + DesiredAccess, + ObjectAttributes, + ParentProcess, + InheritObjectTable, + SectionHandle, + DebugPort, + ExceptionPort); } - } - - return Status; + + /* Return Status */ + return Status; } -VOID -PsUnlockProcess(PEPROCESS Process) +/* + * @implemented + */ +NTSTATUS +STDCALL +NtOpenProcess(OUT PHANDLE ProcessHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN PCLIENT_ID ClientId) { - PAGED_CODE(); - - ASSERT(Process->LockOwner == KeGetCurrentThread()); - - if(InterlockedDecrementUL(&Process->LockCount) == 0) - { - InterlockedExchangePointer(&Process->LockOwner, NULL); - KeSetEvent(&Process->LockEvent, IO_NO_INCREMENT, FALSE); - } - - KeLeaveCriticalRegion(); + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + NTSTATUS Status = STATUS_INVALID_PARAMETER; + PEPROCESS Process; + PETHREAD Thread = NULL; + + DPRINT("NtOpenProcess(ProcessHandle %x, DesiredAccess %x, " + "ObjectAttributes %x, ClientId %x { UniP %d, UniT %d })\n", + ProcessHandle, DesiredAccess, ObjectAttributes, ClientId, + ClientId->UniqueProcess, ClientId->UniqueThread); + + PAGED_CODE(); + + /* Open by name if one was given */ + DPRINT("Checking type\n"); + if (ObjectAttributes->ObjectName) + { + /* Open it */ + DPRINT("Opening by name\n"); + Status = ObOpenObjectByName(ObjectAttributes, + PsProcessType, + NULL, + PreviousMode, + DesiredAccess, + NULL, + ProcessHandle); + + if (Status != STATUS_SUCCESS) + { + DPRINT1("Could not open object by name\n"); + } + + /* Return Status */ + DPRINT("Found: %x\n", ProcessHandle); + return(Status); + } + else if (ClientId) + { + /* Open by Thread ID */ + if (ClientId->UniqueThread) + { + /* Get the Process */ + DPRINT("Opening by Thread ID\n"); + Status = PsLookupProcessThreadByCid(ClientId, + &Process, + &Thread); + DPRINT("Found: %x\n", Process); + } + else + { + /* Get the Process */ + DPRINT("Opening by Process ID\n"); + Status = PsLookupProcessByProcessId(ClientId->UniqueProcess, + &Process); + DPRINT("Found: %x\n", Process); + } + + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failure to find process\n"); + return Status; + } + + /* Open the Process Object */ + Status = ObOpenObjectByPointer(Process, + ObjectAttributes->Attributes, + NULL, + 0, + PsProcessType, + PreviousMode, + ProcessHandle); + if(!NT_SUCCESS(Status)) + { + DPRINT1("Failure to open process\n"); + } + + /* Dereference the thread if we used it */ + if (Thread) ObDereferenceObject(Thread); + + /* Dereference the Process */ + ObDereferenceObject(Process); + } + + return Status; } - /* EOF */ diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index d8070ab7f56..7adcef1f0b2 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -14,13 +14,28 @@ #define NDEBUG #include +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 ***************************************************************/ VOID PiShutdownProcessManager(VOID) { DPRINT("PiShutdownProcessManager()\n"); - PiKillMostProcesses(); + PspKillMostProcesses(); } VOID INIT_FUNCTION @@ -33,7 +48,177 @@ PiInitProcessManager(VOID) 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 * PsGetVersion diff --git a/reactos/ntoskrnl/ps/quota.c b/reactos/ntoskrnl/ps/quota.c new file mode 100644 index 00000000000..73015e76ff6 --- /dev/null +++ b/reactos/ntoskrnl/ps/quota.c @@ -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 +#define NDEBUG +#include + +/* 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 */ diff --git a/reactos/ntoskrnl/ps/suspend.c b/reactos/ntoskrnl/ps/suspend.c index 579a5c2e410..be6707d6f0c 100644 --- a/reactos/ntoskrnl/ps/suspend.c +++ b/reactos/ntoskrnl/ps/suspend.c @@ -18,9 +18,6 @@ ULONG STDCALL KeResumeThread(PKTHREAD Thread); -ULONG -STDCALL -KeSuspendThread(PKTHREAD Thread); /* FUNCTIONS *****************************************************************/ /* diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index b5583c703d2..b2a69f9be3d 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -428,6 +428,573 @@ PsPrepareForApplicationProcessorInit(ULONG Id) 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 PsInitThreadManagment(VOID) /*