Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendebug.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/debug.c 00005 * PURPOSE: Process Manager: Debugging Support (Set/Get Context) 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 #if DBG 00019 VOID 00020 NTAPI 00021 PspDumpThreads(BOOLEAN IncludeSystem) 00022 { 00023 PLIST_ENTRY CurrentThread, CurrentProcess; 00024 PEPROCESS Process; 00025 PETHREAD Thread; 00026 ULONG nThreads = 0; 00027 00028 /* Loop all Active Processes */ 00029 CurrentProcess = PsActiveProcessHead.Flink; 00030 while(CurrentProcess != &PsActiveProcessHead) 00031 { 00032 /* Get the process */ 00033 Process = CONTAINING_RECORD(CurrentProcess, EPROCESS, ActiveProcessLinks); 00034 00035 /* Skip the Initial Process if requested */ 00036 if((Process != PsInitialSystemProcess) || 00037 (Process == PsInitialSystemProcess && IncludeSystem)) 00038 { 00039 /* Loop all its threads */ 00040 CurrentThread = Process->ThreadListHead.Flink; 00041 while(CurrentThread != &Process->ThreadListHead) 00042 { 00043 00044 /* Get teh Thread */ 00045 Thread = CONTAINING_RECORD(CurrentThread, ETHREAD, ThreadListEntry); 00046 nThreads++; 00047 00048 /* Print the Info */ 00049 DbgPrint("State %d Affinity %08x Priority %d PID.TID %d.%d Name %.8s Stack: \n", 00050 Thread->Tcb.State, 00051 Thread->Tcb.Affinity, 00052 Thread->Tcb.Priority, 00053 Thread->Cid.UniqueProcess, 00054 Thread->Cid.UniqueThread, 00055 Thread->ThreadsProcess->ImageFileName); 00056 00057 /* Make sure it's not running */ 00058 if(Thread->Tcb.State == Ready || 00059 Thread->Tcb.State == Standby || 00060 Thread->Tcb.State == Waiting) 00061 { 00062 ULONG i = 0; 00063 PULONG Esp = (PULONG)Thread->Tcb.KernelStack; 00064 PULONG Ebp = (PULONG)Esp[4]; 00065 00066 /* Print EBP */ 00067 DbgPrint("Ebp 0x%.8X\n", Ebp); 00068 00069 /* Walk it */ 00070 while(Ebp != 0 && Ebp >= (PULONG)Thread->Tcb.StackLimit) 00071 { 00072 /* Print what's on the stack */ 00073 DbgPrint("%.8X %.8X%s", Ebp[0], Ebp[1], (i % 8) == 7 ? "\n" : " "); 00074 Ebp = (PULONG)Ebp[0]; 00075 i++; 00076 } 00077 00078 /* Print a new line if there's nothing */ 00079 if((i % 8) != 0) DbgPrint("\n"); 00080 } 00081 00082 /* Move to the next Thread */ 00083 CurrentThread = CurrentThread->Flink; 00084 } 00085 } 00086 00087 /* Move to the next Process */ 00088 CurrentProcess = CurrentProcess->Flink; 00089 } 00090 } 00091 #endif 00092 00093 /* PUBLIC FUNCTIONS **********************************************************/ 00094 00095 /* 00096 * @implemented 00097 */ 00098 NTSTATUS 00099 NTAPI 00100 PsGetContextThread(IN PETHREAD Thread, 00101 IN OUT PCONTEXT ThreadContext, 00102 IN KPROCESSOR_MODE PreviousMode) 00103 { 00104 GET_SET_CTX_CONTEXT GetSetContext; 00105 ULONG Size = 0, Flags = 0; 00106 NTSTATUS Status; 00107 00108 /* Enter SEH */ 00109 _SEH2_TRY 00110 { 00111 /* Set default ength */ 00112 Size = sizeof(CONTEXT); 00113 00114 /* Read the flags */ 00115 Flags = ProbeForReadUlong(&ThreadContext->ContextFlags); 00116 00117 #ifdef _M_IX86 00118 /* Check if the caller wanted extended registers */ 00119 if ((Flags & CONTEXT_EXTENDED_REGISTERS) != 00120 CONTEXT_EXTENDED_REGISTERS) 00121 { 00122 /* Cut them out of the size */ 00123 Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00124 } 00125 #endif 00126 00127 /* Check if we came from user mode */ 00128 if (PreviousMode != KernelMode) 00129 { 00130 /* Probe the context */ 00131 ProbeForWrite(ThreadContext, Size, sizeof(ULONG)); 00132 } 00133 } 00134 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00135 { 00136 /* Return the exception code */ 00137 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00138 } 00139 _SEH2_END; 00140 00141 /* Initialize the wait event */ 00142 KeInitializeEvent(&GetSetContext.Event, NotificationEvent, FALSE); 00143 00144 /* Set the flags and previous mode */ 00145 GetSetContext.Context.ContextFlags = Flags; 00146 GetSetContext.Mode = PreviousMode; 00147 00148 /* Check if we're running in the same thread */ 00149 if (Thread == PsGetCurrentThread()) 00150 { 00151 /* Setup APC parameters manually */ 00152 GetSetContext.Apc.SystemArgument1 = NULL; 00153 GetSetContext.Apc.SystemArgument2 = Thread; 00154 00155 /* Enter a guarded region to simulate APC_LEVEL */ 00156 KeEnterGuardedRegion(); 00157 00158 /* Manually call the APC */ 00159 PspGetOrSetContextKernelRoutine(&GetSetContext.Apc, 00160 NULL, 00161 NULL, 00162 &GetSetContext.Apc.SystemArgument1, 00163 &GetSetContext.Apc.SystemArgument2); 00164 00165 /* Leave the guarded region */ 00166 KeLeaveGuardedRegion(); 00167 00168 /* We are done */ 00169 Status = STATUS_SUCCESS; 00170 } 00171 else 00172 { 00173 /* Initialize the APC */ 00174 KeInitializeApc(&GetSetContext.Apc, 00175 &Thread->Tcb, 00176 OriginalApcEnvironment, 00177 PspGetOrSetContextKernelRoutine, 00178 NULL, 00179 NULL, 00180 KernelMode, 00181 NULL); 00182 00183 /* Queue it as a Get APC */ 00184 if (!KeInsertQueueApc(&GetSetContext.Apc, NULL, Thread, 2)) 00185 { 00186 /* It was already queued, so fail */ 00187 Status = STATUS_UNSUCCESSFUL; 00188 } 00189 else 00190 { 00191 /* Wait for the APC to complete */ 00192 Status = KeWaitForSingleObject(&GetSetContext.Event, 00193 0, 00194 KernelMode, 00195 FALSE, 00196 NULL); 00197 } 00198 } 00199 00200 _SEH2_TRY 00201 { 00202 /* Copy the context */ 00203 RtlCopyMemory(ThreadContext, &GetSetContext.Context, Size); 00204 } 00205 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00206 { 00207 /* Get the exception code */ 00208 Status = _SEH2_GetExceptionCode(); 00209 } 00210 _SEH2_END; 00211 00212 /* Return status */ 00213 return Status; 00214 } 00215 00216 /* 00217 * @implemented 00218 */ 00219 NTSTATUS 00220 NTAPI 00221 PsSetContextThread(IN PETHREAD Thread, 00222 IN OUT PCONTEXT ThreadContext, 00223 IN KPROCESSOR_MODE PreviousMode) 00224 { 00225 GET_SET_CTX_CONTEXT GetSetContext; 00226 ULONG Size = 0, Flags = 0; 00227 NTSTATUS Status; 00228 00229 /* Enter SEH */ 00230 _SEH2_TRY 00231 { 00232 /* Set default length */ 00233 Size = sizeof(CONTEXT); 00234 00235 /* Read the flags */ 00236 Flags = ProbeForReadUlong(&ThreadContext->ContextFlags); 00237 00238 #ifdef _M_IX86 00239 /* Check if the caller wanted extended registers */ 00240 if ((Flags & CONTEXT_EXTENDED_REGISTERS) != 00241 CONTEXT_EXTENDED_REGISTERS) 00242 { 00243 /* Cut them out of the size */ 00244 Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters); 00245 } 00246 #endif 00247 00248 /* Check if we came from user mode */ 00249 if (PreviousMode != KernelMode) 00250 { 00251 /* Probe the context */ 00252 ProbeForRead(ThreadContext, Size, sizeof(ULONG)); 00253 } 00254 00255 /* Copy the context */ 00256 RtlCopyMemory(&GetSetContext.Context, ThreadContext, Size); 00257 } 00258 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00259 { 00260 /* Return the exception code */ 00261 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00262 } 00263 _SEH2_END; 00264 00265 /* Initialize the wait event */ 00266 KeInitializeEvent(&GetSetContext.Event, NotificationEvent, FALSE); 00267 00268 /* Set the flags and previous mode */ 00269 GetSetContext.Context.ContextFlags = Flags; 00270 GetSetContext.Mode = PreviousMode; 00271 00272 /* Check if we're running in the same thread */ 00273 if (Thread == PsGetCurrentThread()) 00274 { 00275 /* Setup APC parameters manually */ 00276 GetSetContext.Apc.SystemArgument1 = UlongToPtr(1); 00277 GetSetContext.Apc.SystemArgument2 = Thread; 00278 00279 /* Enter a guarded region to simulate APC_LEVEL */ 00280 KeEnterGuardedRegion(); 00281 00282 /* Manually call the APC */ 00283 PspGetOrSetContextKernelRoutine(&GetSetContext.Apc, 00284 NULL, 00285 NULL, 00286 &GetSetContext.Apc.SystemArgument1, 00287 &GetSetContext.Apc.SystemArgument2); 00288 00289 /* Leave the guarded region */ 00290 KeLeaveGuardedRegion(); 00291 00292 /* We are done */ 00293 Status = STATUS_SUCCESS; 00294 } 00295 else 00296 { 00297 /* Initialize the APC */ 00298 KeInitializeApc(&GetSetContext.Apc, 00299 &Thread->Tcb, 00300 OriginalApcEnvironment, 00301 PspGetOrSetContextKernelRoutine, 00302 NULL, 00303 NULL, 00304 KernelMode, 00305 NULL); 00306 00307 /* Queue it as a Get APC */ 00308 if (!KeInsertQueueApc(&GetSetContext.Apc, UlongToPtr(1), Thread, 2)) 00309 { 00310 /* It was already queued, so fail */ 00311 Status = STATUS_UNSUCCESSFUL; 00312 } 00313 else 00314 { 00315 /* Wait for the APC to complete */ 00316 Status = KeWaitForSingleObject(&GetSetContext.Event, 00317 0, 00318 KernelMode, 00319 FALSE, 00320 NULL); 00321 } 00322 } 00323 00324 /* Return status */ 00325 return Status; 00326 } 00327 00328 NTSTATUS 00329 NTAPI 00330 NtGetContextThread(IN HANDLE ThreadHandle, 00331 IN OUT PCONTEXT ThreadContext) 00332 { 00333 PETHREAD Thread; 00334 NTSTATUS Status; 00335 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00336 PAGED_CODE(); 00337 00338 /* Get the Thread Object */ 00339 Status = ObReferenceObjectByHandle(ThreadHandle, 00340 THREAD_GET_CONTEXT, 00341 PsThreadType, 00342 PreviousMode, 00343 (PVOID*)&Thread, 00344 NULL); 00345 00346 if (!NT_SUCCESS(Status)) return Status; 00347 00348 /* Make sure it's not a system thread */ 00349 if (Thread->SystemThread) 00350 { 00351 /* Fail */ 00352 Status = STATUS_INVALID_HANDLE; 00353 } 00354 else 00355 { 00356 /* Call the kernel API */ 00357 Status = PsGetContextThread(Thread, ThreadContext, PreviousMode); 00358 } 00359 00360 /* Dereference it and return */ 00361 ObDereferenceObject(Thread); 00362 return Status; 00363 } 00364 00365 NTSTATUS 00366 NTAPI 00367 NtSetContextThread(IN HANDLE ThreadHandle, 00368 IN PCONTEXT ThreadContext) 00369 { 00370 PETHREAD Thread; 00371 NTSTATUS Status; 00372 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 00373 PAGED_CODE(); 00374 00375 /* Get the Thread Object */ 00376 Status = ObReferenceObjectByHandle(ThreadHandle, 00377 THREAD_SET_CONTEXT, 00378 PsThreadType, 00379 PreviousMode, 00380 (PVOID*)&Thread, 00381 NULL); 00382 00383 if (!NT_SUCCESS(Status)) return Status; 00384 00385 /* Make sure it's not a system thread */ 00386 if (Thread->SystemThread) 00387 { 00388 /* Fail */ 00389 Status = STATUS_INVALID_HANDLE; 00390 } 00391 else 00392 { 00393 /* Call the kernel API */ 00394 Status = PsSetContextThread(Thread, ThreadContext, PreviousMode); 00395 } 00396 00397 /* Dereference it and return */ 00398 ObDereferenceObject(Thread); 00399 return Status; 00400 } 00401 00402 /* EOF */ Generated on Sat May 26 2012 04:16:28 for ReactOS by
1.7.6.1
|