Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

psctx.c File Reference

#include "psp.h"

Go to the source code of this file.

Functions

VOID PspQueueApcSpecialApc (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
NTSYSAPI NTSTATUS NTAPI NtQueueApcThread (IN HANDLE ThreadHandle, IN PPS_APC_ROUTINE ApcRoutine, IN PVOID ApcArgument1, IN PVOID ApcArgument2, IN PVOID ApcArgument3)
NTSTATUS NtGetContextThread (IN HANDLE ThreadHandle, IN OUT PCONTEXT ThreadContext)
NTSTATUS NtSetContextThread (IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)


Function Documentation

NTSTATUS NtGetContextThread IN HANDLE  ThreadHandle,
IN OUT PCONTEXT  ThreadContext
 

Definition at line 151 of file psctx.c.

References _GETSETCONTEXT::Apc, APC_LEVEL, _GETSETCONTEXT::Context, CONTEXT_EXTENDED_INTEGER, EXCEPTION_EXECUTE_HANDLER, Executive, FALSE, GETSETCONTEXT, IS_SYSTEM_THREAD, KeInitializeApc(), KeInitializeEvent, KeInsertQueueApc(), KeLowerIrql(), KeRaiseIrql(), KernelMode, KeWaitForSingleObject(), KPROCESSOR_MODE, _GETSETCONTEXT::Mode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _GETSETCONTEXT::OperationComplete, OriginalApcEnvironment, PAGED_CODE, ProbeAndReadUlong, ProbeForWrite(), PsGetCurrentThread, PspGetSetContextSpecialApc(), PsThreadType, Status, _KAPC::SystemArgument1, _KAPC::SystemArgument2, ThreadContext, and ThreadHandle.

Referenced by RtlRemoteCall().

00158 : 00159 00160 This function returns the usermode context of the specified thread. This 00161 function will fail if the specified thread is a system thread. It will 00162 return the wrong answer if the thread is a non-system thread that does 00163 not execute in user-mode. 00164 00165 Arguments: 00166 00167 ThreadHandle - Supplies an open handle to the thread object from 00168 which to retrieve context information. The handle 00169 must allow THREAD_GET_CONTEXT access to the thread. 00170 00171 ThreadContext - Supplies the address of a buffer that will receive 00172 the context of the specified thread. 00173 00174 Return Value: 00175 00176 None. 00177 00178 --*/ 00179 00180 { 00181 00182 ULONG Alignment; 00183 ULONG ContextFlags; 00184 GETSETCONTEXT ContextFrame; 00185 ULONG ContextLength; 00186 KIRQL Irql; 00187 KPROCESSOR_MODE Mode; 00188 NTSTATUS Status; 00189 PETHREAD Thread; 00190 00191 PAGED_CODE(); 00192 00193 // 00194 // Get previous mode and reference specified thread. 00195 // 00196 00197 Mode = KeGetPreviousMode(); 00198 Status = ObReferenceObjectByHandle(ThreadHandle, 00199 THREAD_GET_CONTEXT, 00200 PsThreadType, 00201 Mode, 00202 (PVOID *)&Thread, 00203 NULL); 00204 00205 // 00206 // If the reference was successful, the check if the specified thread 00207 // is a system thread. 00208 // 00209 00210 if (NT_SUCCESS(Status)) { 00211 00212 // 00213 // If the thread is not a system thread, then attempt to get the 00214 // context of the thread. 00215 // 00216 00217 if (IS_SYSTEM_THREAD(Thread) == FALSE) { 00218 00219 // 00220 // Attempt to get the context of the specified thread. 00221 // 00222 00223 try { 00224 00225 // 00226 // Set the default alignment, capture the context flags, 00227 // and set the default size of the context record. 00228 // 00229 00230 Alignment = CONTEXT_ALIGN; 00231 ContextFlags = ProbeAndReadUlong(&ThreadContext->ContextFlags); 00232 ContextLength = sizeof(CONTEXT); 00233 00234 #if defined(_X86_) 00235 // 00236 // CONTEXT_EXTENDED_REGISTERS is SET, then we want sizeof(CONTEXT) set above 00237 // otherwise (not set) we only want the old part of the context record. 00238 // 00239 if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS) != CONTEXT_EXTENDED_REGISTERS) { 00240 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00241 } 00242 #endif 00243 00244 #if defined(_MIPS_) 00245 00246 // 00247 // The following code is included for backward compatibility 00248 // with old code that does not understand extended context 00249 // records on MIPS systems. 00250 // 00251 00252 if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) { 00253 Alignment = sizeof(ULONG); 00254 ContextLength = FIELD_OFFSET(CONTEXT, ContextFlags) + 4; 00255 } 00256 00257 #endif 00258 00259 if (Mode != KernelMode) { 00260 ProbeForWrite(ThreadContext, ContextLength, Alignment); 00261 } 00262 00263 } except(EXCEPTION_EXECUTE_HANDLER) { 00264 Status = GetExceptionCode(); 00265 } 00266 00267 // 00268 // If an exception did not occur during the probe of the thread 00269 // context, then get the context of the target thread. 00270 // 00271 00272 if (NT_SUCCESS(Status)) { 00273 KeInitializeEvent(&ContextFrame.OperationComplete, 00274 NotificationEvent, 00275 FALSE); 00276 00277 ContextFrame.Context.ContextFlags = ContextFlags; 00278 00279 ContextFrame.Mode = Mode; 00280 if (Thread == PsGetCurrentThread()) { 00281 ContextFrame.Apc.SystemArgument1 = NULL; 00282 ContextFrame.Apc.SystemArgument2 = Thread; 00283 KeRaiseIrql(APC_LEVEL, &Irql); 00284 PspGetSetContextSpecialApc(&ContextFrame.Apc, 00285 NULL, 00286 NULL, 00287 &ContextFrame.Apc.SystemArgument1, 00288 &ContextFrame.Apc.SystemArgument2); 00289 00290 KeLowerIrql(Irql); 00291 00292 // 00293 // Move context to specfied context record. If an exception 00294 // occurs, then silently handle it and return success. 00295 // 00296 00297 try { 00298 RtlMoveMemory(ThreadContext, 00299 &ContextFrame.Context, 00300 ContextLength); 00301 00302 } except(EXCEPTION_EXECUTE_HANDLER) { 00303 } 00304 00305 } else { 00306 KeInitializeApc(&ContextFrame.Apc, 00307 &Thread->Tcb, 00308 OriginalApcEnvironment, 00309 PspGetSetContextSpecialApc, 00310 NULL, 00311 NULL, 00312 KernelMode, 00313 NULL); 00314 00315 if (!KeInsertQueueApc(&ContextFrame.Apc, NULL, Thread, 2)) { 00316 Status = STATUS_UNSUCCESSFUL; 00317 00318 } else { 00319 KeWaitForSingleObject(&ContextFrame.OperationComplete, 00320 Executive, 00321 KernelMode, 00322 FALSE, 00323 NULL); 00324 // 00325 // Move context to specfied context record. If an 00326 // exception occurs, then silently handle it and 00327 // return success. 00328 // 00329 00330 try { 00331 RtlMoveMemory(ThreadContext, 00332 &ContextFrame.Context, 00333 ContextLength); 00334 00335 } except(EXCEPTION_EXECUTE_HANDLER) { 00336 } 00337 } 00338 } 00339 } 00340 00341 } else { 00342 Status = STATUS_INVALID_HANDLE; 00343 } 00344 00345 ObDereferenceObject(Thread); 00346 } 00347 00348 return Status; 00349 }

NTSYSAPI NTSTATUS NTAPI NtQueueApcThread IN HANDLE  ThreadHandle,
IN PPS_APC_ROUTINE  ApcRoutine,
IN PVOID  ApcArgument1,
IN PVOID  ApcArgument2,
IN PVOID  ApcArgument3
 

Definition at line 56 of file psctx.c.

References ExAllocatePoolWithQuotaTag, ExFreePool(), IS_SYSTEM_THREAD, KeInitializeApc(), KeInsertQueueApc(), KPROCESSOR_MODE, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OriginalApcEnvironment, PAGED_CODE, PKNORMAL_ROUTINE, POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, PspQueueApcSpecialApc(), PsThreadType, ThreadHandle, and UserMode.

Referenced by RtlCreateTimer(), RtlDebugPrintTimes(), RtlDeleteTimer(), RtlDeleteTimerQueueEx(), RtlDeregisterWaitEx(), RtlpQueueIOWorkerRequest(), RtlpQueueWorkerRequest(), RtlpWaitForEvent(), RtlRegisterWait(), RtlThreadPoolCleanup(), and RtlUpdateTimer().

00066 : 00067 00068 This function is used to queue a user-mode APC to the specified thread. The APC 00069 will fire when the specified thread does an alertable wait 00070 00071 Arguments: 00072 00073 ThreadHandle - Supplies a handle to a thread object. The caller 00074 must have THREAD_SET_CONTEXT access to the thread. 00075 00076 ApcRoutine - Supplies the address of the APC routine to execute when the 00077 APC fires. 00078 00079 ApcArgument1 - Supplies the first PVOID passed to the APC 00080 00081 ApcArgument2 - Supplies the second PVOID passed to the APC 00082 00083 ApcArgument3 - Supplies the third PVOID passed to the APC 00084 00085 Return Value: 00086 00087 Returns an NT Status code indicating success or failure of the API 00088 00089 --*/ 00090 00091 { 00092 PETHREAD Thread; 00093 NTSTATUS st; 00094 KPROCESSOR_MODE Mode; 00095 KIRQL Irql; 00096 PKAPC Apc; 00097 00098 PAGED_CODE(); 00099 00100 Mode = KeGetPreviousMode(); 00101 00102 st = ObReferenceObjectByHandle( 00103 ThreadHandle, 00104 THREAD_SET_CONTEXT, 00105 PsThreadType, 00106 Mode, 00107 (PVOID *)&Thread, 00108 NULL 00109 ); 00110 00111 if ( NT_SUCCESS(st) ) { 00112 st = STATUS_SUCCESS; 00113 if ( IS_SYSTEM_THREAD(Thread) ) { 00114 st = STATUS_INVALID_HANDLE; 00115 } 00116 else { 00117 Apc = ExAllocatePoolWithQuotaTag( 00118 (NonPagedPool | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE), 00119 sizeof(*Apc), 00120 'pasP' 00121 ); 00122 00123 if ( !Apc ) { 00124 st = STATUS_NO_MEMORY; 00125 } 00126 else { 00127 KeInitializeApc( 00128 Apc, 00129 &Thread->Tcb, 00130 OriginalApcEnvironment, 00131 PspQueueApcSpecialApc, 00132 NULL, 00133 (PKNORMAL_ROUTINE)ApcRoutine, 00134 UserMode, 00135 ApcArgument1 00136 ); 00137 00138 if ( !KeInsertQueueApc(Apc,ApcArgument2,ApcArgument3,0) ) { 00139 ExFreePool(Apc); 00140 st = STATUS_UNSUCCESSFUL; 00141 } 00142 } 00143 } 00144 ObDereferenceObject(Thread); 00145 } 00146 00147 return st; 00148 }

NTSTATUS NtSetContextThread IN HANDLE  ThreadHandle,
IN PCONTEXT  ThreadContext
 

Definition at line 352 of file psctx.c.

References _GETSETCONTEXT::Apc, APC_LEVEL, _GETSETCONTEXT::Context, CONTEXT_EXTENDED_INTEGER, EXCEPTION_EXECUTE_HANDLER, Executive, FALSE, IS_SYSTEM_THREAD, KeInitializeApc(), KeInitializeEvent, KeInsertQueueApc(), KeLowerIrql(), KeRaiseIrql(), KernelMode, KeWaitForSingleObject(), KPROCESSOR_MODE, _GETSETCONTEXT::Mode, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _GETSETCONTEXT::OperationComplete, OriginalApcEnvironment, PAGED_CODE, ProbeAndReadUlong, ProbeForRead, PsGetCurrentThread, PspGetSetContextSpecialApc(), PsThreadType, Status, _KAPC::SystemArgument1, _KAPC::SystemArgument2, ThreadContext, and ThreadHandle.

Referenced by RtlRemoteCall().

00359 : 00360 00361 This function sets the usermode context of the specified thread. This 00362 function will fail if the specified thread is a system thread. It will 00363 return the wrong answer if the thread is a non-system thread that does 00364 not execute in user-mode. 00365 00366 Arguments: 00367 00368 ThreadHandle - Supplies an open handle to the thread object from 00369 which to retrieve context information. The handle 00370 must allow THREAD_SET_CONTEXT access to the thread. 00371 00372 ThreadContext - Supplies the address of a buffer that contains new 00373 context for the specified thread. 00374 00375 Return Value: 00376 00377 None. 00378 00379 --*/ 00380 00381 { 00382 00383 ULONG Alignment; 00384 ULONG ContextFlags; 00385 GETSETCONTEXT ContextFrame; 00386 ULONG ContextLength; 00387 KIRQL Irql; 00388 KPROCESSOR_MODE Mode; 00389 NTSTATUS Status; 00390 PETHREAD Thread; 00391 00392 PAGED_CODE(); 00393 00394 // 00395 // Get previous mode and reference specified thread. 00396 // 00397 00398 Mode = KeGetPreviousMode(); 00399 Status = ObReferenceObjectByHandle(ThreadHandle, 00400 THREAD_SET_CONTEXT, 00401 PsThreadType, 00402 Mode, 00403 (PVOID *)&Thread, 00404 NULL); 00405 00406 // 00407 // If the reference was successful, the check if the specified thread 00408 // is a system thread. 00409 // 00410 00411 if (NT_SUCCESS(Status)) { 00412 00413 // 00414 // If the thread is not a system thread, then attempt to get the 00415 // context of the thread. 00416 // 00417 00418 if (IS_SYSTEM_THREAD(Thread) == FALSE) { 00419 00420 // 00421 // Attempt to get the context of the specified thread. 00422 // 00423 00424 try { 00425 00426 // 00427 // Set the default alignment, capture the context flags, 00428 // and set the default size of the context record. 00429 // 00430 00431 Alignment = CONTEXT_ALIGN; 00432 ContextFlags = ProbeAndReadUlong(&ThreadContext->ContextFlags); 00433 ContextLength = sizeof(CONTEXT); 00434 00435 #if defined(_X86_) 00436 // 00437 // CONTEXT_EXTENDED_REGISTERS is SET, then we want sizeof(CONTEXT) set above 00438 // otherwise (not set) we only want the old part of the context record. 00439 // 00440 if ((ContextFlags & CONTEXT_EXTENDED_REGISTERS) != CONTEXT_EXTENDED_REGISTERS) { 00441 ContextLength = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00442 } 00443 #endif 00444 00445 #if defined(_MIPS_) 00446 00447 // 00448 // The following code is included for backward compatibility 00449 // with old code that does not understand extended context 00450 // records on MIPS systems. 00451 // 00452 00453 if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) { 00454 Alignment = sizeof(ULONG); 00455 ContextLength = FIELD_OFFSET(CONTEXT, ContextFlags) + 4; 00456 } 00457 00458 #endif 00459 00460 if (Mode != KernelMode) { 00461 ProbeForRead(ThreadContext, ContextLength, Alignment); 00462 } 00463 00464 RtlMoveMemory(&ContextFrame.Context, ThreadContext, ContextLength); 00465 00466 } except(EXCEPTION_EXECUTE_HANDLER) { 00467 Status = GetExceptionCode(); 00468 } 00469 00470 // 00471 // If an exception did not occur during the probe of the thread 00472 // context, then set the context of the target thread. 00473 // 00474 00475 if (NT_SUCCESS(Status)) { 00476 KeInitializeEvent(&ContextFrame.OperationComplete, 00477 NotificationEvent, 00478 FALSE); 00479 00480 ContextFrame.Context.ContextFlags = ContextFlags; 00481 00482 ContextFrame.Mode = Mode; 00483 if (Thread == PsGetCurrentThread()) { 00484 ContextFrame.Apc.SystemArgument1 = (PVOID)1; 00485 ContextFrame.Apc.SystemArgument2 = Thread; 00486 KeRaiseIrql(APC_LEVEL, &Irql); 00487 PspGetSetContextSpecialApc(&ContextFrame.Apc, 00488 NULL, 00489 NULL, 00490 &ContextFrame.Apc.SystemArgument1, 00491 &ContextFrame.Apc.SystemArgument2); 00492 00493 KeLowerIrql(Irql); 00494 00495 } else { 00496 KeInitializeApc(&ContextFrame.Apc, 00497 &Thread->Tcb, 00498 OriginalApcEnvironment, 00499 PspGetSetContextSpecialApc, 00500 NULL, 00501 NULL, 00502 KernelMode, 00503 NULL); 00504 00505 if (!KeInsertQueueApc(&ContextFrame.Apc, (PVOID)1, Thread, 2)) { 00506 Status = STATUS_UNSUCCESSFUL; 00507 00508 } else { 00509 KeWaitForSingleObject(&ContextFrame.OperationComplete, 00510 Executive, 00511 KernelMode, 00512 FALSE, 00513 NULL); 00514 } 00515 } 00516 } 00517 00518 } else { 00519 Status = STATUS_INVALID_HANDLE; 00520 } 00521 00522 ObDereferenceObject(Thread); 00523 } 00524 00525 return Status; 00526 } }

VOID PspQueueApcSpecialApc IN PKAPC  Apc,
IN PKNORMAL_ROUTINE NormalRoutine,
IN PVOID *  NormalContext,
IN PVOID *  SystemArgument1,
IN PVOID *  SystemArgument2
 

Definition at line 40 of file psctx.c.

References ExFreePool(), and PAGED_CODE.

Referenced by NtQueueApcThread().

00047 { 00048 PAGED_CODE(); 00049 00050 ExFreePool(Apc); 00051 }


Generated on Sat May 15 19:45:22 2004 for test by doxygen 1.3.7