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.
20 /* $Id: debug.c,v 1.12 2004/07/02 01:36:25 royce Exp $
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
;
72 TrapFrame
->Edx
= Context
->Edx
;
73 TrapFrame
->Esi
= Context
->Esi
;
74 TrapFrame
->Edi
= Context
->Edi
;
76 if ((Context
->ContextFlags
& CONTEXT_SEGMENTS
) == CONTEXT_SEGMENTS
)
78 TrapFrame
->Ds
= Context
->SegDs
;
79 TrapFrame
->Es
= Context
->SegEs
;
80 TrapFrame
->Fs
= Context
->SegFs
;
81 TrapFrame
->Gs
= Context
->SegGs
;
83 if ((Context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
)
89 if ((Context
->ContextFlags
& CONTEXT_DEBUG_REGISTERS
) == CONTEXT_DEBUG_REGISTERS
)
98 KeTrapFrameToContext(PKTRAP_FRAME TrapFrame
,
101 if ((Context
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
)
103 Context
->SegSs
= TrapFrame
->Ss
;
104 Context
->Esp
= TrapFrame
->Esp
;
105 Context
->SegCs
= TrapFrame
->Cs
;
106 Context
->Eip
= TrapFrame
->Eip
;
107 Context
->EFlags
= TrapFrame
->Eflags
;
108 Context
->Ebp
= TrapFrame
->Ebp
;
110 if ((Context
->ContextFlags
& CONTEXT_INTEGER
) == CONTEXT_INTEGER
)
112 Context
->Eax
= TrapFrame
->Eax
;
113 Context
->Ebx
= TrapFrame
->Ebx
;
114 Context
->Ecx
= TrapFrame
->Ecx
;
116 * NOTE: In the trap frame which is built on entry to a system
117 * call TrapFrame->Edx will actually hold the address of the
118 * previous TrapFrame. I don't believe leaking this information
119 * has security implications. Also EDX holds the address of the
120 * arguments to the system call in progress so it isn't of much
121 * interest to the debugger.
123 Context
->Edx
= TrapFrame
->Edx
;
124 Context
->Esi
= TrapFrame
->Esi
;
125 Context
->Edi
= TrapFrame
->Edi
;
127 if ((Context
->ContextFlags
& CONTEXT_SEGMENTS
) == CONTEXT_SEGMENTS
)
129 Context
->SegDs
= TrapFrame
->Ds
;
130 Context
->SegEs
= TrapFrame
->Es
;
131 Context
->SegFs
= TrapFrame
->Fs
;
132 Context
->SegGs
= TrapFrame
->Gs
;
134 if ((Context
->ContextFlags
& CONTEXT_DEBUG_REGISTERS
) == CONTEXT_DEBUG_REGISTERS
)
137 * FIXME: Implement this case
140 if ((Context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
)
143 * FIXME: Implement this case
147 if ((Context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
)
150 * FIXME: Investigate this
157 KeGetSetContextRundownRoutine(PKAPC Apc
)
162 Event
= (PKEVENT
)Apc
->SystemArgument1
;
163 Status
= (PNTSTATUS
)Apc
->SystemArgument2
;
164 (*Status
) = STATUS_THREAD_IS_TERMINATING
;
165 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
169 KeGetContextKernelRoutine(PKAPC Apc
,
170 PKNORMAL_ROUTINE
* NormalRoutine
,
171 PVOID
* NormalContext
,
172 PVOID
* SystemArgument1
,
173 PVOID
* SystemArgument2
)
175 * FUNCTION: This routine is called by an APC sent by NtGetContextThread to
176 * copy the context of a thread into a buffer.
183 Context
= (PCONTEXT
)(*NormalContext
);
184 Event
= (PKEVENT
)(*SystemArgument1
);
185 Status
= (PNTSTATUS
)(*SystemArgument2
);
187 KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame
, Context
);
189 *Status
= STATUS_SUCCESS
;
190 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
194 NtGetContextThread(IN HANDLE ThreadHandle
,
195 OUT PCONTEXT UnsafeContext
)
204 Status
= MmCopyFromCaller(&Context
, UnsafeContext
, sizeof(CONTEXT
));
205 if (! NT_SUCCESS(Status
))
209 Status
= ObReferenceObjectByHandle(ThreadHandle
,
215 if (! NT_SUCCESS(Status
))
219 if (Thread
== PsGetCurrentThread())
222 * I don't know if trying to get your own context makes much
223 * sense but we can handle it more efficently.
226 KeTrapFrameToContext(Thread
->Tcb
.TrapFrame
, &Context
);
227 Status
= STATUS_SUCCESS
;
231 KeInitializeEvent(&Event
,
234 AStatus
= STATUS_SUCCESS
;
236 KeInitializeApc(&Apc
,
238 OriginalApcEnvironment
,
239 KeGetContextKernelRoutine
,
240 KeGetSetContextRundownRoutine
,
244 if (!KeInsertQueueApc(&Apc
,
249 Status
= STATUS_THREAD_IS_TERMINATING
;
253 Status
= KeWaitForSingleObject(&Event
,
258 if (NT_SUCCESS(Status
) && !NT_SUCCESS(AStatus
))
264 if (NT_SUCCESS(Status
))
266 Status
= MmCopyToCaller(UnsafeContext
, &Context
, sizeof(Context
));
269 ObDereferenceObject(Thread
);
274 KeSetContextKernelRoutine(PKAPC Apc
,
275 PKNORMAL_ROUTINE
* NormalRoutine
,
276 PVOID
* NormalContext
,
277 PVOID
* SystemArgument1
,
278 PVOID
* SystemArgument2
)
280 * FUNCTION: This routine is called by an APC sent by NtSetContextThread to
281 * set the context of a thread from a buffer.
288 Context
= (PCONTEXT
)(*NormalContext
);
289 Event
= (PKEVENT
)(*SystemArgument1
);
290 Status
= (PNTSTATUS
)(*SystemArgument2
);
292 KeContextToTrapFrame(Context
, KeGetCurrentThread()->TrapFrame
);
294 *Status
= STATUS_SUCCESS
;
295 KeSetEvent(Event
, IO_NO_INCREMENT
, FALSE
);
299 NtSetContextThread(IN HANDLE ThreadHandle
,
300 IN PCONTEXT UnsafeContext
)
309 Status
= MmCopyFromCaller(&Context
, UnsafeContext
, sizeof(CONTEXT
));
310 if (! NT_SUCCESS(Status
))
314 Status
= ObReferenceObjectByHandle(ThreadHandle
,
320 if (!NT_SUCCESS(Status
))
325 if (Thread
== PsGetCurrentThread())
328 * I don't know if trying to set your own context makes much
329 * sense but we can handle it more efficently.
332 KeContextToTrapFrame(&Context
, Thread
->Tcb
.TrapFrame
);
333 Status
= STATUS_SUCCESS
;
337 KeInitializeEvent(&Event
,
340 AStatus
= STATUS_SUCCESS
;
342 KeInitializeApc(&Apc
,
344 OriginalApcEnvironment
,
345 KeSetContextKernelRoutine
,
346 KeGetSetContextRundownRoutine
,
350 if (!KeInsertQueueApc(&Apc
,
355 Status
= STATUS_THREAD_IS_TERMINATING
;
359 Status
= KeWaitForSingleObject(&Event
,
364 if (NT_SUCCESS(Status
) && !NT_SUCCESS(AStatus
))
371 ObDereferenceObject(Thread
);