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, 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, 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, ; ; 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, 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, ; ; 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, ; 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, mov eax, [esp].ErExceptionCode mov esp,ebp pop ebp ; restore return code ret stdENDP _KiRaiseUserExceptionDispatcher endif ;; ndef WX86_i386 _TEXT ENDS END