mirror of
https://github.com/reactos/reactos.git
synced 2024-12-26 17:14:41 +00:00
(Hopefully) fix (parts of) terribly broken NtSet/GetContextThread functions ;-)
If we have a test for this anywhere, it must be reaaally broken! Thanks to Alex and KJK for helping! svn path=/trunk/; revision=18964
This commit is contained in:
parent
de1acafe9a
commit
cc0933a118
1 changed files with 29 additions and 16 deletions
|
@ -23,6 +23,7 @@ typedef struct _GET_SET_CTX_CONTEXT {
|
||||||
KEVENT Event;
|
KEVENT Event;
|
||||||
CONTEXT Context;
|
CONTEXT Context;
|
||||||
KPROCESSOR_MODE Mode;
|
KPROCESSOR_MODE Mode;
|
||||||
|
NTSTATUS Status;
|
||||||
} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
|
} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,9 +45,11 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
|
||||||
PKEVENT Event;
|
PKEVENT Event;
|
||||||
PCONTEXT Context;
|
PCONTEXT Context;
|
||||||
KPROCESSOR_MODE Mode;
|
KPROCESSOR_MODE Mode;
|
||||||
PETHREAD Thread;
|
|
||||||
PKTRAP_FRAME TrapFrame;
|
PKTRAP_FRAME TrapFrame;
|
||||||
|
|
||||||
|
TrapFrame = (PKTRAP_FRAME)((ULONG_PTR)KeGetCurrentThread()->InitialStack -
|
||||||
|
sizeof (FX_SAVE_AREA) - sizeof (KTRAP_FRAME));
|
||||||
|
|
||||||
/* Get the Context Structure */
|
/* Get the Context Structure */
|
||||||
GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
|
GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
|
||||||
Context = &GetSetContext->Context;
|
Context = &GetSetContext->Context;
|
||||||
|
@ -54,20 +57,21 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
|
||||||
Mode = GetSetContext->Mode;
|
Mode = GetSetContext->Mode;
|
||||||
Thread = SystemArgument2;
|
Thread = SystemArgument2;
|
||||||
|
|
||||||
/* Get trap frame */
|
if (TrapFrame->Cs == KERNEL_CS && Mode != KernelMode)
|
||||||
TrapFrame = (PKTRAP_FRAME)((ULONG_PTR)Thread->Tcb.InitialStack -
|
|
||||||
sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA));
|
|
||||||
|
|
||||||
/* Check if it's a set or get */
|
|
||||||
if (SystemArgument1)
|
|
||||||
{
|
{
|
||||||
/* Get the Context */
|
GetSetContext->Status = STATUS_ACCESS_DENIED;
|
||||||
KeTrapFrameToContext(TrapFrame, NULL, Context);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Set the Context */
|
/* Check if it's a set or get */
|
||||||
KeContextToTrapFrame(Context, NULL, TrapFrame, Mode);
|
if (*SystemArgument1) {
|
||||||
|
/* Get the Context */
|
||||||
|
KeTrapFrameToContext(TrapFrame, NULL, Context);
|
||||||
|
} else {
|
||||||
|
/* Set the Context */
|
||||||
|
KeContextToTrapFrame(Context, NULL, TrapFrame, Mode);
|
||||||
|
}
|
||||||
|
GetSetContext->Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify the Native API that we are done */
|
/* Notify the Native API that we are done */
|
||||||
|
@ -77,7 +81,7 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
STDCALL
|
STDCALL
|
||||||
NtGetContextThread(IN HANDLE ThreadHandle,
|
NtGetContextThread(IN HANDLE ThreadHandle,
|
||||||
OUT PCONTEXT ThreadContext)
|
IN OUT PCONTEXT ThreadContext)
|
||||||
{
|
{
|
||||||
PETHREAD Thread;
|
PETHREAD Thread;
|
||||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||||
|
@ -94,6 +98,8 @@ NtGetContextThread(IN HANDLE ThreadHandle,
|
||||||
ProbeForWrite(ThreadContext,
|
ProbeForWrite(ThreadContext,
|
||||||
sizeof(CONTEXT),
|
sizeof(CONTEXT),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
|
GetSetContext.Context = *ThreadContext;
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
} _SEH_HANDLE {
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
@ -159,6 +165,8 @@ NtGetContextThread(IN HANDLE ThreadHandle,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Status = GetSetContext.Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +175,6 @@ NtGetContextThread(IN HANDLE ThreadHandle,
|
||||||
|
|
||||||
/* Check for success and return the Context */
|
/* Check for success and return the Context */
|
||||||
if(NT_SUCCESS(Status)) {
|
if(NT_SUCCESS(Status)) {
|
||||||
|
|
||||||
_SEH_TRY {
|
_SEH_TRY {
|
||||||
|
|
||||||
*ThreadContext = GetSetContext.Context;
|
*ThreadContext = GetSetContext.Context;
|
||||||
|
@ -231,13 +238,17 @@ NtSetContextThread(IN HANDLE ThreadHandle,
|
||||||
if(Thread == PsGetCurrentThread()) {
|
if(Thread == PsGetCurrentThread()) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I don't know if trying to get your own context makes much
|
* I don't know if trying to set your own context makes much
|
||||||
* sense but we can handle it more efficently.
|
* sense but we can handle it more efficently.
|
||||||
*/
|
*/
|
||||||
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame, PreviousMode);
|
KeContextToTrapFrame(ThreadContext, NULL, Thread->Tcb.TrapFrame, PreviousMode);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
/* Copy context into GetSetContext if not already done */
|
||||||
|
if(PreviousMode == KernelMode)
|
||||||
|
GetSetContext.Context = *ThreadContext;
|
||||||
|
|
||||||
/* Use an APC... Initialize the Event */
|
/* Use an APC... Initialize the Event */
|
||||||
KeInitializeEvent(&GetSetContext.Event,
|
KeInitializeEvent(&GetSetContext.Event,
|
||||||
NotificationEvent,
|
NotificationEvent,
|
||||||
|
@ -258,7 +269,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
|
||||||
|
|
||||||
/* Queue it as a Get APC */
|
/* Queue it as a Get APC */
|
||||||
if (!KeInsertQueueApc(&GetSetContext.Apc,
|
if (!KeInsertQueueApc(&GetSetContext.Apc,
|
||||||
NULL,
|
(PVOID)0,
|
||||||
NULL,
|
NULL,
|
||||||
IO_NO_INCREMENT)) {
|
IO_NO_INCREMENT)) {
|
||||||
|
|
||||||
|
@ -272,6 +283,8 @@ NtSetContextThread(IN HANDLE ThreadHandle,
|
||||||
KernelMode,
|
KernelMode,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
Status = GetSetContext.Status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue