windows-nt/Source/XPSP1/NT/base/ntos/rtl/i386/userdisp.asm
2020-09-26 16:20:57 +08:00

324 lines
8.7 KiB
NASM

title "User Mode Dispatcher Code"
;++
;
; Copyright (c) 1989 Microsoft Corporation
;
; Module Name:
;
; userdisp.asm
;
; Abstract:
;
; The module contains procedures to do user mode dispatching
; ("trampolining") of user apcs and user exceptions.
;
; Author:
;
; Bryan M Willman (bryanwi) 31-Aug-90
;
; Environment:
;
; User mode.
;
; Revision History:
;
;--
.386p
.xlist
include ks386.inc
include callconv.inc ; calling convention macros
.list
ifndef WX86_i386
EXTRNP _ZwCallbackReturn,3
endif
EXTRNP _ZwContinue,2
EXTRNP _RtlDispatchException,2
EXTRNP _RtlRaiseStatus,1
EXTRNP _ZwRaiseException,3
EXTRNP _RtlRaiseException,1
;
; Exception record size definition.
;
ExceptionRecordSize = (ErNumberParameters + 4 + 3) AND 0fffffffcH ;
page ,132
_TEXT SEGMENT DWORD PUBLIC 'CODE'
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
ifndef WX86_i386
page
subttl "User APC Dispatcher"
;++
;
; VOID
; KiUserApcDispatcher (
; IN PKNORMAL_ROUTINE NormalRoutine,
; IN PVOID NormalContext,
; IN PVOID SystemArgument1,
; IN PVOID SystemArgument2,
; IN CONTEXT ContinueContext
; )
;
; Routine Description:
;
; This routine is entered on return from kernel mode to deliver an APC
; in user mode. The context frame for this routine was built when the
; APC interrupt was processed and contains the entire machine state of
; the current thread. The specified APC routine is called and then the
; machine state is restored and execution is continued.
;
; Arguments:
;
; NormalRoutine - Supplies that address of the function that is to be called.
;
; NormalContext] - Supplies the normal context parameter that was specified
; when the APC was initialized.
;
; SystemArgument1 - Supplies the first argument that was provied by the
; executive when the APC was queued.
;
; SystemArgument2 - Supplies the second argument that was provided by
; the executive when the APC was queued.
;
; ContinueContext - Context record to pass to Continue call.
;
;
; Return Value:
;
; None.
;
;--
cPublicProc _KiUserApcDispatcher ,5
lea edi, [esp+16] ; (edi)->context frame
pop eax ; (eax)->specified function
call eax ; call the specified function
; 1 - set alert argument true
; ebp - addr of context frame
; execute system service to continue
stdCall _ZwContinue, <edi, 1>
stdENDP _KiUserApcDispatcher
page
subttl "User Callback Dispatcher"
;++
;
; VOID
; KiUserCallbackDispatcher (
; IN ULONG ApiNumber,
; IN PVOID InputBuffer,
; IN ULONG INputLength
; )
;
; Routine Description:
;
; This routine is entered on a callout from kernel mode to execute a
; user mode callback function. All arguments for this function have
; been placed on the stack.
;
; Arguments:
;
; ApiNumber - Supplies the API number of the callback function that is
; executed.
;
; InputBuffer - Supplies a pointer to the input buffer.
;
; InputLength - Supplies the input buffer length.
;
; Return Value:
;
; This function returns to kernel mode.
;
;--
cPublicProc _KiUserCallbackDispatcher, 3
.FPO (0, 0, 0, 0, 0, 0)
add esp,4 ; skip over return address
pop edx ; get address of callback function
; get peb pointer from teb
mov eax,fs:[PcTeb]
mov eax,[eax].TebPeb
mov eax,[eax].PebKernelCallbackTable ; get address of callback table
call [eax+edx*4] ; call specified function
;
; If a return from the callback function occurs, then the output buffer
; address and length are returned as NULL.
;
xor ecx,ecx ; clear output buffer address
ifdef BUILD_WOW6432
stdCall _ZwCallbackReturn, <ecx, ecx, eax>
else
xor edx,edx ; clear output buffer length
int 02bH ; return from callback
endif
int 3 ; break if return occurs
stdENDP _KiUserCallbackDispatcher
endif ;; ndef WX86_i386
page
subttl "User Exception Dispatcher"
;++
;
; VOID
; KiUserExceptionDispatcher (
; IN PEXCEPTION_RECORD ExceptionRecord,
; IN PCONTEXT ContextRecord
; )
;
; Routine Description:
;
; This routine is entered on return from kernel mode to dispatch a user
; mode exception. If a frame based handler handles the exception, then
; the execution is continued. Else last chance processing is performed.
;
; NOTE: This procedure is not called, but rather dispatched to.
; It depends on there not being a return address on the stack
; (assumption w.r.t. argument offsets.)
;
; Arguments:
;
; ExceptionRecord (esp+0) - Supplies a pointer to an exception record.
;
; ContextRecord (esp+4) - Supplies a pointer to a context frame.
;
; Return Value:
;
; None.
;
;--
cPublicProc _KiUserExceptionDispatcher ,2
.FPO (0, 2, 0, 0, 0, 0)
mov ecx, [esp+4] ; (ecx)->context record
mov ebx, [esp] ; (ebx)->exception record
; attempt to dispatch the exception
stdCall _RtlDispatchException, <ebx, ecx>
;
; If the return status is TRUE, then the exception was handled and execution
; should be continued with the NtContinue service in case the context was
; changed. If the return statusn is FALSE, then the exception was not handled
; and ZwRaiseException is called to perform last chance exception processing.
;
or al,al
je short kued10
;
; Continue execution.
;
pop ebx ; (ebx)->exception record
pop ecx ; (ecx)->context record
; continue execution
stdCall _ZwContinue, <ecx, 0>
jmp short kued20 ; join common code
;
; Last chance processing.
;
; (esp+0) = ExceptionRecord
; (esp+4) = ContextRecord
;
kued10: pop ebx ; (ebx)->exception record
pop ecx ; (ecx)->context record
; ecx - context record
; ebx - exception record
; perform last chance processiong
stdCall _ZwRaiseException, <ebx, ecx, 0>
;
; Common code for nonsuccessful completion of the continue or raiseexception
; services. Use the return status as the exception code, set noncontinuable
; exception and attempt to raise another exception. Note the stack grows
; and eventually this loop will end.
;
.FPO(0, 0, 0, 0, 0, 0)
kued20: add esp, -ExceptionRecordSize ; allocate stack space
mov [esp]+ErExceptionCode, eax ; set exception code
mov dword ptr [esp]+ErExceptionFlags, EXCEPTION_NONCONTINUABLE
mov [esp]+ErExceptionRecord,ebx ; set associated exception record
mov dword ptr [esp]+ErNumberParameters, 0
; set number of parameters
; esp - addr of exception record
stdCall _RtlRaiseException, <esp>
; never return
stdRET _KiUserExceptionDispatcher
stdENDP _KiUserExceptionDispatcher
page
subttl "Raise User Exception Dispatcher"
ifndef WX86_i386
;++
;
; NTSTATUS
; KiUserExceptionDispatcher (
; IN PVOID ReturnAddress
; IN NTSTATUS ExceptionCode
; )
;
; Routine Description:
;
; This routine is entered on return from kernel mode to raise a user
; mode exception.
;
; NOTE: This procedure is not called, but rather dispatched to.
;
; The exception code to be raised is passed in the TEB.
;
; Arguments:
;
; ExceptionCode (TEB->ExceptionCode) - Supplies the exception code to be raised
;
; Return Value:
;
; The exception code that was raised.
;
;--
cPublicProc _KiRaiseUserExceptionDispatcher
push ebp ; make the debugger happy
mov ebp, esp
sub esp, ExceptionRecordLength ; allocate exception record
mov [esp].ErExceptionAddress, eax ; set exception address
mov eax,fs:[PcTeb] ; get exception code to be raised
mov eax,[eax].TbExceptionCode ;
mov [esp].ErExceptionCode, eax ; store exception code
mov [esp].ErExceptionFlags, 0 ; set exception flags
mov [esp].ErExceptionRecord, 0 ; set exception record
mov [esp].ErNumberParameters, 0 ; set number of parameters
; raise the exception
stdCall _RtlRaiseException, <esp>
mov eax, [esp].ErExceptionCode
mov esp,ebp
pop ebp ; restore return code
ret
stdENDP _KiRaiseUserExceptionDispatcher
endif ;; ndef WX86_i386
_TEXT ENDS
END