定位MFC中SDK创建窗口API的位置

admin 2021年12月29日07:06:13评论67 views字数 3112阅读10分22秒阅读模式

定位MFC中SDK创建窗口API的位置

SDK中用于创建窗口的API

在SDK中创建窗口的过程,我们可以将其称为为创建窗口6要素。

其分别为:

  1. 设计窗口类

  2. 创建窗口实例

  3. 显示窗口

  4. 更新窗口

  5. 建立消息循环

  6. 实现窗口过程函数

其中对应的API为:

  1. RegisterClass

  2. CreateWindow

  3. ShowWindow

  4. UpdateWindow

  5. GetMessage、TranslateMessage、DispatchMessage

  6. WindowProc、DefWindowProc

在MFC中对其进行了封装,接下来我们通过一系列的操作来定位到MFC中对应的SDK窗口的创建过程。

MFC单文件工程

定位消息循环

创建完项目后,配置项目属性。

属性页->配置属性->高级->在静态库中使用MFC

将其默认的在共享 DLL 中使用 MFC改成在静态库中使用MFC,就可以进行MFC框架的调试了。


定位MFC中SDK创建窗口API的位置


消息循环,使用F10无法步过,会陷入到函数里面,所以可以采用一路F10,然后依次跟进循环里面的方法来进行。

按F10运行断到Main函数的位置。


定位MFC中SDK创建窗口API的位置


按F11跟进AfxWinMain函数中(此处如果不进行配置在静态库中使用MFC会进入到别的函数)


定位MFC中SDK创建窗口API的位置


接下来一路F10,可以看到程序陷入了函数中。


定位MFC中SDK创建窗口API的位置


下断点,重新运行,F11进入该函数。


定位MFC中SDK创建窗口API的位置


接着F11进入CWinThread::Run()


定位MFC中SDK创建窗口API的位置


可以看到for循环是一个死循环,接着一路F10,可以发现程序在do while语句之间一直循环。


定位MFC中SDK创建窗口API的位置


do while循环中有三个函数,我们进入PumpMessage()函数进行查看


定位MFC中SDK创建窗口API的位置


再紧接着进入AfxInternalPumpMessage()函数中


定位MFC中SDK创建窗口API的位置


可以看到该函数中存在处理消息的APIGetMessageTranslateMessageDispatchMessage,据此可以判定,其为消息循环部分。

定位窗口过程函数

窗口过程函数是用来处理消息的,可以在发送消息处,下断点,通过栈回溯,找到窗口回调函数。

在控件操作处下断点,然后运行,触发该操作。

这里我们选择的是关于窗口的确定按钮控件。


定位MFC中SDK创建窗口API的位置


点击关于窗口的确定按钮


定位MFC中SDK创建窗口API的位置


可以看到断在了下断点的位置,打开调用堆栈窗口从上往下依次分析。


定位MFC中SDK创建窗口API的位置


窗口过程函数的参数为

  • HWND hWnd

  • UINT Msg   

  • WPARAM wParam

  • LPARAM lParam

从上到下依次进行分析,哪个调用函数符合。

最终定位到CALLBACK其参数列表完全符合可以确定其就是窗口过程函数。


定位MFC中SDK创建窗口API的位置


UpdateWindow && ShowWindow

MSDN对该API描述如下:如果窗口的更新区域不为空,则通过向窗口发送WM_PAINT消息来更新指定窗口的客户端区域。该函数直接向指定窗口的窗口过程发送WM_PAINT消息,绕过应用程序队列。如果更新区域为空,则不发送消息。

我们可以判断,其会发送WM_PAINT消息,所以我们寻找MFC中的绘制函数在绘制时会发送WM_PAINT消息,最终确定了OnDraw函数。


定位MFC中SDK创建窗口API的位置


在OnDraw函数内部下断点


定位MFC中SDK创建窗口API的位置


运行后查看调用堆栈


定位MFC中SDK创建窗口API的位置


双击进入该函数即可看到UpdateWindow API


定位MFC中SDK创建窗口API的位置


再往上回溯一层


定位MFC中SDK创建窗口API的位置


进入InitInstance()可以看到ShowWindowAPI


定位MFC中SDK创建窗口API的位置


UpdateWindow当有效区存在时会调用窗口过程函数发送WM_PAINT消息。


关系链如下:

UpdateWindow->(发送WM_PAINT消息)->WndProc->(处理WM_PAINT消息)->OnDraw

因此可以通过栈回溯定位到UpdateWindow

CreateWindow

在返回之前,Create Window向窗口过程发送WM_CREATE消息。

因此在处理WM_CREATE处下断点,通过栈回溯可以定位到CreateWindow

MainFrm.cpp中的OnCreate函数处下断点。


定位MFC中SDK创建窗口API的位置


查看调用堆栈,进行分析。


定位MFC中SDK创建窗口API的位置


可以看到其参数与CreateWindowAPI的参数列表完全吻合


定位MFC中SDK创建窗口API的位置


可以判定其就是CreateWindowAPI


定位MFC中SDK创建窗口API的位置


定位RegisterClass

通过CreateWindow的类名进行回溯RegisterClass


定位MFC中SDK创建窗口API的位置


查看调用堆栈中上一层的函数的调用。


定位MFC中SDK创建窗口API的位置


可以看到其也来源于上层函数调用,再往上回溯一层。


定位MFC中SDK创建窗口API的位置


此时可以看到类名来源于GetIconWndClass函数,按F9下断点,F5继续运行到当前断点后F11跟进去。


定位MFC中SDK创建窗口API的位置


我们关注该函数的返回值,可以看到其有两个返回,排除返回为NULL的那个,在另一个返回处下断点,跟进。


定位MFC中SDK创建窗口API的位置


我们同样关注该函数的返回,其有两个返回,从上到下依次进行分析,首先在GetClassInfo处下断点跟进。


定位MFC中SDK创建窗口API的位置


按F11发现其并没有进入函数内部,继续关注另一个函数AfxRegisterClass,下断点跟进。


定位MFC中SDK创建窗口API的位置


在该函数内部可以发现RegisterClass的宏定义,跟进后确定其RegisterClassAPI的位置。


定位MFC中SDK创建窗口API的位置


以上我们依次,找到了创建窗口的六要素的位置。

总结

  • RegisterClass 通过CreateWindow回溯ClassName。

  • CreateWindow 找到处理WM_CREATE消息处OnCreate,进行栈回溯。

  • UpdateWindow 找到处理WM_PAINT消息处OnDraw处下断点进行栈回溯。

  • ShowWindow 找到处理WM_PAINT消息处OnDraw处下断点进行栈回溯。

  • 消息循环 F10,然后依次跟进循环内部进行分析。

  • 窗口过程函数 在发送消息处,下断点,通过栈回溯,找到窗口回调函数。

以上就完成了MFC单文件工程中,SDK创建窗口API的定位,根据上面的知识来进行下面的练习。

练习:MFC对话框工程

创建MFC对话框工程, 定位对话框API的位置

  • CreateDialog

  • 消息循环

练习答案

消息循环

这里消息循环采用和上面一样的方法进行寻找,即一路F10,跟进程序陷入的循环中。

首先F10运行程序,按F11进入AfxWinMain函数中,一路F10查看其陷入的位置,可以看到程序在执行到该行程序时,会陷入到循环中。


定位MFC中SDK创建窗口API的位置


我们下断点跟进该函数,继续F10定位到dlg.DoModal()函数继续F11跟进。


定位MFC中SDK创建窗口API的位置


一路F10定位到DoModal函数中的,CreateRunDlgIndirect函数,继续F11跟进。


定位MFC中SDK创建窗口API的位置


紧接着定位到VERIFY(RunModalLoop(dwFlags) == m_nModalResult);,继续跟进


定位MFC中SDK创建窗口API的位置


在RunModalLoop函数内,发现了for(;;)循环以及do while循环,继续F10发现程序陷入了do while循环之中。


定位MFC中SDK创建窗口API的位置


接下来我们来分析 do while循环中的函数。

首先分析AfxPumpMessage,按F11跟进。


定位MFC中SDK创建窗口API的位置


我们首先跟进pThread->PumpMessage()进行分析(因为该函数主要的功能是进行返回,首先要分析操作返回值的功能)


定位MFC中SDK创建窗口API的位置


继续再次跟进AfxInternalPumpMessage


定位MFC中SDK创建窗口API的位置


根据函数中的GetMessage、TranslateMessage和DispatchMessage可以判定,我们定位到了消息循环的位置。

CreateDialog

通过查询MSDN,我们知道了

创建对话框函数使用CreateWindowEx函数创建对话框。创建Dialog,然后向对话框过程发送WM_INITDIALOG消息

所以我们在处理WM_INITDIALOG的函数处下断点,通过栈回溯就可以定位到CreateDialogAPI了。

通过查看头文件,最终可以定位到处理WM_INITDIALOG消息的函数OnInitDialog,在其函数头部下断点。


定位MFC中SDK创建窗口API的位置


断下后依次对调用堆栈内的函数进行分析,对比CreateDialog的参数。


定位MFC中SDK创建窗口API的位置


最终定位到CreateDialog的位置


定位MFC中SDK创建窗口API的位置


定位MFC中SDK创建窗口API的位置


本文始发于微信公众号(疯猫网络):定位MFC中SDK创建窗口API的位置

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月29日07:06:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   定位MFC中SDK创建窗口API的位置http://cn-sec.com/archives/505234.html

发表评论

匿名网友 填写信息