📄 夜行动物 - 驱动程序简单入门.htm
字号:
<tr>
<td align="center">
<a href="http://www.showlife8.com/" title="showlife's blog" target="_blank">showlife's blog</a>
</td>
</tr>
<tr>
<td align="center">
<a href="http://netxfly.blogbus.com/" title="netxfly" target="_blank">netxfly's blog</a>
</td>
</tr>
<tr>
<td align="center">
<a href="http://www.16198.com/shift/blog1/" title="haicao" target="_blank">haicao's blog</a>
</td>
</tr>
<tr>
<td align="center">
<a href="http://heijin.blogchina.com/" title="exploit's blog" target="_blank">exploit's blog</a>
</td>
</tr>
<tr>
<td align="center">
<a href="http://blog.csdn.net/hkbyest/" title="落叶树的BLOG" target="_blank">落叶树的BLOG</a>
</td>
</tr>
</table></td>
<td width="3" background="images/table1bg_4.gif"></td>
</tr>
</table>
<table width="170" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="3"><IMG SRC="images/table1di_1.gif" WIDTH=3 HEIGHT=18 ALT=""></td>
<td background="images/table1di_2.gif"> </td>
<td width="12"><IMG SRC="images/table1di_4.gif" WIDTH=12 HEIGHT=18 ALT=""></td>
<td width="70" align="right" background="images/table1di_6.gif"><a href="link.asp" OnmouseOver="window.status='在本站申请一个链接。';return true;"
OnMouseOut="window.status='';">申请链接</a></td>
<td width="4"><IMG SRC="images/table1di_7.gif" WIDTH=3 HEIGHT=18 ALT=""></td>
</tr>
</table></td>
</tr>
</table>
</td>
<td align="right" valign="top"><table width="100%" border="0" cellspacing="5">
<tr>
<td><table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="4"><IMG SRC="images/table1top_1.gif" WIDTH=4 HEIGHT=25 ALT=""></td>
<td width="600" background="images/table1top_3.gif" class="table_name"><img src="images/mnuCopy.gif" width="16" height="16" border="0" alt=""> 驱动程序简单入门</td>
<td width="15"><IMG SRC="images/table1top_5.gif" WIDTH=15 HEIGHT=25 ALT=""></td>
<td background="images/table1top_7.gif"> </td>
<td width="24" align="right"><IMG SRC="images/table1top_8.gif" WIDTH=24 HEIGHT=25 ALT=""></td>
</tr>
</table>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="3" background="images/table1bg_1.gif"></td>
<td background="images/table1bg_2.gif">
<table width="100%" border="0" cellspacing="5">
<tr>
<td >
<div id="info" ><font id="main" >我们学习程序设计,都是从“Hello World”开始的,驱动程序也不例外,今天我就写一个驱动版的“Hello World”来热热身,目的希望大家能对驱动程序的基本框架有所了解。<br>
<br>
<br>
驱动程序分为2类,一个是Kernel模式驱动,另一个是Windows模式驱动,2种模式本质是相同,但细节不同,本文介绍的是内核模式驱动和驱动程序的安装、使用。<br>
<br>
<br>
驱动程序同普通的EXE,DLL一样,都属于PE文件,而且都有一个入口函数。但EXE中,入口函数是main()/WinMain()和Unicode的wmain()/wWinmain(),DLL的入口函数<br>
则可有可无,它是DllMain()。驱动程序也有入口函数,而且是必须的,它是DriverEntry(),再次提示,它是必须的,因为I/O管理器会首先调用驱动程序的DriverEntry()<br>
,它的作用就像DllMain()--完成一些初始化工作。DriverEntry()一共有2个参数:1)PDRIVER_OBJECT DriverObject,指向驱动程序对象的指针,我们操作驱动程序,<br>
全靠它,它是由I/O管理器传递进来的;2)PUNICODE_STRING RegistryPath,驱动程序的服务主键,这个参数的使用并不多,但要注意,在DriverEntry()返回后,它可能<br>
会消失,所以如果需要使用,记住先要保存下来。DriverEntry()的返回一个NTSTATUS值,它是一个ULONG值,具体的定义,请参见DDK中的NTSTATUS.H头文件,里边有详细<br>
的定义。<br>
<br>
<br>
<br>
既然要写驱动版的“Hello World”,就需要确定如何来与驱动程序通信,常用的共享内存,共享事件,IOCTL宏,或者直接用ReadFile()或WriteFile()进行读写,在本文<br>
<br>
里我就采用一种简单的、但又很常用的IOCTL宏,它依赖的IRP派遣例程是IRP_MJ_DEVICE_CONTROL,Win32程序使用DeviceIoControl()与驱动进行通信,根据不同的IOCTL宏,<br>
<br>
输出不同的调试信息。为了简便,我并没有使用ReadFile()将信息读出来,而是直接用DbgPrint()输出,所以需要使用DbgView查看,其他调试工具也可以。PS:偷懒!<br>
<br>
<br>
驱动程序与I/O管理器通信,使用的是IRP,即I/O请求包。IRP分为2部分:1)IRP首部;2)IRP堆栈。IRP首部信息如下:<br>
<br>
IRP首部:<br>
<br>
IO_STATUS_BLOCK IoStatus 包含I/O请求的状态 <br>
<br>
PVOID AssociatedIrp.SystemBuffer 如果执行缓冲区I/O,这个指针指向系统缓冲区 <br>
<br>
PMDL MdlAddress 如果直接I/O,这个指针指向用户缓冲区的存储器描述符表 <br>
<br>
PVOID UserBuffer I/O缓冲区的用户空间地址<br>
<br>
IRP堆栈:<br>
<br>
UCHAR MajorFunction 指示IRP_MJ_XXX派遣例程 <br>
<br>
UCHAR MinorFunction 同上,一般文件系统和SCSI驱动程序使用它 <br>
<br>
union Parameters MajorFunction的联合类型 <br>
{ <br>
struct Read IRP_MJ_READ的参数 <br>
ULONG Length <br>
ULONG Key <br>
LARGE_INTEGER ByteOffset <br>
<br>
struct Write IRP_MJ_WRITE的参数 <br>
ULONG Length <br>
ULONG Key <br>
LARGE_INTEGER ByteOffset <br>
<br>
struct DeviceIoControl IRP_MJ_DEVICE_CONTROL和IRP_MJ_INTERNAL_DEVICE_CONTROL的参数 <br>
ULONG OutputBufferLength <br>
ULONG InputBufferLength <br>
ULONG IoControlCode <br>
PVOID Type3InputBuffer <br>
} <br>
PDEVICE_OBJECT DeviceObject 请求的目标设备对象的指针 <br>
<br>
PFILE_OBJECT FileObject 请求的目标文件对象的指针,如果有的话<br>
<br>
<br>
<br>
操作IRP。对于不同的IRP函数,操作也是不同的:有的只操作IRP首部;有的只操作IRP堆栈;还有操作IRP整体,<br>
<br>
下面是一些常用的函数:<br>
<br>
IRP整体:<br>
<br>
名称 描述 调用者<br>
IoStartPacket 发送IRP到Start I/O例程 Dispatch <br>
<br>
IoCompleteRequest 表示所有的处理完成 DpcForIsr <br>
<br>
IoStartNextPacket 发送下一个IRP到Start I/O例程 DpcForIsr <br>
<br>
IoCallDriver 发送IRP请求 Dispatch <br>
<br>
IoAllocateIrp 请求另外的IRP Dispatch <br>
<br>
IoFreeIrp 释放驱动程序分配的IRP I/O Completion <br>
<br>
IRP堆栈:<br>
<br>
名称 描述 调用者<br>
IoGetCurrentIrpStackLocation 得到调用者堆栈的指针 Dispatch <br>
<br>
IoMarkIrpPending 为进一步的处理标记调用者I/O堆栈 Dispatch <br>
<br>
IoGetNextIrpStackLocation 得到下一个驱动程序的I/O堆栈的指针 Dispatch <br>
<br>
IoSetNextIrpStackLocation 将I/O堆栈指针压入堆栈 Dispatc<br>
<br>
在驱动程序,IRP派遣例程起着很重要的作用,每个IRP派遣例程,几乎都有对应的Win32函数,下面是几个常用的:<br>
<br>
IRP派遣例程:<br>
<br>
名称 描述 调用者<br>
IRP_MJ_CREATE 请求一个句柄 CreateFile <br>
<br>
IRP_MJ_CLEANUP 在关闭句柄时取消悬挂的IRP CloseHandle <br>
<br>
IRP_MJ_CLOSE 关闭句柄 CloseHandle <br>
<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -