- use inlined probing macros for basic types
[reactos.git] / reactos / ntoskrnl / ps / suspend.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/suspend.c
6 * PURPOSE: Thread managment
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 ULONG
18 STDCALL
19 KeResumeThread(PKTHREAD Thread);
20
21 /* FUNCTIONS *****************************************************************/
22
23 /*
24 * FUNCTION: Decrements a thread's resume count
25 * ARGUMENTS:
26 * ThreadHandle = Handle to the thread that should be resumed
27 * ResumeCount = The resulting resume count.
28 * RETURNS: Status
29 */
30 NTSTATUS
31 STDCALL
32 NtResumeThread(IN HANDLE ThreadHandle,
33 IN PULONG SuspendCount OPTIONAL)
34 {
35 PETHREAD Thread;
36 ULONG Prev;
37 KPROCESSOR_MODE PreviousMode;
38 NTSTATUS Status = STATUS_SUCCESS;
39
40 PAGED_CODE();
41
42 PreviousMode = ExGetPreviousMode();
43
44 DPRINT("NtResumeThead(ThreadHandle %lx SuspendCount %p)\n",
45 ThreadHandle, SuspendCount);
46
47 /* Check buffer validity */
48 if(SuspendCount && PreviousMode != KernelMode) {
49
50 _SEH_TRY {
51
52 ProbeForWriteUlong(SuspendCount);
53 } _SEH_HANDLE {
54
55 Status = _SEH_GetExceptionCode();
56
57 } _SEH_END;
58
59 if(!NT_SUCCESS(Status)) return Status;
60 }
61
62 /* Get the Thread Object */
63 Status = ObReferenceObjectByHandle(ThreadHandle,
64 THREAD_SUSPEND_RESUME,
65 PsThreadType,
66 PreviousMode,
67 (PVOID*)&Thread,
68 NULL);
69 if (!NT_SUCCESS(Status)) {
70
71 return Status;
72 }
73
74 /* Call the Kernel Function */
75 Prev = KeResumeThread(&Thread->Tcb);
76
77 /* Return it */
78 if(SuspendCount) {
79
80 _SEH_TRY {
81
82 *SuspendCount = Prev;
83
84 } _SEH_HANDLE {
85
86 Status = _SEH_GetExceptionCode();
87
88 } _SEH_END;
89 }
90
91 /* Dereference and Return */
92 ObDereferenceObject ((PVOID)Thread);
93 return Status;
94 }
95
96 /*
97 * FUNCTION: Increments a thread's suspend count
98 * ARGUMENTS:
99 * ThreadHandle = Handle to the thread that should be resumed
100 * PreviousSuspendCount = The resulting/previous suspend count.
101 * REMARK:
102 * A thread will be suspended if its suspend count is greater than 0.
103 * This procedure maps to the win32 SuspendThread function. (
104 * documentation about the the suspend count can be found here aswell )
105 * The suspend count is not increased if it is greater than
106 * MAXIMUM_SUSPEND_COUNT.
107 * RETURNS: Status
108 */
109 NTSTATUS
110 STDCALL
111 NtSuspendThread(IN HANDLE ThreadHandle,
112 IN PULONG PreviousSuspendCount OPTIONAL)
113 {
114 PETHREAD Thread;
115 ULONG Prev;
116 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
117 NTSTATUS Status = STATUS_SUCCESS;
118 PAGED_CODE();
119
120 /* Check buffer validity */
121 if(PreviousSuspendCount && PreviousMode != KernelMode)
122 {
123 _SEH_TRY
124 {
125 ProbeForWriteUlong(PreviousSuspendCount);
126 }
127 _SEH_HANDLE
128 {
129 Status = _SEH_GetExceptionCode();
130 } _SEH_END;
131
132 if(!NT_SUCCESS(Status)) return Status;
133 }
134
135 /* Get the Thread Object */
136 Status = ObReferenceObjectByHandle(ThreadHandle,
137 THREAD_SUSPEND_RESUME,
138 PsThreadType,
139 PreviousMode,
140 (PVOID*)&Thread,
141 NULL);
142 if (!NT_SUCCESS(Status)) return Status;
143
144 /* Guard with SEH because KeSuspendThread can raise an exception */
145 _SEH_TRY
146 {
147 /* Make sure the thread isn't terminating */
148 if ((Thread != PsGetCurrentThread()) && (Thread->Terminated))
149 {
150 ObDereferenceObject(Thread);
151 return STATUS_THREAD_IS_TERMINATING;
152 }
153
154 /* Call the Kernel function */
155 Prev = KeSuspendThread(&Thread->Tcb);
156
157 /* Return the Previous Count */
158 if (PreviousSuspendCount) *PreviousSuspendCount = Prev;
159 }
160 _SEH_HANDLE
161 {
162 Status = _SEH_GetExceptionCode();
163
164 /* Don't fail if we merely couldn't write the handle back */
165 if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS;
166 } _SEH_END;
167
168 /* Return */
169 ObDereferenceObject(Thread);
170 return Status;
171 }
172
173
174 /*
175 * @unimplemented
176 */
177 NTSTATUS
178 STDCALL
179 NtSuspendProcess(IN HANDLE ProcessHandle)
180 {
181 KPROCESSOR_MODE PreviousMode;
182 PEPROCESS Process;
183 NTSTATUS Status;
184
185 PAGED_CODE();
186
187 PreviousMode = ExGetPreviousMode();
188
189 Status = ObReferenceObjectByHandle(ProcessHandle,
190 PROCESS_SUSPEND_RESUME,
191 PsProcessType,
192 PreviousMode,
193 (PVOID*)&Process,
194 NULL);
195 if (NT_SUCCESS(Status))
196 {
197 /* FIXME */
198 Status = STATUS_NOT_IMPLEMENTED;
199 DPRINT1("NtSuspendProcess not yet implemented!\n");
200
201 ObDereferenceObject(Process);
202 }
203
204 return Status;
205 }
206
207
208 /*
209 * @unimplemented
210 */
211 NTSTATUS
212 STDCALL
213 NtResumeProcess(IN HANDLE ProcessHandle)
214 {
215 KPROCESSOR_MODE PreviousMode;
216 PEPROCESS Process;
217 NTSTATUS Status;
218
219 PAGED_CODE();
220
221 PreviousMode = ExGetPreviousMode();
222
223 Status = ObReferenceObjectByHandle(ProcessHandle,
224 PROCESS_SUSPEND_RESUME,
225 PsProcessType,
226 PreviousMode,
227 (PVOID*)&Process,
228 NULL);
229 if (NT_SUCCESS(Status))
230 {
231 /* FIXME */
232 Status = STATUS_NOT_IMPLEMENTED;
233 DPRINT1("NtResumeProcess not yet implemented!\n");
234
235 ObDereferenceObject(Process);
236 }
237
238 return Status;
239 }
240
241 /* EOF */