http://www.directui.com/blog/?p=7

DirectUI底儿朝天

零碎收集到得资料,原作者已经隐藏了blog相关部分内容,这里权作备份。

DirectUI XML渲染器正式登场.

我们现在所知道的是,无论是MSN还是OC,其使用DirectUI的方式都是以解析XML实体信息生成界面这种途径进行,那么我们能否用类似的方法来生成DUI界面呢?答案是肯定的.

虽然之前已经找到运行时创建各类型元素实例的方法,但毕竟在VC层面来做是繁琐的,而且为其设置各种属性还要通过DirectUI::Value类型来进行,虽说可以找到常见的Wrapper仍不理想;另一方面,要描述元素的一些动态效果,如鼠标在其上时的显示图片,VC层面来做着实困难,而在XML描述文件中是可以直接指定一个元素的在各种属性状态下的不同表现的.

按照有着多年C++编程经验的正常人的想法(指微软shell组的那帮同学)来说,完成这个功能,必然有一个渲染器类,既然这样,看起来首先要寻找的应该是本类的构造函数,或者按照其DirectUI类库设计的一般原则,似乎能找到静态工厂函数,要做这件事没有什么可以借助的力量,只好先寻找本类的成员函数,记录其this指针,通过查询其虚函数表的RVA找IDA pro拍肩完成.

由于XML文件是在资源中的,可以拦截WINAPI FindResource,在参数为DUI的XML序号时,记录RVA,找IDA pro拍肩F5后:

HMODULE __thiscall sub_49509C(int this, LPCWSTR lpName, HMODULE lpMultiByteStr, int a4)
{
HRSRC v4; // eax@1
HRSRC v5; // ebx@1
int v6; // edi@1
HMODULE v7; // esi@1
HGLOBAL v8; // eax@2
int v9; // eax@3
void *v10; // esi@3
const WCHAR *v12; // ST04_4@1
HMODULE v13; // ST00_4@1
UINT v14; // eax@3

v7 = lpMultiByteStr;
v12 = lpName;
v6 = this;
v13 = lpMultiByteStr;
*(_DWORD *)(this + 16) = lpMultiByteStr;
lpMultiByteStr = (HMODULE)-2147221414;
v4 = FindResourceW(v13, v12, &Type);
v5 = v4;
if ( v4 )
{
    v8 = LoadResource(v7, v4);
    if ( v8 )
    {
      lpMultiByteStr = LockResource(v8);
      v14 = SizeofResource(v7, v5);
      v9 = sub_491CC5(lpMultiByteStr, v14);
      v10 = (void *)v9;
      if ( v9 )
      {
        lpMultiByteStr = (HMODULE)sub_494EEC((LPCWSTR)v9, *(_DWORD *)(v6 + 16), a4);
        sub_47FEBC(v10);
      }
      else
      {
        lpMultiByteStr = (HMODULE)-2147024882;
      }
    }
}
return lpMultiByteStr;
}
出乎意料的顺利,很明显这个函数就是通过资源ID来读取XML的调用,并且可以看到sub_494EEC是通过字符串来读取XML的调用,该函数接收的参数依次为XML字符串,所关联的模块句柄,和一个未知数据(一般为0).

拦截本函数,由此记录本类对象虚函数表RVA在0×00005ed0.

找IDA pro拍肩并且反复上溯数据引用/指令引用,若干层后如期发现渲染器生产函数.

该函数接收5个参数,第一个是要创建的渲染器指针的地址,后面四个为某些可选CALLBACK函数指针,可置空.

这么做之后只是创建了渲染器并且为其设置了XML,并没有实际构建DUI元素树,寻找这个调用的方法比较离奇,在IDA pro的数据视图里闲着无聊搜索D.U.I.X.,结果搜到一个DUIXMLParse字符串,跳转到反汇编视图,反复上溯数据引用/指令引用,如期找到构建树的调用.

这个调用有三个参数,依次为要构建的元素树的id,在xml中表现为resid=”XXX”的这个XXX,第二个元素可以将元素树头领元素偏特化,一般置空即可,最后一个参数自然就是出口参数了,也就是所创建的元素树的头领元素指针.

至此,已经可以使用自己创建的渲染器来轻松的构建DUI元素树,并将其加入到已有DUI元素结点中,最后不用渲染器得时候自然要释放掉它,这个销毁调用查找渲染器生产函数的引用,可顺便获取.

发现可以控制DUI渲染器通过XML构建元素树后,随之而来的一个想法就是能否自由创建自己的DUI窗口呢.

首先,要介绍三类对象:

1.NativeHWNDHost,它负责host DUI框架窗口和框架元素,特别注意的是这个东西不是个DUI元素,如同他的名字中所包含的Native,它是个纯粹的WIN32原生窗口.在一般的DirectUI界面软件中如果一个窗口类名为NativeHWNDHost,则指的就是它了.

2.HWNDElement,它负责将DUI框架元素融合进一个win32窗口,实际应用中直接和上面的那哥们配合,不仅会创建出一个框架元素还会生成对应的窗口,类名为DirectUIHWND

3.HWNDHost,它负责将WIN32窗口绑定在一个DUI元素上,DUI内部已经预写了一些标准WIN32控件的其派生类,好处就是WIN32窗口遵从DUI布局管理器的摆布.

要创建自己的DUI窗口,要创建NativeHWNDHost对象和HWNDElement对象,然后让前者host后者,再渲染XML出DUI元素树,加入到后者的子结点中.

这俩对象的静态生产函数的寻找方法不提了,说来说去就那几招,找IDA拍肩系列,题外话,微软财大气粗就是没法弄,生砸钱让你拍肩XBOX360看你就范不…

NativeHWNDHost对象的生产函数参数表如下:

(LPCWSTR lpClassName, LPCWSTR lpWindowName, HWND hWndParent, int, int X, int Y, int nWidth, int nHeight, DWORD dwExStyle, int, HINSTANCE hInstance, int, int**),没啥可特别注意的.

HWNDElement对象的生产函数参数分别是父窗口句柄,一个消息过滤有关的类对象指针,和返回的对象指针.

这个类对象指针所在的类务必实现一个虚函数,原形为virtual int OO(DWORD,DWORD,DWORD,DWORD,DWORD),以后细说.

至于host调用的地址寻找,则是印象中年初的时候记录过,后来翻了一下以前的日志直接取出来了.如果不是这样的话,大概需要拦一下生产函数,在创建出的对象4字节位置设置一个写内存断点来查找.

肯定还存在问题,窗口出来了,但是似乎元素没有得到通知,问题待查,用WalkOnDirectUI工具看一下的话:

而所渲染的XML内容为:

L” “;

是相吻合的.

今天起来之后吓一跳,有位在美国微软公司的华人来了一趟,而且还是直接访问不是搜索或者从谁那跳过来的,这事就有点诡异了,不过据老板讲微软中国没问题就行了,我就不关心了.

先说好消息,之前提到XML渲染器构建元素树时的第2个参数是一个DUI元素,可以用来偏特化,这话说得有点问题.

当第2个参数不为空时,表示XML渲染器将修改这个元素作为要构建的DUI元素数首领元素.

举例来说:

这个元素,如果想运行时让其不可见,

可以给DUIXML渲染器传输如下字符串:

<绿坝娘 visible=”False” resid=”main”>

显然DirectUI不可能生产出一个绿坝娘来,再最终生产的时候会作用在传入的第2个参数上,也就是这个WebBrowserHost.

题外话,绿坝娘现在已经在人群中惊起一片玛勒戈壁,现在这种kuso东西越来越多了.

也就是说,这种用法可以颠覆某个DirectUI元素结点和他的孩子们.

创建自己的DUI窗口方面,还是没找到问题所在,应该不是NativeHWNDHost方面的问题,让自己创建的这个窗口去host OC登录窗口的HWNDElement(实际上是它的派生类)是正常的:

可以看到没有显示完全在OC窗口上,而是保持了那个OYe!窗口的大小.

至少用XML渲染出一个HWNDElement的派生类再加进来应该是没问题的,但是创建DUI XML渲染器时,并非4个CALLBACK而是2个CALLBACK 2个用户自定义指针(因为CALLBACK不能作为成员函数),其中一个用来获取样式表的资料,没有实现这个函数的话,后面不会成功构建出元素树.

从整体来说,已经基本达到底儿朝天的目标,从概念上已经感同身受DirectUI和其设计者.于是以后主要涉及到的就是一些细节问题的解决方案了.

对于用IDA pro看各种软件和编程情境还原法来逆向分析,其实在DirectUI这个过程中是从一无所知开始的,现在基本形成了IDA静态分析(F5)配合VS调试的个人风格,实在不行上FPE,后者在名为某某HDD的程序分析中派上不少用场.

言归正传,之前的系列中提到DUI的核心是元素Element,对于元素来说,决定它表现的是各种属性的值,(从另一种角度上看是DUSER的Gadget,距离应用太远不提),大致有如下几类:

层次属性(指父子关系)
可见性
可用性
位置
布局(布局属性说明的是该元素的布局管理器,对子元素生效)
边框
留白
内容
字体
激活性
焦点
光标
tooltip(这个还是用英文比较好)
标识定义
样式
MSAA相关

另外客户端还可以设置自定义属性.

而决定它行为的是各类事件,事件又分两大类,输入事件和本类型元素专有事件,事件的传递过程有三种类型,冒泡,路由,单挑,这些以前都提过,对于事件的相应,元素类有虚函数专门响应,基类的处理是分发给元素的监听器.

元素可粗分为2大类, DirectUI原生元素和WIN32 wrapper元素,Element Button Edit之类的属于前者,而后者其实都是HWNDHost类型元素的特化类型,HWNDHost型元素为了将win32窗口融合进DUI布局,会优先创建一个host窗口,类名为CtrlNotifySink,用来处理WIN32 控件给父窗口的通知消息之类的需求,虽然Windows操作系统的shell部分以及msn,oc所采用的DUI版本不尽相同,用spy++看看这类元素,仍能看到相同的窗口类名.

针对要将WIN32窗口融入DUI布局这个实际需求,个人认为现在公司才采用的创建一个HWNDHost元素的派生类(一个WIN32标准按钮),然后隐藏那个win32窗口将自己的窗口绑定到host窗口就挺好了,在XML中可直接描述HWNDHost生产本类型元素的,只会生成host窗口,这样将自己的窗口设置为它的自窗口贴上去的话,或许更好,减少无谓窗口开销.

对于几种常见WIN32 控件,DUI都提供了预写的wrapper元素,像CCListView,CCSysLink,CCAVI,CCVScrollBar之类.

还是再提一下DUI布局管理器吧.

在某些场合,设置元素的宽度和高度并不能见效,实际上并非没有生效,而是在立刻生效后被DUI布局管理器记录抹去了.
也就是说,DirectUI元素的定位是由布局控制的,布局可以认为是一些设定好的规则,而最终的表现还是通过元素本身的属性实现.

对于一个元素来说,他可以被绝对定位或者在父元素所拥有的布局中被即时定位,前者实际上超脱了布局定位机制.

元素和布局相关的属性有Layout LayoutPos PosInLayout SizeInLayout LastDSConst,其中后三个为只读属性,是引擎内部使用的,Layout可以指定所使用的本元素对子元素使用的布局管理器,LayoutPos 可制定本元素在父元素的布局中的逻辑位置,当指定为absolute时为绝对定位.

常用的内置布局管理器有FillLayout,BorderLayout,FlowLayout,TableLayout等等,基本可以顾名思义,当然也要实际使用一下看看效果.

RowLayout可以实现按列对齐特性,同一序号的子元素将被对齐,想起似乎有在OC联系人列表里添加一列的需求,怀疑这里用的是RowLayout,于是测试了一下发现不是,不过:

这个ListView其实每行是一个元素,这个元素在联系人这块有6个BuddyColumn元素,这个例子在每行的元素里加入了一个BuddyColumn元素,再在其中加入要显示的文字.

在XML中搜索BuddyColumn:   可以发现BuddyColumn元素还有Priority(优先级)之类的属性.

这样的话,如果要加入一列,似乎在BuddyColumns元素里加入BuddyColumn就可以.

昨天吃完了上周去肥鸟那里拿的20包牛羊配,今天要更新感觉少了点什么,出去买了瓶饮料凑合一下先.

来聊聊DUI样式表.

样式表sheet是元素的属性,对该元素和它旗下的子元素生效,当子元素自身也有样式表时,父元素的样式表不会对其生效.

样式表里东西可以分为两部分,条件和约束.

如样式表:

则被称为条件,被称为约束。

不在任何if或者unless内部的约束在渲染时抢先生效,当然如果元素的本地属性已经被设置,则会被其冲掉。
约束中开头字符串如Element,不代表一个元素实例,而表示本类型元素,可联想IClassInfo,也就是说只对本型元素生效,不会对其派生类元素施展。

条件有两类,if或unless,分别在后面的约束情况成立或者不成立时生效其中包含的约束。
可以嵌套,相当于并且的关系

等价。

这里出现的属性可以是动态变化的,如Press Check之类,当元素的属性变化时,DUI属性管理器将通知样式表施展约束。

当运行时要改变元素的行为(也就是约束的表现),可以用DUI XML渲染器修改该元素的sheet属性,XML串后面追加样式表串即可。

如果样式表和元素不再同一渲染器中,渲染器将以函数指针的方式回调创建时传入的第2个参数,做最后的努力。

DirectUI底儿朝天相关推荐

  1. 发现一个windows7(32bit或64bit)DirectUI的bug

    前段时间发现一个windows7的一个bug,不是什么严重的问题,我在此记录下.(转载请指明出于breaksoftware的csdn博客) 重现步骤如下: 0 在文件夹的"更改您的视图&qu ...

  2. Git命令家底儿及Git数据通信原理详解

    声明:本文为CSDN原创投稿文章,未经许可,禁止任何形式的转载. 作者:周立伟(花名:华序,ITeye博客),关注分布式.高并发和Java中间件的研究. 责编:钱曙光,关注架构和算法领域,寻求报道或者 ...

  3. DirectUI介绍

    最近由于项目的需要学习了一下DirectUI方面的东西,主要借鉴的是一个国外程序员写的代码(见引用一),看了后发现它更多的是探讨一种实现的可能性和思路,和实际应用还是有距离的,不过其实现还是很有意思的 ...

  4. 基于DirectUI搭建Windows窗体程序

    使用DirectUI需要directuiCom.dll,包含IDirectUI.h和DirectuiDef.h.在你的应用程序中初始化CLSID_DirectUI,并获取IDirectUI(IID_I ...

  5. 以 DirectUI 方式实现的ImageButton

    [文章归类] C++,Windows 应用程序开发. 这是一篇比较简单的文章,主要讲解的是用 DirectUI 方式实现的对话框上的按钮.例如,QQ界面上的按钮.我在前一篇文章中讲解的 PS 油画滤镜 ...

  6. 基于DirectUI技术开发的发卡系统

    基于DirectUI技术开发的Demo 源代码工程 https://github.com/chenhaifeng2016/DuilibDemo

  7. directUI的心得

    2019独角兽企业重金招聘Python工程师标准>>> 0. WPF, Windows Live, QQ 和 百度 hi 的界面其实并不神秘.大家都想学习而不得其门而入.我也经历了跟 ...

  8. DirectUI的初步分析-转

    DirectUI的初步分析(一) 最近由于项目的需要学习了一下DirectUI方面的东西,主要借鉴的是一个国外程序员写的代码(见引用一),看了后发现它更多的是探讨一种实现的可能性和思路,和实际应用还是 ...

  9. 【Golang】Go语言Windows GUI库XCGUI,DirectUI设计思想,高度自定义界面,支持Direct2D硬件加速

    Github地址 https://github.com/twgh/xcgui 介绍 本库封装自炫彩界面库,功能丰富(1000多个API接口),简单易用,轻量级,高度DIY自定义,支持一键换肤. 炫彩界 ...

最新文章

  1. oracle expdp自动导出数据,Oracle expdp数据泵远程导出
  2. JSP页面最终是编译为Servlet执行的
  3. 数据挖掘、机器学习书籍推荐!!
  4. arcore之路-unity开发从入门到实践_Unity游戏开发——单例模式的最佳实践
  5. 当大家都不理解你的时候,就是你成就的捷径
  6. 蓝桥杯 ADV-166算法提高 聪明的美食家
  7. mysql workbench企业_甲骨文发布MySQL Workbench 6.0版本
  8. Hibernate XXX.hbm.xml 里的class标签的 schema 属性解释
  9. 【新知实验室】体验腾讯云音视频
  10. 线性代数(预备知识)
  11. tcpdump抓取网络
  12. 国子监祭酒是个什么官
  13. 计算机文化基础0008 17秋在线作业1,川大《计算机文化基础0008》17秋在线作业1(100分)...
  14. 若依框架获取和修改当前登录用户信息
  15. 浅析dToF和iToF成像技术
  16. scratch案例——深水炸弹
  17. 蓝牙 - 苹果iOS所支持的profile
  18. Learning English Lesson 2 - ( Accents )
  19. Sentinel之限流、降级、系统保护、热点、授权规则
  20. 微软teams软件_如何在Microsoft Teams中创建快速投票

热门文章

  1. 3:cordova-plugin-whitelist 协议白名单配置整理
  2. EBank 电子银行发布 2.1.0 版本
  3. 统信UOS系统之间文件共享
  4. 【VP9】libvpx在Windows和Linux平台下的编译和vp9编解码器的命令行参数
  5. 【ElementUI】【Vue】el-Radio失效,无法切换选中效果
  6. C/C++ const和指针记忆口诀
  7. 细谈操作系统导论之文件系统
  8. mysql_不区分大小写
  9. 通过Spring来读取文件的各种方法
  10. 神奇的字符串-包含26个字母