PsConvertToGuiThread函数调用前传

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