Fix NtGetContextThread() and implement NtSetContextThread()

svn path=/trunk/; revision=4872
This commit is contained in:
Gé van Geldorp 2003-06-07 19:13:43 +00:00
parent 32f2d198df
commit 472ebde7ec
2 changed files with 218 additions and 91 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: irq.c,v 1.30 2003/06/07 10:14:40 chorns Exp $ /* $Id: irq.c,v 1.31 2003/06/07 19:13:43 gvg Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/irq.c * FILE: ntoskrnl/ke/i386/irq.c
@ -270,14 +270,12 @@ typedef struct _KIRQ_TRAPFRAME
ULONG Eflags; ULONG Eflags;
} KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME; } KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME;
#ifdef DBG
VOID VOID
KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame, KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
PKTRAP_FRAME TrapFrame) PKTRAP_FRAME TrapFrame)
{ {
TrapFrame->Fs = IrqTrapFrame->Fs; TrapFrame->Fs = IrqTrapFrame->Fs;
TrapFrame->Fs = IrqTrapFrame->Es; TrapFrame->Es = IrqTrapFrame->Es;
TrapFrame->Ds = IrqTrapFrame->Ds; TrapFrame->Ds = IrqTrapFrame->Ds;
TrapFrame->Eax = IrqTrapFrame->Eax; TrapFrame->Eax = IrqTrapFrame->Eax;
TrapFrame->Ecx = IrqTrapFrame->Ecx; TrapFrame->Ecx = IrqTrapFrame->Ecx;
@ -292,7 +290,25 @@ KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
TrapFrame->Eflags = IrqTrapFrame->Eflags; TrapFrame->Eflags = IrqTrapFrame->Eflags;
} }
#endif VOID
KeTrapFrameToIRQTrapFrame(PKTRAP_FRAME TrapFrame,
PKIRQ_TRAPFRAME IrqTrapFrame)
{
IrqTrapFrame->Fs = TrapFrame->Fs;
IrqTrapFrame->Es = TrapFrame->Es;
IrqTrapFrame->Ds = TrapFrame->Ds;
IrqTrapFrame->Eax = TrapFrame->Eax;
IrqTrapFrame->Ecx = TrapFrame->Ecx;
IrqTrapFrame->Edx = TrapFrame->Edx;
IrqTrapFrame->Ebx = TrapFrame->Ebx;
IrqTrapFrame->Esp = TrapFrame->Esp;
IrqTrapFrame->Ebp = TrapFrame->Ebp;
IrqTrapFrame->Esi = TrapFrame->Esi;
IrqTrapFrame->Edi = TrapFrame->Edi;
IrqTrapFrame->Eip = TrapFrame->Eip;
IrqTrapFrame->Cs = TrapFrame->Cs;
IrqTrapFrame->Eflags = TrapFrame->Eflags;
}
#ifdef MP #ifdef MP
@ -449,6 +465,17 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
*/ */
{ {
KIRQL old_level; KIRQL old_level;
KTRAP_FRAME KernelTrapFrame;
PKTHREAD CurrentThread;
PKTRAP_FRAME OldTrapFrame;
CurrentThread = KeGetCurrentThread();
if (NULL != CurrentThread && NULL == CurrentThread->TrapFrame)
{
OldTrapFrame = CurrentThread->TrapFrame;
KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
CurrentThread->TrapFrame = &KernelTrapFrame;
}
/* /*
* At this point we have interrupts disabled, nothing has been done to * At this point we have interrupts disabled, nothing has been done to
@ -498,6 +525,13 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
*/ */
__asm__("cli\n\t"); __asm__("cli\n\t");
HalEndSystemInterrupt (old_level, 0); HalEndSystemInterrupt (old_level, 0);
assert(KeGetCurrentThread() == CurrentThread);
if (NULL != CurrentThread && CurrentThread->TrapFrame == &KernelTrapFrame)
{
KeTrapFrameToIRQTrapFrame(&KernelTrapFrame, Trapframe);
CurrentThread->TrapFrame = OldTrapFrame;
}
} }
#endif /* MP */ #endif /* MP */

View file

@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: debug.c,v 1.8 2003/06/05 23:36:35 gdalsnes Exp $ /* $Id: debug.c,v 1.9 2003/06/07 19:13:43 gvg Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/debug.c * FILE: ntoskrnl/ps/debug.c
@ -44,6 +44,7 @@
#include <string.h> #include <string.h>
#include <internal/ps.h> #include <internal/ps.h>
#include <internal/ob.h> #include <internal/ob.h>
#include <internal/safe.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
@ -157,15 +158,15 @@ KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
} }
VOID STDCALL VOID STDCALL
KeGetContextRundownRoutine(PKAPC Apc) KeGetSetContextRundownRoutine(PKAPC Apc)
{ {
PKEVENT Event; PKEVENT Event;
PNTSTATUS Status; PNTSTATUS Status;
Event = (PKEVENT)Apc->SystemArgument1; Event = (PKEVENT)Apc->SystemArgument1;
Status = (PNTSTATUS)Apc->SystemArgument2; Status = (PNTSTATUS)Apc->SystemArgument2;
(*Status) = STATUS_THREAD_IS_TERMINATING; (*Status) = STATUS_THREAD_IS_TERMINATING;
KeSetEvent(Event, IO_NO_INCREMENT, FALSE); KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
} }
VOID STDCALL VOID STDCALL
@ -179,97 +180,189 @@ KeGetContextKernelRoutine(PKAPC Apc,
* copy the context of a thread into a buffer. * copy the context of a thread into a buffer.
*/ */
{ {
PKEVENT Event; PKEVENT Event;
PCONTEXT Context; PCONTEXT Context;
PNTSTATUS Status; PNTSTATUS Status;
Context = (PCONTEXT)(*NormalContext); Context = (PCONTEXT)(*NormalContext);
Event = (PKEVENT)(*SystemArgument1); Event = (PKEVENT)(*SystemArgument1);
Status = (PNTSTATUS)(*SystemArgument2); Status = (PNTSTATUS)(*SystemArgument2);
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context); KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
*Status = STATUS_SUCCESS; *Status = STATUS_SUCCESS;
KeSetEvent(Event, IO_NO_INCREMENT, FALSE); KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
} }
NTSTATUS STDCALL NTSTATUS STDCALL
NtGetContextThread(IN HANDLE ThreadHandle, NtGetContextThread(IN HANDLE ThreadHandle,
OUT PCONTEXT Context) OUT PCONTEXT UnsafeContext)
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
CONTEXT Context;
KAPC Apc;
KEVENT Event;
NTSTATUS AStatus;
Status = ObReferenceObjectByHandle(ThreadHandle, Status = MmCopyFromCaller(&Context, UnsafeContext, sizeof(CONTEXT));
THREAD_GET_CONTEXT, if (! NT_SUCCESS(Status))
PsThreadType, {
UserMode, return Status;
(PVOID*)&Thread, }
NULL); Status = ObReferenceObjectByHandle(ThreadHandle,
if (!NT_SUCCESS(Status)) THREAD_GET_CONTEXT,
{ PsThreadType,
return(Status); UserMode,
} (PVOID*)&Thread,
if (Thread == PsGetCurrentThread()) NULL);
{ if (! NT_SUCCESS(Status))
/* {
* I don't know if trying to get your own context makes much return Status;
* sense but we can handle it more efficently. }
*/ if (Thread == PsGetCurrentThread())
{
/*
* I don't know if trying to get your own context makes much
* sense but we can handle it more efficently.
*/
KeTrapFrameToContext(Thread->Tcb.TrapFrame, Context); KeTrapFrameToContext(Thread->Tcb.TrapFrame, &Context);
ObDereferenceObject(Thread); Status = STATUS_SUCCESS;
return(STATUS_SUCCESS); }
} else
else {
{ KeInitializeEvent(&Event,
KAPC Apc; NotificationEvent,
KEVENT Event; FALSE);
NTSTATUS AStatus; AStatus = STATUS_SUCCESS;
CONTEXT KContext;
KContext.ContextFlags = Context->ContextFlags; KeInitializeApc(&Apc,
KeInitializeEvent(&Event, &Thread->Tcb,
NotificationEvent, OriginalApcEnvironment,
FALSE); KeGetContextKernelRoutine,
AStatus = STATUS_SUCCESS; KeGetSetContextRundownRoutine,
NULL,
KernelMode,
(PVOID)&Context);
KeInsertQueueApc(&Apc,
(PVOID)&Event,
(PVOID)&AStatus,
IO_NO_INCREMENT);
Status = KeWaitForSingleObject(&Event,
0,
UserMode,
FALSE,
NULL);
if (NT_SUCCESS(Status) && ! NT_SUCCESS(AStatus))
{
Status = AStatus;
}
}
KeInitializeApc(&Apc, if (NT_SUCCESS(Status))
&Thread->Tcb, {
OriginalApcEnvironment, Status = MmCopyToCaller(UnsafeContext, &Context, sizeof(Context));
KeGetContextKernelRoutine, }
KeGetContextRundownRoutine,
NULL, ObDereferenceObject(Thread);
KernelMode, return Status;
(PVOID)&KContext); }
KeInsertQueueApc(&Apc,
(PVOID)&Event, VOID STDCALL
(PVOID)&AStatus, KeSetContextKernelRoutine(PKAPC Apc,
IO_NO_INCREMENT); PKNORMAL_ROUTINE* NormalRoutine,
Status = KeWaitForSingleObject(&Event, PVOID* NormalContext,
0, PVOID* SystemArgument1,
UserMode, PVOID* SystemArgument2)
FALSE, /*
NULL); * FUNCTION: This routine is called by an APC sent by NtSetContextThread to
if (!NT_SUCCESS(Status)) * set the context of a thread from a buffer.
{ */
return(Status); {
} PKEVENT Event;
if (!NT_SUCCESS(AStatus)) PCONTEXT Context;
{ PNTSTATUS Status;
return(AStatus);
} Context = (PCONTEXT)(*NormalContext);
memcpy(Context, &KContext, sizeof(CONTEXT)); Event = (PKEVENT)(*SystemArgument1);
ObDereferenceObject(Thread); Status = (PNTSTATUS)(*SystemArgument2);
return(STATUS_SUCCESS);
} KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
*Status = STATUS_SUCCESS;
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
} }
NTSTATUS STDCALL NTSTATUS STDCALL
NtSetContextThread(IN HANDLE ThreadHandle, NtSetContextThread(IN HANDLE ThreadHandle,
IN PCONTEXT Context) IN PCONTEXT UnsafeContext)
{ {
UNIMPLEMENTED; PETHREAD Thread;
NTSTATUS Status;
KAPC Apc;
KEVENT Event;
NTSTATUS AStatus;
CONTEXT Context;
Status = MmCopyFromCaller(&Context, UnsafeContext, sizeof(CONTEXT));
if (! NT_SUCCESS(Status))
{
return Status;
}
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SET_CONTEXT,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
if (Thread == PsGetCurrentThread())
{
/*
* I don't know if trying to set your own context makes much
* sense but we can handle it more efficently.
*/
KeContextToTrapFrame(&Context, Thread->Tcb.TrapFrame);
Status = STATUS_SUCCESS;
}
else
{
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
AStatus = STATUS_SUCCESS;
KeInitializeApc(&Apc,
&Thread->Tcb,
OriginalApcEnvironment,
KeSetContextKernelRoutine,
KeGetSetContextRundownRoutine,
NULL,
KernelMode,
(PVOID)&Context);
KeInsertQueueApc(&Apc,
(PVOID)&Event,
(PVOID)&AStatus,
IO_NO_INCREMENT);
Status = KeWaitForSingleObject(&Event,
0,
UserMode,
FALSE,
NULL);
if (NT_SUCCESS(Status) && ! NT_SUCCESS(AStatus))
{
Status = AStatus;
}
}
ObDereferenceObject(Thread);
return Status;
} }
/* EOF */ /* EOF */