Leaked source code of windows server 2003
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.

647 lines
14 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. PAGED_CODE();
  46. if (Thread == PsGetCurrentThread ()) {
  47. try {
  48. LocalPreviousSuspendCount = (ULONG) KeSuspendThread (&Thread->Tcb);
  49. Status = STATUS_SUCCESS;
  50. } except ((GetExceptionCode () == STATUS_SUSPEND_COUNT_EXCEEDED)?
  51. EXCEPTION_EXECUTE_HANDLER :
  52. EXCEPTION_CONTINUE_SEARCH) {
  53. Status = GetExceptionCode();
  54. }
  55. } else {
  56. //
  57. // Protect the remote thread from being rundown.
  58. //
  59. if (ExAcquireRundownProtection (&Thread->RundownProtect)) {
  60. //
  61. // Don't allow suspend if we are being deleted
  62. //
  63. if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
  64. Status = STATUS_THREAD_IS_TERMINATING;
  65. } else {
  66. try {
  67. LocalPreviousSuspendCount = (ULONG) KeSuspendThread (&Thread->Tcb);
  68. Status = STATUS_SUCCESS;
  69. } except ((GetExceptionCode () == STATUS_SUSPEND_COUNT_EXCEEDED)?
  70. EXCEPTION_EXECUTE_HANDLER :
  71. EXCEPTION_CONTINUE_SEARCH) {
  72. Status = GetExceptionCode();
  73. }
  74. //
  75. // If deletion was started after we suspended then wake up the thread
  76. //
  77. if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
  78. KeForceResumeThread (&Thread->Tcb);
  79. LocalPreviousSuspendCount = 0;
  80. Status = STATUS_THREAD_IS_TERMINATING;
  81. }
  82. }
  83. ExReleaseRundownProtection (&Thread->RundownProtect);
  84. } else {
  85. Status = STATUS_THREAD_IS_TERMINATING;
  86. }
  87. }
  88. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  89. *PreviousSuspendCount = LocalPreviousSuspendCount;
  90. }
  91. return Status;
  92. }
  93. NTSTATUS
  94. PsSuspendProcess (
  95. PEPROCESS Process
  96. )
  97. /*++
  98. Routine Description:
  99. This function suspends all the PS threads in a process.
  100. Arguments:
  101. Process - Process whose threads are to be suspended
  102. Return Value:
  103. NTSTATUS - Status of operation.
  104. --*/
  105. {
  106. NTSTATUS Status;
  107. PETHREAD Thread;
  108. PAGED_CODE ();
  109. if (ExAcquireRundownProtection (&Process->RundownProtect)) {
  110. for (Thread = PsGetNextProcessThread (Process, NULL);
  111. Thread != NULL;
  112. Thread = PsGetNextProcessThread (Process, Thread)) {
  113. PsSuspendThread (Thread, NULL);
  114. }
  115. ExReleaseRundownProtection (&Process->RundownProtect);
  116. Status = STATUS_SUCCESS;
  117. } else {
  118. Status = STATUS_PROCESS_IS_TERMINATING;
  119. }
  120. return Status;
  121. }
  122. NTSTATUS
  123. PsResumeProcess (
  124. PEPROCESS Process
  125. )
  126. /*++
  127. Routine Description:
  128. This function resumes all the PS threads in a process.
  129. Arguments:
  130. Process - Process whose threads are to be suspended
  131. Return Value:
  132. NTSTATUS - Status of operation.
  133. --*/
  134. {
  135. NTSTATUS Status;
  136. PETHREAD Thread;
  137. PAGED_CODE ();
  138. if (ExAcquireRundownProtection (&Process->RundownProtect)) {
  139. for (Thread = PsGetNextProcessThread (Process, NULL);
  140. Thread != NULL;
  141. Thread = PsGetNextProcessThread (Process, Thread)) {
  142. KeResumeThread (&Thread->Tcb);
  143. }
  144. ExReleaseRundownProtection (&Process->RundownProtect);
  145. Status = STATUS_SUCCESS;
  146. } else {
  147. Status = STATUS_PROCESS_IS_TERMINATING;
  148. }
  149. return Status;
  150. }
  151. NTSTATUS
  152. NtSuspendThread(
  153. IN HANDLE ThreadHandle,
  154. OUT PULONG PreviousSuspendCount OPTIONAL
  155. )
  156. /*++
  157. Routine Description:
  158. This function suspends the target thread, and optionally
  159. returns the previous suspend count.
  160. Arguments:
  161. ThreadHandle - Supplies a handle to the thread object to suspend.
  162. PreviousSuspendCount - An optional parameter, that if specified
  163. points to a variable that receives the thread's previous suspend
  164. count.
  165. Return Value:
  166. NTSTATUS - Status of operation.
  167. --*/
  168. {
  169. PETHREAD Thread;
  170. NTSTATUS st;
  171. ULONG LocalPreviousSuspendCount;
  172. KPROCESSOR_MODE Mode;
  173. PAGED_CODE();
  174. Mode = KeGetPreviousMode ();
  175. try {
  176. if (Mode != KernelMode) {
  177. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  178. ProbeForWriteUlong (PreviousSuspendCount);
  179. }
  180. }
  181. } except (EXCEPTION_EXECUTE_HANDLER) {
  182. return GetExceptionCode();
  183. }
  184. st = ObReferenceObjectByHandle (ThreadHandle,
  185. THREAD_SUSPEND_RESUME,
  186. PsThreadType,
  187. Mode,
  188. &Thread,
  189. NULL);
  190. if (!NT_SUCCESS (st)) {
  191. return st;
  192. }
  193. st = PsSuspendThread (Thread, &LocalPreviousSuspendCount);
  194. ObDereferenceObject (Thread);
  195. try {
  196. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  197. *PreviousSuspendCount = LocalPreviousSuspendCount;
  198. }
  199. } except (EXCEPTION_EXECUTE_HANDLER) {
  200. st = GetExceptionCode ();
  201. }
  202. return st;
  203. }
  204. NTSTATUS
  205. PsResumeThread (
  206. IN PETHREAD Thread,
  207. OUT PULONG PreviousSuspendCount OPTIONAL
  208. )
  209. /*++
  210. Routine Description:
  211. This function resumes a thread that was previously suspened
  212. Arguments:
  213. Thread - Thread to resume
  214. PreviousSuspendCount - Optional address of a ULONG to place the previous suspend count in
  215. Return Value:
  216. NTSTATUS - Status of call
  217. --*/
  218. {
  219. ULONG LocalPreviousSuspendCount;
  220. PAGED_CODE();
  221. LocalPreviousSuspendCount = (ULONG) KeResumeThread (&Thread->Tcb);
  222. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  223. *PreviousSuspendCount = LocalPreviousSuspendCount;
  224. }
  225. return STATUS_SUCCESS;
  226. }
  227. NTSTATUS
  228. NtResumeThread(
  229. IN HANDLE ThreadHandle,
  230. OUT PULONG PreviousSuspendCount OPTIONAL
  231. )
  232. /*++
  233. Routine Description:
  234. This function resumes a thread that was previously suspened
  235. Arguments:
  236. ThreadHandle - Handle to thread to resume
  237. PreviousSuspendCount - Optional address of a ULONG to place the previous suspend count in
  238. Return Value:
  239. NTSTATUS - Status of call
  240. --*/
  241. {
  242. PETHREAD Thread;
  243. NTSTATUS st;
  244. KPROCESSOR_MODE Mode;
  245. ULONG LocalPreviousSuspendCount;
  246. PAGED_CODE();
  247. Mode = KeGetPreviousMode ();
  248. try {
  249. if (Mode != KernelMode) {
  250. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  251. ProbeForWriteUlong (PreviousSuspendCount);
  252. }
  253. }
  254. } except (EXCEPTION_EXECUTE_HANDLER) {
  255. return GetExceptionCode ();
  256. }
  257. st = ObReferenceObjectByHandle (ThreadHandle,
  258. THREAD_SUSPEND_RESUME,
  259. PsThreadType,
  260. Mode,
  261. &Thread,
  262. NULL);
  263. if (!NT_SUCCESS (st)) {
  264. return st;
  265. }
  266. PsResumeThread (Thread, &LocalPreviousSuspendCount);
  267. ObDereferenceObject (Thread);
  268. try {
  269. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  270. *PreviousSuspendCount = LocalPreviousSuspendCount;
  271. }
  272. } except (EXCEPTION_EXECUTE_HANDLER) {
  273. return GetExceptionCode ();
  274. }
  275. return STATUS_SUCCESS;
  276. }
  277. NTSTATUS
  278. NtSuspendProcess (
  279. IN HANDLE ProcessHandle
  280. )
  281. /*++
  282. Routine Description:
  283. This function suspends all none-exiting threads in the target process
  284. Arguments:
  285. ProcessHandle - Supplies an open handle to the process to be suspened
  286. Return Value:
  287. NTSTATUS - Status of operation
  288. --*/
  289. {
  290. KPROCESSOR_MODE PreviousMode;
  291. NTSTATUS Status;
  292. PEPROCESS Process;
  293. PAGED_CODE();
  294. PreviousMode = KeGetPreviousMode ();
  295. Status = ObReferenceObjectByHandle (ProcessHandle,
  296. PROCESS_SET_PORT,
  297. PsProcessType,
  298. PreviousMode,
  299. &Process,
  300. NULL);
  301. if (NT_SUCCESS (Status)) {
  302. Status = PsSuspendProcess (Process);
  303. ObDereferenceObject (Process);
  304. }
  305. return Status;
  306. }
  307. NTSTATUS
  308. NtResumeProcess (
  309. IN HANDLE ProcessHandle
  310. )
  311. /*++
  312. Routine Description:
  313. This function suspends all none-exiting threads in the target process
  314. Arguments:
  315. ProcessHandle - Supplies an open handle to the process to be suspened
  316. Return Value:
  317. NTSTATUS - Status of operation
  318. --*/
  319. {
  320. KPROCESSOR_MODE PreviousMode;
  321. NTSTATUS Status;
  322. PEPROCESS Process;
  323. PAGED_CODE();
  324. PreviousMode = KeGetPreviousMode ();
  325. Status = ObReferenceObjectByHandle (ProcessHandle,
  326. PROCESS_SET_PORT,
  327. PsProcessType,
  328. PreviousMode,
  329. &Process,
  330. NULL);
  331. if (NT_SUCCESS (Status)) {
  332. Status = PsResumeProcess (Process);
  333. ObDereferenceObject (Process);
  334. }
  335. return Status;
  336. }
  337. NTSTATUS
  338. NtAlertThread(
  339. IN HANDLE ThreadHandle
  340. )
  341. /*++
  342. Routine Description:
  343. This function alerts the target thread using the previous mode
  344. as the mode of the alert.
  345. Arguments:
  346. ThreadHandle - Supplies an open handle to the thread to be alerted
  347. Return Value:
  348. NTSTATUS - Status of operation
  349. --*/
  350. {
  351. PETHREAD Thread;
  352. NTSTATUS st;
  353. KPROCESSOR_MODE Mode;
  354. PAGED_CODE();
  355. Mode = KeGetPreviousMode ();
  356. st = ObReferenceObjectByHandle (ThreadHandle,
  357. THREAD_ALERT,
  358. PsThreadType,
  359. Mode,
  360. &Thread,
  361. NULL);
  362. if (!NT_SUCCESS (st)) {
  363. return st;
  364. }
  365. KeAlertThread (&Thread->Tcb,Mode);
  366. ObDereferenceObject (Thread);
  367. return STATUS_SUCCESS;
  368. }
  369. NTSTATUS
  370. NtAlertResumeThread(
  371. IN HANDLE ThreadHandle,
  372. OUT PULONG PreviousSuspendCount OPTIONAL
  373. )
  374. /*++
  375. Routine Description:
  376. description-of-function.
  377. Arguments:
  378. argument-name - Supplies | Returns description of argument.
  379. .
  380. .
  381. Return Value:
  382. NTSTATUS - Status of operation
  383. --*/
  384. {
  385. PETHREAD Thread;
  386. NTSTATUS st;
  387. ULONG LocalPreviousSuspendCount;
  388. KPROCESSOR_MODE Mode;
  389. PAGED_CODE();
  390. Mode = KeGetPreviousMode ();
  391. try {
  392. if (Mode != KernelMode ) {
  393. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  394. ProbeForWriteUlong (PreviousSuspendCount);
  395. }
  396. }
  397. } except (EXCEPTION_EXECUTE_HANDLER) {
  398. return GetExceptionCode();
  399. }
  400. st = ObReferenceObjectByHandle (ThreadHandle,
  401. THREAD_SUSPEND_RESUME,
  402. PsThreadType,
  403. Mode,
  404. &Thread,
  405. NULL);
  406. if (!NT_SUCCESS (st)) {
  407. return st;
  408. }
  409. LocalPreviousSuspendCount = (ULONG) KeAlertResumeThread (&Thread->Tcb);
  410. ObDereferenceObject (Thread);
  411. try {
  412. if (ARGUMENT_PRESENT (PreviousSuspendCount)) {
  413. *PreviousSuspendCount = LocalPreviousSuspendCount;
  414. }
  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. }