首先需要安装DDK,这里我选择Microsoft Windows Server 2003 SP1 DDK

Windows驱动分成两类,一类是不支持即插即用的NT式驱动,一类是支持即插即用的WDM驱动.

首先来看一个最简单的NT式驱动。

  1. #pragma once
  2. #ifdef __cplusplus
  3. extern "C"
  4. {
  5. #endif
  6. #include <NTDDK.h>
  7. #ifdef __cplusplus
  8. }
  9. #endif
  10. #define PAGEDCODE code_seg("PAGE")
  11. #define LOCKEDCODE code_seg()
  12. #define INITCODE code_seg("INIT")
  13. #define PAGEDDATA data_seg("PAGE")
  14. #define LOCKEDDATA data_seg()
  15. #define INITDATA data_seg("INIT")
  16. #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
  17. typedef struct _DEVICE_EXTENSION {
  18. PDEVICE_OBJECT pDevice;
  19. UNICODE_STRING ustrDeviceName;    //设备名称
  20. UNICODE_STRING ustrSymLinkName;    //符号链接名
  21. } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  22. // 驱动函数声明
  23. NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
  24. VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
  25. NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
  26. IN PIRP pIrp);

Driver.h头文件中包含了开发NT式驱动所需要的NTDDK.h,此外还定义了几个标志来指明函数和变量分配在分页内存还是非分页内存中。Windows驱动程序的入口函数是DriverEntry函数,

  1. #include "Driver.h"
  2. /************************************************************************
  3. * 函数名称:DriverEntry
  4. * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
  5. * 参数列表:
  6. pDriverObject:从I/O管理器中传进来的驱动对象
  7. pRegistryPath:驱动程序在注册表的中的路径
  8. * 返回 值:返回初始化驱动状态
  9. *************************************************************************/
  10. #pragma INITCODE
  11. extern "C" NTSTATUS DriverEntry (
  12. IN PDRIVER_OBJECT pDriverObject,
  13. IN PUNICODE_STRING pRegistryPath    )
  14. {
  15. NTSTATUS status;
  16. KdPrint(("Enter DriverEntry\n"));
  17. //注册其他驱动调用函数入口
  18. pDriverObject->DriverUnload = HelloDDKUnload;
  19. pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
  20. pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
  21. pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
  22. pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
  23. //创建驱动设备对象
  24. status = CreateDevice(pDriverObject);
  25. KdPrint(("DriverEntry end\n"));
  26. return status;
  27. }
  28. /************************************************************************
  29. * 函数名称:CreateDevice
  30. * 功能描述:初始化设备对象
  31. * 参数列表:
  32. pDriverObject:从I/O管理器中传进来的驱动对象
  33. * 返回 值:返回初始化状态
  34. *************************************************************************/
  35. #pragma INITCODE   //指明此函数加载到INIT内存区域(即只在加载的时候需要载入内存,加载成功后可以从内存中卸载掉)
  36. NTSTATUS CreateDevice (
  37. IN PDRIVER_OBJECT    pDriverObject)
  38. {
  39. NTSTATUS status;
  40. PDEVICE_OBJECT pDevObj;
  41. PDEVICE_EXTENSION pDevExt;
  42. //创建设备名称
  43. UNICODE_STRING devName;
  44. RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
  45. //创建设备
  46. status = IoCreateDevice( pDriverObject,
  47. sizeof(DEVICE_EXTENSION),
  48. &(UNICODE_STRING)devName,
  49. FILE_DEVICE_UNKNOWN,//此种设备为独占设备
  50. 0, TRUE,
  51. &pDevObj );
  52. if (!NT_SUCCESS(status))
  53. return status;
  54. pDevObj->Flags |= DO_BUFFERED_IO;
  55. pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
  56. pDevExt->pDevice = pDevObj;
  57. pDevExt->ustrDeviceName = devName;
  58. //创建符号链接
  59. UNICODE_STRING symLinkName;
  60. RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
  61. pDevExt->ustrSymLinkName = symLinkName;
  62. status = IoCreateSymbolicLink( &symLinkName,&devName );
  63. if (!NT_SUCCESS(status))
  64. {
  65. IoDeleteDevice( pDevObj );
  66. return status;
  67. }
  68. return STATUS_SUCCESS;
  69. }
  70. /************************************************************************
  71. * 函数名称:HelloDDKUnload
  72. * 功能描述:负责驱动程序的卸载操作
  73. * 参数列表:
  74. pDriverObject:驱动对象
  75. * 返回 值:返回状态
  76. *************************************************************************/
  77. #pragma PAGEDCODE
  78. VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
  79. {//遍历系统中所有的此类设备对象,删除设备对象及其符号链接
  80. PDEVICE_OBJECT    pNextObj;
  81. KdPrint(("Enter DriverUnload\n"));
  82. pNextObj = pDriverObject->DeviceObject;
  83. while (pNextObj != NULL)
  84. {
  85. PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
  86. pNextObj->DeviceExtension;
  87. //删除符号链接
  88. UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
  89. IoDeleteSymbolicLink(&pLinkName);
  90. pNextObj = pNextObj->NextDevice;
  91. IoDeleteDevice( pDevExt->pDevice );
  92. }
  93. }
  94. /************************************************************************
  95. * 函数名称:HelloDDKDispatchRoutine
  96. * 功能描述:对读IRP进行处理
  97. * 参数列表:
  98. pDevObj:功能设备对象
  99. pIrp:从IO请求包
  100. * 返回 值:返回状态
  101. *************************************************************************/
  102. #pragma PAGEDCODE
  103. NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
  104. IN PIRP pIrp)
  105. {
  106. KdPrint(("Enter HelloDDKDispatchRoutine\n"));
  107. NTSTATUS status = STATUS_SUCCESS;
  108. // 完成IRP
  109. pIrp->IoStatus.Status = status;
  110. pIrp->IoStatus.Information = 0;    // bytes xfered
  111. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  112. KdPrint(("Leave HelloDDKDispatchRoutine\n"));
  113. return status;
  114. }

有两种编译驱动的办法,一种是用DDK环境来编译,需要在源代码所在目录下创建两个文件makefile和Sources,

makefile内容如下,功能是引入DDK的bin目录下的makefile.def文件:

  1. !INCLUDE $(NTMAKEENV)\makefile.def

Sources内容如下:

  1. TARGETNAME=HelloDDK
  2. TARGETTYPE=DRIVER
  3. TARGETPATH=OBJ
  4. INCLUDES=$(BASEDIR)\inc;\
  5. $(BASEDIR)\inc\ddk;\
  6. SOURCES=Driver.cpp\

然后在开始菜单中选择“Windows XP Checked Build Environment”编译环境,进入需要编译的目录,输入”build“命令就可以,

编译后的驱动位于objchk_wxp_x86"i386目录下,名为HelloDDK.sys

第二种编译方式是使用VC++进行编译

1,用vc新建工程。在"project"选项卡中,选择win32 Application,选择一个空的工程。
2,将两个源文件Driver.h和Driver.cpp拷贝到工程目录中,并添加到工程中。
3,增加新的编译版本,去掉Debug 和Release 版本,增加一个Win32 Driver Check Edition

4,修改工程属性。选择"Project|Setting",或者直接按下Alt+F7键,弹出"Project Settings"。在对话框中,选择“General”选项卡。将Intermediate files和Output files都改为MyDriver_Check.
5,选择C/C++选项卡,将原有的Project Options 内容全部删除替换成如下内容:

  1. /nologo /Gz /MLd /W3 /WX /Z7 /Od /D WIN32=100 /D _X86_=1 /D WINVER=0x500 /D DBG=1 /Fo"MyDriver_Check/" /Fd"MyDriver_Check/" /FD /c

6,选择Link选项卡,将原有的Project Options 内容全部删除,替换成如下内容:

  1. ntoskrnl.lib /nologo /base:"0x10000" /stack:0x400000,0x1000 /entry:"DriverEntry" /subsystem:console /incremental:no /pdb:"MyDriver_Check/HelloDDK.pdb" /map:"MyDriver_Check/HelloDDK.map" /debug /machine:I386 /nodefaultlib /out:"MyDriver_Check/HelloDDK.sys" /pdbtype:sept /subsystem:native /driver /SECTION:INIT,D /RELEASE /IGNORE:4078

7。修改VC的lib目录和include目录。

在vc中选择"Tools"|"Options",在弹出的对话框中选择“Directories”选项卡。在“Show directories for”下拉菜单中选择“Include files”菜单,添加

  1. D:\WINDDK\3790.1830\INC\W2K

  1. D:\WINDDK\3790.1830\INC\DDK\W2K

并将这两个目录置于最上。

在"Show directories for "下拉菜单中选择“Library files”菜单,添加目录

  1. D:\WINDDK\3790.1830\LIB\W2K\I386

并置于最上端。
8,按照书上所述的步骤做完后编译,会报错如下:

  1. fatal error C1083: Cannot open include file: 'specstrings.h': No such file or directory

原因是include目录设置没完整,加入如下目录既可以正确编译

  1. D:\WINDDK\3790.1830\INC\CRT

最后来安装此驱动,这里使用Driver Studio3.2.1中的Driver Monitor来完成

转载于:https://blog.51cto.com/phinecos/368163

《Windows驱动开发技术详解》读书笔记(一)相关推荐

  1. mysql数据库权威指南_MySQL_MySQL权威指南读书笔记(三),第二章:MYSQL数据库里面的数 - phpStudy...

    MySQL权威指南读书笔记(三) 第二章:MYSQL数据库里面的数据 用想用好MYSQL,就必须透彻理解MYSQL是如何看待和处理数据的.本章主要讨论了两个问题:一是SQL所能处理的数据值的类型:二是 ...

  2. MongoDB权威指南读书笔记——CRUD

    插入并保存文档 插入是向MongoDB中添加数据的基本方法.可以使用Insert方法向目标集合插入一个文档:db.foo.insert({"bar" : "baz&quo ...

  3. HTTP权威指南读书笔记

    <<HTTP权威指南>>读书笔记 第一部分:Web的基础 第1章:HTTP概述 主要内容 1.什么是HTTP 2.HTTP的基本组件 HTTP HTTP:HTTP(Hypert ...

  4. HTML5权威指南----读书笔记

    <!DOCTYPE html> <html> <head><meta name = 'keywords' content="HTML5权威指南--- ...

  5. 计算机网络和http权威指南 读书笔记

    计算机网络笔记 网络层 网络层向上提供无连接的,尽最大努力交付的数据报服务 网络层不提供数据质量承诺 物理层使用的中间设备叫转发器repeater 数据链路层叫网桥bridge 网络层叫路由器rout ...

  6. MapReduce总结 + 相关Hadoop权威指南读书笔记(未完......欢迎补充,互相学习)

    文章目录 MapReduce概述 MapReduce优缺点 MapReduce核心思想 MapReduce进程 MapReduce编程规范 WordCount 案例实操 本地测试 集群测试 Hadoo ...

  7. android开发读书笔记,android开发权威指南读书笔记

    第17章 Fragment 1.在res目录下增加 layout-sw600dp 目录,用于存放7英寸及以上尺寸屏幕的布局文件.10英寸以上平板用 sw720dp.如果是更小的屏幕,如 480*800 ...

  8. java性能权威指南中文_Java性能权威指南读书笔记--之一

    JIT(即时编译) 解释型代码:程序可移植,相同的代码在任何有适当解释器的机器上,都能运行,但是速度慢. 编译型代码:速度快,电视不同CPU平台的代码无法兼容. java则是使用java的编译器先将其 ...

  9. javascript权威指南读书笔记之二——词法结构

    本章讲述的内容,用通俗的语言来说,就是应该注意的地方,这些也许和我们所学的其他语言类似,也许完全不同,比如一开始就介绍说javascript程序中的每个字符都是用两个字节表示的,但有些程序设计者习惯于 ...

  10. HTTP权威指南读书笔记(一)HTTP概述、URL和资源及报文详解

    一.HTTP概述 1.WEB客户端和服务器. 2.资源:资源可以是各种格式的静态文件,也可以是应用程序. 3.媒体类型 4.URI:统一资源标识符 URL:统一资源定位符. URL的第一部分称为方案: ...

最新文章

  1. Appium如何获取appPackage和appActivity
  2. Oracle常用知识
  3. nginx文件系统大小_Nginx 了解一下?
  4. 【LeetCode】12. Integer to Roman 整型数转罗马数
  5. hive-2.3.3安装指北
  6. jar包引用版本不一致引发的问题
  7. D3DXIntersectTri 求三角形与射线相交
  8. 运用正则表达式在Asp中过滤Html标签代码的四种不同方法
  9. 宝塔面板部署python项目
  10. android 启动界面修改工具下载,安卓开机画面更改软件
  11. Photoshop CS3 Dreamwaver教程集合
  12. 小米怎么和计算机连接网络连接网络,电脑怎么连接小米路由器上网
  13. centos8修改主机名称
  14. 微信Android热补丁方案Tinker
  15. Gartner发布2022年中国智慧城市和可持续发展技术成熟度曲线
  16. 关于win11兼容性视图模式
  17. qt mingw32编译项目报错:Nothing to be done for 'first'.
  18. 中国职业教育政策解读 | 职业教育系列报告(三)
  19. 利用python目录化整理PPT素材文件
  20. uni-app升级APP,包含apk整包升级和wgt应用资源升级

热门文章

  1. C#之Directory类、DirectoryInfo类和Fileinfo,File以及FilesSystemInfo
  2. C# 中对WinForm窗体中的控件快速设置TableIndex次序
  3. 推荐的 CSS 书写顺序
  4. 自定义Background
  5. TensorFlow – A Collection of Resources
  6. Python常用语句及流程控制
  7. keepalived之 Keepalived 原理(定义、VRRP 协议、VRRP 工作机制)
  8. Python~第三方模块
  9. WinObjC?这是什么鬼?
  10. 计数排序,基数排序,桶排序