Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

641 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. psspnd.c
  5. Abstract:
  6. This module implements NtSuspendThread and NtResumeThread
  7. Author:
  8. Mark Lucovsky (markl) 25-May-1989
  9. Revision History:
  10. --*/
  11. #include "psp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE, NtSuspendThread)
  14. #pragma alloc_text(PAGE, NtResumeThread)
  15. #pragma alloc_text(PAGE, NtAlertThread)
  16. #pragma alloc_text(PAGE, NtAlertResumeThread)
  17. #pragma alloc_text(PAGE, NtTestAlert)
  18. #pragma alloc_text(PAGE, NtSuspendProcess)
  19. #pragma alloc_text(PAGE, NtResumeProcess)
  20. #pragma alloc_text(PAGE, PsSuspendThread)
  21. #pragma alloc_text(PAGE, PsSuspendProcess)
  22. #pragma alloc_text(PAGE, PsResumeProcess)
  23. #pragma alloc_text(PAGE, PsResumeThread)
  24. #endif
  25. NTSTATUS
  26. PsSuspendThread (
  27. IN PETHREAD Thread,
  28. OUT PULONG PreviousSuspendCount OPTIONAL
  29. )
  30. /*++
  31. Routine Description:
  32. This function suspends the target thread, and optionally
  33. returns the previous suspend count.
  34. Arguments:
  35. ThreadHandle - Supplies a handle to the thread object to suspend.
  36. PreviousSuspendCount - An optional parameter, that if specified
  37. points to a variable that receives the thread's previous suspend
  38. count.
  39. Return Value:
  40. NTSTATUS - Status of call
  41. --*/
  42. {
  43. NTSTATUS Status;
  44. ULONG LocalPreviousSuspendCount = 0;
  45. if ( Thread == PsGetCurrentThread() ) {
  46. try {
  47. LocalPreviousSuspendCount = (ULONG) KeSuspendThread(&Thread->Tcb);
  48. Status = STATUS_SUCCESS;
  49. } except (EXCEPTION_EXECUTE_HANDLER) {
  50. Status = GetExceptionCode();
  51. }
  52. } else {
  53. //
  54. // Protect the remote thread from being rundown.
  55. //
  56. if (ExAcquireRundownProtection (&Thread->RundownProtect)) {
  57. //
  58. // Don't allow suspend if we are being deleted
  59. //
  60. if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
  61. Status = STATUS_THREAD_IS_TERMINATING;
  62. } else {
  63. try {
  64. LocalPreviousSuspendCount = (ULONG) KeSuspendThread (&Thread->Tcb);
  65. Status = STATUS_SUCCESS;
  66. } except (EXCEPTION_EXECUTE_HANDLER) {
  67. Status = GetExceptionCode();
  68. }
  69. //
  70. // If deletion was started after we suspended then wake up the thread
  71. //
  72. if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
  73. KeForceResumeThread (&Thread->Tcb);
  74. LocalPreviousSuspendCount = 0;
  75. Status = STATUS_THREAD_IS_TERMINATING;
  76. }
  77. }
  78. ExReleaseRundownProtection (&Thread->RundownProtect);
  79. } else {
  80. Status = STATUS_THREAD_IS_TERMINATING;
  81. }
  82. }
  83. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  84. *PreviousSuspendCount = LocalPreviousSuspendCount;
  85. }
  86. return Status;
  87. }
  88. NTSTATUS
  89. PsSuspendProcess (
  90. PEPROCESS Process
  91. )
  92. /*++
  93. Routine Description:
  94. This function suspends all the PS threads in a process.
  95. Arguments:
  96. Process - Process whose threads are to be suspended
  97. Return Value:
  98. NTSTATUS - Status of operation.
  99. --*/
  100. {
  101. NTSTATUS Status;
  102. PETHREAD Thread;
  103. PAGED_CODE ();
  104. if (ExAcquireRundownProtection (&Process->RundownProtect)) {
  105. for (Thread = PsGetNextProcessThread (Process, NULL);
  106. Thread != NULL;
  107. Thread = PsGetNextProcessThread (Process, Thread)) {
  108. PsSuspendThread (Thread, NULL);
  109. }
  110. ExReleaseRundownProtection (&Process->RundownProtect);
  111. Status = STATUS_SUCCESS;
  112. } else {
  113. Status = STATUS_PROCESS_IS_TERMINATING;
  114. }
  115. return Status;
  116. }
  117. NTSTATUS
  118. PsResumeProcess (
  119. PEPROCESS Process
  120. )
  121. /*++
  122. Routine Description:
  123. This function resumes all the PS threads in a process.
  124. Arguments:
  125. Process - Process whose threads are to be suspended
  126. Return Value:
  127. NTSTATUS - Status of operation.
  128. --*/
  129. {
  130. NTSTATUS Status;
  131. PETHREAD Thread;
  132. PAGED_CODE ();
  133. if (ExAcquireRundownProtection (&Process->RundownProtect)) {
  134. for (Thread = PsGetNextProcessThread (Process, NULL);
  135. Thread != NULL;
  136. Thread = PsGetNextProcessThread (Process, Thread)) {
  137. KeResumeThread (&Thread->Tcb);
  138. }
  139. ExReleaseRundownProtection (&Process->RundownProtect);
  140. Status = STATUS_SUCCESS;
  141. } else {
  142. Status = STATUS_PROCESS_IS_TERMINATING;
  143. }
  144. return Status;
  145. }
  146. NTSTATUS
  147. NtSuspendThread(
  148. IN HANDLE ThreadHandle,
  149. OUT PULONG PreviousSuspendCount OPTIONAL
  150. )
  151. /*++
  152. Routine Description:
  153. This function suspends the target thread, and optionally
  154. returns the previous suspend count.
  155. Arguments:
  156. ThreadHandle - Supplies a handle to the thread object to suspend.
  157. PreviousSuspendCount - An optional parameter, that if specified
  158. points to a variable that receives the thread's previous suspend
  159. count.
  160. Return Value:
  161. return-value - Description of conditions needed to return value. - or -
  162. None.
  163. --*/
  164. {
  165. PETHREAD Thread;
  166. NTSTATUS st;
  167. ULONG LocalPreviousSuspendCount;
  168. KPROCESSOR_MODE Mode;
  169. PAGED_CODE();
  170. try {
  171. Mode = KeGetPreviousMode();
  172. if ( Mode != KernelMode ) {
  173. if (ARGUMENT_PRESENT(PreviousSuspendCount)) {
  174. ProbeForWriteUlong(PreviousSuspendCount);
  175. }
  176. }
  177. } except (EXCEPTION_EXECUTE_HANDLER) {
  178. return GetExceptionCode();
  179. }
  180. st = ObReferenceObjectByHandle(
  181. ThreadHandle,
  182. THREAD_SUSPEND_RESUME,
  183. PsThreadType,
  184. Mode,
  185. (PVOID *)&Thread,
  186. NULL
  187. );
  188. if ( !NT_SUCCESS(st) ) {
  189. return st;
  190. }
  191. st = PsSuspendThread (Thread, &LocalPreviousSuspendCount);
  192. ObDereferenceObject(Thread);
  193. try {
  194. if (ARGUMENT_PRESENT(PreviousSuspendCount)) {
  195. *PreviousSuspendCount = LocalPreviousSuspendCount;
  196. }
  197. } except (EXCEPTION_EXECUTE_HANDLER) {
  198. st = GetExceptionCode();
  199. }
  200. return st;
  201. }
  202. NTSTATUS
  203. PsResumeThread (
  204. IN PETHREAD Thread,
  205. OUT PULONG PreviousSuspendCount OPTIONAL
  206. )
  207. /*++
  208. Routine Description:
  209. This function resumes a thread that was previously suspened
  210. Arguments:
  211. Thread - Thread to resume
  212. PreviousSuspendCount - Optional address of a ULONG to place the previous suspend count in
  213. Return Value:
  214. NTSTATUS - Status of call
  215. --*/
  216. {
  217. ULONG LocalPreviousSuspendCount;
  218. LocalPreviousSuspendCount = (ULONG) KeResumeThread(&Thread->Tcb);
  219. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  220. *PreviousSuspendCount = LocalPreviousSuspendCount;
  221. }
  222. return STATUS_SUCCESS;
  223. }
  224. NTSTATUS
  225. NtResumeThread(
  226. IN HANDLE ThreadHandle,
  227. OUT PULONG PreviousSuspendCount OPTIONAL
  228. )
  229. /*++
  230. Routine Description:
  231. This function resumes a thread that was previously suspened
  232. Arguments:
  233. ThreadHandle - Handle to thread to resume
  234. PreviousSuspendCount - Optional address of a ULONG to place the previous suspend count in
  235. Return Value:
  236. NTSTATUS - Status of call
  237. --*/
  238. {
  239. PETHREAD Thread;
  240. NTSTATUS st;
  241. KPROCESSOR_MODE Mode;
  242. ULONG LocalPreviousSuspendCount;
  243. PAGED_CODE();
  244. try {
  245. Mode = KeGetPreviousMode();
  246. if ( Mode != KernelMode ) {
  247. if (ARGUMENT_PRESENT(PreviousSuspendCount))
  248. ProbeForWriteUlong(PreviousSuspendCount);
  249. }
  250. } except (EXCEPTION_EXECUTE_HANDLER) {
  251. return GetExceptionCode();
  252. }
  253. st = ObReferenceObjectByHandle(
  254. ThreadHandle,
  255. THREAD_SUSPEND_RESUME,
  256. PsThreadType,
  257. Mode,
  258. (PVOID *)&Thread,
  259. NULL
  260. );
  261. if ( !NT_SUCCESS(st) ) {
  262. return st;
  263. }
  264. PsResumeThread (Thread, &LocalPreviousSuspendCount);
  265. ObDereferenceObject (Thread);
  266. try {
  267. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  268. *PreviousSuspendCount = LocalPreviousSuspendCount;
  269. }
  270. } except (EXCEPTION_EXECUTE_HANDLER) {
  271. return GetExceptionCode ();
  272. }
  273. return STATUS_SUCCESS;
  274. }
  275. NTSTATUS
  276. NtSuspendProcess (
  277. IN HANDLE ProcessHandle
  278. )
  279. /*++
  280. Routine Description:
  281. This function suspends all none-exiting threads in the target process
  282. Arguments:
  283. ProcessHandle - Supplies an open handle to the process to be suspened
  284. Return Value:
  285. NTSTATUS - Status of operation
  286. --*/
  287. {
  288. KPROCESSOR_MODE PreviousMode;
  289. NTSTATUS Status;
  290. PEPROCESS Process;
  291. PreviousMode = KeGetPreviousMode();
  292. Status = ObReferenceObjectByHandle (ProcessHandle,
  293. PROCESS_SET_PORT,
  294. PsProcessType,
  295. PreviousMode,
  296. &Process,
  297. NULL);
  298. if (NT_SUCCESS (Status)) {
  299. Status = PsSuspendProcess (Process);
  300. ObDereferenceObject (Process);
  301. }
  302. return Status;
  303. }
  304. NTSTATUS
  305. NtResumeProcess (
  306. IN HANDLE ProcessHandle
  307. )
  308. /*++
  309. Routine Description:
  310. This function suspends all none-exiting threads in the target process
  311. Arguments:
  312. ProcessHandle - Supplies an open handle to the process to be suspened
  313. Return Value:
  314. NTSTATUS - Status of operation
  315. --*/
  316. {
  317. KPROCESSOR_MODE PreviousMode;
  318. NTSTATUS Status;
  319. PEPROCESS Process;
  320. PreviousMode = KeGetPreviousMode();
  321. Status = ObReferenceObjectByHandle (ProcessHandle,
  322. PROCESS_SET_PORT,
  323. PsProcessType,
  324. PreviousMode,
  325. &Process,
  326. NULL);
  327. if (NT_SUCCESS (Status)) {
  328. Status = PsResumeProcess (Process);
  329. ObDereferenceObject (Process);
  330. }
  331. return Status;
  332. }
  333. NTSTATUS
  334. NtAlertThread(
  335. IN HANDLE ThreadHandle
  336. )
  337. /*++
  338. Routine Description:
  339. This function alerts the target thread using the previous mode
  340. as the mode of the alert.
  341. Arguments:
  342. ThreadHandle - Supplies an open handle to the thread to be alerted
  343. Return Value:
  344. TBD
  345. --*/
  346. {
  347. PETHREAD Thread;
  348. NTSTATUS st;
  349. KPROCESSOR_MODE Mode;
  350. PAGED_CODE();
  351. Mode = KeGetPreviousMode();
  352. st = ObReferenceObjectByHandle(
  353. ThreadHandle,
  354. THREAD_ALERT,
  355. PsThreadType,
  356. Mode,
  357. (PVOID *)&Thread,
  358. NULL
  359. );
  360. if ( !NT_SUCCESS(st) ) {
  361. return st;
  362. }
  363. (VOID) KeAlertThread(&Thread->Tcb,Mode);
  364. ObDereferenceObject(Thread);
  365. return STATUS_SUCCESS;
  366. }
  367. NTSTATUS
  368. NtAlertResumeThread(
  369. IN HANDLE ThreadHandle,
  370. OUT PULONG PreviousSuspendCount OPTIONAL
  371. )
  372. /*++
  373. Routine Description:
  374. description-of-function.
  375. Arguments:
  376. argument-name - Supplies | Returns description of argument.
  377. .
  378. .
  379. Return Value:
  380. return-value - Description of conditions needed to return value. - or -
  381. None.
  382. --*/
  383. {
  384. PETHREAD Thread;
  385. NTSTATUS st;
  386. ULONG LocalPreviousSuspendCount;
  387. KPROCESSOR_MODE Mode;
  388. PAGED_CODE();
  389. try {
  390. Mode = KeGetPreviousMode();
  391. if ( Mode != KernelMode ) {
  392. if (ARGUMENT_PRESENT(PreviousSuspendCount)) {
  393. ProbeForWriteUlong(PreviousSuspendCount);
  394. }
  395. }
  396. } except (EXCEPTION_EXECUTE_HANDLER) {
  397. return GetExceptionCode();
  398. }
  399. st = ObReferenceObjectByHandle(
  400. ThreadHandle,
  401. THREAD_SUSPEND_RESUME,
  402. PsThreadType,
  403. Mode,
  404. (PVOID *)&Thread,
  405. NULL
  406. );
  407. if ( !NT_SUCCESS(st) ) {
  408. return st;
  409. }
  410. LocalPreviousSuspendCount = (ULONG) KeAlertResumeThread(&Thread->Tcb);
  411. ObDereferenceObject(Thread);
  412. try {
  413. if (ARGUMENT_PRESENT(PreviousSuspendCount))
  414. *PreviousSuspendCount = LocalPreviousSuspendCount;
  415. } except (EXCEPTION_EXECUTE_HANDLER) {
  416. return GetExceptionCode ();
  417. }
  418. return STATUS_SUCCESS;
  419. }
  420. NTSTATUS
  421. NtTestAlert(
  422. VOID
  423. )
  424. /*++
  425. Routine Description:
  426. This function tests the alert flag inside the current thread. If
  427. an alert is pending for the previous mode, then the alerted status
  428. is returned, pending APC's may also be delivered at this time.
  429. Arguments:
  430. None
  431. Return Value:
  432. STATUS_ALERTED - An alert was pending for the current thread at the
  433. time this function was called.
  434. STATUS_SUCCESS - No alert was pending for this thread.
  435. --*/
  436. {
  437. PAGED_CODE();
  438. if ( KeTestAlertThread(KeGetPreviousMode()) ) {
  439. return STATUS_ALERTED;
  440. } else {
  441. return STATUS_SUCCESS;
  442. }
  443. }