2.2.XP系统中系统调用的内核入口KiSystemService函数的实现

2.2.XP系统中系统调用的内核入口KiSystemService函数的实现

2.2.XP系统中系统调用的内核入口KiSystemService函数的实现


_KiSystemService

改代码是汇编,xp的核心代码C写的,部分汇编写的。

_KiSystemService        proc

        ENTER_SYSCALL   kss_a, kss_t    ; set up trap frame and save state

?FpoValue = 0

;
; (eax) = Service number
; (edx) = Callers stack pointer
; (esi) = Current thread address
;
; All other registers have been saved and are free.
;
; Check if the service number within valid range
;

_KiSystemServiceRepeat:
        mov     edi, eax                ; copy system service number
        shr     edi, SERVICE_TABLE_SHIFT ; isolate service table number
        and     edi, SERVICE_TABLE_MASK ;
        mov     ecx, edi                ; save service table number
        add     edi, [esi]+ThServiceTable ; compute service descriptor address
        mov     ebx, eax                ; save system service number
        and     eax, SERVICE_NUMBER_MASK ; isolate service table offset

;
; If the specified system service number is not within range, then attempt
; to convert the thread to a GUI thread and retry the service dispatch.
;

        cmp     eax, [edi]+SdLimit      ; check if valid service
        jae     Kss_ErrorHandler        ; if ae, try to convert to GUI thread

;
; If the service is a GUI service and the GDI user batch queue is not empty,
; then call the appropriate service to flush the user batch.
;

        cmp     ecx, SERVICE_TABLE_TEST ; test if GUI service
        jne     short Kss40             ; if ne, not GUI service
        mov     ecx, PCR[PcTeb]         ; get current thread TEB address
        xor     ebx, ebx                ; get number of batched GDI calls

KiSystemServiceAccessTeb:
        or      ebx, [ecx]+TbGdiBatchCount ; may cause an inpage exception

        jz      short Kss40             ; if z, no batched calls
        push    edx                     ; save address of user arguments
        push    eax                     ; save service number
        call    [_KeGdiFlushUserBatch]  ; flush GDI user batch
        pop     eax                     ; restore service number
        pop     edx                     ; restore address of user arguments

;
; The arguments are passed on the stack. Therefore they always need to get
; copied since additional space has been allocated on the stack for the
; machine state frame.  Note that we don't check for the zero argument case -
; copy is always done regardless of the number of arguments because the
; zero argument case is very rare.
;

Kss40:  inc     dword ptr PCR[PcPrcbData+PbSystemCalls] ; system calls

if DBG
        mov     ecx, [edi]+SdCount      ; get count table address
        jecxz   Kss45                   ; if zero, table not specified
        inc     dword ptr [ecx+eax*4]   ; increment service count
Kss45:  push    dword ptr [esi]+ThApcStateIndex ; (ebp-4)
        push    dword ptr [esi]+ThKernelApcDisable ; (ebp-8)

        ;
        ; work around errata 19 which can in some cases cause an
        ; extra dword to be moved in the rep movsd below. In the DBG
        ; build, this will usually case a bugcheck 1 where ebp-8 is no longer
        ; the kernel apc disable count
        ;

        sub     esp,4


?FpoValue = ?FpoValue+3
endif

FPOFRAME ?FpoValue, 0

        mov     esi, edx                ; (esi)->User arguments
        mov     ebx, [edi]+SdNumber     ; get argument table address
        xor     ecx, ecx
        mov     cl, byte ptr [ebx+eax]  ; (ecx) = argument size
        mov     edi, [edi]+SdBase       ; get service table address
        mov     ebx, [edi+eax*4]        ; (ebx)-> service routine
        sub     esp, ecx                ; allocate space for arguments
        shr     ecx, 2                  ; (ecx) = number of argument DWORDs
        mov     edi, esp                ; (es:edi)->location to receive 1st arg
        cmp     esi, _MmUserProbeAddress ; check if user address
        jae     kss80                   ; if ae, then not user address

KiSystemServiceCopyArguments:
        rep     movsd                   ; copy the arguments to top of stack.
                                        ; Since we usually copy more than 3
                                        ; arguments.  rep movsd is faster than
                                        ; mov instructions.
if DBG
;
; Check for user mode call into system at elevated IRQL.
;

        test    byte ptr [ebp]+TsSegCs,MODE_MASK
        jz      short kss50a                  ; kernel mode, skip test
        stdCall _KeGetCurrentIrql
        or      al, al                  ; bogus irql, go bugcheck
        jnz     kss100
kss50a:

        test    _MmInjectUserInpageErrors, 2
        jz      short @f
        stdCall _MmTrimProcessMemory, <0>
        jmp     short kssdoit
@@:

        mov     eax,PCR[PcPrcbData+PbCurrentThread]
        mov     eax,[eax]+ThApcState+AsProcess
        test    dword ptr [eax]+PrFlags,0100000h ; is this a inpage-err process?
        je      short @f
        stdCall _MmTrimProcessMemory, <0>
@@:
endif

;
; Make actual call to system service
;
kssdoit:
        CAPSTARTX <_KiSystemService,ebx>
        call    ebx                     ; call system service
        CAPENDX <_KiSystemService>

kss60:

if DBG
        mov     ecx,PCR[PcPrcbData+PbCurrentThread] ; (ecx)-> Current Thread

;
; Check for return to user mode at elevated IRQL.
;
        test    byte ptr [ebp]+TsSegCs,MODE_MASK
        jz      short kss50b
        mov     esi, eax
        stdCall _KeGetCurrentIrql
        or      al, al
        jnz     kss100                  ; bogus irql, go bugcheck
        mov     eax, esi
kss50b:

;
; Check that APC state has not changed
;
        mov     edx, [ebp-4]
        cmp     dl, [ecx]+ThApcStateIndex
        jne     kss120

        mov     edx, [ebp-8]
        cmp     edx, [ecx]+ThKernelApcDisable
        jne     kss120

endif

kss61:

;
; Upon return, (eax)= status code
;

        mov     esp, ebp                ; deallocate stack space for arguments

;
; Restore old trap frame address from the current trap frame.
;

kss70:  mov     ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
        mov     edx, [ebp].TsEdx        ; restore previous trap frame address
        mov     [ecx].ThTrapFrame, edx  ;

;
;   System service's private version of KiExceptionExit
;   (Also used by KiDebugService)
;
;   Check for pending APC interrupts, if found, dispatch to them
;   (saving eax in frame first).
;
        public  _KiServiceExit
_KiServiceExit:

        cli                                         ; disable interrupts
        DISPATCH_USER_APC   ebp, ReturnCurrentEax

;
; Exit from SystemService
;

        EXIT_ALL    NoRestoreSegs, NoRestoreVolatile

;
; The address of the argument list is not a user address. If the previous mode
; is user, then return an access violation as the status of the system service.
; Otherwise, copy the argument list and execute the system service.
;

kss80:  test    byte ptr [ebp].TsSegCs, MODE_MASK ; test previous mode
        jz      KiSystemServiceCopyArguments ; if z, previous mode kernel
        mov     eax, STATUS_ACCESS_VIOLATION ; set service status
        jmp     kss60                   ;

;++
;
;   _KiServiceExit2 - same as _KiServiceExit BUT the full trap_frame
;       context is restored
;
;--
        public  _KiServiceExit2
_KiServiceExit2:

        cli                             ; disable interrupts
        DISPATCH_USER_APC   ebp

;
; Exit from SystemService
;

        EXIT_ALL                            ; RestoreAll




if DBG
kss100: push    PCR[PcIrql]                 ; put bogus value on stack for dbg
?FpoValue = ?FpoValue + 1
FPOFRAME ?FpoValue, 0
        mov     byte ptr PCR[PcIrql],0      ; avoid recursive trap
        cli

;
; IRQL_GT_ZERO_AT_SYSTEM_SERVICE Returning to usermode at elevated IRQL.
;
; KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
;              System Call Handler (address of system routine),
;              Irql,
;              0,
;              0,
;              );
;
        stdCall   _KeBugCheckEx,<IRQL_GT_ZERO_AT_SYSTEM_SERVICE, ebx, eax, 0, 0>

;
; APC_INDEX_MISMATCH This is probably caused by the system call entering
; critical regions and not leaving them.   This is fatal.   Include as
; much information in the bugcheck as possible.
;
; KeBugCheckEx(APC_INDEX_MISMATCH,
;              System Call Handler (address of system routine),
;              Thread->ApcStateIndex << 8 | Saved ApcStateIndex,
;              Thread->KernelApcDisable,
;              Saved KernelApcDisable
;              );
;

kss120: mov       eax, [ebp]-4
        mov       ah,  [ecx]+ThApcStateIndex
        stdCall   _KeBugCheckEx,<APC_INDEX_MISMATCH, ebx, eax, [ecx]+ThKernelApcDisable, dword ptr [ebp]-8>

endif
        ret

;
; If the sysenter instruction was executed in 16 bit mode, generate
; an error rather than trying to process the system call.   There is
; no way to return to the correct code in user mode.
;

Kfsc90:
        push    0                           ; save VX86 Es, Ds, Fs, Gs
        push    0
        push    0
        push    0

        push    01bh                        ; save transition CS
        push    0                           ; can't know user esp
        push    EFLAGS_INTERRUPT_MASK+EFLAGS_V86_MASK+2h; eflags with VX86 set
        push    01bh                        ; CS
        push    0                           ; don't know original EIP
        jmp     _KiTrap06                   ; turn exception into illegal op.

_KiSystemService endp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值