Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstate.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/ps/state.c 00005 * PURPOSE: Process Manager: Process/Thread State Control 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Thomas Weidenmueller (w3seek@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* PRIVATE FUNCTIONS *********************************************************/ 00017 00018 VOID 00019 NTAPI 00020 PspQueueApcSpecialApc(IN PKAPC Apc, 00021 IN OUT PKNORMAL_ROUTINE* NormalRoutine, 00022 IN OUT PVOID* NormalContext, 00023 IN OUT PVOID* SystemArgument1, 00024 IN OUT PVOID* SystemArgument2) 00025 { 00026 /* Free the APC and do nothing else */ 00027 ExFreePool(Apc); 00028 } 00029 00030 NTSTATUS 00031 NTAPI 00032 PsResumeThread(IN PETHREAD Thread, 00033 OUT PULONG PreviousCount OPTIONAL) 00034 { 00035 ULONG OldCount; 00036 PAGED_CODE(); 00037 00038 /* Resume the thread */ 00039 OldCount = KeResumeThread(&Thread->Tcb); 00040 00041 /* Return the count if asked */ 00042 if (PreviousCount) *PreviousCount = OldCount; 00043 return STATUS_SUCCESS; 00044 } 00045 00046 NTSTATUS 00047 NTAPI 00048 PsSuspendThread(IN PETHREAD Thread, 00049 OUT PULONG PreviousCount OPTIONAL) 00050 { 00051 NTSTATUS Status; 00052 ULONG OldCount = 0; 00053 PAGED_CODE(); 00054 00055 /* Guard with SEH because KeSuspendThread can raise an exception */ 00056 _SEH2_TRY 00057 { 00058 /* Check if we're suspending ourselves */ 00059 if (Thread == PsGetCurrentThread()) 00060 { 00061 /* Do the suspend */ 00062 OldCount = KeSuspendThread(&Thread->Tcb); 00063 00064 /* We are done */ 00065 Status = STATUS_SUCCESS; 00066 } 00067 else 00068 { 00069 /* Acquire rundown */ 00070 if (ExAcquireRundownProtection(&Thread->RundownProtect)) 00071 { 00072 /* Make sure the thread isn't terminating */ 00073 if (Thread->Terminated) 00074 { 00075 /* Fail */ 00076 Status = STATUS_THREAD_IS_TERMINATING; 00077 } 00078 else 00079 { 00080 /* Otherwise, do the suspend */ 00081 OldCount = KeSuspendThread(&Thread->Tcb); 00082 00083 /* Check if it terminated during the suspend */ 00084 if (Thread->Terminated) 00085 { 00086 /* Wake it back up and fail */ 00087 KeForceResumeThread(&Thread->Tcb); 00088 Status = STATUS_THREAD_IS_TERMINATING; 00089 OldCount = 0; 00090 } 00091 } 00092 00093 /* Release rundown protection */ 00094 ExReleaseRundownProtection(&Thread->RundownProtect); 00095 00096 /* We are done */ 00097 Status = STATUS_SUCCESS; 00098 } 00099 else 00100 { 00101 /* Thread is terminating */ 00102 Status = STATUS_THREAD_IS_TERMINATING; 00103 } 00104 } 00105 } 00106 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00107 { 00108 /* Get the exception code */ 00109 Status = _SEH2_GetExceptionCode(); 00110 00111 /* Don't fail if we merely couldn't write the handle back */ 00112 if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS; 00113 } 00114 _SEH2_END; 00115 00116 /* Write back the previous count */ 00117 if (PreviousCount) *PreviousCount = OldCount; 00118 return Status; 00119 } 00120 00121 NTSTATUS 00122 NTAPI 00123 PsResumeProcess(IN PEPROCESS Process) 00124 { 00125 PETHREAD Thread; 00126 PAGED_CODE(); 00127 00128 /* Lock the Process */ 00129 if (!ExAcquireRundownProtection(&Process->RundownProtect)) 00130 { 00131 /* Process is terminating */ 00132 return STATUS_PROCESS_IS_TERMINATING; 00133 } 00134 00135 /* Get the first thread */ 00136 Thread = PsGetNextProcessThread(Process, NULL); 00137 while (Thread) 00138 { 00139 /* Resume it */ 00140 KeResumeThread(&Thread->Tcb); 00141 00142 /* Move to the next thread */ 00143 Thread = PsGetNextProcessThread(Process, Thread); 00144 } 00145 00146 /* Unlock the process */ 00147 ExReleaseRundownProtection(&Process->RundownProtect); 00148 return STATUS_SUCCESS; 00149 } 00150 00151 NTSTATUS 00152 NTAPI 00153 PsSuspendProcess(IN PEPROCESS Process) 00154 { 00155 PETHREAD Thread; 00156 PAGED_CODE(); 00157 00158 /* Lock the Process */ 00159 if (!ExAcquireRundownProtection(&Process->RundownProtect)) 00160 { 00161 /* Process is terminating */ 00162 return STATUS_PROCESS_IS_TERMINATING; 00163 } 00164 00165 /* Get the first thread */ 00166 Thread = PsGetNextProcessThread(Process, NULL); 00167 while (Thread) 00168 { 00169 /* Resume it */ 00170 PsSuspendThread(Thread, NULL); 00171 00172 /* Move to the next thread */ 00173 Thread = PsGetNextProcessThread(Process, Thread); 00174 } 00175 00176 /* Unlock the process */ 00177 ExReleaseRundownProtection(&Process->RundownProtect); 00178 return STATUS_SUCCESS; 00179 } 00180 00181 /* PUBLIC FUNCTIONS **********************************************************/ 00182 00183 /* 00184 * @implemented 00185 */ 00186 NTSTATUS 00187 NTAPI 00188 NtAlertThread(IN HANDLE ThreadHandle) 00189 { 00190 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00191 PETHREAD Thread; 00192 NTSTATUS Status; 00193 00194 /* Reference the Object */ 00195 Status = ObReferenceObjectByHandle(ThreadHandle, 00196 THREAD_SUSPEND_RESUME, 00197 PsThreadType, 00198 PreviousMode, 00199 (PVOID*)&Thread, 00200 NULL); 00201 if (NT_SUCCESS(Status)) 00202 { 00203 /* 00204 * Do an alert depending on the processor mode. If some kmode code wants to 00205 * enforce a umode alert it should call KeAlertThread() directly. If kmode 00206 * code wants to do a kmode alert it's sufficient to call it with Zw or just 00207 * use KeAlertThread() directly 00208 */ 00209 KeAlertThread(&Thread->Tcb, PreviousMode); 00210 00211 /* Dereference Object */ 00212 ObDereferenceObject(Thread); 00213 } 00214 00215 /* Return status */ 00216 return Status; 00217 } 00218 00219 NTSTATUS 00220 NTAPI 00221 NtAlertResumeThread(IN HANDLE ThreadHandle, 00222 OUT PULONG SuspendCount) 00223 { 00224 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00225 PETHREAD Thread; 00226 NTSTATUS Status; 00227 ULONG PreviousState; 00228 00229 /* Check if we came from user mode with a suspend count */ 00230 if ((SuspendCount) && (PreviousMode != KernelMode)) 00231 { 00232 /* Enter SEH for probing */ 00233 _SEH2_TRY 00234 { 00235 /* Probe the count */ 00236 ProbeForWriteUlong(SuspendCount); 00237 } 00238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00239 { 00240 /* Return the exception code */ 00241 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00242 } 00243 _SEH2_END; 00244 } 00245 00246 /* Reference the Object */ 00247 Status = ObReferenceObjectByHandle(ThreadHandle, 00248 THREAD_SUSPEND_RESUME, 00249 PsThreadType, 00250 PreviousMode, 00251 (PVOID*)&Thread, 00252 NULL); 00253 if (NT_SUCCESS(Status)) 00254 { 00255 /* Call the Kernel Function */ 00256 PreviousState = KeAlertResumeThread(&Thread->Tcb); 00257 00258 /* Dereference Object */ 00259 ObDereferenceObject(Thread); 00260 00261 /* Check if the caller gave a suspend count */ 00262 if (SuspendCount) 00263 { 00264 /* Enter SEH for write */ 00265 _SEH2_TRY 00266 { 00267 /* Write state back */ 00268 *SuspendCount = PreviousState; 00269 } 00270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00271 { 00272 /* Get exception code */ 00273 Status = _SEH2_GetExceptionCode(); 00274 } 00275 _SEH2_END; 00276 } 00277 } 00278 00279 /* Return status */ 00280 return Status; 00281 } 00282 00283 NTSTATUS 00284 NTAPI 00285 NtResumeThread(IN HANDLE ThreadHandle, 00286 OUT PULONG SuspendCount OPTIONAL) 00287 { 00288 PETHREAD Thread; 00289 ULONG Prev; 00290 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00291 NTSTATUS Status; 00292 PAGED_CODE(); 00293 00294 /* Check if caller gave a suspend count from user mode */ 00295 if ((SuspendCount) && (PreviousMode != KernelMode)) 00296 { 00297 /* Enter SEH for probing */ 00298 _SEH2_TRY 00299 { 00300 /* Probe the count */ 00301 ProbeForWriteUlong(SuspendCount); 00302 } 00303 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00304 { 00305 /* Return the exception code */ 00306 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00307 } 00308 _SEH2_END; 00309 } 00310 00311 /* Get the Thread Object */ 00312 Status = ObReferenceObjectByHandle(ThreadHandle, 00313 THREAD_SUSPEND_RESUME, 00314 PsThreadType, 00315 PreviousMode, 00316 (PVOID*)&Thread, 00317 NULL); 00318 if (!NT_SUCCESS(Status)) return Status; 00319 00320 /* Call the internal function */ 00321 Status = PsResumeThread(Thread, &Prev); 00322 00323 /* Check if the caller wanted the count back */ 00324 if (SuspendCount) 00325 { 00326 /* Enter SEH for write back */ 00327 _SEH2_TRY 00328 { 00329 /* Write the count */ 00330 *SuspendCount = Prev; 00331 } 00332 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00333 { 00334 /* Get the exception code */ 00335 Status = _SEH2_GetExceptionCode(); 00336 } 00337 _SEH2_END; 00338 } 00339 00340 /* Dereference and return */ 00341 ObDereferenceObject(Thread); 00342 return Status; 00343 } 00344 00345 NTSTATUS 00346 NTAPI 00347 NtSuspendThread(IN HANDLE ThreadHandle, 00348 OUT PULONG PreviousSuspendCount OPTIONAL) 00349 { 00350 PETHREAD Thread; 00351 ULONG Prev; 00352 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00353 NTSTATUS Status; 00354 PAGED_CODE(); 00355 00356 /* Check if caller gave a suspend count from user mode */ 00357 if ((PreviousSuspendCount) && (PreviousMode != KernelMode)) 00358 { 00359 /* Enter SEH for probing */ 00360 _SEH2_TRY 00361 { 00362 /* Probe the count */ 00363 ProbeForWriteUlong(PreviousSuspendCount); 00364 } 00365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00366 { 00367 /* Return the exception code */ 00368 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00369 } 00370 _SEH2_END; 00371 } 00372 00373 /* Get the Thread Object */ 00374 Status = ObReferenceObjectByHandle(ThreadHandle, 00375 THREAD_SUSPEND_RESUME, 00376 PsThreadType, 00377 PreviousMode, 00378 (PVOID*)&Thread, 00379 NULL); 00380 if (!NT_SUCCESS(Status)) return Status; 00381 00382 /* Call the internal function */ 00383 Status = PsSuspendThread(Thread, &Prev); 00384 ObDereferenceObject(Thread); 00385 if (!NT_SUCCESS(Status)) return Status; 00386 00387 /* Protect write with SEH */ 00388 _SEH2_TRY 00389 { 00390 /* Return the Previous Count */ 00391 if (PreviousSuspendCount) *PreviousSuspendCount = Prev; 00392 } 00393 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00394 { 00395 /* Get the exception code */ 00396 Status = _SEH2_GetExceptionCode(); 00397 } 00398 _SEH2_END; 00399 00400 /* Return */ 00401 return Status; 00402 } 00403 00404 NTSTATUS 00405 NTAPI 00406 NtSuspendProcess(IN HANDLE ProcessHandle) 00407 { 00408 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00409 PEPROCESS Process; 00410 NTSTATUS Status; 00411 PAGED_CODE(); 00412 00413 /* Reference the process */ 00414 Status = ObReferenceObjectByHandle(ProcessHandle, 00415 PROCESS_SUSPEND_RESUME, 00416 PsProcessType, 00417 PreviousMode, 00418 (PVOID*)&Process, 00419 NULL); 00420 if (NT_SUCCESS(Status)) 00421 { 00422 /* Call the internal function */ 00423 Status = PsSuspendProcess(Process); 00424 ObDereferenceObject(Process); 00425 } 00426 00427 /* Return status */ 00428 return Status; 00429 } 00430 00431 NTSTATUS 00432 NTAPI 00433 NtResumeProcess(IN HANDLE ProcessHandle) 00434 { 00435 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00436 PEPROCESS Process; 00437 NTSTATUS Status; 00438 PAGED_CODE(); 00439 00440 /* Reference the process */ 00441 Status = ObReferenceObjectByHandle(ProcessHandle, 00442 PROCESS_SUSPEND_RESUME, 00443 PsProcessType, 00444 PreviousMode, 00445 (PVOID*)&Process, 00446 NULL); 00447 if (NT_SUCCESS(Status)) 00448 { 00449 /* Call the internal function */ 00450 Status = PsResumeProcess(Process); 00451 ObDereferenceObject(Process); 00452 } 00453 00454 /* Return status */ 00455 return Status; 00456 } 00457 00458 NTSTATUS 00459 NTAPI 00460 NtTestAlert(VOID) 00461 { 00462 /* Check and Alert Thread if needed */ 00463 return KeTestAlertThread(ExGetPreviousMode()) ? 00464 STATUS_ALERTED : STATUS_SUCCESS; 00465 } 00466 00467 /*++ 00468 * @name NtQueueApcThread 00469 * NT4 00470 * 00471 * This routine is used to queue an APC from user-mode for the specified 00472 * thread. 00473 * 00474 * @param ThreadHandle 00475 * Handle to the Thread. 00476 * This handle must have THREAD_SET_CONTEXT privileges. 00477 * 00478 * @param ApcRoutine 00479 * Pointer to the APC Routine to call when the APC executes. 00480 * 00481 * @param NormalContext 00482 * Pointer to the context to send to the Normal Routine. 00483 * 00484 * @param SystemArgument[1-2] 00485 * Pointer to a set of two parameters that contain untyped data. 00486 * 00487 * @return STATUS_SUCCESS or failure cute from associated calls. 00488 * 00489 * @remarks The thread must enter an alertable wait before the APC will be 00490 * delivered. 00491 * 00492 *--*/ 00493 NTSTATUS 00494 NTAPI 00495 NtQueueApcThread(IN HANDLE ThreadHandle, 00496 IN PKNORMAL_ROUTINE ApcRoutine, 00497 IN PVOID NormalContext, 00498 IN PVOID SystemArgument1, 00499 IN PVOID SystemArgument2) 00500 { 00501 PKAPC Apc; 00502 PETHREAD Thread; 00503 NTSTATUS Status = STATUS_SUCCESS; 00504 PAGED_CODE(); 00505 00506 /* Get ETHREAD from Handle */ 00507 Status = ObReferenceObjectByHandle(ThreadHandle, 00508 THREAD_SET_CONTEXT, 00509 PsThreadType, 00510 ExGetPreviousMode(), 00511 (PVOID)&Thread, 00512 NULL); 00513 if (!NT_SUCCESS(Status)) return Status; 00514 00515 /* Check if this is a System Thread */ 00516 if (Thread->SystemThread) 00517 { 00518 /* Fail */ 00519 Status = STATUS_INVALID_HANDLE; 00520 goto Quit; 00521 } 00522 00523 /* Allocate an APC */ 00524 Apc = ExAllocatePoolWithTag(NonPagedPool | 00525 POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, 00526 sizeof(KAPC), 00527 TAG_PS_APC); 00528 if (!Apc) 00529 { 00530 /* Fail */ 00531 Status = STATUS_NO_MEMORY; 00532 goto Quit; 00533 } 00534 00535 /* Initialize the APC */ 00536 KeInitializeApc(Apc, 00537 &Thread->Tcb, 00538 OriginalApcEnvironment, 00539 PspQueueApcSpecialApc, 00540 NULL, 00541 ApcRoutine, 00542 UserMode, 00543 NormalContext); 00544 00545 /* Queue it */ 00546 if (!KeInsertQueueApc(Apc, 00547 SystemArgument1, 00548 SystemArgument2, 00549 IO_NO_INCREMENT)) 00550 { 00551 /* We failed, free it */ 00552 ExFreePool(Apc); 00553 Status = STATUS_UNSUCCESSFUL; 00554 } 00555 00556 /* Dereference Thread and Return */ 00557 Quit: 00558 ObDereferenceObject(Thread); 00559 return Status; 00560 } 00561 00562 /* EOF */ Generated on Sun May 27 2012 04:20:29 for ReactOS by
1.7.6.1
|