📄 夜行动物 - 驱动程序简单入门.htm
字号:
IRP_MJ_READ 从设备得到数据 ReadFile <br>
<br>
IRP_MJ_WRITE 传送数据到设备 WriteFile <br>
<br>
IRP_MJ_DEVICE_CONTROL 控制操作(利用IOCTL宏) DeviceIoControl <br>
<br>
IRP_MJ_INTERNAL_DEVICE_CONTROL 控制操作(只能被内核调用) N/A <br>
<br>
IRP_MJ_QUERY_INFORMATION 得到文件的长度 GetFileSize <br>
<br>
IRP_MJ_SET_INFORMATION 设置文件的长度 SetFileSize <br>
<br>
IRP_MJ_FLUSH_BUFFERS 写输出缓冲区或者丢弃输入缓冲区 FlushFileBuffers FlushConsoleInputBuffer PurgeComm <br>
<br>
IRP_MJ_SHUTDOWN 系统关闭 InitiateSystemShutdown<br>
<br>
=================================================================================================================================<br>
<br>
下面开始写我们的驱动版的“Hello World”,程序很简单,先介绍一下流程:<br>
<br>
1,调用IoCreateDevice()创建一个设备,并返回一个设备对象。<br>
2,调用IoCreateSynbolicLink()创建一个符号连接,使Win32程序可以使用驱动程序<br>
3,设置IRP_MJ_DEVICE_CONTROL派遣例程HelloWorldDispatch()和卸载例程HelloWorldUnLoad()。<br>
<br>
如果Win32程序使用DeviceIoControl(),则执行HelloWorldDispatch()函数<br>
4,调用IoGetCurrentIrpStackLocation()得到当前调用者的IRP指针<br>
5,取得IO控制代码,完成后使用IoCompleteRequest()完成IRP操作<br>
<br>
如果使用ControlService()停止驱动程序,则执行HelloWorldUnLoad()函数<br>
4,调用IoDeleteSymbolicLink()删除符号连接<br>
5,调用IoDeleteDevice()删除已建立的设备<br>
<br>
<br>
<br>
驱动入口DriverEntry()<br>
<br>
//创建设备<br>
IoCreateDevice(DriverObject, //驱动程序对象<br>
0, //扩展设备的大小,由于不需要,所以置0<br>
&DeviceNameString, //设备名称<br>
FILE_DEVICE_UNKNOWN, //设备类型<br>
0, //指示设备允许的操作<br>
FALSE, //如果为TRUE,表示只能有一个线程使用该设备,为FALSE,则没有限制<br>
&lpDeviceObject); //返回的设备对象<br>
<br>
//创建符号连接<br>
IoCreateSymbolicLink(&DeviceLinkString, //存放符号连接的UNICODE_STRING<br>
&DeviceNameString); //设备名称<br>
<br>
//派遣例程和卸载例程<br>
DriverObject->MajorFunction[IRP_MJ_CREATE]=<br>
DriverObject->MajorFunction[IRP_MJ_CLOSE]=<br>
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloWorldDispatch;<br>
DriverObject->DriverUnload=HelloWorldUnLoad;<br>
<br>
IRP派遣例程HelloWorldDispatch()<br>
<br>
IrpStack=IoGetCurrentIrpStackLocation(pIrp); //得到当前调用者的IRP堆栈<br>
<br>
//获取IO控制代码,并执行指定操作,这里只是DbgPrint()<br>
IoControlCodes=IrpStack->Parameters.DeviceIoControl.IoControlCode;<br>
switch (IoControlCodes) {<br>
......<br>
<br>
IoCompleteRequest(pIrp,IO_NO_INCREMENT); //完成IRP操作<br>
<br>
卸载例程HelloWorldUnLoad()<br>
<br>
//删除符号连接和设备<br>
IoDeleteSymbolicLink(&DeviceLinkString);<br>
IoDeleteDevice(DriverObject->DeviceObject);<br>
<br>
=================================================================================================================================<br>
<br>
完整代码:<br>
<br>
=================================================================================================================================<br>
<br>
驱动程序的编译需要使用DDK中的build实用程序,它是一个命令行程序,使用不是很方便。VC知识库有一篇在VC++ 6.0中编译驱动的文章,有兴趣可以去看看。<br>
<br>
1,makefile<br>
编译驱动程序,首先应该准备一个makefile,这个文件很简单,只有一句代码:<br>
#<br>
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source<br>
# file to this component. This file merely indirects to the real make file<br>
# that is shared by all the driver components of the Windows NT DDK<br>
#<br>
<br>
!INCLUDE $(NTMAKEENV)\makefile.def<br>
<br>
正如描述的那样,不要修改这个文件---它是通用的!<br>
<br>
2,sources<br>
准备的第二个文件就是sources,它描述了一些编译的细节。针对本文的程序,sources文件的内容是这样的:<br>
TARGETNAME=HelloWorld //驱动名称<br>
TARGETPATH=. //编译后SYS的路径<br>
TARGETTYPE=DRIVER //类型为驱动程序<br>
<br>
SOURCES= HelloWorld.c //只有一个源文件<br>
<br>
有了这2个文件后,就可以使用build进行编译了。进入「开始」菜单\程序\Development Kits\Windows 2000 DDK,<br>
分别有3个CMD程序:1)Checked 64 Bit Build Environment,“Debug”的64位版本;2)Checked Build Environment<br>
“Debug”的32位版本;3)Free Build Environment,“Release”的32位版本。不用说,肯定是使用Free Build Environment。<br>
<br>
New or updated MSVC detected. Updating DDK environment....<br>
<br>
Setting environment for using Microsoft Visual C++ tools.<br>
Starting dirs creation...Completed.<br>
<br>
C:\NTDDK>cd\<br>
<br>
C:\>cd HelloWorld<br>
<br>
C:\HelloWorld>build<br>
BUILD: Object root set to: ==> objfre<br>
BUILD: /i switch ignored<br>
BUILD: Compile and Link for i386<br>
BUILD: Loading c:\NTDDK\build.dat...<br>
BUILD: Computing Include file dependencies:<br>
BUILD: Examining c:\helloworld directory for files to compile.<br>
c:\helloworld - 1 source files (127 lines)<br>
BUILD: Saving c:\NTDDK\build.dat...<br>
BUILD: Compiling c:\helloworld directory<br>
Compiling - helloworld.c for i386<br>
BUILD: Linking c:\helloworld directory<br>
Linking Executable - i386\helloworld.sys for i386<br>
BUILD: Done<br>
<br>
1 file compiled<br>
1 executable built<br>
<br>
C:\HelloWorld><br>
<br>
现在C:\HelloWorld\i386目录下,就有了HelloWorld.sys。<br>
<br>
=================================================================================================================================<br>
<br>
驱动程序的安装如同安装服务一样,唯一不同的是,创建服务时,类型是内核驱动,其他跟操作服务没什么区别。<br>
<br>
安装驱动程序流程:<br>
1,调用OpenSCManager()打开服务控制管理器<br>
2,调用CreateService()创建一个服务,服务类型为内核驱动<br>
3,调用OpenService()取得服务句柄<br>
启动服务<br>
4,调用StartService()启动服务<br>
停止服务<br>
4,调用ControlService()停止服务<br>
删除服务<br>
4,调用DeleteService()删除服务<br>
5,调用CloseServiceHandle()关闭服务句柄<br>
<br>
操作驱动程序流程: <br>
1,调用CreateFile()取得设备句柄<br>
2,调用DeviceIoControl()传递I/O控制代码<br>
3,调用CloseHandle()关闭设备句柄<br>
<br>
http://www.xfocus.net/tools/200411/882.html<br>
这里有一个完整的驱动安装程序,所以我就不写了,只给出操作驱动程序的代码<br>
<br>
完整代码:<br>
<br>
=================================================================================================================================<br>
<br>
参考资料<br>
<br>
《Windows 2000 DDK》<br>
<br>
《Windows 2000 驱动程序设计》<br>
<br>
<br>
附录代码:<br>
<code><OL><LI></LI><LI>#ifndef __HELLOWORLD_C__</LI><LI>#define __HELLOWORLD_C__</LI><LI></LI><LI>#define DEBUGMSG</LI><LI></LI><LI>#include <ntddk.h></LI><LI></LI><LI>#define DEVICE_HELLO_INDEX 0x860</LI><LI></LI><LI>//2个IOCTL宏</LI><LI>#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)</LI><LI>#define STOP_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_HELLO_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)</LI><LI></LI><LI>#define NT_DEVICE_NAME L"\\Device\\HelloWorld" //设备名称</LI><LI>#define DOS_DEVICE_NAME L"\\DosDevices\\HelloWorld" //符号连接</LI><LI></LI><LI>NTSTATUS HelloWorldDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);</LI><LI></LI><LI>VOID HelloWorldUnLoad (IN PDRIVER_OBJECT DriverObject);</LI><LI></LI><LI>//驱动入口</LI><LI>NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)</LI><LI>{</LI><LI> NTSTATUS ntStatus=STATUS_SUCCESS;</LI><LI> PDEVICE_OBJECT lpDeviceObject=NULL; //指向设备对象的指针</LI><LI> UNICODE_STRING DeviceNameString={0}; //设备名称</LI><LI> UNICODE_STRING DeviceLinkString={0}; //符号连接</LI><LI></LI><LI> //调试信息</LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("Starting DriverEntry()\n");</LI><LI> #endif</LI><LI></LI><LI> RtlInitUnicodeString(&DeviceNameString,NT_DEVICE_NAME); //初始化Unicode字符串</LI><LI> //创建设备</LI><LI> ntStatus=IoCreateDevice(DriverObject,0,&DeviceNameString,FILE_DEVICE_UNKNOWN,0,FALSE,&lpDeviceObject);</LI><LI></LI><LI> //使用NT_SUCCESS宏检测函数调用是否成功</LI><LI> if (!NT_SUCCESS(ntStatus))</LI><LI> {</LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("IoCreateDevice() error reports 0x%08X\n",ntStatus);</LI><LI> #endif</LI><LI> return ntStatus;</LI><LI> }</LI><LI></LI><LI> RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);</LI><LI> //创建符号连接</LI><LI> ntStatus=IoCreateSymbolicLink(&DeviceLinkString,&DeviceNameString);</LI><LI></LI><LI> if (!NT_SUCCESS(ntStatus))</LI><LI> {</LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("IoCreateSymbolicLink() error reports 0x%08X\n",ntStatus);</LI><LI> #endif</LI><LI> if (lpDeviceObject)</LI><LI> IoDeleteDevice(lpDeviceObject);</LI><LI> return ntStatus;</LI><LI> }</LI><LI></LI><LI> //设置IRP派遣例程和卸载例程</LI><LI> DriverObject->MajorFunction[IRP_MJ_CREATE]=</LI><LI> DriverObject->MajorFunction[IRP_MJ_CLOSE]=</LI><LI> DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloWorldDispatch;</LI><LI> DriverObject->DriverUnload=HelloWorldUnLoad;</LI><LI></LI><LI> return ntStatus;</LI><LI>}</LI><LI></LI><LI>NTSTATUS HelloWorldDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)</LI><LI>{</LI><LI> NTSTATUS ntStatus=STATUS_SUCCESS;</LI><LI> PIO_STACK_LOCATION IrpStack=NULL; //IRP堆栈</LI><LI> ULONG IoControlCodes=0; //I/O控制代码</LI><LI></LI><LI> //设置IRP状态</LI><LI> pIrp->IoStatus.Status=STATUS_SUCCESS;</LI><LI> pIrp->IoStatus.Information=0;</LI><LI></LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("Starting HelloWorldDispatch()\n");</LI><LI> #endif</LI><LI></LI><LI> IrpStack=IoGetCurrentIrpStackLocation(pIrp); //得到当前调用者的IRP</LI><LI></LI><LI> switch (IrpStack->MajorFunction)</LI><LI> {</LI><LI> case IRP_MJ_CREATE:</LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("IRP_MJ_CREATE\n");</LI><LI> #endif</LI><LI> break;</LI><LI></LI><LI> case IRP_MJ_CLOSE:</LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("IRP_MJ_CLOSE\n");</LI><LI> #endif</LI><LI> break;</LI><LI></LI><LI> case IRP_MJ_DEVICE_CONTROL:</LI><LI></LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("IRP_MJ_DEVICE_CONTROL\n");</LI><LI> #endif</LI><LI></LI><LI> //取得I/O控制代码</LI><LI> IoControlCodes=IrpStack->Parameters.DeviceIoControl.IoControlCode;</LI><LI></LI><LI> switch (IoControlCodes)</LI><LI> {</LI><LI> //启动</LI><LI> case START_HELLPWORLD:</LI><LI> DbgPrint("Starting \"Hello World\"\n");</LI><LI> break;</LI><LI></LI><LI> //停止</LI><LI> case STOP_HELLPWORLD:</LI><LI> DbgPrint("Stoping \"Hello World\"\n");</LI><LI> break;</LI><LI></LI><LI> default:</LI><LI> pIrp->IoStatus.Status=STATUS_INVALID_PARAMETER;</LI><LI> break;</LI><LI> }</LI><LI></LI><LI> break;</LI><LI></LI><LI> default:</LI><LI> break;</LI><LI> }</LI><LI></LI><LI> ntStatus=pIrp->IoStatus.Status;</LI><LI> IoCompleteRequest(pIrp,IO_NO_INCREMENT);</LI><LI></LI><LI> return ntStatus;</LI><LI>}</LI><LI></LI><LI>VOID HelloWorldUnLoad (IN PDRIVER_OBJECT DriverObject)</LI><LI>{</LI><LI> UNICODE_STRING DeviceLinkString={0};</LI><LI> PDEVICE_OBJECT DeviceObjectTemp1=NULL;</LI><LI> PDEVICE_OBJECT DeviceObjectTemp2=NULL;</LI><LI></LI><LI> #ifdef DEBUGMSG</LI><LI> DbgPrint("Starting HelloWorldUnLoad()\n");</LI><LI> #endif</LI><LI></LI><LI> RtlInitUnicodeString(&DeviceLinkString,DOS_DEVICE_NAME);</LI><LI></LI><LI> if (DeviceLinkString.Buffer)</LI><LI> IoDeleteSymbolicLink(&DeviceLinkString);</LI><LI></LI><LI> if (DriverObject)</LI><LI> {</LI><LI> DeviceObjectTemp1=DriverObject->DeviceObject;</LI><LI></LI><LI> while (DeviceObjectTemp1)</LI><LI> {</LI><LI> DeviceObjectTemp2=DeviceObjectTemp1;</LI><LI> DeviceObjectTemp1=DeviceObjectTemp1->NextDevice;</LI><LI> IoDeleteDevice(DeviceObjectTemp2);</LI><LI> }</LI><LI> }</LI><LI>}</LI><LI></LI><LI>#endif</LI><LI></LI><LI></LI></OL></code>
<br>
<br>
用户态程序:<br>
<code><OL><LI></LI><LI>#define DEBUGMSG</LI><LI></LI><LI>#include <windows.h></LI><LI>#include <winioctl.h></LI><LI>#include <stdio.h></LI><LI></LI><LI>#define DEVICE_FILTER_INDEX 0x860</LI><LI></LI><LI>#define START_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_FILTER_INDEX,METHOD_BUFFERED,FILE_ANY_ACCESS)</LI><LI>#define STOP_HELLPWORLD CTL_CODE(FILE_DEVICE_UNKNOWN,DEVICE_FILTER_INDEX+1,METHOD_BUFFERED,FILE_ANY_ACCESS)</LI><LI></LI><LI>#define erron GetLastError()</LI><LI></LI><LI>#define MY_DEVICE_NAME "\\\\.\\HelloWorld"</LI><LI></LI><LI>#define MY_DEVICE_START "-start"</LI><LI>#define MY_DEVICE_STOP "-stop"</LI><LI></LI><LI>BOOL DriverControl (TCHAR *Maik);</LI><LI></LI><LI>void Usage (TCHAR *Paramerter);</LI><LI></LI><LI>int main (int argc,TCHAR *argv[])</LI><LI>{</LI><LI> if (argc!=2)</LI><LI> {</LI><LI> Usage(argv[0]);</LI><LI> return 0;</LI><LI> }</LI><LI></LI><LI> if (strcmpi(argv[1],MY_DEVICE_START)==0 || strcmpi(argv[1],MY_DEVICE_STOP)==0)</LI><LI> DriverControl(argv[1]);</LI><LI> else</LI><LI> {</LI><LI> Usage(argv[0]);</LI><LI> return 0;</LI><LI> }</LI><LI></LI><LI> return 0;</LI><LI>}</LI><LI></LI><LI>BOOL DriverControl (TCHAR *Maik)</LI><LI>{</LI><LI> HANDLE hDevice=NULL; //设备句柄</LI><LI></LI><LI> //获得设备句柄</LI><LI> hDevice=CreateFile(MY_DEVICE_NAME,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);</LI><LI></LI><LI> if (hDevice==INVALID_HANDLE_VALUE)</LI><LI> {</LI><LI> #ifdef DEBUGMSG</LI><LI> printf("CreateFile() GetLastError reports %d\n",erron);</LI><LI> #endif</LI><LI> return FALSE;</LI><LI> }</LI><LI></LI><LI> //启动</LI><LI> if (strcmpi(Maik,MY_DEVICE_START)==0)</LI><LI> {</LI><LI> //传递启动的I/O控制代码</LI><LI> if (!(DeviceIoControl(hDevice,START_HELLPWORLD,NULL,0,NULL,0,NULL,NULL)))</LI><LI> {</LI><LI> #ifdef DEBUGMSG</LI><LI> printf("DeviceIoControl() GetLastError reports %d\n",erron);</LI><LI> #endif</LI><LI> CloseHandle(hDevice);</LI><LI> return FALSE;</LI><LI> }</LI><LI> }</LI><LI></LI><LI> //停止</LI><LI> if (strcmpi(Maik,MY_DEVICE_STOP)==0)</LI><LI> {</LI><LI> //传递停止的I/O控制代码</LI><LI> if (!(DeviceIoControl(hDevice,STOP_HELLPWORLD,NULL,0,NULL,0,NULL,NULL)))</LI><LI> {</LI><LI> #ifdef DEBUGMSG</LI><LI> printf("DeviceIoControl() GetLastError reports %d\n",erron);</LI><LI> #endif</LI><LI> CloseHandle(hDevice);</LI><LI> return FALSE;</LI><LI> }</LI><LI> }</LI><LI></LI><LI> if (hDevice)</LI><LI> CloseHandle(hDevice); //关闭句柄</LI><LI></LI><LI> return TRUE;</LI><LI>}</LI><LI></LI><LI>void Usage (TCHAR *Paramerter)</LI><LI>{</LI><LI> fprintf(stderr,"============================================================================\n"</LI><LI> " 驱动版Hello World\n"</LI><LI> "作者:dahubaob
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -