mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Fix NtGetContextThread() and implement NtSetContextThread()
svn path=/trunk/; revision=4872
This commit is contained in:
parent
32f2d198df
commit
472ebde7ec
2 changed files with 218 additions and 91 deletions
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue