Windows新闻机制要点

2019-11-03 13:14栏目:电脑操作

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酷路泽D(wParam)表示菜单项,工具栏按钮或控件的ID。假诺是控件, HIWO陆风X8D(wParam)表示控件音信类型
3> 控件文告(Notify Message) 
控件通告新闻, 那是最灵敏的信息格式, 其Message, wParam, lParam分别为:WM_NOTIFY, 控件ID,指向NMHD库罗德的指针。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安德拉独有在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卡塔 尔(英语:State of Qatar)

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消息了

版权声明:本文由威尼斯人app发布于电脑操作,转载请注明出处:Windows新闻机制要点