reactos/ntoskrnl/ke/procobj.c

968 lines
28 KiB
C
Raw Normal View History

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/procobj.c
* PURPOSE: Kernel Process Management and System Call Tables
* PROGRAMMERS: Alex Ionescu
* Gregor Anich
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
LIST_ENTRY KiProcessListHead;
LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
LIST_ENTRY KiStackInSwapListHead;
KEVENT KiSwapEvent;
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[SSDT_MAX_ENTRIES];
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES];
PVOID KeUserApcDispatcher;
PVOID KeUserCallbackDispatcher;
PVOID KeUserExceptionDispatcher;
PVOID KeRaiseUserExceptionDispatcher;
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
KiAttachProcess(IN PKTHREAD Thread,
IN PKPROCESS Process,
IN PKLOCK_QUEUE_HANDLE ApcLock,
IN PRKAPC_STATE SavedApcState)
{
#if 0
PLIST_ENTRY ListHead, NextEntry;
PKTHREAD CurrentThread;
#endif
ASSERT(Process != Thread->ApcState.Process);
/* Increase Stack Count */
ASSERT(Process->StackCount != MAXULONG_PTR);
Process->StackCount++;
/* Swap the APC Environment */
KiMoveApcState(&Thread->ApcState, SavedApcState);
/* Reinitialize Apc State */
InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
Thread->ApcState.Process = Process;
Thread->ApcState.KernelApcInProgress = FALSE;
Thread->ApcState.KernelApcPending = FALSE;
Thread->ApcState.UserApcPending = FALSE;
/* Update Environment Pointers if needed*/
if (SavedApcState == &Thread->SavedApcState)
{
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->
SavedApcState;
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
Thread->ApcStateIndex = AttachedApcEnvironment;
}
/* Check if the process is paged in */
if (Process->State == ProcessInMemory)
{
/* Scan the ready list */
#if 0
ListHead = &Process->ReadyListHead;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the thread */
CurrentThread = CONTAINING_RECORD(NextEntry, KTHREAD, WaitListEntry);
/* Remove it */
RemoveEntryList(NextEntry);
CurrentThread->ProcessReadyQueue = FALSE;
/* Mark it ready */
KiReadyThread(CurrentThread);
/* Go to the next one */
NextEntry = ListHead->Flink;
}
#endif
/* Release dispatcher lock */
KiReleaseDispatcherLockFromDpcLevel();
/* Release lock */
KiReleaseApcLockFromDpcLevel(ApcLock);
/* Swap Processes */
KiSwapProcess(Process, SavedApcState->Process);
/* Exit the dispatcher */
KiExitDispatcher(ApcLock->OldIrql);
}
else
{
DPRINT1("Errr. ReactOS doesn't support paging out processes yet...\n");
ASSERT(FALSE);
}
}
VOID
NTAPI
KeInitializeProcess(IN OUT PKPROCESS Process,
IN KPRIORITY Priority,
IN KAFFINITY Affinity,
IN PULONG_PTR DirectoryTableBase,
IN BOOLEAN Enable)
{
#ifdef CONFIG_SMP
ULONG i = 0;
UCHAR IdealNode = 0;
PKNODE Node;
#endif
/* Initialize the Dispatcher Header */
Process->Header.Type = ProcessObject;
Process->Header.Size = sizeof(KPROCESS) / sizeof(ULONG);
Process->Header.SignalState = 0;
InitializeListHead(&(Process->Header.WaitListHead));
/* Initialize Scheduler Data, Alignment Faults and Set the PDE */
Process->Affinity = Affinity;
Process->BasePriority = (CHAR)Priority;
Process->QuantumReset = 6;
Process->DirectoryTableBase[0] = DirectoryTableBase[0];
Process->DirectoryTableBase[1] = DirectoryTableBase[1];
Process->AutoAlignment = Enable;
#if defined(_M_IX86)
Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
#endif
/* Initialize the lists */
InitializeListHead(&Process->ThreadListHead);
InitializeListHead(&Process->ProfileListHead);
InitializeListHead(&Process->ReadyListHead);
/* Initialize the current State */
Process->State = ProcessInMemory;
/* Check how many Nodes there are on the system */
#ifdef CONFIG_SMP
if (KeNumberNodes > 1)
{
/* Set the new seed */
KeProcessNodeSeed = (KeProcessNodeSeed + 1) / KeNumberNodes;
IdealNode = KeProcessNodeSeed;
/* Loop every node */
do
{
/* Check if the affinity matches */
if (KeNodeBlock[IdealNode]->ProcessorMask != Affinity) break;
/* No match, try next Ideal Node and increase node loop index */
IdealNode++;
i++;
/* Check if the Ideal Node is beyond the total number of nodes */
if (IdealNode >= KeNumberNodes)
{
/* Normalize the Ideal Node */
IdealNode -= KeNumberNodes;
}
} while (i < KeNumberNodes);
}
/* Set the ideal node and get the ideal node block */
Process->IdealNode = IdealNode;
Node = KeNodeBlock[IdealNode];
ASSERT(Node->ProcessorMask & Affinity);
/* Find the matching affinity set to calculate the thread seed */
Affinity &= Node->ProcessorMask;
Process->ThreadSeed = KeFindNextRightSetAffinity(Node->Seed,
(ULONG)Affinity);
Node->Seed = Process->ThreadSeed;
#endif
}
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
ULONG
NTAPI
KeSetProcess(IN PKPROCESS Process,
IN KPRIORITY Increment,
IN BOOLEAN InWait)
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
{
KIRQL OldIrql;
ULONG OldState;
ASSERT_PROCESS(Process);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
/* Lock Dispatcher */
OldIrql = KiAcquireDispatcherLock();
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
/* Get Old State */
OldState = Process->Header.SignalState;
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
/* Signal the Process */
Process->Header.SignalState = TRUE;
/* Check if was unsignaled and has waiters */
if (!(OldState) &&
!(IsListEmpty(&Process->Header.WaitListHead)))
{
/* Unwait the threads */
KxUnwaitThread(&Process->Header, Increment);
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
}
/* Release Dispatcher Database */
KiReleaseDispatcherLock(OldIrql);
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
/* Return the previous State */
return OldState;
Thread/Process Termination/Repeaing Rewrite + Fixes --------------------------------------------------- - ps/cid.c: * Moved CID Lookup functions here - ps/security.c: * Moved all security related functions here. Makes other files neater and security functions easier to locate. - ps/thread.c: * Moved most of the Thread Scheduling/Dispatching code that belongs in the Kernel to /ke and renamed functions from Ps to Ki. * Implemented PsIsSystemThread. * Removed Reaper Thread Init (now obsolete). * Renamed PiDeleteThread to PspDeleteThread. * Moved Thread State functions from tinfo.c to here. - ps/process.c: * Removed Query/Set Process functions and moved to ps/query.c * Renamed PiDeletePRocess to PspDeleteProcess * Removed obsoleted Process Termination functions, moved persistent one to kill.c - ps/create.c: * Moved the security APIs to security.c * Correctly implemented PsCreateSystemThread to actually create system threads. - ps/suspend.c * Rewrote Nt Executive functions to use Kernel functions. * Moved Ps* Routines into ke/kthread.c and fixed them. The implementation was wrong in some aspects, especially the issue of the APC looping around the KeWaitXxx call and the fact that the routines excluded/ignored the FreezeCount. - ps/debug.c * Fixed completely broken implementation of Get/SetThreadContext. The old version crashed when called and did not work at all. Suspend Regression test now works. * Moved Context<->TrapFrame functions to ke/i386/ * Combined Set/GetThreadContext APCs into a single one, and used special context structure. - ps/query.c: * Moved Thread/Process Query/Set Routines here. - ps/tinfo.c: * Removed. - ps/kill.c * Removed complicated Process Termination semantics and useless Attach/Detach in favor for a much more lightweight function which performs the same tasks as before and actually works. TaskManager can now terminate foreign processes. * Rewrote Thread Reaping to use the HyperCritical Work Queue instead of manually controlled thread. This results in much less code as well as an increase in speed and less micro management. The reaper is PspReapRoutine. Closing CMD.EXE now works properly without requiring masks that were added as hacks to allow it. * Renamed PiTerminateProcessThreads to PspTerminateProcessThreads. Fixed it to work with new termination code. * Added PspDeleteProcess to handle Process Object deletion. Kills the CID Handle here as done by Hartmut. * Added PspDeletethread here. * Renamed and rewrote PsTerminateCurrentThread to PspExitThread. Used NT Implementation out- lined in Windows Internals, Chapter 13. Uses less locks, a more concise order of actions, actually parses the Termination Ports, handles Dbgk notification. Timers are now rundown, and Mutex rundown is in a dedicated Kernel function. Final termination handled by KeTerminate Thread as documented. * Renamed PsTerminateOtherThread to PspTerminateThreadByPointer and modified implementation to be compatible with the changes above. * Renamed and regrouped Process Termination into PspExitProcess. Also implemented as described above, and moved each subsystem specific termination helper into its own subsytem. * Improved NtTerminateProcess and added more debugging messages. * Improved NtTerminateThread and added check against System Thread and made it compatible with new implementation. * Corrected PsTerminateSystemThread now that we support System Threads. * Corrected NtRegisterThreadTerminatePort to use same structure name as on windows for the port, and added tag to pool allocation (documented in pooltag.txt) include/internal/*.h: * Defined Scheduler Functions and misc new functions or renamed functions. ke/apc.c: * Fixed critical bug where APCs were not delivered at all if the thread wastion and cancels any timers that are associated to a thread, as well as their APCs and DPCs. REGRESSIONS FOUND: NONE BUGS/REGRESSIOSN FIXED: * Thread/Get Set Context now works. * Suspend Regression test now works. * Task manager can now kill foreign processes, even hung ones (like it should). * ExitProcess/closing cmd.exe with the 'x' button now works correctly without hacks. KNOWN ISSUES: I left a bit of a mess in the headers and some stuff still needs to be moved into the right places. I just wanted to have this first part ready first, so that it won't get too big. svn path=/trunk/; revision=14174
2005-03-18 05:53:04 +00:00
}
VOID
NTAPI
KeSetQuantumProcess(IN PKPROCESS Process,
IN UCHAR Quantum)
{
KLOCK_QUEUE_HANDLE ProcessLock;
PLIST_ENTRY NextEntry, ListHead;
PKTHREAD Thread;
ASSERT_PROCESS(Process);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Set new quantum */
Process->QuantumReset = Quantum;
/* Loop all child threads */
ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Set quantum */
Thread->QuantumReset = Quantum;
/* Go to the next one */
NextEntry = NextEntry->Flink;
}
/* Release lock */
KiReleaseProcessLock(&ProcessLock);
}
KAFFINITY
NTAPI
KeSetAffinityProcess(IN PKPROCESS Process,
IN KAFFINITY Affinity)
{
KLOCK_QUEUE_HANDLE ProcessLock;
PLIST_ENTRY NextEntry, ListHead;
KAFFINITY OldAffinity;
PKTHREAD Thread;
ASSERT_PROCESS(Process);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
ASSERT((Affinity & KeActiveProcessors) != 0);
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Acquire the dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Capture old affinity and update it */
OldAffinity = Process->Affinity;
Process->Affinity = Affinity;
/* Loop all child threads */
ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Set affinity on it */
KiSetAffinityThread(Thread, Affinity);
NextEntry = NextEntry->Flink;
}
/* Release Dispatcher Database */
KiReleaseDispatcherLockFromDpcLevel();
/* Release the process lock */
KiReleaseProcessLockFromDpcLevel(&ProcessLock);
KiExitDispatcher(ProcessLock.OldIrql);
/* Return previous affinity */
return OldAffinity;
}
BOOLEAN
NTAPI
KeSetAutoAlignmentProcess(IN PKPROCESS Process,
IN BOOLEAN Enable)
{
/* Set or reset the bit depending on what the enable flag says */
if (Enable)
{
return InterlockedBitTestAndSet(&Process->ProcessFlags,
KPSF_AUTO_ALIGNMENT_BIT);
}
else
{
return InterlockedBitTestAndReset(&Process->ProcessFlags,
KPSF_AUTO_ALIGNMENT_BIT);
}
}
BOOLEAN
NTAPI
KeSetDisableBoostProcess(IN PKPROCESS Process,
IN BOOLEAN Disable)
{
/* Set or reset the bit depending on what the disable flag says */
if (Disable)
{
return InterlockedBitTestAndSet(&Process->ProcessFlags,
KPSF_DISABLE_BOOST_BIT);
}
else
{
return InterlockedBitTestAndReset(&Process->ProcessFlags,
KPSF_DISABLE_BOOST_BIT);
}
}
KPRIORITY
NTAPI
KeSetPriorityAndQuantumProcess(IN PKPROCESS Process,
IN KPRIORITY Priority,
IN UCHAR Quantum OPTIONAL)
{
KLOCK_QUEUE_HANDLE ProcessLock;
KPRIORITY Delta;
PLIST_ENTRY NextEntry, ListHead;
KPRIORITY NewPriority, OldPriority;
PKTHREAD Thread;
ASSERT_PROCESS(Process);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if the process already has this priority */
if (Process->BasePriority == Priority) return Process->BasePriority;
/* If the caller gave priority 0, normalize to 1 */
if (!Priority) Priority = LOW_PRIORITY + 1;
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Check if we are modifying the quantum too */
if (Quantum) Process->QuantumReset = Quantum;
/* Save the current base priority and update it */
OldPriority = Process->BasePriority;
Process->BasePriority = (SCHAR)Priority;
/* Calculate the priority delta */
Delta = Priority - OldPriority;
/* Set the list head and list entry */
ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink;
/* Check if this is a real-time priority */
if (Priority >= LOW_REALTIME_PRIORITY)
{
/* Loop the thread list */
while (NextEntry != ListHead)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Update the quantum if we had one */
if (Quantum) Thread->QuantumReset = Quantum;
/* Acquire the thread lock */
KiAcquireThreadLock(Thread);
/* Calculate the new priority */
NewPriority = Thread->BasePriority + Delta;
if (NewPriority < LOW_REALTIME_PRIORITY)
{
/* We're in real-time range, don't let it go below */
NewPriority = LOW_REALTIME_PRIORITY;
}
else if (NewPriority > HIGH_PRIORITY)
{
/* We're going beyond the maximum priority, normalize */
NewPriority = HIGH_PRIORITY;
}
/*
* If priority saturation occured or the old priority was still in
* the real-time range, don't do anything.
*/
if (!(Thread->Saturation) || (OldPriority < LOW_REALTIME_PRIORITY))
{
/* Check if we had priority saturation */
if (Thread->Saturation > 0)
{
/* Boost priority to maximum */
NewPriority = HIGH_PRIORITY;
}
else if (Thread->Saturation < 0)
{
/* If we had negative saturation, set minimum priority */
NewPriority = LOW_REALTIME_PRIORITY;
}
/* Update priority and quantum */
Thread->BasePriority = (SCHAR)NewPriority;
Thread->Quantum = Thread->QuantumReset;
/* Disable decrements and update priority */
Thread->PriorityDecrement = 0;
KiSetPriorityThread(Thread, NewPriority);
}
/* Release the thread lock */
KiReleaseThreadLock(Thread);
/* Go to the next thread */
NextEntry = NextEntry->Flink;
}
}
else
{
/* Loop the thread list */
while (NextEntry != ListHead)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Update the quantum if we had one */
if (Quantum) Thread->QuantumReset = Quantum;
/* Lock the thread */
KiAcquireThreadLock(Thread);
/* Calculate the new priority */
NewPriority = Thread->BasePriority + Delta;
if (NewPriority >= LOW_REALTIME_PRIORITY)
{
/* We're not real-time range, don't let it enter RT range */
NewPriority = LOW_REALTIME_PRIORITY - 1;
}
else if (NewPriority <= LOW_PRIORITY)
{
/* We're going below the minimum priority, normalize */
NewPriority = 1;
}
/*
* If priority saturation occured or the old priority was still in
* the real-time range, don't do anything.
*/
if (!(Thread->Saturation) ||
(OldPriority >= LOW_REALTIME_PRIORITY))
{
/* Check if we had priority saturation */
if (Thread->Saturation > 0)
{
/* Boost priority to maximum */
NewPriority = LOW_REALTIME_PRIORITY - 1;
}
else if (Thread->Saturation < 0)
{
/* If we had negative saturation, set minimum priority */
NewPriority = 1;
}
/* Update priority and quantum */
Thread->BasePriority = (SCHAR)NewPriority;
Thread->Quantum = Thread->QuantumReset;
/* Disable decrements and update priority */
Thread->PriorityDecrement = 0;
KiSetPriorityThread(Thread, NewPriority);
}
/* Release the thread lock */
KiReleaseThreadLock(Thread);
/* Go to the next thread */
NextEntry = NextEntry->Flink;
}
}
/* Release Dispatcher Database */
KiReleaseDispatcherLockFromDpcLevel();
/* Release the process lock */
KiReleaseProcessLockFromDpcLevel(&ProcessLock);
KiExitDispatcher(ProcessLock.OldIrql);
/* Return previous priority */
return OldPriority;
}
VOID
NTAPI
KeQueryValuesProcess(IN PKPROCESS Process,
PPROCESS_VALUES Values)
{
PEPROCESS EProcess;
PLIST_ENTRY NextEntry;
ULONG TotalKernel, TotalUser;
KLOCK_QUEUE_HANDLE ProcessLock;
ASSERT_PROCESS(Process);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Initialize user and kernel times */
TotalKernel = Process->KernelTime;
TotalUser = Process->UserTime;
/* Copy the IO_COUNTERS from the process */
EProcess = (PEPROCESS)Process;
Values->IoInfo.ReadOperationCount = EProcess->ReadOperationCount.QuadPart;
Values->IoInfo.WriteOperationCount = EProcess->WriteOperationCount.QuadPart;
Values->IoInfo.OtherOperationCount = EProcess->OtherOperationCount.QuadPart;
Values->IoInfo.ReadTransferCount = EProcess->ReadTransferCount.QuadPart;
Values->IoInfo.WriteTransferCount = EProcess->WriteTransferCount.QuadPart;
Values->IoInfo.OtherTransferCount = EProcess->OtherTransferCount.QuadPart;
/* Loop all child threads and sum up their times */
for (NextEntry = Process->ThreadListHead.Flink;
NextEntry != &Process->ThreadListHead;
NextEntry = NextEntry->Flink)
{
PKTHREAD Thread;
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Sum up times */
TotalKernel += Thread->KernelTime;
TotalUser += Thread->UserTime;
}
/* Release the process lock */
KiReleaseProcessLock(&ProcessLock);
/* Compute total times */
Values->TotalKernelTime.QuadPart = TotalKernel * (LONGLONG)KeMaximumIncrement;
Values->TotalUserTime.QuadPart = TotalUser * (LONGLONG)KeMaximumIncrement;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
VOID
NTAPI
KeAttachProcess(IN PKPROCESS Process)
{
KLOCK_QUEUE_HANDLE ApcLock;
PKTHREAD Thread = KeGetCurrentThread();
ASSERT_PROCESS(Process);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if we're already in that process */
if (Thread->ApcState.Process == Process) return;
/* Check if a DPC is executing or if we're already attached */
if ((Thread->ApcStateIndex != OriginalApcEnvironment) ||
(KeIsExecutingDpc()))
{
/* Invalid attempt */
KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
(ULONG_PTR)Process,
(ULONG_PTR)Thread->ApcState.Process,
Thread->ApcStateIndex,
KeIsExecutingDpc());
}
else
{
/* Acquire APC Lock */
KiAcquireApcLock(Thread, &ApcLock);
/* Acquire the dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Legit attach attempt: do it! */
KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
}
}
/*
* @implemented
*/
VOID
NTAPI
KeDetachProcess(VOID)
{
PKTHREAD Thread = KeGetCurrentThread();
KLOCK_QUEUE_HANDLE ApcLock;
PKPROCESS Process;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if it's attached */
if (Thread->ApcStateIndex == OriginalApcEnvironment) return;
/* Acquire APC Lock */
KiAcquireApcLock(Thread, &ApcLock);
/* Check for invalid attach attempts */
if ((Thread->ApcState.KernelApcInProgress) ||
!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
!(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
{
/* Crash the system */
KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
}
/* Get the process */
Process = Thread->ApcState.Process;
/* Acquire dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Decrease the stack count */
ASSERT(Process->StackCount != 0);
ASSERT(Process->State == ProcessInMemory);
Process->StackCount--;
/* Check if we can swap the process out */
if (!Process->StackCount)
{
/* FIXME: Swap the process out */
}
/* Release dispatcher lock */
KiReleaseDispatcherLockFromDpcLevel();
/* Restore the APC State */
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
Thread->SavedApcState.Process = NULL;
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
Thread->ApcStateIndex = OriginalApcEnvironment;
/* Release lock */
KiReleaseApcLockFromDpcLevel(&ApcLock);
/* Swap Processes */
KiSwapProcess(Thread->ApcState.Process, Process);
/* Exit the dispatcher */
KiExitDispatcher(ApcLock.OldIrql);
/* Check if we have pending APCs */
if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
{
/* What do you know, we do! Request them to be delivered */
Thread->ApcState.KernelApcPending = TRUE;
HalRequestSoftwareInterrupt(APC_LEVEL);
}
}
/*
* @implemented
*/
BOOLEAN
NTAPI
KeIsAttachedProcess(VOID)
{
/* Return the APC State */
return KeGetCurrentThread()->ApcStateIndex;
}
/*
* @implemented
*/
VOID
NTAPI
KeStackAttachProcess(IN PKPROCESS Process,
OUT PRKAPC_STATE ApcState)
{
KLOCK_QUEUE_HANDLE ApcLock;
PKTHREAD Thread = KeGetCurrentThread();
ASSERT_PROCESS(Process);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Crash system if DPC is being executed! */
if (KeIsExecutingDpc())
{
/* Executing a DPC, crash! */
KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
(ULONG_PTR)Process,
(ULONG_PTR)Thread->ApcState.Process,
Thread->ApcStateIndex,
KeIsExecutingDpc());
}
/* Check if we are already in the target process */
if (Thread->ApcState.Process == Process)
{
/* Set magic value so we don't crash later when detaching */
ApcState->Process = (PKPROCESS)1;
return;
}
/* Acquire APC Lock */
KiAcquireApcLock(Thread, &ApcLock);
/* Acquire dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Check if the Current Thread is already attached */
if (Thread->ApcStateIndex != OriginalApcEnvironment)
{
/* We're already attached, so save the APC State into what we got */
KiAttachProcess(Thread, Process, &ApcLock, ApcState);
}
else
{
/* We're not attached, so save the APC State into SavedApcState */
KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
ApcState->Process = NULL;
}
}
/*
* @implemented
*/
VOID
NTAPI
KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
{
KLOCK_QUEUE_HANDLE ApcLock;
PKTHREAD Thread = KeGetCurrentThread();
PKPROCESS Process;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check for magic value meaning we were already in the same process */
if (ApcState->Process == (PKPROCESS)1) return;
/* Loop to make sure no APCs are pending */
for (;;)
{
/* Acquire APC Lock */
KiAcquireApcLock(Thread, &ApcLock);
/* Check if a kernel APC is pending */
if (Thread->ApcState.KernelApcPending)
{
/* Check if kernel APC should be delivered */
if (!(Thread->KernelApcDisable) && (ApcLock.OldIrql <= APC_LEVEL))
{
/* Release the APC lock so that the APC can be delivered */
KiReleaseApcLock(&ApcLock);
continue;
}
}
/* Otherwise, break out */
break;
}
/*
* Check if the process isn't attacked, or has a Kernel APC in progress
* or has pending APC of any kind.
*/
if ((Thread->ApcStateIndex == OriginalApcEnvironment) ||
(Thread->ApcState.KernelApcInProgress) ||
(!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
(!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
{
/* Bugcheck the system */
KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
}
/* Get the process */
Process = Thread->ApcState.Process;
/* Acquire dispatcher lock */
KiAcquireDispatcherLockAtDpcLevel();
/* Decrease the stack count */
ASSERT(Process->StackCount != 0);
ASSERT(Process->State == ProcessInMemory);
Process->StackCount--;
/* Check if we can swap the process out */
if (!Process->StackCount)
{
/* FIXME: Swap the process out */
}
/* Release dispatcher lock */
KiReleaseDispatcherLockFromDpcLevel();
/* Check if there's an APC state to restore */
if (ApcState->Process)
{
/* Restore the APC State */
KiMoveApcState(ApcState, &Thread->ApcState);
}
else
{
/* The ApcState parameter is useless, so use the saved data and reset it */
KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
Thread->SavedApcState.Process = NULL;
Thread->ApcStateIndex = OriginalApcEnvironment;
Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
}
/* Release lock */
KiReleaseApcLockFromDpcLevel(&ApcLock);
/* Swap Processes */
KiSwapProcess(Thread->ApcState.Process, Process);
/* Exit the dispatcher */
KiExitDispatcher(ApcLock.OldIrql);
/* Check if we have pending APCs */
if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
{
/* What do you know, we do! Request them to be delivered */
Thread->ApcState.KernelApcPending = TRUE;
HalRequestSoftwareInterrupt(APC_LEVEL);
}
}
/*
* @implemented
*/
ULONG
NTAPI
KeQueryRuntimeProcess(IN PKPROCESS Process,
OUT PULONG UserTime)
{
ULONG TotalUser, TotalKernel;
KLOCK_QUEUE_HANDLE ProcessLock;
PLIST_ENTRY NextEntry, ListHead;
PKTHREAD Thread;
ASSERT_PROCESS(Process);
/* Initialize user and kernel times */
TotalUser = Process->UserTime;
TotalKernel = Process->KernelTime;
/* Lock the process */
KiAcquireProcessLock(Process, &ProcessLock);
/* Loop all child threads and sum up their times */
ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{
/* Get the thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
/* Sum up times */
TotalKernel += Thread->KernelTime;
TotalUser += Thread->UserTime;
/* Go to the next one */
NextEntry = NextEntry->Flink;
}
/* Release lock */
KiReleaseProcessLock(&ProcessLock);
/* Return the user time */
*UserTime = TotalUser;
/* Return the kernel time */
return TotalKernel;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
KeAddSystemServiceTable(IN PULONG_PTR Base,
IN PULONG Count OPTIONAL,
IN ULONG Limit,
IN PUCHAR Number,
IN ULONG Index)
{
PAGED_CODE();
/* Check if descriptor table entry is free */
if ((Index > SSDT_MAX_ENTRIES - 1) ||
(KeServiceDescriptorTable[Index].Base) ||
(KeServiceDescriptorTableShadow[Index].Base))
{
/* It's not, fail */
return FALSE;
}
/* Initialize the shadow service descriptor table */
KeServiceDescriptorTableShadow[Index].Base = Base;
KeServiceDescriptorTableShadow[Index].Limit = Limit;
KeServiceDescriptorTableShadow[Index].Number = Number;
KeServiceDescriptorTableShadow[Index].Count = Count;
return TRUE;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
KeRemoveSystemServiceTable(IN ULONG Index)
{
PAGED_CODE();
/* Make sure the Index is valid */
if (Index > (SSDT_MAX_ENTRIES - 1)) return FALSE;
/* Is there a Normal Descriptor Table? */
if (!KeServiceDescriptorTable[Index].Base)
{
/* Not with the index, is there a shadow at least? */
if (!KeServiceDescriptorTableShadow[Index].Base) return FALSE;
}
/* Now clear from the Shadow Table. */
KeServiceDescriptorTableShadow[Index].Base = NULL;
KeServiceDescriptorTableShadow[Index].Number = NULL;
KeServiceDescriptorTableShadow[Index].Limit = 0;
KeServiceDescriptorTableShadow[Index].Count = NULL;
/* Check if we should clean from the Master one too */
if (Index == 1)
{
KeServiceDescriptorTable[Index].Base = NULL;
KeServiceDescriptorTable[Index].Number = NULL;
KeServiceDescriptorTable[Index].Limit = 0;
KeServiceDescriptorTable[Index].Count = NULL;
}
/* Return success */
return TRUE;
}
/* EOF */