mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:56:00 +00:00
[NTOSKRNL]
Rewrite NtCallbackReturn in C svn path=/trunk/; revision=60709
This commit is contained in:
parent
3440678be4
commit
4385bb351d
3 changed files with 150 additions and 169 deletions
|
@ -1050,6 +1050,14 @@ KiCallUserMode(
|
||||||
IN PULONG OutputLength
|
IN PULONG OutputLength
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DECLSPEC_NORETURN
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
KiCallbackReturn(
|
||||||
|
IN PVOID Stack,
|
||||||
|
IN NTSTATUS Status
|
||||||
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
NTAPI
|
NTAPI
|
||||||
KiInitMachineDependent(VOID);
|
KiInitMachineDependent(VOID);
|
||||||
|
|
|
@ -351,5 +351,140 @@ KiUserModeCallout(PKCALLOUT_FRAME CalloutFrame)
|
||||||
KiServiceExit(CallbackTrapFrame, 0);
|
KiServiceExit(CallbackTrapFrame, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*++
|
||||||
|
* @name NtCallbackReturn
|
||||||
|
*
|
||||||
|
* The NtCallbackReturn routine returns to kernel mode after a user-mode
|
||||||
|
* callback was done through KeUserModeCallback. It uses the callback frame
|
||||||
|
* which was setup in order to return the information, restores the stack,
|
||||||
|
* and resumes execution where it was left off.
|
||||||
|
*
|
||||||
|
* @param Result
|
||||||
|
* Pointer to a caller-allocated buffer where the return data
|
||||||
|
* from the user-mode function is located.
|
||||||
|
*
|
||||||
|
* @param ResultLength
|
||||||
|
* Size of the Output Buffer described above.
|
||||||
|
*
|
||||||
|
* @param CallbackStatus
|
||||||
|
* Status code of the callback operation.
|
||||||
|
*
|
||||||
|
* @return Status code of the callback operation.
|
||||||
|
*
|
||||||
|
* @remark This call MUST be paired with KeUserModeCallback.
|
||||||
|
*
|
||||||
|
*--*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtCallbackReturn(
|
||||||
|
_In_ PVOID Result,
|
||||||
|
_In_ ULONG ResultLength,
|
||||||
|
_In_ NTSTATUS CallbackStatus)
|
||||||
|
{
|
||||||
|
PKTHREAD CurrentThread;
|
||||||
|
PKCALLOUT_FRAME CalloutFrame;
|
||||||
|
PKTRAP_FRAME CallbackTrapFrame, TrapFrame;
|
||||||
|
PFX_SAVE_AREA FxSaveArea, CbFxSaveArea;
|
||||||
|
ULONG Size;
|
||||||
|
PKPCR Pcr;
|
||||||
|
PKTSS Tss;
|
||||||
|
|
||||||
|
/* Get the current thread and make sure we have a callback stack */
|
||||||
|
CurrentThread = KeGetCurrentThread();
|
||||||
|
CalloutFrame = CurrentThread->CallbackStack;
|
||||||
|
if (CalloutFrame == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_NO_CALLBACK_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the trap frame */
|
||||||
|
CallbackTrapFrame = CurrentThread->TrapFrame;
|
||||||
|
|
||||||
|
/* Restore the exception list */
|
||||||
|
Pcr = KeGetPcr();
|
||||||
|
Pcr->NtTib.ExceptionList = CallbackTrapFrame->ExceptionList;
|
||||||
|
|
||||||
|
/* Store the results in the callback stack */
|
||||||
|
*((PVOID*)CalloutFrame->Result) = Result;
|
||||||
|
*((ULONG*)CalloutFrame->ResultLength) = ResultLength;
|
||||||
|
|
||||||
|
/* Disable interrupts for NPX save and stack switch */
|
||||||
|
_disable();
|
||||||
|
|
||||||
|
/* Set desination and origin NPX Frames */
|
||||||
|
CbFxSaveArea = (PVOID)((ULONG)CurrentThread->InitialStack - sizeof(FX_SAVE_AREA));
|
||||||
|
FxSaveArea = (PVOID)(CalloutFrame->InitialStack - sizeof(FX_SAVE_AREA));
|
||||||
|
|
||||||
|
/* Now copy back NPX State */
|
||||||
|
FxSaveArea->U.FnArea.ControlWord = CbFxSaveArea->U.FnArea.ControlWord;
|
||||||
|
FxSaveArea->U.FnArea.StatusWord = CbFxSaveArea->U.FnArea.StatusWord;
|
||||||
|
FxSaveArea->U.FnArea.TagWord = CbFxSaveArea->U.FnArea.TagWord;
|
||||||
|
FxSaveArea->U.FnArea.DataSelector = CbFxSaveArea->U.FnArea.DataSelector;
|
||||||
|
FxSaveArea->Cr0NpxState = CbFxSaveArea->Cr0NpxState;
|
||||||
|
|
||||||
|
/* Get the previous trap frame */
|
||||||
|
TrapFrame = (PKTRAP_FRAME)CalloutFrame->TrapFrame;
|
||||||
|
|
||||||
|
/* Check if we failed in user mode */
|
||||||
|
if (CallbackStatus == STATUS_CALLBACK_POP_STACK)
|
||||||
|
{
|
||||||
|
/* Check if we came from v86 mode */
|
||||||
|
if (CallbackTrapFrame->EFlags & EFLAGS_V86_MASK)
|
||||||
|
{
|
||||||
|
Size = sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, SegFs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Size = FIELD_OFFSET(KTRAP_FRAME, V86Es) - FIELD_OFFSET(KTRAP_FRAME, SegFs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy back part of the trap frame */
|
||||||
|
RtlCopyMemory(&TrapFrame->SegFs, &CallbackTrapFrame->SegFs, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear DR7 */
|
||||||
|
TrapFrame->Dr7 = 0;
|
||||||
|
|
||||||
|
/* Check if debugging was active */
|
||||||
|
if (CurrentThread->Header.DebugActive & 0xFF)
|
||||||
|
{
|
||||||
|
/* Copy debug registers data from it */
|
||||||
|
TrapFrame->Dr0 = CallbackTrapFrame->Dr0;
|
||||||
|
TrapFrame->Dr1 = CallbackTrapFrame->Dr1;
|
||||||
|
TrapFrame->Dr2 = CallbackTrapFrame->Dr2;
|
||||||
|
TrapFrame->Dr3 = CallbackTrapFrame->Dr3;
|
||||||
|
TrapFrame->Dr6 = CallbackTrapFrame->Dr6;
|
||||||
|
TrapFrame->Dr7 = CallbackTrapFrame->Dr7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get TSS */
|
||||||
|
Tss = Pcr->TSS;
|
||||||
|
|
||||||
|
/* Check for V86 mode */
|
||||||
|
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
|
||||||
|
{
|
||||||
|
/* Set new stack address in TSS (full trap frame) */
|
||||||
|
Tss->Esp0 = (ULONG_PTR)(TrapFrame + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set new stack address in TSS (non-V86 trap frame) */
|
||||||
|
Tss->Esp0 = (ULONG_PTR)&TrapFrame->V86Es;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the initial stack and restore it */
|
||||||
|
CurrentThread->InitialStack = (PVOID)CalloutFrame->InitialStack;
|
||||||
|
|
||||||
|
/* Restore the trap frame and the previous callback stack */
|
||||||
|
CurrentThread->TrapFrame = TrapFrame;
|
||||||
|
CurrentThread->CallbackStack = (PVOID)CalloutFrame->CallbackStack;
|
||||||
|
|
||||||
|
/* Bring interrupts back */
|
||||||
|
_enable();
|
||||||
|
|
||||||
|
/* Now switch back to the old stack */
|
||||||
|
KiCallbackReturn(&CalloutFrame->Edi, CallbackStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -76,184 +76,22 @@ _KiCallUserMode@8:
|
||||||
ret 8
|
ret 8
|
||||||
|
|
||||||
|
|
||||||
/*++
|
|
||||||
* @name NtCallbackReturn
|
|
||||||
*
|
|
||||||
* The NtCallbackReturn routine returns to kernel mode after a user-mode
|
|
||||||
* callback was done through KeUserModeCallback. It uses the callback frame
|
|
||||||
* which was setup in order to return the information, restores the stack,
|
|
||||||
* and resumes execution where it was left off.
|
|
||||||
*
|
|
||||||
* @param Result
|
|
||||||
* Pointer to a caller-allocated buffer where the return data
|
|
||||||
* from the user-mode function is located.
|
|
||||||
*
|
|
||||||
* @param ResultLength
|
|
||||||
* Size of the Output Buffer described above.
|
|
||||||
*
|
|
||||||
* @param CallbackStatus
|
|
||||||
* Status code of the callback operation.
|
|
||||||
*
|
|
||||||
* @return Status code of the callback operation.
|
|
||||||
*
|
|
||||||
* @remark This call MUST be paired with KeUserModeCallback.
|
|
||||||
*
|
|
||||||
*--*/
|
|
||||||
PUBLIC _NtCallbackReturn@12
|
|
||||||
_NtCallbackReturn@12:
|
|
||||||
|
|
||||||
/* Get the current thread and make sure we have a callback stack */
|
PUBLIC @KiCallbackReturn@8
|
||||||
mov eax, fs:[KPCR_CURRENT_THREAD]
|
@KiCallbackReturn@8:
|
||||||
mov ecx, [eax+KTHREAD_CALLBACK_STACK]
|
|
||||||
test ecx, ecx
|
|
||||||
jz NoStack
|
|
||||||
|
|
||||||
/* Get the trap frame */
|
/* Restore the stack */
|
||||||
mov ebx, [eax+KTHREAD_TRAP_FRAME]
|
mov esp, ecx
|
||||||
|
|
||||||
/* Restore the exception list */
|
|
||||||
mov edx, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
|
|
||||||
mov fs:[KPCR_EXCEPTION_LIST], edx
|
|
||||||
|
|
||||||
/* Get the result, the result length and the status */
|
|
||||||
mov edi, [esp+4]
|
|
||||||
mov esi, [esp+8]
|
|
||||||
mov ebp, [esp+12]
|
|
||||||
|
|
||||||
/* Store the results in the callback stack */
|
|
||||||
mov ebx, [ecx+CBSTACK_RESULT]
|
|
||||||
mov [ebx], edi
|
|
||||||
mov ebx, [ecx+CBSTACK_RESULT_LENGTH]
|
|
||||||
mov [ebx], esi
|
|
||||||
|
|
||||||
/* Get the previous stack */
|
|
||||||
mov ebx, [ecx]
|
|
||||||
|
|
||||||
/* Disable interrupts for NPX save and stack switch */
|
|
||||||
cli
|
|
||||||
|
|
||||||
/* Get the initial stack and restore it */
|
|
||||||
mov esi, [eax+KTHREAD_INITIAL_STACK]
|
|
||||||
mov [eax+KTHREAD_INITIAL_STACK], ebx
|
|
||||||
|
|
||||||
/* Set desination and origin NPX Frames */
|
|
||||||
sub esi, NPX_FRAME_LENGTH
|
|
||||||
sub ebx, NPX_FRAME_LENGTH
|
|
||||||
|
|
||||||
/* Copy NPX Data */
|
|
||||||
mov edx, [esi+FP_CONTROL_WORD]
|
|
||||||
mov [ebx+FP_CONTROL_WORD], edx
|
|
||||||
mov edx, [esi+FP_STATUS_WORD]
|
|
||||||
mov [ebx+FP_STATUS_WORD], edx
|
|
||||||
mov edx, [esi+FP_TAG_WORD]
|
|
||||||
mov [ebx+FP_TAG_WORD], edx
|
|
||||||
mov edx, [esi+FP_DATA_SELECTOR]
|
|
||||||
mov [ebx+FP_DATA_SELECTOR], edx
|
|
||||||
mov edx, [esi+FN_CR0_NPX_STATE]
|
|
||||||
mov [ebx+FN_CR0_NPX_STATE], edx
|
|
||||||
|
|
||||||
/* Check if we failed in user mode */
|
|
||||||
cmp ebp, STATUS_CALLBACK_POP_STACK
|
|
||||||
mov edi, [ecx+CBSTACK_TRAP_FRAME]
|
|
||||||
jz UserFault
|
|
||||||
|
|
||||||
CheckDebug:
|
|
||||||
|
|
||||||
/* Clear DR7 */
|
|
||||||
and dword ptr [edi+KTRAP_FRAME_DR7], 0
|
|
||||||
|
|
||||||
/* Check if debugging was active */
|
|
||||||
test byte ptr [eax+KTHREAD_DEBUG_ACTIVE], HEX(0FF)
|
|
||||||
jnz RestoreDebug
|
|
||||||
|
|
||||||
RestoreStack:
|
|
||||||
|
|
||||||
/* Get TSS */
|
|
||||||
mov edx, fs:[KPCR_TSS]
|
|
||||||
|
|
||||||
/* Restore stack pointer */
|
|
||||||
lea esp, [ecx+CBSTACK_CALLBACK_STACK]
|
|
||||||
|
|
||||||
/* Check if we were in V86 mode */
|
|
||||||
test dword ptr [edi+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
|
|
||||||
jnz V86Ret
|
|
||||||
sub ebx, 16
|
|
||||||
|
|
||||||
V86Ret:
|
|
||||||
/* Restore the ESP in TSS */
|
|
||||||
mov [edx+KTSS_ESP0], ebx
|
|
||||||
|
|
||||||
/* Restore the trap frame */
|
|
||||||
mov [eax+KTHREAD_TRAP_FRAME], edi
|
|
||||||
|
|
||||||
/* Bring interrupts back */
|
|
||||||
sti
|
|
||||||
|
|
||||||
/* Restore the callback stack*/
|
|
||||||
pop [eax+KTHREAD_CALLBACK_STACK]
|
|
||||||
|
|
||||||
/* Set status and return */
|
/* Set status and return */
|
||||||
mov eax, ebp
|
mov eax, edx
|
||||||
pop edi
|
pop edi
|
||||||
pop esi
|
pop esi
|
||||||
pop ebx
|
pop ebx
|
||||||
pop ebp
|
pop ebp
|
||||||
pop edx
|
|
||||||
|
|
||||||
/* Clean stack and jump back */
|
/* Clean stack and return */
|
||||||
add esp, 8
|
ret 8
|
||||||
jmp edx
|
|
||||||
|
|
||||||
UserFault:
|
|
||||||
/* Set size to copy */
|
|
||||||
mov ecx, (KTRAP_FRAME_V86_ES - KTRAP_FRAME_FS) / 4
|
|
||||||
|
|
||||||
/* Check if this was V86 mode */
|
|
||||||
mov esi, [eax+KTHREAD_TRAP_FRAME]
|
|
||||||
test dword ptr [esi+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
|
|
||||||
|
|
||||||
/* Save EDI and load destination */
|
|
||||||
mov edx, edi
|
|
||||||
lea edi, [edi+KTRAP_FRAME_FS]
|
|
||||||
jz NotV86
|
|
||||||
add ecx, 16 / 4
|
|
||||||
|
|
||||||
NotV86:
|
|
||||||
/* Set source and copy */
|
|
||||||
lea esi, [esi+KTRAP_FRAME_FS]
|
|
||||||
rep movsd
|
|
||||||
|
|
||||||
/* Restore ECX and ECX */
|
|
||||||
mov ecx, [eax+KTHREAD_CALLBACK_STACK]
|
|
||||||
mov edi, edx
|
|
||||||
jmp CheckDebug
|
|
||||||
|
|
||||||
RestoreDebug:
|
|
||||||
/* Get a pointer to thread's trap frame */
|
|
||||||
mov esi, [eax+KTHREAD_TRAP_FRAME]
|
|
||||||
|
|
||||||
/* Copy debug registers data from it */
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR0]
|
|
||||||
mov [edi+KTRAP_FRAME_DR0], edx
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR1]
|
|
||||||
mov [edi+KTRAP_FRAME_DR1], edx
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR2]
|
|
||||||
mov [edi+KTRAP_FRAME_DR2], edx
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR3]
|
|
||||||
mov [edi+KTRAP_FRAME_DR3], edx
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR6]
|
|
||||||
mov [edi+KTRAP_FRAME_DR6], edx
|
|
||||||
mov edx, [esi+KTRAP_FRAME_DR7]
|
|
||||||
mov [edi+KTRAP_FRAME_DR7], edx
|
|
||||||
|
|
||||||
/* Jump back */
|
|
||||||
jmp RestoreStack
|
|
||||||
|
|
||||||
NoStack:
|
|
||||||
|
|
||||||
/* Return failure */
|
|
||||||
mov eax, STATUS_NO_CALLBACK_ACTIVE
|
|
||||||
ret 12
|
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* @name KeSwitchKernelStack
|
* @name KeSwitchKernelStack
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue