1) Corrected bugs in ERESOURCE code
[reactos.git] / reactos / ntoskrnl / ps / kill.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/kill.c
5 * PURPOSE: Terminating a thread
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/ps.h>
15 #include <internal/ke.h>
16 #include <internal/mm.h>
17 #include <internal/ob.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* GLOBALS *******************************************************************/
23
24 extern ULONG PiNrThreads;
25 extern ULONG PiNrRunnableThreads;
26 extern KSPIN_LOCK PiThreadListLock;
27
28 /* FUNCTIONS *****************************************************************/
29
30 VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
31 /*
32 * FUNCTION: Terminates the current thread
33 */
34 {
35 KIRQL oldlvl;
36 PETHREAD CurrentThread;
37
38 PiNrThreads--;
39
40 CurrentThread = PsGetCurrentThread();
41
42 CurrentThread->ExitStatus = ExitStatus;
43
44 DPRINT("terminating %x\n",CurrentThread);
45 ObDereferenceObject(CurrentThread->ThreadsProcess);
46 CurrentThread->ThreadsProcess = NULL;
47 KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
48
49 ObDereferenceObject(CurrentThread);
50 DPRINT("ObGetReferenceCount(CurrentThread) %d\n",
51 ObGetReferenceCount(CurrentThread));
52
53 CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
54 KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
55
56 PsDispatchThread(THREAD_STATE_TERMINATED);
57 KeBugCheck(0);
58 }
59
60 VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
61 /*
62 * FUNCTION: Terminate a thread when calling from that thread's context
63 */
64 {
65 KIRQL oldIrql;
66
67 KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
68 PiNrThreads--;
69 if (Thread->Tcb.State == THREAD_STATE_RUNNABLE)
70 {
71 PiNrRunnableThreads--;
72 RemoveEntryList(&Thread->Tcb.QueueListEntry);
73 }
74 Thread->Tcb.State = THREAD_STATE_TERMINATED;
75 Thread->Tcb.DispatcherHeader.SignalState = TRUE;
76 KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader);
77 ObDereferenceObject(Thread->ThreadsProcess);
78 ObDereferenceObject(Thread);
79 Thread->ThreadsProcess = NULL;
80 KeReleaseSpinLock(&PiThreadListLock, oldIrql);
81 }
82
83
84 NTSTATUS STDCALL NtTerminateProcess(IN HANDLE ProcessHandle,
85 IN NTSTATUS ExitStatus)
86 {
87 NTSTATUS Status;
88 PEPROCESS Process;
89 KIRQL oldlvl;
90
91 DPRINT("NtTerminateProcess(ProcessHandle %x, ExitStatus %x)\n",
92 ProcessHandle, ExitStatus);
93
94 Status = ObReferenceObjectByHandle(ProcessHandle,
95 PROCESS_TERMINATE,
96 PsProcessType,
97 UserMode,
98 (PVOID*)&Process,
99 NULL);
100 if (Status != STATUS_SUCCESS)
101 {
102 return(Status);
103 }
104
105 PiTerminateProcessThreads(Process, ExitStatus);
106 KeRaiseIrql(DISPATCH_LEVEL, &oldlvl);
107 Process->Pcb.ProcessState = PROCESS_STATE_TERMINATED;
108 Process->Pcb.DispatcherHeader.SignalState = TRUE;
109 KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
110 if (PsGetCurrentThread()->ThreadsProcess == Process)
111 {
112 KeLowerIrql(oldlvl);
113 ObDereferenceObject(Process);
114 PsTerminateCurrentThread(ExitStatus);
115 }
116 KeLowerIrql(oldlvl);
117 ObDereferenceObject(Process);
118 return(STATUS_SUCCESS);
119 }
120
121
122 NTSTATUS STDCALL NtTerminateThread(IN HANDLE ThreadHandle,
123 IN NTSTATUS ExitStatus)
124 {
125 PETHREAD Thread;
126 NTSTATUS Status;
127
128 Status = ObReferenceObjectByHandle(ThreadHandle,
129 THREAD_TERMINATE,
130 PsThreadType,
131 UserMode,
132 (PVOID*)&Thread,
133 NULL);
134 if (Status != STATUS_SUCCESS)
135 {
136 return(Status);
137 }
138
139 if (Thread == PsGetCurrentThread())
140 {
141 PsTerminateCurrentThread(ExitStatus);
142 }
143 else
144 {
145 PsTerminateOtherThread(Thread, ExitStatus);
146 }
147 return(STATUS_SUCCESS);
148 }
149
150
151 NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus)
152 /*
153 * FUNCTION: Terminates the current thread
154 * ARGUMENTS:
155 * ExitStatus = Status to pass to the creater
156 * RETURNS: Doesn't
157 */
158 {
159 PsTerminateCurrentThread(ExitStatus);
160 return(STATUS_SUCCESS);
161 }
162
163
164 NTSTATUS STDCALL NtRegisterThreadTerminatePort(HANDLE TerminationPort)
165 {
166 UNIMPLEMENTED;
167 }