xref: /reactos/ntoskrnl/ps/state.c (revision 34593d93)
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