Home > 开源软件 > ezgdi – gdi++移植到64位Windows

ezgdi – gdi++移植到64位Windows

August 28th, 2009

ezgdi是我最近做的一个小项目, 将用于字体美化的gdi++动态链接库移植到x64平台上. 原始想法来源于极限主题论坛的相关讨论[1][2][3].

gdi++移植到64位windows, 为什么?

gdi++替换了操作系统的gdi接口功能, 可以提供更加伤心悦目的字体渲染效果. 而gdi++的一个重要特点, 即操作系统接口替换, 是依赖于微软研究院发布的一个库, 叫detours, 现在detours版本号是2.1, express版可以免费使用, 但不支持64位程序. 而支持64位的Professional版本不免费, 要$1000, 而且有钱也不能用, 因为微软禁止你用detours开发GPL类开源软件. 据我所知, 很多很好的项目都依赖于detours, 以至于迟迟不能提供对64位的支持.

64位是未来的趋势, Linux, Windows现在发布, 都主推64位版本. 如果gdi++不支持64, 会严重影响我升级64位操作系统的决心. 所以我觉得gdi++移植到64位windows, 是一件挺有意义的事情.

怎么移植? 为什么选择easyhook?

首先, easyhook提供与detours类似的操作系统API劫持功能. 并且开源, 支持x64平台. 所以将gdi++对detours的依赖移植到easyhook上, 可以编译出64位的gdi++.dll, 用于渲染64位Windows程序.

截止到8月26日, 从detours到easyhook的移植工作基本完成雏形. 这意味着, 使用easyhook代替detours的方案是可行的.

ezgdi 怎么用?

将来64位的gdi++.dll和32位的gdi++.dll会并存, 分别负责渲染64/32位程序. 虽然目前只支持注册表加载, 但实现成gditray的支持那种也是可行的.

虽然我目前是基于freetype版做出的修改, 但其实修改的内容都和freetype没关系, 所以推广到其他版本应该也不是问题.

总的来说, 从使用来讲没什么不一样的. 想试用当前的版本, 可以参见安装说明.

移植当前是什么状态? 什么时候可以用?

目前把gdi++从detours移植到easyhook的工作已经基本完成, 32-bit和64-bit的DLL都能正确生成. 但运行不稳定. 尤其是x64的dll, 会导致IE crash. 即使这样, 如果你还是感兴趣, 可以下载试用.

现在我有两个忧虑, 一是性能, 我怕easyhook相对detours的实现会产生明显的性能瓶颈, 二是全面性, 目前已经发现有些操作系统的界面easyhook不能渲染, 不知道是不是easyhook做不到.

上述两个问题有可能是植根于easyhook本身的技术实现, 无法解决的. 所以最坏的结果是, 走了一圈, 发现此路不通.

需要帮忙么?

非常需要, 我一个人的精力能力毕竟有限. 如果觉得ezgdi有一点价值, 可以关注ezgdi项目的主页. 上面有一些文档, 和我改动之后的代码

目前的缺陷

目前的ezgdi尚有很多较为严重的问题没有解决, 大概有下面几点:
1. 只支持注册表加载, 需要将gditray这种也用easyhook改写才能支持其他加载方式
2. 有些程序中渲中文字体不能渲染(SVN中r27应该已经解决, 至少一部分)
3. x64的DLL非常不稳定, 肯定有从32位到64位移植遗留的bug没有发现. 访问中文站点会导致IE 64-bit崩溃
4. 不能正常截获开始菜单, IE等Windows主界面的内容, 怀疑和easyhook有关, 还未确认.

下步计划

完善, 不断完善. 尤其是改善x64的DLL稳定性, 因为移植到easyhook的优点就是支持x64平台.

Categories: 开源软件 Tags: , , , , ,
  1. chuanp
    October 21st, 2009 at 16:12 | #1

    您好!
    我最近也在做一个X64的移植项目。该项目以前是用Detours做的拦截,现在要移植到64位的系统下,我用EasyHook库替换Detours.遇到一个问题:无法拦截到系统调用API函数,能够拦截到64位程序调用API函数。
    请问您知道什么原因吗?
    我是仿照EasyHook提供的例子UnmanagedHook做的,删除了以下两个部分:
    Installing test driver
    Testing stealth thread creation
    接下来就是仿照例子进行安装钩子,请问有什么问题吗?
    期待您的指导。

  2. October 21st, 2009 at 16:18 | #2

    我也是照着UnmanagedHook例子改的. 也是删除了你说的那几段代码, 截获MessageBeep函数成功.
    不过, 没太理解你说的”无法拦截到系统调用API函数”, “能够拦截64位程序调用API函数”之间的区别.

  3. chuanp
    October 21st, 2009 at 16:29 | #3

    @dipplum
    就是我拦截了函数NetShareAdd,制作成DLL后,可以拦截64位对话框调用NetShareAdd,但无法拦截系统进行设置共享操作。
    用Detours拦截NetShareAdd,是可以拦截到系统进行共享的。

  4. October 21st, 2009 at 16:39 | #4

    原来是这样, 这个问题恐怕我也遇到了, 就是ezgdi渲染范围好像没有gdi++全. 当时就猜测是不是easyhook原理和detours不太一样, 导致有些程序的调用截获不了.

    有一阵没看了, 这问题也都都没解决呢. 抱歉啊.

    我觉得, 应该搞清楚为什么拦截不了. 要么从原理出发, 分析分析easyhook和detours的原理. 要么看看设置共享的是哪个进程, 如有可能调试一下, 看看dll是否正常载入, installhook函数是否执行了之类的.

  5. chuanp
    October 21st, 2009 at 16:56 | #5

    @dipplum
    我注入技术的选用的是建立系统范围的Windows钩子,可以成功地拦截到CreateProcess这个函数,当系统创建新的进程时,都可以拦截到。
    难道EasyHook只能拦截一部分API?

  6. chuanp
    October 23rd, 2009 at 10:50 | #6

    您好!
    再问一个问题:EasyHook库中的RhCreateAndInject可以代替Detours库中的DetourCreateProcessWithDll吗?
    RhCreateAndInject怎么调用?我老是不成功。
    谢谢!

  7. October 23rd, 2009 at 13:56 | #7

    我没试过, 不过我猜测是可以替代的.

    但是在64位系统下, 好像easyhook的RhCreateAndInject是要装一个driver, 绕过Windows的PatchGuard, 不知道你装了没有.

  8. chuanp
    October 23rd, 2009 at 14:46 | #8

    @dipplum
    哦,还得装driver,装哪个driver?我没用过。

  9. October 23rd, 2009 at 18:24 | #9

    从README摘出来的, 应该是叫EasyHookXXDrv.sys. 不过没编译出来, 可能是要WDK才能编译吧, 猜想.
    (optional; only required for kernel hooking)
    "Debug\x86\EasyHook32Drv.sys" -> "Deploy\EasyHook32Drv.sys"
    "Debug\x64\EasyHook64Drv.sys" -> "Deploy\EasyHook64Drv.sys"

  10. chuanp
    October 26th, 2009 at 11:35 | #10

    我在http://www.codeplex.com/easyhook网站上下载的EasyHook 2.6 Binaries中找到了EasyHook64Drv.sys,并用RhInstallSupportDriver()和RhInstallDriver装的。但RhCreateAndInject还是没有执行成功。
    另外,EasyHook可以挂载控制台程序吗?

  11. October 26th, 2009 at 18:27 | #11

    这样啊, 我哪天编译一个RhCreateAndInject的例子看看.
    Easyhook可以挂载控制台程序, 我确信.

  12. s_m_l_x
    October 27th, 2009 at 11:07 | #12

    你们好,我有个问题,在easyhook中非托管代码只有hook api的例子,但是不知道,在hook的api怎么执行原api的方法,想问下这个是怎么实现的?

  13. chuanp
    October 27th, 2009 at 16:30 | #13

    @dipplum
    EasyHook挂载控制台程序是靠哪个函数实现的?
    您如果编译RhCreateAndInject成功的话,请告诉我一声。谢谢了。

  14. chuanp
    October 28th, 2009 at 17:57 | #14

    我调用RhCreateAndInject报的错位”Unable to find the required native entry point in the given 64-bit library.”.

  15. chuanp
    October 29th, 2009 at 17:12 | #15

    RhCreateAndInject我已经调用成功了,不需要安装驱动。就是需要一个入口,在API里有介绍。
    现在就是无法拦截控制台程序,是不是和LhSetGlobalInclusiveACL,LhSetExclusiveACL,LhSetGlobalInclusiveACL,LhSetInclusiveACL有关?它们的调用顺序是什么?

  16. October 30th, 2009 at 02:31 | #16

    我拦截的控制台程序不是通过RhCreateAndInject注射之后调用LhSetGlobalInclusiveACL的方法拦截的, 我改编gdi++的时候, 是用在注册表中设置AppInit_DLLs的方法拦截的. 所以我不需要调用RhCreateAndInject, 可以直接让命令行程序载入时运行我的dll, 运行注册钩子等函数. 这样做是可以的.

    如果你可以用你的方法正常拦截Win32程序, 不能拦截控制台程序, 那就是另一个问题了.

  17. chuanp
    October 30th, 2009 at 09:47 | #17

    @dipplum

    我可以成功地在运行命令行程序时载入我的DLL,但就是无法拦截。
    再者,我试过了拦截应用程序调用,用的是LhSetInclusiveACL,而拦截系统调用用的是LhSetExclusiveACL。但两个函数都调用时,只是后调用的函数起作用。无法实现同时拦截。

  18. NeoBetas
    November 20th, 2009 at 00:30 | #18

    您好,

    請教您一個比較題外的問題,如果我不是用VC++寫的程式,有辦法調用gdi++.dll而讓我寫的程式開始執行時原生就有字體渲染的功能嗎?如果可以的話能給點實作的提示嗎?

    謝謝!

  19. November 20th, 2009 at 05:13 | #19

    不是VC++写的,应该有办法调用WIN32 API吧。在程序最开始,用LoadLibrary函数调用把gdi++.dll载入内存,参见 http://is.gd/4Z5Lq

  20. Avatar.tsz
    May 10th, 2010 at 15:30 | #20

    你好, 我想反应一些关于EZGDI的问题, 我是WIN7x64 的用户, 安装了SQL数据库,EZGDI对SQL字体可以渲染,但当我进入SSMS(企业管理器)对数据库点右键属性时,会使Ssms做成崩溃并弹出窗口[尝试读取或写入受保护的内存].这是我证实上述问题的经过:本来一直用EZGDI渲染我喜欢的字体,没有出现过什么问题,但因为需要,安装了SQL数据库,但安装后发现,SQL出现上述的问题,我就立即上百度搜索,一直得不到解决方法,就在这问题耗了几天,最后别无它法,重做系统. 做好系统,立即换字体,用上EZGDI,安装一些常用的软件,最后就安装SQL数据库,噢,晴天霹雳的事情出现了, 打开SSMS对数据库管理,令我抓狂的问题出现了,NND~~~ 再重做系统,好了,吸取教训,第一时间把SQL安装上,再打开SSMS,爽歪歪的,没事,一切正常!!! 那我就一完装软件,就立即创建系统还原点,就这样到最后一步,换字体,安装上EZGDI. 重启后,问题再次出现!!! 我就想,我的妈…没有漂亮字体啦!!! 就把原来字体换回去,EZGDI没有理会,因为有它,字体不会难看. 可是不如意啊,问题还在,我想,不会是它吧(EZGDI). 就把它关闭了…再用试一试的心抬来一遍….竟然成功了….我哭……折腾几天就因为它…请您一定要联络一下EZGDI作者,再修改一下这个问题嘛…麻烦你了..就是觉得EZGDI不错..很有感情, 最后,这么多的字,你能看到这里,十分感谢!!

  21. Avatar.tsz
    May 10th, 2010 at 15:33 | #21

    ;字体载入方法
    ; 0:FreeType 1:WIN32
    FontLoader=1
    把配置更改成这样就没问题了,不过许多字体变得大小不一….好难看…

  22. kelven
    June 3rd, 2010 at 11:42 | #22

    最新版r83无法渲染visual studio 2010 界面,
    望解决!

  23. monkey1107
    October 21st, 2010 at 22:23 | #23

    r87 have a problem with EasyHook32.dll
    EasyHook32.dll > EasyHook32d.dll XD…

  24. xiaotiantian890522
    November 1st, 2010 at 14:33 | #24

    请问有办法只渲染浏览器吗
    我机子安装ezgdi或gdipp都会感到不顺畅
    不知道能不能支持类似http://free.flop.jp/gdi++/的程序
    可以只支持单个程序渲染

Comments are closed.