1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Kernel
3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: ntoskrnl/ps/state.c
5c2c66affSColin Finck * PURPOSE: Process Manager: Process/Thread State Control
6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck * Thomas Weidenmueller (w3seek@reactos.org)
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck /* INCLUDES ******************************************************************/
11c2c66affSColin Finck
12c2c66affSColin Finck #include <ntoskrnl.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck
16c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
17c2c66affSColin Finck
18c2c66affSColin Finck VOID
19c2c66affSColin Finck NTAPI
PspQueueApcSpecialApc(IN PKAPC Apc,IN OUT PKNORMAL_ROUTINE * NormalRoutine,IN OUT PVOID * NormalContext,IN OUT PVOID * SystemArgument1,IN OUT PVOID * SystemArgument2)20c2c66affSColin Finck PspQueueApcSpecialApc(IN PKAPC Apc,
21c2c66affSColin Finck IN OUT PKNORMAL_ROUTINE* NormalRoutine,
22c2c66affSColin Finck IN OUT PVOID* NormalContext,
23c2c66affSColin Finck IN OUT PVOID* SystemArgument1,
24c2c66affSColin Finck IN OUT PVOID* SystemArgument2)
25c2c66affSColin Finck {
26c2c66affSColin Finck /* Free the APC and do nothing else */
27c2c66affSColin Finck ExFreePool(Apc);
28c2c66affSColin Finck }
29c2c66affSColin Finck
30c2c66affSColin Finck NTSTATUS
31c2c66affSColin Finck NTAPI
PsResumeThread(IN PETHREAD Thread,OUT PULONG PreviousCount OPTIONAL)32c2c66affSColin Finck PsResumeThread(IN PETHREAD Thread,
33c2c66affSColin Finck OUT PULONG PreviousCount OPTIONAL)
34c2c66affSColin Finck {
35c2c66affSColin Finck ULONG OldCount;
36c2c66affSColin Finck PAGED_CODE();
37c2c66affSColin Finck
38c2c66affSColin Finck /* Resume the thread */
39c2c66affSColin Finck OldCount = KeResumeThread(&Thread->Tcb);
40c2c66affSColin Finck
41c2c66affSColin Finck /* Return the count if asked */
42c2c66affSColin Finck if (PreviousCount) *PreviousCount = OldCount;
43c2c66affSColin Finck return STATUS_SUCCESS;
44c2c66affSColin Finck }
45c2c66affSColin Finck
46c2c66affSColin Finck NTSTATUS
47c2c66affSColin Finck NTAPI
PsSuspendThread(IN PETHREAD Thread,OUT PULONG PreviousCount OPTIONAL)48c2c66affSColin Finck PsSuspendThread(
49c2c66affSColin Finck IN PETHREAD Thread,
50c2c66affSColin Finck OUT PULONG PreviousCount OPTIONAL)
51c2c66affSColin Finck {
52c2c66affSColin Finck NTSTATUS Status;
53c2c66affSColin Finck ULONG OldCount = 0;
54c2c66affSColin Finck PAGED_CODE();
55c2c66affSColin Finck
56c2c66affSColin Finck /* Assume success */
57c2c66affSColin Finck Status = STATUS_SUCCESS;
58c2c66affSColin Finck
59c2c66affSColin Finck /* Check if we're suspending ourselves */
60c2c66affSColin Finck if (Thread == PsGetCurrentThread())
61c2c66affSColin Finck {
62c2c66affSColin Finck /* Guard with SEH because KeSuspendThread can raise an exception */
63c2c66affSColin Finck _SEH2_TRY
64c2c66affSColin Finck {
65c2c66affSColin Finck /* Do the suspend */
66c2c66affSColin Finck OldCount = KeSuspendThread(&Thread->Tcb);
67c2c66affSColin Finck }
68c2c66affSColin Finck _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
69c2c66affSColin Finck {
70c2c66affSColin Finck /* Get the exception code */
71c2c66affSColin Finck Status = _SEH2_GetExceptionCode();
72c2c66affSColin Finck }
73c2c66affSColin Finck _SEH2_END;
74c2c66affSColin Finck }
75c2c66affSColin Finck else
76c2c66affSColin Finck {
77c2c66affSColin Finck /* Acquire rundown protection */
78c2c66affSColin Finck if (ExAcquireRundownProtection(&Thread->RundownProtect))
79c2c66affSColin Finck {
80c2c66affSColin Finck /* Make sure the thread isn't terminating */
81c2c66affSColin Finck if (Thread->Terminated)
82c2c66affSColin Finck {
83c2c66affSColin Finck /* Fail */
84c2c66affSColin Finck Status = STATUS_THREAD_IS_TERMINATING;
85c2c66affSColin Finck }
86c2c66affSColin Finck else
87c2c66affSColin Finck {
88c2c66affSColin Finck /* Guard with SEH because KeSuspendThread can raise an exception */
89c2c66affSColin Finck _SEH2_TRY
90c2c66affSColin Finck {
91c2c66affSColin Finck /* Do the suspend */
92c2c66affSColin Finck OldCount = KeSuspendThread(&Thread->Tcb);
93c2c66affSColin Finck }
94c2c66affSColin Finck _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
95c2c66affSColin Finck {
96c2c66affSColin Finck /* Get the exception code */
97c2c66affSColin Finck Status = _SEH2_GetExceptionCode();
98c2c66affSColin Finck }
99c2c66affSColin Finck _SEH2_END;
100c2c66affSColin Finck
101c2c66affSColin Finck /* Check if it was terminated during the suspend */
102c2c66affSColin Finck if (Thread->Terminated)
103c2c66affSColin Finck {
104c2c66affSColin Finck /* Wake it back up and fail */
105c2c66affSColin Finck KeForceResumeThread(&Thread->Tcb);
106c2c66affSColin Finck Status = STATUS_THREAD_IS_TERMINATING;
107c2c66affSColin Finck OldCount = 0;
108c2c66affSColin Finck }
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck /* Release rundown protection */
112c2c66affSColin Finck ExReleaseRundownProtection(&Thread->RundownProtect);
113c2c66affSColin Finck }
114c2c66affSColin Finck else
115c2c66affSColin Finck {
116c2c66affSColin Finck /* Thread is terminating */
117c2c66affSColin Finck Status = STATUS_THREAD_IS_TERMINATING;
118c2c66affSColin Finck }
119c2c66affSColin Finck }
120c2c66affSColin Finck
121c2c66affSColin Finck /* Write back the previous count */
122c2c66affSColin Finck if (PreviousCount) *PreviousCount = OldCount;
123c2c66affSColin Finck return Status;
124c2c66affSColin Finck }
125c2c66affSColin Finck
126c2c66affSColin Finck NTSTATUS
127c2c66affSColin Finck NTAPI
PsResumeProcess(IN PEPROCESS Process)128c2c66affSColin Finck PsResumeProcess(IN PEPROCESS Process)
129c2c66affSColin Finck {
130c2c66affSColin Finck PETHREAD Thread;
131c2c66affSColin Finck PAGED_CODE();
132c2c66affSColin Finck
133c2c66affSColin Finck /* Lock the Process */
134c2c66affSColin Finck if (!ExAcquireRundownProtection(&Process->RundownProtect))
135c2c66affSColin Finck {
136c2c66affSColin Finck /* Process is terminating */
137c2c66affSColin Finck return STATUS_PROCESS_IS_TERMINATING;
138c2c66affSColin Finck }
139c2c66affSColin Finck
140c2c66affSColin Finck /* Get the first thread */
141c2c66affSColin Finck Thread = PsGetNextProcessThread(Process, NULL);
142c2c66affSColin Finck while (Thread)
143c2c66affSColin Finck {
144c2c66affSColin Finck /* Resume it */
145c2c66affSColin Finck KeResumeThread(&Thread->Tcb);
146c2c66affSColin Finck
147c2c66affSColin Finck /* Move to the next thread */
148c2c66affSColin Finck Thread = PsGetNextProcessThread(Process, Thread);
149c2c66affSColin Finck }
150c2c66affSColin Finck
151c2c66affSColin Finck /* Unlock the process */
152c2c66affSColin Finck ExReleaseRundownProtection(&Process->RundownProtect);
153c2c66affSColin Finck return STATUS_SUCCESS;
154c2c66affSColin Finck }
155c2c66affSColin Finck
156c2c66affSColin Finck NTSTATUS
157c2c66affSColin Finck NTAPI
PsSuspendProcess(IN PEPROCESS Process)158c2c66affSColin Finck PsSuspendProcess(IN PEPROCESS Process)
159c2c66affSColin Finck {
160c2c66affSColin Finck PETHREAD Thread;
161c2c66affSColin Finck PAGED_CODE();
162c2c66affSColin Finck
163c2c66affSColin Finck /* Lock the Process */
164c2c66affSColin Finck if (!ExAcquireRundownProtection(&Process->RundownProtect))
165c2c66affSColin Finck {
166c2c66affSColin Finck /* Process is terminating */
167c2c66affSColin Finck return STATUS_PROCESS_IS_TERMINATING;
168c2c66affSColin Finck }
169c2c66affSColin Finck
170c2c66affSColin Finck /* Get the first thread */
171c2c66affSColin Finck Thread = PsGetNextProcessThread(Process, NULL);
172c2c66affSColin Finck while (Thread)
173c2c66affSColin Finck {
174c2c66affSColin Finck /* Resume it */
175c2c66affSColin Finck PsSuspendThread(Thread, NULL);
176c2c66affSColin Finck
177c2c66affSColin Finck /* Move to the next thread */
178c2c66affSColin Finck Thread = PsGetNextProcessThread(Process, Thread);
179c2c66affSColin Finck }
180c2c66affSColin Finck
181c2c66affSColin Finck /* Unlock the process */
182c2c66affSColin Finck ExReleaseRundownProtection(&Process->RundownProtect);
183c2c66affSColin Finck return STATUS_SUCCESS;
184c2c66affSColin Finck }
185c2c66affSColin Finck
186c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
187c2c66affSColin Finck
188c2c66affSColin Finck /*
189c2c66affSColin Finck * @implemented
190c2c66affSColin Finck */
191c2c66affSColin Finck NTSTATUS
192c2c66affSColin Finck NTAPI
NtAlertThread(IN HANDLE ThreadHandle)193c2c66affSColin Finck NtAlertThread(IN HANDLE ThreadHandle)
194c2c66affSColin Finck {
195c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
196c2c66affSColin Finck PETHREAD Thread;
197c2c66affSColin Finck NTSTATUS Status;
198c2c66affSColin Finck
199c2c66affSColin Finck /* Reference the Object */
200c2c66affSColin Finck Status = ObReferenceObjectByHandle(ThreadHandle,
201c2c66affSColin Finck THREAD_SUSPEND_RESUME,
202c2c66affSColin Finck PsThreadType,
203c2c66affSColin Finck PreviousMode,
204c2c66affSColin Finck (PVOID*)&Thread,
205c2c66affSColin Finck NULL);
206c2c66affSColin Finck if (NT_SUCCESS(Status))
207c2c66affSColin Finck {
208c2c66affSColin Finck /*
209c2c66affSColin Finck * Do an alert depending on the processor mode. If some kmode code wants to
210c2c66affSColin Finck * enforce a umode alert it should call KeAlertThread() directly. If kmode
211c2c66affSColin Finck * code wants to do a kmode alert it's sufficient to call it with Zw or just
212c2c66affSColin Finck * use KeAlertThread() directly
213c2c66affSColin Finck */
214c2c66affSColin Finck KeAlertThread(&Thread->Tcb, PreviousMode);
215c2c66affSColin Finck
216c2c66affSColin Finck /* Dereference Object */
217c2c66affSColin Finck ObDereferenceObject(Thread);
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck /* Return status */
221c2c66affSColin Finck return Status;
222c2c66affSColin Finck }
223c2c66affSColin Finck
224c2c66affSColin Finck NTSTATUS
225c2c66affSColin Finck NTAPI
NtAlertResumeThread(IN HANDLE ThreadHandle,OUT PULONG SuspendCount)226c2c66affSColin Finck NtAlertResumeThread(IN HANDLE ThreadHandle,
227c2c66affSColin Finck OUT PULONG SuspendCount)
228c2c66affSColin Finck {
229c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
230c2c66affSColin Finck PETHREAD Thread;
231c2c66affSColin Finck NTSTATUS Status;
232c2c66affSColin Finck ULONG PreviousState;
233c2c66affSColin Finck
234c2c66affSColin Finck /* Check if we came from user mode with a suspend count */
235c2c66affSColin Finck if ((SuspendCount) && (PreviousMode != KernelMode))
236c2c66affSColin Finck {
237c2c66affSColin Finck /* Enter SEH for probing */
238c2c66affSColin Finck _SEH2_TRY
239c2c66affSColin Finck {
240c2c66affSColin Finck /* Probe the count */
241c2c66affSColin Finck ProbeForWriteUlong(SuspendCount);
242c2c66affSColin Finck }
243c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
244c2c66affSColin Finck {
245c2c66affSColin Finck /* Return the exception code */
246c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode());
247c2c66affSColin Finck }
248c2c66affSColin Finck _SEH2_END;
249c2c66affSColin Finck }
250c2c66affSColin Finck
251c2c66affSColin Finck /* Reference the Object */
252c2c66affSColin Finck Status = ObReferenceObjectByHandle(ThreadHandle,
253c2c66affSColin Finck THREAD_SUSPEND_RESUME,
254c2c66affSColin Finck PsThreadType,
255c2c66affSColin Finck PreviousMode,
256c2c66affSColin Finck (PVOID*)&Thread,
257c2c66affSColin Finck NULL);
258c2c66affSColin Finck if (NT_SUCCESS(Status))
259c2c66affSColin Finck {
260c2c66affSColin Finck /* Call the Kernel Function */
261c2c66affSColin Finck PreviousState = KeAlertResumeThread(&Thread->Tcb);
262c2c66affSColin Finck
263c2c66affSColin Finck /* Dereference Object */
264c2c66affSColin Finck ObDereferenceObject(Thread);
265c2c66affSColin Finck
266c2c66affSColin Finck /* Check if the caller gave a suspend count */
267c2c66affSColin Finck if (SuspendCount)
268c2c66affSColin Finck {
269c2c66affSColin Finck /* Enter SEH for write */
270c2c66affSColin Finck _SEH2_TRY
271c2c66affSColin Finck {
272c2c66affSColin Finck /* Write state back */
273c2c66affSColin Finck *SuspendCount = PreviousState;
274c2c66affSColin Finck }
275c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
276c2c66affSColin Finck {
277c2c66affSColin Finck /* Get exception code */
278c2c66affSColin Finck Status = _SEH2_GetExceptionCode();
279c2c66affSColin Finck }
280c2c66affSColin Finck _SEH2_END;
281c2c66affSColin Finck }
282c2c66affSColin Finck }
283c2c66affSColin Finck
284c2c66affSColin Finck /* Return status */
285c2c66affSColin Finck return Status;
286c2c66affSColin Finck }
287c2c66affSColin Finck
288c2c66affSColin Finck NTSTATUS
289c2c66affSColin Finck NTAPI
NtResumeThread(IN HANDLE ThreadHandle,OUT PULONG SuspendCount OPTIONAL)290c2c66affSColin Finck NtResumeThread(IN HANDLE ThreadHandle,
291c2c66affSColin Finck OUT PULONG SuspendCount OPTIONAL)
292c2c66affSColin Finck {
293c2c66affSColin Finck PETHREAD Thread;
294c2c66affSColin Finck ULONG Prev;
295c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
296c2c66affSColin Finck NTSTATUS Status;
297c2c66affSColin Finck PAGED_CODE();
298c2c66affSColin Finck
299c2c66affSColin Finck /* Check if caller gave a suspend count from user mode */
300c2c66affSColin Finck if ((SuspendCount) && (PreviousMode != KernelMode))
301c2c66affSColin Finck {
302c2c66affSColin Finck /* Enter SEH for probing */
303c2c66affSColin Finck _SEH2_TRY
304c2c66affSColin Finck {
305c2c66affSColin Finck /* Probe the count */
306c2c66affSColin Finck ProbeForWriteUlong(SuspendCount);
307c2c66affSColin Finck }
308c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
309c2c66affSColin Finck {
310c2c66affSColin Finck /* Return the exception code */
311c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode());
312c2c66affSColin Finck }
313c2c66affSColin Finck _SEH2_END;
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck /* Get the Thread Object */
317c2c66affSColin Finck Status = ObReferenceObjectByHandle(ThreadHandle,
318c2c66affSColin Finck THREAD_SUSPEND_RESUME,
319c2c66affSColin Finck PsThreadType,
320c2c66affSColin Finck PreviousMode,
321c2c66affSColin Finck (PVOID*)&Thread,
322c2c66affSColin Finck NULL);
323c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
324c2c66affSColin Finck
325c2c66affSColin Finck /* Call the internal function */
326c2c66affSColin Finck Status = PsResumeThread(Thread, &Prev);
327c2c66affSColin Finck
328c2c66affSColin Finck /* Check if the caller wanted the count back */
329c2c66affSColin Finck if (SuspendCount)
330c2c66affSColin Finck {
331c2c66affSColin Finck /* Enter SEH for write back */
332c2c66affSColin Finck _SEH2_TRY
333c2c66affSColin Finck {
334c2c66affSColin Finck /* Write the count */
335c2c66affSColin Finck *SuspendCount = Prev;
336c2c66affSColin Finck }
337c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
338c2c66affSColin Finck {
339c2c66affSColin Finck /* Get the exception code */
340c2c66affSColin Finck Status = _SEH2_GetExceptionCode();
341c2c66affSColin Finck }
342c2c66affSColin Finck _SEH2_END;
343c2c66affSColin Finck }
344c2c66affSColin Finck
345c2c66affSColin Finck /* Dereference and return */
346c2c66affSColin Finck ObDereferenceObject(Thread);
347c2c66affSColin Finck return Status;
348c2c66affSColin Finck }
349c2c66affSColin Finck
350c2c66affSColin Finck NTSTATUS
351c2c66affSColin Finck NTAPI
NtSuspendThread(IN HANDLE ThreadHandle,OUT PULONG PreviousSuspendCount OPTIONAL)352c2c66affSColin Finck NtSuspendThread(IN HANDLE ThreadHandle,
353c2c66affSColin Finck OUT PULONG PreviousSuspendCount OPTIONAL)
354c2c66affSColin Finck {
355c2c66affSColin Finck PETHREAD Thread;
356c2c66affSColin Finck ULONG Prev;
357c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
358c2c66affSColin Finck NTSTATUS Status;
359c2c66affSColin Finck PAGED_CODE();
360c2c66affSColin Finck
361c2c66affSColin Finck /* Check if caller gave a suspend count from user mode */
362c2c66affSColin Finck if ((PreviousSuspendCount) && (PreviousMode != KernelMode))
363c2c66affSColin Finck {
364c2c66affSColin Finck /* Enter SEH for probing */
365c2c66affSColin Finck _SEH2_TRY
366c2c66affSColin Finck {
367c2c66affSColin Finck /* Probe the count */
368c2c66affSColin Finck ProbeForWriteUlong(PreviousSuspendCount);
369c2c66affSColin Finck }
370c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
371c2c66affSColin Finck {
372c2c66affSColin Finck /* Return the exception code */
373c2c66affSColin Finck _SEH2_YIELD(return _SEH2_GetExceptionCode());
374c2c66affSColin Finck }
375c2c66affSColin Finck _SEH2_END;
376c2c66affSColin Finck }
377c2c66affSColin Finck
378c2c66affSColin Finck /* Get the Thread Object */
379c2c66affSColin Finck Status = ObReferenceObjectByHandle(ThreadHandle,
380c2c66affSColin Finck THREAD_SUSPEND_RESUME,
381c2c66affSColin Finck PsThreadType,
382c2c66affSColin Finck PreviousMode,
383c2c66affSColin Finck (PVOID*)&Thread,
384c2c66affSColin Finck NULL);
385c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
386c2c66affSColin Finck
387c2c66affSColin Finck /* Call the internal function */
388c2c66affSColin Finck Status = PsSuspendThread(Thread, &Prev);
389c2c66affSColin Finck ObDereferenceObject(Thread);
390c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
391c2c66affSColin Finck
392c2c66affSColin Finck /* Protect write with SEH */
393c2c66affSColin Finck _SEH2_TRY
394c2c66affSColin Finck {
395c2c66affSColin Finck /* Return the Previous Count */
396c2c66affSColin Finck if (PreviousSuspendCount) *PreviousSuspendCount = Prev;
397c2c66affSColin Finck }
398c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
399c2c66affSColin Finck {
400c2c66affSColin Finck /* Get the exception code */
401c2c66affSColin Finck Status = _SEH2_GetExceptionCode();
402c2c66affSColin Finck }
403c2c66affSColin Finck _SEH2_END;
404c2c66affSColin Finck
405c2c66affSColin Finck /* Return */
406c2c66affSColin Finck return Status;
407c2c66affSColin Finck }
408c2c66affSColin Finck
409c2c66affSColin Finck NTSTATUS
410c2c66affSColin Finck NTAPI
NtSuspendProcess(IN HANDLE ProcessHandle)411c2c66affSColin Finck NtSuspendProcess(IN HANDLE ProcessHandle)
412c2c66affSColin Finck {
413c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
414c2c66affSColin Finck PEPROCESS Process;
415c2c66affSColin Finck NTSTATUS Status;
416c2c66affSColin Finck PAGED_CODE();
417c2c66affSColin Finck
418c2c66affSColin Finck /* Reference the process */
419c2c66affSColin Finck Status = ObReferenceObjectByHandle(ProcessHandle,
420c2c66affSColin Finck PROCESS_SUSPEND_RESUME,
421c2c66affSColin Finck PsProcessType,
422c2c66affSColin Finck PreviousMode,
423c2c66affSColin Finck (PVOID*)&Process,
424c2c66affSColin Finck NULL);
425c2c66affSColin Finck if (NT_SUCCESS(Status))
426c2c66affSColin Finck {
427c2c66affSColin Finck /* Call the internal function */
428c2c66affSColin Finck Status = PsSuspendProcess(Process);
429c2c66affSColin Finck ObDereferenceObject(Process);
430c2c66affSColin Finck }
431c2c66affSColin Finck
432c2c66affSColin Finck /* Return status */
433c2c66affSColin Finck return Status;
434c2c66affSColin Finck }
435c2c66affSColin Finck
436c2c66affSColin Finck NTSTATUS
437c2c66affSColin Finck NTAPI
NtResumeProcess(IN HANDLE ProcessHandle)438c2c66affSColin Finck NtResumeProcess(IN HANDLE ProcessHandle)
439c2c66affSColin Finck {
440c2c66affSColin Finck KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
441c2c66affSColin Finck PEPROCESS Process;
442c2c66affSColin Finck NTSTATUS Status;
443c2c66affSColin Finck PAGED_CODE();
444c2c66affSColin Finck
445c2c66affSColin Finck /* Reference the process */
446c2c66affSColin Finck Status = ObReferenceObjectByHandle(ProcessHandle,
447c2c66affSColin Finck PROCESS_SUSPEND_RESUME,
448c2c66affSColin Finck PsProcessType,
449c2c66affSColin Finck PreviousMode,
450c2c66affSColin Finck (PVOID*)&Process,
451c2c66affSColin Finck NULL);
452c2c66affSColin Finck if (NT_SUCCESS(Status))
453c2c66affSColin Finck {
454c2c66affSColin Finck /* Call the internal function */
455c2c66affSColin Finck Status = PsResumeProcess(Process);
456c2c66affSColin Finck ObDereferenceObject(Process);
457c2c66affSColin Finck }
458c2c66affSColin Finck
459c2c66affSColin Finck /* Return status */
460c2c66affSColin Finck return Status;
461c2c66affSColin Finck }
462c2c66affSColin Finck
463c2c66affSColin Finck NTSTATUS
464c2c66affSColin Finck NTAPI
NtTestAlert(VOID)465c2c66affSColin Finck NtTestAlert(VOID)
466c2c66affSColin Finck {
467c2c66affSColin Finck /* Check and Alert Thread if needed */
468c2c66affSColin Finck return KeTestAlertThread(ExGetPreviousMode()) ?
469c2c66affSColin Finck STATUS_ALERTED : STATUS_SUCCESS;
470c2c66affSColin Finck }
471c2c66affSColin Finck
472c2c66affSColin Finck /*++
473*b607e011SAndrew Boyarshin * @name NtQueueApcThreadEx
474c2c66affSColin Finck * NT4
475c2c66affSColin Finck *
476c2c66affSColin Finck * This routine is used to queue an APC from user-mode for the specified
477c2c66affSColin Finck * thread.
478c2c66affSColin Finck *
479c2c66affSColin Finck * @param ThreadHandle
480c2c66affSColin Finck * Handle to the Thread.
481c2c66affSColin Finck * This handle must have THREAD_SET_CONTEXT privileges.
482c2c66affSColin Finck *
483*b607e011SAndrew Boyarshin * @param UserApcReserveHandle
484*b607e011SAndrew Boyarshin * Optional handle to reserve object (introduced in Windows 7), providing ability to
485*b607e011SAndrew Boyarshin * reserve memory before performing stability-critical parts of code.
486*b607e011SAndrew Boyarshin *
487c2c66affSColin Finck * @param ApcRoutine
488c2c66affSColin Finck * Pointer to the APC Routine to call when the APC executes.
489c2c66affSColin Finck *
490c2c66affSColin Finck * @param NormalContext
491c2c66affSColin Finck * Pointer to the context to send to the Normal Routine.
492c2c66affSColin Finck *
493c2c66affSColin Finck * @param SystemArgument[1-2]
494c2c66affSColin Finck * Pointer to a set of two parameters that contain untyped data.
495c2c66affSColin Finck *
496c2c66affSColin Finck * @return STATUS_SUCCESS or failure cute from associated calls.
497c2c66affSColin Finck *
498c2c66affSColin Finck * @remarks The thread must enter an alertable wait before the APC will be
499c2c66affSColin Finck * delivered.
500c2c66affSColin Finck *
501c2c66affSColin Finck *--*/
502c2c66affSColin Finck NTSTATUS
503c2c66affSColin Finck NTAPI
NtQueueApcThreadEx(IN HANDLE ThreadHandle,IN OPTIONAL HANDLE UserApcReserveHandle,IN PKNORMAL_ROUTINE ApcRoutine,IN PVOID NormalContext,IN OPTIONAL PVOID SystemArgument1,IN OPTIONAL PVOID SystemArgument2)504*b607e011SAndrew Boyarshin NtQueueApcThreadEx(IN HANDLE ThreadHandle,
505*b607e011SAndrew Boyarshin IN OPTIONAL HANDLE UserApcReserveHandle,
506c2c66affSColin Finck IN PKNORMAL_ROUTINE ApcRoutine,
507c2c66affSColin Finck IN PVOID NormalContext,
508*b607e011SAndrew Boyarshin IN OPTIONAL PVOID SystemArgument1,
509*b607e011SAndrew Boyarshin IN OPTIONAL PVOID SystemArgument2)
510c2c66affSColin Finck {
511c2c66affSColin Finck PKAPC Apc;
512c2c66affSColin Finck PETHREAD Thread;
513c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
514c2c66affSColin Finck PAGED_CODE();
515c2c66affSColin Finck
516c2c66affSColin Finck /* Get ETHREAD from Handle */
517c2c66affSColin Finck Status = ObReferenceObjectByHandle(ThreadHandle,
518c2c66affSColin Finck THREAD_SET_CONTEXT,
519c2c66affSColin Finck PsThreadType,
520c2c66affSColin Finck ExGetPreviousMode(),
521c2c66affSColin Finck (PVOID)&Thread,
522c2c66affSColin Finck NULL);
523c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
524c2c66affSColin Finck
525c2c66affSColin Finck /* Check if this is a System Thread */
526c2c66affSColin Finck if (Thread->SystemThread)
527c2c66affSColin Finck {
528c2c66affSColin Finck /* Fail */
529c2c66affSColin Finck Status = STATUS_INVALID_HANDLE;
530c2c66affSColin Finck goto Quit;
531c2c66affSColin Finck }
532c2c66affSColin Finck
533c2c66affSColin Finck /* Allocate an APC */
534c2c66affSColin Finck Apc = ExAllocatePoolWithQuotaTag(NonPagedPool |
535c2c66affSColin Finck POOL_QUOTA_FAIL_INSTEAD_OF_RAISE,
536c2c66affSColin Finck sizeof(KAPC),
537c2c66affSColin Finck TAG_PS_APC);
538c2c66affSColin Finck if (!Apc)
539c2c66affSColin Finck {
540c2c66affSColin Finck /* Fail */
541c2c66affSColin Finck Status = STATUS_NO_MEMORY;
542c2c66affSColin Finck goto Quit;
543c2c66affSColin Finck }
544c2c66affSColin Finck
545c2c66affSColin Finck /* Initialize the APC */
546c2c66affSColin Finck KeInitializeApc(Apc,
547c2c66affSColin Finck &Thread->Tcb,
548c2c66affSColin Finck OriginalApcEnvironment,
549c2c66affSColin Finck PspQueueApcSpecialApc,
550c2c66affSColin Finck NULL,
551c2c66affSColin Finck ApcRoutine,
552c2c66affSColin Finck UserMode,
553c2c66affSColin Finck NormalContext);
554c2c66affSColin Finck
555c2c66affSColin Finck /* Queue it */
556c2c66affSColin Finck if (!KeInsertQueueApc(Apc,
557c2c66affSColin Finck SystemArgument1,
558c2c66affSColin Finck SystemArgument2,
559c2c66affSColin Finck IO_NO_INCREMENT))
560c2c66affSColin Finck {
561c2c66affSColin Finck /* We failed, free it */
562c2c66affSColin Finck ExFreePool(Apc);
563c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
564c2c66affSColin Finck }
565c2c66affSColin Finck
566c2c66affSColin Finck /* Dereference Thread and Return */
567c2c66affSColin Finck Quit:
568c2c66affSColin Finck ObDereferenceObject(Thread);
569c2c66affSColin Finck return Status;
570c2c66affSColin Finck }
571c2c66affSColin Finck
572*b607e011SAndrew Boyarshin /*++
573*b607e011SAndrew Boyarshin * @name NtQueueApcThread
574*b607e011SAndrew Boyarshin * NT4
575*b607e011SAndrew Boyarshin *
576*b607e011SAndrew Boyarshin * This routine is used to queue an APC from user-mode for the specified
577*b607e011SAndrew Boyarshin * thread.
578*b607e011SAndrew Boyarshin *
579*b607e011SAndrew Boyarshin * @param ThreadHandle
580*b607e011SAndrew Boyarshin * Handle to the Thread.
581*b607e011SAndrew Boyarshin * This handle must have THREAD_SET_CONTEXT privileges.
582*b607e011SAndrew Boyarshin *
583*b607e011SAndrew Boyarshin * @param ApcRoutine
584*b607e011SAndrew Boyarshin * Pointer to the APC Routine to call when the APC executes.
585*b607e011SAndrew Boyarshin *
586*b607e011SAndrew Boyarshin * @param NormalContext
587*b607e011SAndrew Boyarshin * Pointer to the context to send to the Normal Routine.
588*b607e011SAndrew Boyarshin *
589*b607e011SAndrew Boyarshin * @param SystemArgument[1-2]
590*b607e011SAndrew Boyarshin * Pointer to a set of two parameters that contain untyped data.
591*b607e011SAndrew Boyarshin *
592*b607e011SAndrew Boyarshin * @return STATUS_SUCCESS or failure cute from associated calls.
593*b607e011SAndrew Boyarshin *
594*b607e011SAndrew Boyarshin * @remarks The thread must enter an alertable wait before the APC will be
595*b607e011SAndrew Boyarshin * delivered.
596*b607e011SAndrew Boyarshin *
597*b607e011SAndrew Boyarshin *--*/
598*b607e011SAndrew Boyarshin NTSTATUS
599*b607e011SAndrew Boyarshin NTAPI
NtQueueApcThread(IN HANDLE ThreadHandle,IN PKNORMAL_ROUTINE ApcRoutine,IN PVOID NormalContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2)600*b607e011SAndrew Boyarshin NtQueueApcThread(IN HANDLE ThreadHandle,
601*b607e011SAndrew Boyarshin IN PKNORMAL_ROUTINE ApcRoutine,
602*b607e011SAndrew Boyarshin IN PVOID NormalContext,
603*b607e011SAndrew Boyarshin IN PVOID SystemArgument1,
604*b607e011SAndrew Boyarshin IN PVOID SystemArgument2)
605*b607e011SAndrew Boyarshin {
606*b607e011SAndrew Boyarshin return NtQueueApcThreadEx(ThreadHandle, NULL, ApcRoutine, NormalContext, SystemArgument1, SystemArgument2);
607*b607e011SAndrew Boyarshin }
608*b607e011SAndrew Boyarshin
609c2c66affSColin Finck /* EOF */
610