PsConvertToGuiThread函数调用前传
第一部分:位置
ch@chenghaodeiMac base % grep "Kss_ErrorHandler" -nr ./
.//ntos/ke/i386/trap.asm:1026:Kss_ErrorHandler:
.//ntos/ke/i386/trap.asm:1220: jae Kss_ErrorHandler ; if ae, try to convert to GUI thread
第二部分:
指定的系统服务号不在范围内。尝试转换为一个GUI线程。如果指定的系统服务不是基本服务,线程尚未转换为
GUI线程。
;
; The specified system service number is not within range. Attempt to
; convert the thread to a GUI thread if the specified system service is
; not a base service and the thread has not already been converted to a
; GUI thread.
;
Kss_ErrorHandler:
cmp ecx, SERVICE_TABLE_TEST ; test if GUI service
jne short Kss_LimitError ; if ne, not GUI service
push edx ; save argument registers
push ebx ;
stdcall _PsConvertToGuiThread ; attempt to convert to GUI thread
or eax, eax ; check if service was successful
pop eax ; restore argument registers
pop edx ;
mov ebp, esp ; reset trap frame address
mov [esi]+ThTrapFrame, ebp ; save address of trap frame
jz _KiSystemServiceRepeat ; if eq, successful conversion
;
; The conversion to a GUI thread failed. The correct return value is encoded
; in a byte table indexed by the service number that is at the end of the
; service address table. The encoding is as follows:
;
; 0 - return 0.
; -1 - return -1.
; 1 - return status code.
;
lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST ;
mov ecx, [edx]+SdLimit ; get service number limit
mov edx, [edx]+SdBase ; get service table base
lea edx, [edx][ecx*4] ; get ending service table address
and eax, SERVICE_NUMBER_MASK ; isolate service number
add edx, eax ; compute return value address
movsx eax, byte ptr [edx] ; get status byte
or eax, eax ; check for 0 or -1
jle Kss70 ; if le, return value set
Kss_LimitError: ;
mov eax, STATUS_INVALID_SYSTEM_SERVICE ; set return status
jmp kss70 ;
ifndef NT_UP
ENTER_DR_ASSIST kfce_a, kfce_t,NoAbiosAssist,NoV86Assist
endif
ENTER_DR_ASSIST kss_a, kss_t,NoAbiosAssist,NoV86Assist
;
; Fast System Call entry point
;
; At entry:
; EAX = service number
; EDX = Pointer to caller's arguments
; ECX = unused
; ESP = DPC stack for this processor
;
; Create a stack frame like a call to inner privilege then continue
; in KiSystemService.
;
;
; Normal entry is at KiFastCallEntry, not KiFastCallEntry2. Entry
; is via KiFastCallEntry2 if a double fault (trap08) occured and EIP
; was KiFastCallEntry. This happens if a single step exception occurs
; on the instruction following SYSENTER instruction because there is
; no kernel stack fot the debug exception (trap01) to run on.
;
; This is NOT a performance path.
PUBLIC _KiFastCallEntry2
_KiFastCallEntry2:
ifndef NT_UP
mov ecx, KGDT_R0_PCR
else
mov ecx, KGDT_R3_TEB OR RPL_MASK
endif
mov fs, ecx
mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
;
; Calculate initial stack pointer from thread initial stack.
; If this isn't the same as esp0 then we are a VX86 thread and we are rejected
;
mov ecx, [ecx].ThInitialStack
lea esp, [ecx-(NPX_FRAME_LENGTH + (TsV86Gs - TsHardwareSegSS))]
mov ecx, PCR[PcTss]
cmp esp, [ecx].TssEsp0
jne Kfsc90
; adjust return address in user mode to renable EFLAGS TF so
; single step is turned back on.
mov ecx, MM_SHARED_USER_DATA_VA+UsSystemCall+fscrOffset+1
jmp short Kfsc10
align 16
PUBLIC _KiFastCallEntry
_KiFastCallEntry proc
;
; Return to the instruction immediately following the sysenter
; instruction which is at a known location in the shared user
; data structure (this is so we can dynamically place the right
; code for the processor at system init).
;
ifndef NT_UP
mov ecx, KGDT_R0_PCR
mov fs, ecx
endif ;; NT_UP
mov ecx, PCR[PcPrcbData+PbCurrentThread] ; get current thread address
;
; Calculate initial stack pointer from thread initial stack.
; If this isn't the same as esp0 then we are a VX86 thread and we are rejected
;
mov ecx, [ecx].ThInitialStack
lea esp, [ecx-(NPX_FRAME_LENGTH + (TsV86Gs - TsHardwareSegSS))]
mov ecx, PCR[PcTss]
cmp esp, [ecx].TssEsp0
jne Kfsc90
;
; Set ecx to return address in user mode
;
mov ecx, MM_SHARED_USER_DATA_VA+UsSystemCall+fscrOffset
Kfsc10:
push KGDT_R3_DATA OR RPL_MASK ; Push user SS
push edx ; Push ESP
pushfd
push 2 ; Sanitize eflags
popfd ;
add edx, 8 ; (edx) -> arguments
or dword ptr [esp], EFLAGS_INTERRUPT_MASK ; Enable interrupts
push KGDT_R3_CODE OR RPL_MASK ; Push user CS
push ecx ; push return address
ifndef NT_UP
; For the MP case, FS is already loaded above
ENTER_SYSCALL kfce_a, kfce_t, NoFSLoad
jmp _KiSystemServiceRepeat
endif ;; NT_UP
_KiFastCallEntry endp
;
; General System service entrypoint
;
PUBLIC _KiSystemService
_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