您的位置:澳门新葡8455最新网站 > 澳门新葡8455最新网站 > hang的由来分析,Windows新闻机制要点

hang的由来分析,Windows新闻机制要点

发布时间:2019-10-07 20:57编辑:澳门新葡8455最新网站浏览(122)

    1. 问题

    1. 窗口进度 
    各种窗口会有三个叫做窗口进程的回调函数(WndProc),它包罗几个参数,分别为:窗口句柄(Window Handle),音讯ID(Message ID),和多少个新闻参数(wParam, lParam),当窗口收到消息时系统就能够调用此窗口进度来管理音讯。(所以叫回调函数)

    当在console中调用API ShellExecuteEx打开"test.iqy"文件时,发掘excel会hang住,console退出后excel才会响应,但直接双击"test.iqy"是绝非难题的,风趣的是其一情状唯有在xp发生,在win7上未曾这些主题素材。

    2 消息类型 
    1) 系统定义音信(System-Defined Messages)
     
    在SDK中优先定义好的音信,非客户定义的,其范围在[0x0000, 0x03ff]以内, 能够分成以下三类:
    1>窗口音信(Windows Message) 
    与窗口的在那之中运转有关,如创制窗口,绘制窗口,销毁窗口等。能够是日常的窗口,也足以是Dialog,控件等。
    如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL...
    2>命令新闻(Command Message):注意那类新闻通称为WM_COMMAND
    与拍卖顾客乞请有关, 如单击菜单项或工具栏或控件时, 就能够发出命令音讯。
    WM_COMMAND, LOWO奥迪Q5D(wParam)表示菜单项,工具栏按键或控件的ID。若是是控件, HIWO揽胜D(wParam)表示控件新闻类型
    3> 控件公告(Notify Message) 
    控件通告消息, 那是最灵敏的音信格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHD福特Explorer的指针。NMHD兰德纳瓦拉蕴含控件通告的内容, 能够自由增加。
    2) 程序定义音信(Application-Defined Messages) 
    客商自定义的信息, 对于其范围有如下规定:
    WM_USER: 0x0400-0x7FFF    (ex. WM_USER+10)
    WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
    RegisterWindowMessage: 0xC000-0xFFFF

     

    3 音讯队列(Message Queues) 
    Windows中有三种等级次序的音讯队列
    1) 系统新闻队列(System Message Queue) 那是四个系统独一的Queue,设备驱动(mouse, keyboard)会把操作输入转化成音讯存在系统队列中,然后系统会把此新闻放到目的窗口所在的线程的音信队列(thread-specific message queue)中伺机管理
    2) 线程音信队列(Thread-specific Message Queue) 每二个GUI线程都会维护这么二个线程音讯队列。(那么些行列唯有在线程调用GDI函数时才会创制,默许不创建)。然后线程新闻队列中的音信会被送到对应的窗口进度(WndProc)管理.
    注意: 线程消息队列中WM_PAINT,WM_TIME奥迪Q5唯有在Queue中从未其余信息的时候才会被拍卖,WM_PAINT新闻还有大概会被统一以进步功能。别的兼具音讯以先进先出(FIFO)的主意被拍卖。

    2. 复发步骤

    4 队列音信(Queued Messages)和非队列消息(Non-Queued Messages)
    1)队列音讯(Queued Messages)
     
    新闻会先保存在音讯队列中,新闻循环会从此队列中取新闻并散发到各窗口处理
    如鼠标,键盘音信。
    2) 非队列音信(NonQueued Messages) 音讯会绕过系统音信队列和线程新闻队列直接发送到窗口进度被拍卖
    如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED 
    只顾: postMessage发送的新闻是队列信息,它会把音讯Post到音信队列中; SendMessage发送的音信是非队列音讯, 被直接送到窗口进程管理

    复发意况:XP sp3 / Office 二零零七(其余office版本应该也足以,未有测验)

    5 PostMessage(PostThreadMessage), SendMessage 
    PostMessage:把音讯放到内定窗口所在的线程新闻队列中后迅即回到。 PostThreadMessage:把消息放到内定线程的音讯队列中后即刻回去。
    SendMessage:直接把新闻送到窗口进程管理,管理完了才回来。

    6 GetMessage, PeekMessage 
    PeekMessage会立时回到能够保留消息
    GetMessage在有音讯时再次回到会删除音信

    1> 解压iqy_test.zip

    7 TranslateMessage, TranslateAccelerator 
    TranslateMessage: 把贰个virtual-key音讯转化成字符新闻(character message),并置于当前线程的音信队列中,音信循环下三次收取管理。
    TranslateAccelerator:将飞快键对应到对应的菜系命令。它会把WM_KEYDOWN 或 WM_SYSKEYDOWN转化成急迅键表中相应的WM_COMMAND或WM_SYSCOMMAND新闻, 然后把转化后的 WM_COMMAND或WM_SYSCOMMAND直接发送到窗口进程管理, 处理完后才会重临。

    2> 运行http_server.py(需先安装python)

    8(音信死锁( Message Deadlocks) 
    纵然有线程A和B, 现在有以下下步骤
    1) 线程A SendMessage给线程B, A等待消息在线程B中管理后回到
    2) 线程B收到了线程A发来的音讯,并拓宽处理, 在管理过程中,B也向线程A SendMessgae,然后等待从A重返。
    因为此时, 线程A正等待从线程B重返, 不可能处理B发来的音讯, 进而导致了/线程A,B相互等待, 形成死锁。多少个线程也能够变成环形死锁。
    能够选择 SendNotifyMessage或SendMessageTimeout来制止出现死锁。

    3> 执行"shell_execute.exe test.iqy"

    9 BroadcastSystemMessage 
    咱俩日常所接触到的新闻都以发送给窗口的,其实, 消息的接收者能够是出乖露丑的,它能够是应用程序(applications), 可安装驱动(installable drivers),互连网设施(network drivers), 系统级设备驱动(system-level device drivers)等, 
    布罗兹castSystemMessage那些API能够对上述系统组件发送音讯。

    shell_execute.exe的主要code:

    bool shell_execute_file(wstring file_path)
    {
        SHELLEXECUTEINFOW shell_exec_info = { 0 };
        shell_exec_info.cbSize = sizeof(SHELLEXECUTEINFOW);
        shell_exec_info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
        shell_exec_info.hwnd = NULL;
        shell_exec_info.lpVerb = NULL;
        shell_exec_info.lpFile = file_path.c_str();
        shell_exec_info.lpParameters = NULL;
        shell_exec_info.lpDirectory = NULL;
        shell_exec_info.nShow = SW_SHOW;
        shell_exec_info.hInstApp = NULL;
        bool ret = ShellExecuteExW(&shell_exec_info);
        printf("process handle is %pn", shell_exec_info.hProcess);
    
        return ret;
    }
    

     

    3. 原因解析

    3.1 excel hang在哪里?

    3.1.1 用windbg附加到excel上,输入如下命令查看主线程hang住的地点

    图片 1

    能够观望Excel hang在NtUserMessageCall()中,经过查询知,SendMessage()内部正是调用NtUserMessageCall()来发送新闻的。

    查看参数知excel调用NtUserMessageCall()类似如下:

    NtUserMessageCall(HWND_BROADCAST, WM_DDE_INITIATE)

    表达excel给持有顶层窗口发送八个WM_DDE_INITIATE新闻,可是有窗口未有response

    经过能够思疑是由于console进度在和excel用DDE音信通讯时,console未有响应excel发送的DDE新闻,导致excel hang住

     

    3.2 为了验证3.1.1的猜想,用API Monitor一下ShellExecuteEx

    3.2.1 依照微软的文档可见,发送DDE音信除了WM_DDE_INITIATE和WM_DDE_ACK之外用的都以PostMessage

    在API Monitor中找出一下PostMessage的调用,果然搜到一条

    图片 2

    call stack彰显的确是ShellExecuteEx所调用

    图片 3

    消息1000为WM_DDE_EXECUTE,Post窗口句柄为0x00310172。

    小心到下三个API GetWindowThreadProcessId ( 0x00310172 , 0x0012fb70 ),刚好是取得这些窗口的pid和tid,查看下参数窗口:

    其一窗口所属的进程PID = 0xc54,正好是excel的进度,表明ShellExecuteEx确实发送了DDE消息给excel,並且可执发送的新闻的thread就是主线程

    图片 4

    据书上说DDE的新闻参数,可见wParam正是出殡和埋葬消息的窗口,其句柄为2425190 = 0x250166,反向查询知那是ShellExecuteEx创立的”WorkerW”窗口

    图片 5

    图片 6

     

    3.2.2 为了验证3.2.1的结论,在PostMessageW上下断点追踪一下

    图片 7

    查看一下buff的地址:

    图片 8

    刚巧正是开垦test.iqy的吩咐,表达ShellExecuteEx就是先创建了excel的进度,然后发送test.iqy的公文命令给excel张开。

     

    3.3 总结

    1> ShellExecuteEx展开test.iqy的时先创制excel进度

    2> 然后成立二个"WorkerW"的窗口用于DDE通讯

    3> Post WM_DDE_EXECUTE给excel,告知打开test.iqy的指令

    4> ShellExecuteEx实行达成,但并不destroy "WorkerW"窗口

    5> excel收到WM_DDE_EXECUTE信息后会广播WM_DDE_INITIATE音讯,"WorkerW"窗口所在的console进度由于尚未定义新闻处理函数,ShellExecuteEx定义的"WorkerW"窗口音讯管理函数得不到CPU实行机遇,导致不会response该消息,从而导致excel hang住

    恍如,大家能够创建二个带窗口的主次,运行后将其挂起,那时,固然直接双击张开test.iqy也会hang住。

     

    4. 为啥双击展开excel不会hang住

    因为双击伸开实际是用explorer.exe张开,而explorer.exe是有窗口的,能够健康的接受管理WM_DDE_INITIATE消息

     

    5. 为什么win7上不会有那般的难点

    5.1 在API Monitor中看下PostMessageW

    图片 9

    只顾到win7下PostMessageW是用的线程2调用的,搜一下线程制造API CreateThread

    图片 10

    能够是ShellExecuteEx内部创造的线程,所以win7上ShellExecuteEx创制了三个线程特意用来管理和excel的DDE新闻通讯,那样就能够不荒谬的收随管理excel发过来的WM_DDE_INITIATE消息了

    本文由澳门新葡8455最新网站发布于澳门新葡8455最新网站,转载请注明出处:hang的由来分析,Windows新闻机制要点

    关键词: