PsConvertToGuiThread函数调用前传

2024-08-26 13:28

本文主要是介绍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

这篇关于PsConvertToGuiThread函数调用前传的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1108692

相关文章

AutoGen Function Call 函数调用解析(一)

目录 一、AutoGen Function Call 1.1 register_for_llm 注册调用 1.2 register_for_execution 注册执行 1.3 三种注册方法 1.3.1 函数定义和注册分开 1.3.2 定义函数时注册 1.3.3  register_function 函数注册 二、实例 本文主要对 AutoGen Function Call

PHP7扩展开发之函数调用

前言 在这篇文章中我们将演示如何在扩展中调用函数,和调用对象的方法。代码示例如下: <?phpclass demo {public function get_site_name ($prefix) {return $prefix."信海龙的博客\n";}}function get_site_url ($prefix) {return $prefix."www.bo56.com\n";}

Win32函数调用约定(Calling Convention)

平常我们在C#中使用DllImportAttribute引入函数时,不指明函数调用约定(CallingConvention)这个参数,也可以正常调用。如FindWindow函数 [DllImport("user32.dll", EntryPoint="FindWindow", SetLastError = true)]public static extern IntPtr FindWindow

C++中类的构造函数调用顺序

当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的 构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。 简而言之,对象是由“底层向上”开始构造的。因为,构造函数一开始构造时,总是 要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时, 如果无专门说明,就调用直接基类的默认构造函数。在对象析构时,其顺序正好相反。

不同驱动模块间的函数调用

linux层的处理 函数注册:     if (ECNT_REGISTER_SUCCESS != ecnt_register_hook(&phy_api_dispatch_hook_ops) ){                                                                   panic("Register hook function

函数调用的开销

函数调用的开销‌ 函数调用时,‌会产生一定的开销,‌主要包括:‌ 1.‌栈帧创建与销毁‌:‌ 调用函数时,‌需为函数局部变量、‌参数等创建栈帧。‌函数返回时,‌栈帧被销毁,‌恢复调用前的栈状态。‌ 2.‌参数传递‌:‌ 实参值需传递给形参,‌涉及数据复制或地址传递。‌对于大型数据结构,‌复制开销可能较大。‌ 3.‌返回值处理‌:‌ 函数执行完毕后,‌需将返回值传递给调用者。‌返回值传

ARM——结构体系(处理器工作模式,CPSR,立即数,汇编语言函数调用)

1、处理器工作模式          ARM有7个基本工作模式:User:非特权模式,大部分任务执行在这种模式FIQ:当一个高优先级(fast)中断产生时将会进入这种模式IRQ:当一个低优先级(normal)中断产生时将会进入这种模式Supervisor:当复位或软中断指令执行时将会进入这种模式Abort:当存取异常时将会进入这种模式Undef:当执行未定义指令时会进入这种模式Sy

python中的函数调用的传递方法

Python中的元素有可变和不可变之分,如整数、浮点数、字符串、元组都属于不可变元素。列表和字典属于可变的。    对于整数、浮点数的不可变:       “=”的作用是将对象引用过与内存中的对象进行绑定,既然整数是不可变的,那么怎么改变一个指向整数的变量的值的呢?  答案是直接在内存中创建一个新的整数,然后将变量引用与其绑定,这虽然本质上和其他高级语言不同,但是在使用上是有差 别的,但若将

请解释Java中的装箱拆箱操作对性能的影响,并讨论其最佳实践。什么是Java中的值传递和引用传递?它们在函数调用中的表现有何不同?

请解释Java中的装箱拆箱操作对性能的影响,并讨论其最佳实践。 在Java中,装箱(Boxing)和拆箱(Unboxing)操作是Java自动类型转换机制的一部分,主要用于基本数据类型(如int, double, char等)和它们对应的包装类(如Integer, Double, Character等)之间的转换。这种机制使得基本数据类型可以像对象一样被操作,但同时也带来了性能上的开销。 装箱

【C++八股题整理】内存布局、堆和栈、内存泄露、函数调用栈

C++八股题整理 内存布局C++中的内存分配情况堆和栈的内存有什么区别? 堆堆内存分配慢如何优化?内存池内存溢出和内存泄漏是什么?如何避免?内存碎片是什么?怎么解决? 栈为什么栈的访问效率比堆高?函数调用时栈的变化?函数的参数列表为什么从右往左入栈? 内存布局 C++中的内存分配情况 区域存储内容分配方式生命周期栈 (Stack)局部变量、局部常量、函数的参数和返回地址自