All pastes #545775 Raw Edit

Stuff

public text v1 · immutable
·published 2007-06-06 21:21 UTC
rendered paste body
;++
;
; NTSTATUS
; NtCallbackReturn (
;    IN PVOID OutputBuffer OPTIONAL,
;    IN ULONG OutputLength,
;    IN NTSTATUS Status
;    )
;
; Routine Description:
;
;    This function returns from a user mode callout to the kernel mode
;    caller of the user mode callback function.
;
;    N.B. This service uses a nonstandard calling sequence.
;
; Arguments:
;
;    OutputBuffer (ecx) - Supplies an optional pointer to an output buffer.
;
;    OutputLength (edx) - Supplies the length of the output buffer.
;
;    Status (esp + 4) - Supplies the status value returned to the caller of
;        the callback function.
;
; Return Value:
;
;    If the callback return cannot be executed, then an error status is
;    returned. Otherwise, the specified callback status is returned to
;    the caller of the callback function.
;
;    N.B. This function returns to the function that called out to user
;         mode is a callout is currently active.
;
;--

align 16
        PUBLIC  _KiCallbackReturn
_KiCallbackReturn proc

        push    fs                      ; save segment register
        push    ecx                     ; save buffer address and return status
        push    eax                     ;
        mov     ecx,KGDT_R0_PCR         ; set PCR segment number
        mov     fs,cx                   ;
        mov     eax,PCR[PcPrcbData + PbCurrentThread] ; get current thread address
        mov     ecx,[eax].ThCallbackStack ; get callback stack address
        or      ecx,ecx                 ; check if callback active
        jz      _KiCbExit               ; if z, no callback active
        mov     edi,[esp] + 4           ; set output buffer address
        mov     esi,edx                 ; set output buffer length
        mov     ebp,[esp] + 0           ; set return status

;
; N.B. The following code is entered with:
;
;    eax - The address of the current thread.
;    ecx - The callback stack address.
;    edi - The output buffer address.
;    esi - The output buffer length.
;    ebp - The callback service status.
;
; Restore the trap frame and callback stack addresses,
; store the output buffer address and length, and set the service status.
;

        cld                             ; clear the direction flag
        mov     ebx,[ecx].CuOutBf       ; get address to store output buffer
        mov     [ebx],edi               ; store output buffer address
        mov     ebx,[ecx].CuOutLn       ; get address to store output length
        mov     [ebx],esi               ; store output buffer length
        mov     esi,PCR[PcInitialStack] ; get source NPX save area address
        mov     ebx,[ecx]               ; get previous initial stack address
        mov     [eax].ThInitialStack,ebx ; restore initial stack address
        sub     ebx,NPX_FRAME_LENGTH    ; compute destination NPX save area

; All we want to do is to copy ControlWord, StatusWord and TagWord from
; the source NPX save area. So we always copy first 3 dwords, irrespective
; of the fact whether the save was done using fxsave or fnsave.

        mov     edx,[esi].FpControlWord ; copy NPX state to previous frame
        mov     [ebx].FpControlWord,edx ;
        mov     edx,[esi].FpStatusWord  ;
        mov     [ebx].FpStatusWord,edx  ;
        mov     edx,[esi].FpTagWord     ;
        mov     [ebx].FpTagWord,edx     ;
        mov     edx,[esi].FpCr0NpxState ;
        mov     [ebx].FpCr0NpxState,edx ;
        mov     edx,PCR[PcTss]          ; get address of task switch segment
        mov     PCR[PcInitialStack],ebx ; restore stack check base address
        sub     ebx,TsV86Gs - TsHardwareSegSs ; bias for missing V86 fields
        mov     [edx].TssEsp0,ebx       ; restore kernel entry stack address
        mov     esp,ecx                 ; trim stack back to callback frame
        add     esp,4                   ;
        sti                             ; enable interrupts
        pop     [eax].ThTrapFrame       ; restore current trap frame address
        pop     [eax].ThCallbackStack   ; restore callback stack address
        mov     eax,ebp                 ; set callback service status

;
; Restore nonvolatile registers, clean call parameters from stack, and
; return to callback caller.
;

        pop     edi                     ; restore nonvolatile registers
        pop     esi                     ;
        pop     ebx                     ;
        pop     ebp                     ;
        pop     edx                     ; save return address
        add     esp,8                   ; remove parameters from stack
        jmp     edx                     ; return to callback caller

;
; Restore segment register, set systerm service status, and return.
;

_KiCbExit:                              ;
        add     esp, 2 * 4              ; remove saved registers from stack
        pop     fs                      ; restore segment register
        mov     eax,STATUS_NO_CALLBACK_ACTIVE ; set service status
        iretd                           ;

_KiCallbackReturn endp