3 * Copyright (C) 2000, 1999, 1998 David Welch <welch@cwcom.net>,
4 * Philip Susi <phreak@iag.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * PROJECT: ReactOS kernel
23 * FILE: ntoskrnl/ps/debug.c
24 * PURPOSE: Thread managment
25 * PROGRAMMER: David Welch (welch@mcmail.com)
28 * 12/10/99: Phillip Susi: Thread priorities, and APC work
34 * All of the routines that manipulate the thread queue synchronize on
39 /* INCLUDES ****************************************************************/
41 #include <ddk/ntddk.h>
42 #include <internal/ke.h>
43 #include <internal/ob.h>
45 #include <internal/ps.h>
46 #include <internal/ob.h>
47 #include <internal/safe.h>
50 #include <internal/debug.h>
52 /* FUNCTIONS ***************************************************************/
55 KeContextToTrapFrame(PCONTEXT Context,
56 PKTRAP_FRAME TrapFrame)
58 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
60 TrapFrame->Esp = Context->Esp;
61 TrapFrame->Ss = Context->SegSs;
62 TrapFrame->Cs = Context->SegCs;
63 TrapFrame->Eip = Context->Eip;
64 TrapFrame->Eflags = Context->EFlags;
65 TrapFrame->Ebp = Context->Ebp;
67 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
69 TrapFrame->Eax = Context->Eax;
70 TrapFrame->Ebx = Context->Ebx;
71 TrapFrame->Ecx = Context->Ecx;
73 * Edx is used in the TrapFrame to hold the old trap frame pointer
74 * so we don't want to overwrite it here
76 /* TrapFrame->Edx = Context->Edx; */
77 TrapFrame->Esi = Context->Esi;
78 TrapFrame->Edi = Context->Edi;
80 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
82 TrapFrame->Ds = Context->SegDs;
83 TrapFrame->Es = Context->SegEs;
84 TrapFrame->Fs = Context->SegFs;
85 TrapFrame->Gs = Context->SegGs;
87 if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
93 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
102 KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
105 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
107 Context->SegSs = TrapFrame->Ss;
108 Context->Esp = TrapFrame->Esp;
109 Context->SegCs = TrapFrame->Cs;
110 Context->Eip = TrapFrame->Eip;
111 Context->EFlags = TrapFrame->Eflags;
112 Context->Ebp = TrapFrame->Ebp;
114 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
116 Context->Eax = TrapFrame->Eax;
117 Context->Ebx = TrapFrame->Ebx;
118 Context->Ecx = TrapFrame->Ecx;
120 * NOTE: In the trap frame which is built on entry to a system
121 * call TrapFrame->Edx will actually hold the address of the
122 * previous TrapFrame. I don't believe leaking this information
123 * has security implications. Also EDX holds the address of the
124 * arguments to the system call in progress so it isn't of much
125 * interest to the debugger.
127 Context->Edx = TrapFrame->Edx;
128 Context->Esi = TrapFrame->Esi;
129 Context->Edi = TrapFrame->Edi;
131 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
133 Context->SegDs = TrapFrame->Ds;
134 Context->SegEs = TrapFrame->Es;
135 Context->SegFs = TrapFrame->Fs;
136 Context->SegGs = TrapFrame->Gs;
138 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
141 * FIXME: Implement this case
144 if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
147 * FIXME: Implement this case
151 if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
154 * FIXME: Investigate this
161 KeGetSetContextRundownRoutine(PKAPC Apc)
166 Event = (PKEVENT)Apc->SystemArgument1;
167 Status = (PNTSTATUS)Apc->SystemArgument2;
168 (*Status) = STATUS_THREAD_IS_TERMINATING;
169 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
173 KeGetContextKernelRoutine(PKAPC Apc,
174 PKNORMAL_ROUTINE* NormalRoutine,
175 PVOID* NormalContext,
176 PVOID* SystemArgument1,
177 PVOID* SystemArgument2)
179 * FUNCTION: This routine is called by an APC sent by NtGetContextThread to
180 * copy the context of a thread into a buffer.
187 Context = (PCONTEXT)(*NormalContext);
188 Event = (PKEVENT)(*SystemArgument1);
189 Status = (PNTSTATUS)(*SystemArgument2);
191 KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
193 *Status = STATUS_SUCCESS;
194 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
198 NtGetContextThread(IN HANDLE ThreadHandle,
199 OUT PCONTEXT UnsafeContext)
208 Status = MmCopyFromCaller(&Context, UnsafeContext, sizeof(CONTEXT));
209 if (! NT_SUCCESS(Status))
213 Status = ObReferenceObjectByHandle(ThreadHandle,
219 if (! NT_SUCCESS(Status))
223 if (Thread == PsGetCurrentThread())
226 * I don't know if trying to get your own context makes much
227 * sense but we can handle it more efficently.
230 KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context);
231 Status = STATUS_SUCCESS;
235 KeInitializeEvent(&Event,
238 AStatus = STATUS_SUCCESS;
240 KeInitializeApc(&Apc,
242 OriginalApcEnvironment,
243 KeGetContextKernelRoutine,
244 KeGetSetContextRundownRoutine,
248 if (!KeInsertQueueApc(&Apc,
253 Status = STATUS_THREAD_IS_TERMINATING;
257 Status = KeWaitForSingleObject(&Event,
262 if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
268 if (NT_SUCCESS(Status))
270 Status = MmCopyToCaller(UnsafeContext, &Context, sizeof(Context));
273 ObDereferenceObject(Thread);
278 KeSetContextKernelRoutine(PKAPC Apc,
279 PKNORMAL_ROUTINE* NormalRoutine,
280 PVOID* NormalContext,
281 PVOID* SystemArgument1,
282 PVOID* SystemArgument2)
284 * FUNCTION: This routine is called by an APC sent by NtSetContextThread to
285 * set the context of a thread from a buffer.
292 Context = (PCONTEXT)(*NormalContext);
293 Event = (PKEVENT)(*SystemArgument1);
294 Status = (PNTSTATUS)(*SystemArgument2);
296 KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
298 *Status = STATUS_SUCCESS;
299 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
303 NtSetContextThread(IN HANDLE ThreadHandle,
304 IN PCONTEXT UnsafeContext)
313 Status = MmCopyFromCaller(&Context, UnsafeContext, sizeof(CONTEXT));
314 if (! NT_SUCCESS(Status))
318 Status = ObReferenceObjectByHandle(ThreadHandle,
324 if (!NT_SUCCESS(Status))
329 if (Thread == PsGetCurrentThread())
332 * I don't know if trying to set your own context makes much
333 * sense but we can handle it more efficently.
336 KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame);
337 Status = STATUS_SUCCESS;
341 KeInitializeEvent(&Event,
344 AStatus = STATUS_SUCCESS;
346 KeInitializeApc(&Apc,
348 OriginalApcEnvironment,
349 KeSetContextKernelRoutine,
350 KeGetSetContextRundownRoutine,
354 if (!KeInsertQueueApc(&Apc,
359 Status = STATUS_THREAD_IS_TERMINATING;
363 Status = KeWaitForSingleObject(&Event,
368 if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
375 ObDereferenceObject(Thread);