Delphi驱动开发研究第一篇--实现原理
Delphi能不能开发Windows的驱动程序(这里的驱动程序当然不是指VxD了^_^)一直是广大Delphi fans关注的问题。姑且先不说能或者不能,我们先来看看用Delphi开发驱动程序需要解决哪些技术上问题。
Delphi的链接器是无法生成Windows内核模式程序的,因此用delphi无法直接生成驱动程序。M$的链接器是可以生成Windows内核模式程序的,那么是否可以用Delphi生成目标文件,然后用M$链接呢?要这么做必须要解决以下的问题:
Delphi生成的目标文件是OMF格式的,而M$ link虽然声称支持OMF格式的目标文件,但基本无用。最好能将OMF格式转换成COFF格式,EliCZ大侠的OMF2D正好可以解决这个问题。解决了目标格式的问题,一切都OK了吗?远没这么简单。继续之前,让我们先来看一下著名的DDDK吧。
DDDK(Delphi Driver Development Kit)是The Hacker Defender Project team发布的一个用Delphi开发Windows驱动程序的工具包,目前最新版是0.0.4版。DDDK是将常用的驱动API用Delphi做了层包装放在DDDK单元中,就像下面这样:
| unit DDDK;
interface const procedure IoCompleteRequest(Irp:PIrp;PriorityBoost:Integer); stdcall; |
然后在每次链接驱动文件之前,用omf2d对dddk.obj中需要引入的驱动API做以下的处理:
omf2d inc\DDDK.obj /U- /CEIoCompleteRequest=_IoCompleteRequest@8 2>nul将DDDK.obj中的IoCompleteRequest改成_IoCompleteRequest@8,为什么要这样做呢?那是因为诸如ntoskrnl.lib之类的导入库都是coff格式的,coff格式就是这样命名的。完成这步以后就可以调用m$ link将目标文件链接成驱动文件了。
这样做虽然可以生成正确的驱动文件,但缺点也是明显的。将驱动API用delphi包装,这些用delphi包装的函数不管是否使用都会被链接到最终生成的驱动文件中,这样会增加驱动文件的尺寸,而且通过delphi的封装函数再去调用驱动API效率也会受影响,还有就是每次链接前都要用omf2d inc\DDDK.obj /U- /CEIoCompleteRequest=_IoCompleteRequest@8去转换delphi的目标文件,既麻烦又容易出错。有没有更好的办法呢?
omf2d的工作就是将delphi的命名方法转换成coff的_xxxxxxx@xx格式,默认omf2d会去掉前导下划线和@xx后缀,可以用/U_*开关让omf2d不删除前导下划线,如果我们再有没有@xx后缀的导入库,那问题就简单多了。但m$并没有提供没有@xx后缀的导入库,那就让我们自己做一个吧^_^,其实很简单,比如我们要生成hal.dll的导入库,只需要编辑一个如下内容的hal.def文件:
| LIBRARY HAL.DLL
EXPORTS |
然后用LINK /LIB /MACHINE:IX86 /DEF:hal.def /OUT:hal.lib命令就可以生成我们需要的没有@xx后缀的导入库文件了。有了这个文件,再加上本人开发的rmcoff工具,事情就好办多了。下面就让我们开始用delphi来开发一个简单的驱动程序beeper吧。
这个驱动程序是从Four-F的KmdKit里的beeper转换过来的,程序的目标就是通过访问端口让PC的扬声器发声,程序通过三种方法让扬声器发声,一种是直接访问端口,一种是调用hal.dll的READ_PORT_UCHAR和WRITE_PORT_UCHAR访问端口,第三种方法则是调用hal.dll的HalMakeBeep函数。
| unit beeper;
interface uses windows, DDDK, hal; function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString):NTSTATUS; stdcall; implementation const DELAY:DWORD = $18000000; {for my ~800mHz box} TONE_1:DWORD = 1141; STATUS_DEVICE_CONFIGURATION_ERROR:DWORD = $00C0000182; procedure MakeBeep1(dwPitch: DWORD); stdcall; assembler; sti procedure MakeBeep2(dwPitch: DWORD); stdcall; function _DriverEntry(DriverObject:PDriverObject;RegistryPath:PUnicodeString):NTSTATUS; stdcall; for i := 1 to DELAY do end. |
| unit hal;
interface uses const function HalMakeBeep(Frequency: ULONG):BOOLEAN; stdcall; implementation function HalMakeBeep(Frequency: ULONG):BOOLEAN; stdcall; external NtHal name '_HalMakeBeep'; end. |
1. 用dcc32 –U ..\include -B -CG -JP -$A-,C-,D-,G-,H-,I-,L-,P-,V-,W+,Y- beeper.pas生成目标文件(此处的..\inc是我保存相关delphi单元文件的目录,你的可能不是这个目录哟)
2. 用rmcoff beeper.obj 处理delphi目标文件的相关符号并将目标文件从OMF格式转换成COFF格式,使其能被m$ link链接
3. 用link /NOLOGO /ALIGN:32 /BASE:0x10000 /SUBSYSTEM:NATIVE /DRIVER /ENTRY:DriverEntry ..\lib\hal.lib beeper.obj /OUT:beeper.sys生成最终的驱动文件。执行完以上的步骤,在你的目录下就会生成一个beeper.sys文件了。把它拷贝到KmdKit的beeper目录中,用它的SCP文件加载,PC的喇叭果然发出的清脆的声音,证明我们的delphi驱动是正确的。用此种方法生成的beeper.sys只有1376字节,只比用KmdKit的汇编代码的beeper.sys大几百个字节,而用DDDK生成的beeper.sys则要超过3K。
打完这么多字真不容易,这篇教程就到这里吧,下一篇我们再来用delphi做一个更有趣的东东。
http://blog.csdn.net/sustzw/article/details/6722250
Delphi驱动开发研究第一篇--实现原理的更多相关文章
- Winform常用开发模式第一篇
Winform常用开发模式第一篇 上一篇博客最后我提到“异步编程模型”(APM),之后本来打算整理一下这方面的材料然后总结一下写篇文章与诸位分享,后来在整理的过程中不断的延伸不断地扩展,发现完全偏离了 ...
- 深入理解javascript作用域系列第一篇——内部原理
× 目录 [1]编译 [2]执行 [3]查询[4]嵌套[5]异常[6]原理 前面的话 javascript拥有一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量,这套规则被称为作用域.作用域 ...
- Python开发【第一篇】:目录
本系列博文包含 Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习编程的童鞋提供一点帮助!!! Python开发[第一篇]:目录 Python开发[第二篇]:初识Python ...
- EnjoyingSoft之Mule ESB开发教程第一篇:初识Mule ESB
目录 1. Mule ESB基本介绍 2. Mule ESB社区版和企业版 3. Mule ESB常用场景 4. Mule ESB软件安装 客户端安装 服务端安装 5. 第一个Mule ESB应用- ...
- Python开发【第一篇】:目录
本系列博文包含Python基础.前端开发.Web框架.缓存以及队列等,希望可以给正在学习Python编程的朋友们提供一点帮助! .Python开发[第一篇]:目录 .Python开发[第二篇]:初始P ...
- .net开发笔记(十三) Winform常用开发模式第一篇
上一篇博客最后我提到“异步编程模型”(APM),之后本来打算整理一下这方面的材料然后总结一下写篇文章与诸位分享,后来在整理的过程中不断的延伸不断地扩展,发现完全偏离了“异步编程”这个概念,前前后后所有 ...
- [转载] Android Metro风格的Launcher开发系列第一篇
前言:从毕业到现在已经三年多了,回忆一下这三年基本上没有写过博客,总是觉得忙,没时间写,也觉得写博客没什么大用.但是看到很多大牛们都在写博客,分享自己的东西,所以嘛本着向大牛看齐,分享第一,记录第二的 ...
- Android Metro风格的Launcher开发系列第一篇
前言:从毕业到现在已经三年多了,回忆一下这三年基本上没有写过博客,总是觉得忙,没时间写,也觉得写博客没什么大用.但是看到很多大牛们都在写博客,分享自己的东西,所以嘛本着向大牛看齐,分享第一,记录第二的 ...
- 《Android深度探索HAL与驱动开发》第一章阅读心得
首先了解到Android系统架构是由四层构成:其中第一层是Linux内核,他的作用是负责Linux的驱动程序以及内存.进程.电源等管理操作:第二层是C/C++代码库,也就是Linux下.so的文件:第 ...
随机推荐
- 买不起360随声wifi怎么办?这些都不是问题
只需轻松一步,点击开启共享 软件下载地址:http://download.csdn.net/detail/lxq_xsyu/6384265 如果身边没有数据线怎么办?? 使用方法: 1.用手机连接Wi ...
- asp.net中c#求百分比
double m= 50;double n= 100; Response.Write((m/ (m+ n)).ToString("0%"));Response.Write((m/ ...
- 【转】mysql的SQL_NO_CACHE(在查询时不使用缓存)和sql_cache用法
转自:http://www.169it.com/article/5994930453423417575.html 为了测试sql语句的效率,有时候要不用缓存来查询. 使用 SELECT SQL_NO_ ...
- 数据中台解析Hive SQL过程
一.数据中台解析SQL的目的: 数据中台需要对外提供数据特征查询的能力,因此中台查找并解析各个平台的sql,找出哪些表中的字段经常被使用,以便沉淀为特征,而我们要做的是找出sql中的数据表及其字段.以 ...
- 取消scrollView上下拉升
if (ios_Vewsion_5_Or_Above) { _scrollView.bounces = NO; } else { for (id subview in _scrollView.subv ...
- Linux性能测试 ss命令
ss即socket state,也就是说,是可以查看系统中socket的状态的.我们可以用netstat,但为什么还要用ss这个工具呢,当然ss也是有好处的.当我们打开的socket数量很多时,net ...
- Python 辨异 —— __init__ 与 __new__
__init__ 更多的作用是初始化属性,__new__ 进行的是创建对象,显然 __new__ 要早于 __init__ 发生. 考虑一个继承自 tuple 的类,显然在 __init__ 无法对其 ...
- WPF Clip实现百叶窗
原文:WPF Clip实现百叶窗 效果图; 后台代码: public MainWindow() { InitializeComponent(); ...
- 非参贝叶斯(Bayesian Non-parameter)初步
0. motivations 如何确定 GMM 模型的 k,既观察到的样本由多少个高斯分布生成.由此在数据属于高维空间中时,根本就无法 visualize,更加难以建立直观,从而很难确定 k,高斯分布 ...
- GoldenGate过程 abend,报错OGG-00868 ORA-02396: Exceeded Maximum Idle Time, Please Connect Again
GoldenGate过程 abend,报错OGG-00868 ORA-02396: Exceeded Maximum Idle Time, Please Connect Again 参考原始: Gol ...