一旦完成API Hook,那么一个实质性的工作就是Office Communicator的资源文件结构分析。OC的UI结构是基于DirectUI技术实现的,因此与标准的Win32软件差异极大,微软内部在很早以前就开始开发DirectUI框架了,至于为什么要实现这样一个框架,原因很复杂,其中一个基本的原因也许是传统的技术每个UI元素大体要匹配一个“窗口”句柄,表面上看,句柄仅仅就是一个32位整数,其实不然,其背后应该是一个很复杂的数据结构,一个进程能够管理的窗口句柄个数应该是有限的,同时窗口句柄过多无疑要给系统增加额外的开销,因此Microsoft的开发者需要简化“窗口句柄”背后的东西,使得其能够响应部分关键的“消息”,因此,他们需要一种窗口对象的替代物,能够正常处理(诸如键盘、鼠标、绘制等)消息,但同时又不是传统的“窗口”,这一点应该是一个很重要的因素,也解释了传统的Spy++实用程序为什么无法直接观察DirectUI内部因素;开发DirectUI的另外一个原因也许是需要基于XML技术描述UI结构,用XML技术描述UI的好处是显而易见的,Windows7的Shell体系很大程度都依赖于DirectUI的实现。
既然DirectUI的关键点之一是“XML”UI描述,那么这些“XML”保存在哪里?如果我们用Visual Studio 2008的Shell直接打开Communicator.exe这个文件,我们会发现其资源结构如下:
这里,msgsres.dll是MSN的资源文件对应的动态链接库,在OC资源的结构树中我们发现了节点“UIFILE”,打开这个节点对应的子元素,我们即可发现我们感兴趣的东西,例如“940”这个节点:
<duixml>
<BuddyListFrame resid="idBuddyListFrame" AccRole="Pane" id="atom(idBuddyListFrame)" Sheet="MainSS" Layout="BorderLayout()">
<PNG id="atom(idMainUIBackground)" LayoutPos="Client" Layout="BorderLayout()">
<MyPane id="atom(idMyPane)" AccName="resstr(2520, library(lclang.dll))" LayoutPos="Top" Layout="FillLayout()" Padding="rect(1,2,1,2)">
<PNG id="atom(idMyPaneBackground)" Layout="BorderLayout()">
<Element Background="ARGB(0,0,0,0)" layoutPos="Left" Margin="rect(0,0,7,0)" ContentAlign="MiddleLeft" Layout="FillLayout()">
<PNG id="atom(idMyPaneAccent)" Active="MouseAndKeyboard"/>
<PNG id="atom(idMyPanePawn)" idres="706"/>
</Element>
<Element LayoutPos="Client" Layout="VerticalFlowLayout(0,3,3,0)" Padding="rect(0,1,0,0)" ContentAlign="TopLeft">
<Element Layout="BorderLayout()" Padding="rect(2,2,2,2)">
<Element id="atom(idMyPaneName)" LayoutPos="Client"/>
<PNG id="atom(idMyLocation)" Active="Mouse" LayoutPos="Right" Padding="rect(3,0,0,0)"/>
<Element id="atom(idMyPaneStatus)" Active="Mouse" LayoutPos="Right" Padding="rect(0,0,0,1)"/>
</Element>
<Element Layout="BorderLayout()" Margin="rect(0,3,0,0)" Padding="rect(2,2,0,1)">
<PNG id="atom(idMyPaneNoteImage)" Flip="False" idres="740" layoutPos="Left" ContentAlign="MiddleLeft"/>
<Element id="atom(idMyPaneNoteParent)" LayoutPos="Client" Layout="FillLayout()">
<Button id="atom(idMyPaneNote)" Active="MouseAndKeyboard"/>
<EditNote id="atom(idMyPaneNoteEdit)" ContentAlign="MiddleLeft" Bottomless="True" MaxTextLength="511" XScrollable="False" YScrollable="False" RichEditStyle="PlainText|MultiLine|DisableDrag" Visible="False" Active="MouseAndKeyboard"/>
</Element>
</Element>
</Element>
<Element id="atom(idMyPaneInfoPanel)" Layout="FillLayout()" Margin="rect(1,0,0,0)">
<PNG id="atom(idMyPaneInfoColumn)" Layout="GridLayout(2,1)">
<CmdButton Layout="FlowLayout(0,3)" id="atom(idMyPaneCallForwarding)" Active="MouseAndKeyboard">
<PNG Flip="false" IdRes="731" id="atom(idMyPaneCallForwardingImage)"/>
<PNG