NT驱动程序和WDM驱动程序的区别
1. Windows驱动程序分为两类,一类是不支持即插即用功能的NT式的驱动程序;另一类是支持即插即用功能的WDM式的驱动程序。
2. NT式的驱动程序要导入的头文件时NTDDK.H,而WDM式的驱动要导入的头文件为WDM.H.
3. DriverEntry需要放在INIT标志的内存中。INIT标志指明该函数只是在加载的时候需要载入内存,而当驱动程序加载成功后,该函数可以从内存中卸载掉。
4.C++编写驱动需要注意:
- #ifdef __cplusplus
- extern “C”
- {
- #endif
- #include <NTDDK.H>
- #ifdef __cplusplus
- }
- #endif
- #pragma INITCODE extern “C” NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath){}
5. 来看一个简单的NT式驱动
Driver.h:
- #pragma once
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #include <NTDDK.h>
- #ifdef __cplusplus
- }
- #endif
- #define PAGEDCODE code_seg("PAGE")
- #define LOCKEDCODE code_seg()
- #define INITCODE code_seg("INIT")
- #define PAGEDDATA data_seg("PAGE")
- #define LOCKEDDATA data_seg()
- #define INITDATA data_seg("INIT")
- #define arraysize(p) (sizeof(p)/sizeof((p)[0]))
- typedef struct _DEVICE_EXTENSION {
- PDEVICE_OBJECT pDevice;
- UNICODE_STRING ustrDeviceName; //设备名称
- UNICODE_STRING ustrSymLinkName; //符号链接名
- } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
- // 驱动函数声明
- NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject);
- VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject);
- NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
- IN PIRP pIrp);
driver.cpp
- /************************************************************************
- * 函数名称:DriverEntry
- * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
- * 参数列表:
- pDriverObject:从I/O管理器中传进来的驱动对象
- pRegistryPath:驱动程序在注册表的中的路径
- * 返回 值:返回初始化驱动状态
- *************************************************************************/
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry (
- IN PDRIVER_OBJECT pDriverObject,
- IN PUNICODE_STRING pRegistryPath )
- {
- NTSTATUS status;
- KdPrint(("Enter DriverEntry\n"));
- //注册其他驱动调用函数入口
- pDriverObject->DriverUnload = HelloDDKUnload;
- pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
- pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
- //创建驱动设备对象
- status = CreateDevice(pDriverObject);
- KdPrint(("DriverEntry end\n"));
- return status;
- }
- /************************************************************************
- * 函数名称:CreateDevice
- * 功能描述:初始化设备对象
- * 参数列表:
- pDriverObject:从I/O管理器中传进来的驱动对象
- * 返回 值:返回初始化状态
- *************************************************************************/
- #pragma INITCODE //指明此函数加载到INIT内存区域(即只在加载的时候需要载入内存,加载成功后可以从内存中卸载掉)
- NTSTATUS CreateDevice (
- IN PDRIVER_OBJECT pDriverObject)
- {
- NTSTATUS status;
- PDEVICE_OBJECT pDevObj;
- PDEVICE_EXTENSION pDevExt;
- //创建设备名称
- UNICODE_STRING devName;
- RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
- //创建设备
- status = IoCreateDevice( pDriverObject,
- sizeof(DEVICE_EXTENSION),
- &(UNICODE_STRING)devName,
- FILE_DEVICE_UNKNOWN,//此种设备为独占设备
- 0, TRUE,
- &pDevObj );
- if (!NT_SUCCESS(status))
- return status;
- pDevObj->Flags |= DO_BUFFERED_IO;
- pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
- pDevExt->pDevice = pDevObj;
- pDevExt->ustrDeviceName = devName;
- //创建符号链接
- UNICODE_STRING symLinkName;
- RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
- pDevExt->ustrSymLinkName = symLinkName;
- status = IoCreateSymbolicLink( &symLinkName,&devName );
- if (!NT_SUCCESS(status))
- {
- IoDeleteDevice( pDevObj );
- return status;
- }
- return STATUS_SUCCESS;
- }
- /************************************************************************
- * 函数名称:HelloDDKUnload
- * 功能描述:负责驱动程序的卸载操作
- * 参数列表:
- pDriverObject:驱动对象
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
- {//遍历系统中所有的此类设备对象,删除设备对象及其符号链接
- PDEVICE_OBJECT pNextObj;
- KdPrint(("Enter DriverUnload\n"));
- pNextObj = pDriverObject->DeviceObject;
- while (pNextObj != NULL)
- {
- PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
- pNextObj->DeviceExtension;
- //删除符号链接
- UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
- IoDeleteSymbolicLink(&pLinkName);
- pNextObj = pNextObj->NextDevice;
- IoDeleteDevice( pDevExt->pDevice );
- }
- }
- /************************************************************************
- * 函数名称:HelloDDKDispatchRoutine
- * 功能描述:对读IRP进行处理
- * 参数列表:
- pDevObj:功能设备对象
- pIrp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
- IN PIRP pIrp)
- {
- KdPrint(("Enter HelloDDKDispatchRoutine\n"));
- NTSTATUS status = STATUS_SUCCESS;
- // 完成IRP
- pIrp->IoStatus.Status = status;
- pIrp->IoStatus.Information = 0; // bytes xfered
- IoCompleteRequest( pIrp, IO_NO_INCREMENT );
- KdPrint(("Leave HelloDDKDispatchRoutine\n"));
- return status;
- }
驱动虽然有了设备名称,但是这种设备名只能在内核态可见,而对于应用程序时不可见的。因此,驱动需要暴露一个符号链接,该链接指向真正的设备名称。
编译好生成的sys文件,我们可以使用 DriverMonitor 加载,加载->启动->停止->卸载。
6.再来看看WDM式驱动有什么不同。头文件就直接忽略了。
DriverEntry入口函数:
- /************************************************************************
- * 函数名称:DriverEntry
- * 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
- * 参数列表:
- pDriverObject:从I/O管理器中传进来的驱动对象
- pRegistryPath:驱动程序在注册表的中的路径
- * 返回 值:返回初始化驱动状态
- *************************************************************************/
- #pragma INITCODE
- extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
- IN PUNICODE_STRING pRegistryPath)
- {
- KdPrint(("Enter DriverEntry\n"));
- pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;
- pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;
- pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
- pDriverObject->MajorFunction[IRP_MJ_CREATE] =
- pDriverObject->MajorFunction[IRP_MJ_READ] =
- pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMDispatchRoutine;
- pDriverObject->DriverUnload = HelloWDMUnload;
- KdPrint(("Leave DriverEntry\n"));
- return STATUS_SUCCESS;
- }
这里增加了一个设置AddDevice回调函数,此回调函数的作用是创建设备对象并由PNP(即插即用)管理器调用。并设置对IRP_MJ_PNP的IRP的回调函数。这都是NT和WDM驱动最大的不同点。而且在WDM驱动中,大部分卸载工作都不是由DriverUnload来处理,而是放在对IRP_MN_REMOVE_DEVICE的IRP的处理函数中处理。
下面是AddDevice回调函数的处理。
- /************************************************************************
- * 函数名称:HelloWDMAddDevice
- * 功能描述:添加新设备
- * 参数列表:
- DriverObject:从I/O管理器中传进来的驱动对象
- PhysicalDeviceObject:从I/O管理器中传进来的物理设备对象
- * 返回 值:返回添加新设备状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PhysicalDeviceObject)
- {
- PAGED_CODE();
- KdPrint(("Enter HelloWDMAddDevice\n"));
- NTSTATUS status;
- PDEVICE_OBJECT fdo;
- UNICODE_STRING devName;
- RtlInitUnicodeString(&devName,L"\\Device\\MyWDMDevice");
- status = IoCreateDevice(
- DriverObject,
- sizeof(DEVICE_EXTENSION),
- &(UNICODE_STRING)devName,
- FILE_DEVICE_UNKNOWN,
- 0,
- FALSE,
- &fdo);
- if( !NT_SUCCESS(status))
- return status;
- PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
- pdx->fdo = fdo;
- pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
- UNICODE_STRING symLinkName;
- RtlInitUnicodeString(&symLinkName,L"\\DosDevices\\HelloWDM");
- pdx->ustrDeviceName = devName;
- pdx->ustrSymLinkName = symLinkName;
- status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);
- if( !NT_SUCCESS(status))
- {
- IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
- status = IoCreateSymbolicLink(&symLinkName,&devName);
- if( !NT_SUCCESS(status))
- {
- return status;
- }
- }
- fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
- fdo->Flags &= ~DO_DEVICE_INITIALIZING;
- KdPrint(("Leave HelloWDMAddDevice\n"));
- return STATUS_SUCCESS;
- }
其中PAGED_CODE是一个DDK提供的宏,只在check版中有效。当此例程所在的中断请求及超过APC_LEVEL时,会产生一个断言。
本例对IRP_MN_REMOVE_DEVICE的处理。
- /************************************************************************
- * 函数名称:HandleRemoveDevice
- * 功能描述:对IRP_MN_REMOVE_DEVICE IRP进行处理
- * 参数列表:
- fdo:功能设备对象
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter HandleRemoveDevice\n"));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- NTSTATUS status = DefaultPnpHandler(pdx, Irp);
- IoDeleteSymbolicLink(&(UNICODE_STRING)pdx->ustrSymLinkName);
- //调用IoDetachDevice()把fdo从设备栈中脱开:
- if (pdx->NextStackDevice)
- IoDetachDevice(pdx->NextStackDevice);
- //删除fdo:
- IoDeleteDevice(pdx->fdo);
- KdPrint(("Leave HandleRemoveDevice\n"));
- return status;
- }
而对卸载例程的处理可以什么都不用做。
其他PNP的IRP如果不需要做处理,那么直接传递到底层驱动,并将底层驱动的结果返回。
- /************************************************************************
- * 函数名称:DefaultPnpHandler
- * 功能描述:对PNP IRP进行缺省处理
- * 参数列表:
- pdx:设备对象的扩展
- Irp:从IO请求包
- * 返回 值:返回状态
- *************************************************************************/
- #pragma PAGEDCODE
- NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP Irp)
- {
- PAGED_CODE();
- KdPrint(("Enter DefaultPnpHandler\n"));
- IoSkipCurrentIrpStackLocation(Irp);
- KdPrint(("Leave DefaultPnpHandler\n"));
- return IoCallDriver(pdx->NextStackDevice, Irp);
- }
安装WDM式驱动需要一个inf文件。inf文件描述了WDM驱动程序的操作硬件设备的信息和驱动程序的一些信息。
可以直接右击这个inf文件进行安装即可。
NT驱动程序和WDM驱动程序的区别相关推荐
- WINDOWS下PCI接口卡WDM驱动程序的DMA编程技术1
摘要: 本文主要讨论了在Windows环境下开发PCI接口卡DMA应用的WDM编程技术,并给出了一个应用DriverWorks和VC++开发的实例程序代码. 关键词:Windows.PCI总线 ...
- WDM驱动程序入门(3)——安装步骤
WDM驱动程序入门(3)--安装步骤 DDK分为98 DDK和2000 DDK两种,它们工作起来是大同小异的,不过有些驱动程序只能在2000 DDK中使用.由于Win98注定是一种即将被淘汰的操作系统 ...
- WDM 驱动程序开发
1.概述 引入了全新的WDM (Win32 Driver Model)的驱动程序架构,说是新技术,其实早在1997年Microsoft就提出了该项技术并在Windows 98中得到了充分的应用,换句 ...
- WDM驱动程序入门(很详细)
WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点.究其原因,还是因为WDM是一种非常"死板板"的程序,它一运行就是工作在系统的底层RIN ...
- WDM驱动程序入门(1)-Hello WDM
WDM驱动程序入门(1)-Hello WDM WDM驱动程序是一种很新的东西,相信很多人都跟我一样,对它很感兴趣,但是又找不到学习的切入点.究其原因,还是因为WDM是一种非常"死板板 ...
- WDM驱动程序介绍(引)
http://zhidao.baidu.com/question/56715021.html WDM(Windows driver model)是微软为开发人员提供的一种编写运行在Windows平台下 ...
- 图形驱动程序和显卡驱动什么区别_我们常说的计算机驱动程序到底是什么,深入解读驱动程序本质...
设备驱动程序通常又被称为设备处理程序,是I/O进程与设备控制器之间的通信程序,主要任务是接受上层软件发来的抽象I/O要求.将它转化为具体要求后,发送给设备控制器,启动设备去执行,也会将设备控制器发来的 ...
- VxWorks设备驱动程序开发指南---驱动程序的分类
8D Spaces Reliability & Stability & Efficiency 目录视图 摘要视图 订阅 VxWorks设备驱动程序开发指南(三)---驱动程序的分类 2 ...
- VxWorks驱动程序开发指南--驱动程序的组织结构
8D Spaces Reliability & Stability & Efficiency 目录视图 摘要视图 订阅 VxWorks驱动程序开发指南(四)--驱动程序的组织结构 20 ...
- USB转WIFI无线网卡驱动程序(RT5370驱动程序)的移植记录之一
学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 今天记录我在I.MX6Q平台移植RT5370无线网卡驱动程序的过程, ...
最新文章
- ProxylessNAS pytorch
- 对的调用没有匹配的函数_前端开发之——函数、事件、js对象
- ubuntu vim php配置文件在哪,ubuntu vim的配置文件在哪
- suitecrm配置(nginx设置)
- django的admin
- 聚合直播源码原生播放器php分享,原生聚合直播搭建源码
- Linux驱动——设备树
- DirectX、Directshow介绍
- 服务器SQL上的MSDTC不可用解决办法
- 年终盘点丨2021边缘计算大事记
- 第八届山东省ACM大学生程序设计竞赛总结
- 【回溯】B033_LQ_填字母游戏(暴搜+注意参数传递机制)
- Winform:自定义滚动条——可自定义皮肤
- 用SVD压缩彩色图片(MATLAB代码)
- 在计算机小三号是多少在英语,计算机的一些常用英语。
- 台式计算机的内存容量,内存容量
- 新手nvm npm 卸载不用依赖包,项识别为 cmdlet、函数、脚本文件,等命令集合
- 【Allegro_SPB_16.6安装详细教程】手把手搭建到Win10
- poky: qmmp_0.5.2.bb的问题以及修改方法。
- 2023新年红包,兔年HTML红包页面代码【2023新年快乐_附源码】
热门文章
- js/vue 动态获取浏览器宽度/高度
- android多个单选框超格,福昕PDF阅读器打印时提示“打印机被意外删除了”怎么处理?...
- GBT9706.1中B型BF型和CF型各表示什么意思?多参监护仪设计
- 《硬件接入》海康威视接入及CPU性能优化思路
- 800元以内创建的双路CPU主机
- aes简单文本加密工具
- 金蝶K3 各个表对应的名称
- u8文件服务器在哪设置,u8 设置文件服务器
- ssh远程连接服务器常用命令
- python调用windows aplication