Windows驱动程序设计入门
- 格式:ppt
- 大小:569.05 KB
- 文档页数:36
课程内容驱动基本概念介绍驱动核心代码分析WDM和WDF介绍Windows 10通用驱动平台驱动程序是一个软件模块,可以使操作系统和硬件设备进行交互驱动程序是操作系统的一个扩展驱动程序一般是由硬件的设计者或厂商进行编写Microsoft已经为符合公共设计规范的硬件设备提供了内置的驱动程序可执行文件,扩展名是.exe入口函数是Main()Main()函数完成大部分工作应用程序完成工作后返回,并释放内存空间在用户态运行可执行文件,扩展名是.sys入口函数是DriverEntry()DriverEntry()不会做很多工作,只是初始化驱动驱动其他部分会注册很多回调函数,会被系统的不同模块调用驱动不会返回,会一直存在直至被显示的释放在内核态或用户态运行Driver StacksPDO位于驱动栈的最底层,和总线驱动相关联当总线驱动被加载时,它会枚举所有挂载在总线上面的设备并请求设备所需要的资源每个设备都有自己对应的PDOPnP管理器会确定每个设备的驱动并在设备的PDO 之上构建适当的设备栈设备栈的核心部分,FDO和设备功能驱动相关联设备功能驱动完成Windows和设备交互的核心功能对上向应用程序和服务提供上层接口对下为设备或其他驱动提供数据交换的接口一个设备栈可以包含多个FiDO,可以在FDO之上或之下每个FiDO和一个过滤驱动相关联,FiDO是可选的通常的目的是修改一些在设备栈中传输的I/O请求,例如可以加密和解密读写请求当一个新设备被插入到系统后,系统总线驱动会向PnP管理器报告这个新设备PnP管理器通过总线驱动查询这个设备的更多信息,比如设备ID和设备所需要的资源PnP管理器利用这个信息去查找是否有有对应的驱动在本地或WU(Windows Update)上面一旦查找到设备对应的驱动,Windows便会安装并加载这个驱动加载驱动到地址空间解析驱动中引入的函数-调用其他模块调用驱动的入口函数(DriverEntry()),因此驱动可以注册回调函数调用AddDevice(),驱动此时可以创建一个“设备对象”,并将这个对象加入到设备栈中所有的事物在驱动框架中都是用对象呈现的(驱动,设备,请求等等)对象拥有属性,方法和事件WDF 对象方法属性事件操作对象的函数被WDF 框架调用用于通知某些事件设置或获取单个属性值的方法Driver (WDFDRIVER)Device (WDFDEVICE)Device (WDFDEVICE)Queue (WDFQUEUE)Queue (WDFQUEUE)……ObjectOperation方法:Status = Wdf Device Create ();属性:Cannot failWdfInterrupt Get Device();WdfInterrupt Set Policy();Can fail:Status = WdfRegistry Assign Value();Status = WdfRegistry Query Value();Status = WdfRequest Retrieve InputBuffer();回调事件:PFN_WDF_INTERRUPT_ENABLE EvtInterruptEnable初始化宏:WDF_XXX_CONFIG_INITWDF_XXX_EVENT_CALLBACKS_INIT当驱动被加载时,DriverEntry是第一个被操作系统调用的函数WdfDriverCreate( RawDriverObject, […] , attributes, &driver )NTSTATUS DriverEntry(_In_PDRIVER_OBJECT DriverObject ,_In_PUNICODE_STRING RegistryPath ) {[…]// Create WDF Driver ObjectWDF_OBJECT_ATTRIBUTES_INIT(&attributes);attributes.EvtDriverUnload = OnDriverUnload;WDF_DRIVER_CONFIG_INIT(&config, OnDeviceAdd);status = WdfDriverCreate(DriverObject ,RegistryPath ,&attributes,&config,&driver );}WDF EventWDF MethodWDF ObjectDeclare vars这是一个过滤驱动程序吗?驱动程序是电源管理策略的所有者吗?为设备对象创建I/O队列创建辅助对象,例如计时器,工作者对象,锁等NTSTATUS OnDeviceAdd( WDFDRIVER Driver,PWDFDEVICE_INIT DeviceInit) {WDFDEVICE device;IWDFIoQueue* pDefaultQueue= NULL;DeviceInit->SetPowerPolicyOwnership(TRUE );status= WdfDeviceCreate(&DeviceInit,&deviceAttributes, &device);context = GetContext(device);context->WdfDevice= device;status = pIWDFDevice->CreateIoQueue(NULL, TRUE, WdfIoQueueDispatchParallel,TRUE, FALSE, &pDefaultQueue);return status;}Static Configuration Device CreateSetting ContextQueue Create进入电源状态管理(D0Entry)使能中断(InterruptEnable)…获取硬件资源,进行一些静态配置,(PrepareHardware)进入电源状态管理(D0Entry)使能中断(InterruptEnable)…获取硬件资源,进行一些静态配置,(PrepareHardware)NTSTATUS OnPrepareHardware(WDFDEVICE Device ,WDFCMRESLIST ResourcesRaw ,WDFCMRESLIST ResourcesTranslated ) {int ResourceCount = WdfCmResourceListGetCount(ResourcesTranslated );for (i=0; i < ResourceCount; i++) {descriptor =WdfCmResourceListGetDescriptor(ResourcesTranslated , i);switch (descriptor->Type) {case CmResourceTypePort : […]case CmResourceTypeMemory : […]case CmResourceTypeInterrupt : […]default : break ;}}return STATUS_SUCCESS ;}进入电源状态管理(D0Entry)使能中断(InterruptEnable)…获取硬件资源,进行一些静态配置,(PrepareHardware)NTSTATUS OnD0Entry(IN WDFDEVICE Device ,IN WDF_POWER_DEVICE_STATE RecentPowerState ){PADXL345AccDevice pAccDevice = nullptr pAccDevice = GetContext(Device);WdfWaitLockAcquire(pAccDevice->m_WaitLock);I2CSensorWriteRegister(pAccDevice->m_I2CIoTarget, MY_REGISTER,MY_VALUE, sizeof (MY_VALUE) );pAccDevice->m_PoweredOn = true ;WdfWaitLockRelease(pAccDevice->m_WaitLock);return STATUS_SUCCESS ;}进入电源状态管理(D0Entry)使能中断(InterruptEnable)…获取硬件资源,进行一些静态配置,(PrepareHardware)NTSTATUS OnInterruptEnable(IN WDFINTERRUPT Interrupt,IN WDFDEVICE Device){PDEVICE_EXTENSION devExt;ULONG regUlong;PULONG intCsr;devContext = GetDeviceContext(WdfInterruptGetDevice(Interrupt) );intRegId = &devContext->IntRegisterId regVal = READ_REGISTER_ULONG( intRegId );regVal = ENABLE_INTERRUPT_BYTE( regVal );WRITE_REGISTER_ULONG( intRegId, regVal );return STATUS_SUCCESS;}进入电源状态管理(D0Entry)使能中断(InterruptEnable)…获取硬件资源,进行一些静态配置,(PrepareHardware)EvtIoResume EvtDMAEnablerFillEvtDeviceSelfManagedIoInitEvtDeviceDisarmWakeFromSxEventChildListScanForChildren EvtDeviceRemoveAddedResourcesStart power-managed queuesEvtIoResume Disarm wake signal, if it was armed. (called onlyduring power up; not called during resource rebalance)EvtDeviceDisarmWakeFromSx EvtDeviceDisarmWakeFromS0Request information about child devicesEvtChildListScanForChildren Enable DMA, if driver supports it EvtDmaEnablerSelfManagedIoStartEvtDmaEnablerEnableEvtDmaEnablerFillConnect interruptsEvtDeviceD0EntryPostInterruptsEnabledEvtInterruptEnable Notify Driver of state change EvtDeviceD0EntryDevice OperationalRestart from here if device is in low power statePrepare hardware for power EvtDevicePrepareHardwareChange resources requirements EvtDeviceRemoveAddedResourcesEvtDeviceFilterAddResourceRequirementsEvtDeviceFilterRemoveResourcRequirementsRestart from here if rebalancing resourcesCreate Device object EvtDriverDeviceAddDevice arrivedEnable self-managed I/O, if driver supports it.EvtDeviceSelfManagedIoInit (implicit power up),EvtDeviceSelfManagedIoRestart (explicit power up)Stop power-managed queuesEvtIoStop Arm wake signal, if it was not armed. (calledonly during power up; not called duringresource rebalance)EvtDeviceArmWakeFromSx EvtDeviceArmWakeFromS0Disable DMA, if driver supports it EvtDmaEnablerSelfManagedIoStopEvtDmaEnablerDisableEvtDmaEnablerFlushDisconnect interrupts EvtDeviceD0EntryPostInterruptsDisabledEvtInterruptDisableNotify Driver of state changeEvtDeviceD0Exit Device OperationalStop here if transitioning to low power stateRelease hardware EvtDeviceReleaseHardwarePurge power-managed queuesEvtIoStop Stop here if rebalancing resourcesFlush I/O if driver supports self-managedI/OEvtDeviceSelfManagedIoFlush Device removedSuspend self-managed I/O, if driver supports it.EvtDeviceSelfManagedIoSuspend Cleanup I/O buffers if driver supports self-managed i/o EvtDeviceSelfManagedIoCleanupDelete device object s context area.EvtDeviceContextCleanupEvtDeviceContextDestroyWDM和操作系统深度耦合,WDM驱动程序直接调用系统服务例程,直接操作系统数据结构WDM驱动程序全部为内核态程序,操作系统对驱动输入只做有限的检查WDF框架处理与操作系统的交互,驱动本身专注于和设备交互WDF基于对象模型和事件驱动WDF支持内核态程序和用户态程序将操作系统底层的复杂逻辑抽象化使驱动代码有可能<20行对不同的硬件设备使用相同的编程模型例如GPIO,UART,I2C,NFC,传感器驱动框架内置的日志系统为数据分析定制的工具支持上千种不同的硬件设备最初UMDF V1基于C++ COMUMDF V2使用和内核态驱动开发相同的模型和语法支持USB周边设备,传感器,NFC,智能卡,HID(包括触控)等等驱动崩溃只会影响宿主进程,不会影响整个操作系统系统重启策略可以自动恢复崩溃的UMDF驱动Windows 10提供了一系列API和DDI,对于所有的Windows平台都是通用的,被称为Universal Windows Platform(UWP) Windows通用驱动是指一个内核态或用户态的驱动并能运行在所有基于UWP的系统上面Windows通用驱动只能调用属于UWP部分的DDI,这部分DDI会在MSDN文档中标记为Universal确定你的驱动是否支持UWP,把你的驱动标记为通用驱动然后重新编译在Visual Studio中打开驱动项目工程在配置选项中把操作系统选择为Windows 10在工程属性中把目标平台改为“通用”,其他选项还有“桌面”和“手机”重新编译驱动,这时可以会出现一些链接器错误尝试修复这些错误,对于出现错误的API,请参考文档是否有通用平台的API可以替代,如果没有,您可能需要重新设计你的驱动KMDF version Release method Included in this versionof Windows Drivers using it run on1.19Windows 10, version1607 WDK Windows 10, version1607Windows 10 version1607 and later,Windows Server 20161.17Windows 10, version1511 WDK Windows 10, version1511Windows 10 version1511 and later,Windows 10 Mobile,Windows 10 IoT Core,Windows Server 20161.15Windows 10 WDK Windows 10Windows 10 for desktop editions, Windows 10 Mobile, IoT Core, Windows Server 2016UMDF version Release method Included in this version ofWindows Drivers using it can run on2.19Windows 10, version 1607WDK Windows 10, version 1607Windows 10, version 1607 (all SKUs), Windows Server 20162.17Windows 10, version 1511WDK Windows 10, version 1511Windows 10 for desktop editions (Home, Pro, Enterprise, and Education), Windows 10 Mobile, Windows 10 IoT Core (IoT Core), Windows Server 20162.15Windows 10 WDK Windows 10Windows 10 for desktop editions, Windows 10 Mobile, IoT Core, Windows Server 2016驱动程序运行在哪个版本的操作系统上驱动程序支持的硬件类型驱动程序使用的驱动模型确定驱动程序是否使用了只有KMDF支持的功能,如果驱动程序没有使用KMDF的功能,并且驱动运行在Windows 8.1或以后的系统上,则可以迁移到UMDF 2https:///en-us/windows/hardware/drivers/wdf/wdf-porting-guide Which Drivers Can Be Ported and WhereDifferences Between WDM and WDFPreparing for PortingSteps in PortingSummary of KMDF and WDM Equivalents。
Windows驱动程序开发笔记一、WDK与DDK环境最新版的WDK 微软已经不提供下载了这里:https:/// 可以下并且这里有好多好东东!不要走进一个误区:下最新版的就好,虽然最新版是Windows Driver Kit (WDK) 7_0_0,支持windows7,vista 2003 xp等但是它的意思是指在windows7操作系统下安装能编写针对windows xp vista的驱动程序,但是不能在xp 2003环境下安装Windows Driver Kit (WDK) 7_0_0这个高版本,否则你在build的时候会有好多好多的问题.上文build指:首先安装好WDK/DDK,然后进入"开始"->"所有程序"->"Windows Driver Kits"->"WDK XXXX.XXXX.X" ->"Windows XP"->"x86 Checked Build Environment"在弹出来的命令行窗口中输入"Build",让它自动生成所需要的库如果你是要给xp下的开发环境还是老老实实的找针对xp的老版DDK吧,并且xp无WDK 版只有DDK版build自己的demo 有个常见问题: 'jvc' 不是内部或外部命令,也不是可运行的程序。
解决办法:去掉build路径中的空格。
二、下载 WDK 开发包的步骤1、访问Microsoft Connect Web site站点2、使用微软 Passport 账户登录站点3、登录进入之后,点击站点目录链接4、在左侧的类别列表中选择开发人员工具,在右侧打开的类别:开发人员工具目录中找到Windows Driver Kit (WDK) and Windows Driver Framework (WDF)并添加到您的控制面板中5、添加该项完毕后,选择您的控制面板,就可以看到新添加进来的项了。
Windows程序设计简介Windows程序设计是指在Windows操作系统上开发和设计应用程序。
Windows操作系统提供了丰富的应用程序开发工具和API,使开发者能够利用各种编程语言(如C++、C#、等)开发功能强大、丰富多样的应用程序。
在Windows上进行程序设计可以涵盖很多方面,包括图形用户界面(GUI)设计、操作系统交互、网络通信、以及与硬件设备的交互等。
本文将重点介绍Windows程序设计的基本概念和一些常用的开发工具和技术。
开发工具在Windows上进行程序设计,可以使用各种开发工具和集成开发环境(IDE)来简化开发过程。
以下是一些常用的Windows程序设计开发工具:1.Visual Studio:Visual Studio是一套功能强大的集成开发环境,由Microsoft开发和维护。
它支持多种编程语言,包括C++、C#、Visual Basic等,并且提供了丰富的开发工具和调试功能。
2.Dev-C++:Dev-C++是一个免费开源的C++编程环境,它提供了一个简单易用的集成开发环境,并且可以方便地编译和调试C++程序。
3.Code::Blocks:Code::Blocks是一个开源的跨平台集成开发环境,支持多种编程语言,包括C++、C等。
它提供了丰富的插件和功能,可以方便地进行Windows程序设计。
除了以上列举的开发工具,还有其他一些可供选择的开发工具,开发者可以根据自己的需求和喜好来选择合适的工具。
Windows程序设计基础在进行Windows程序设计之前,了解Windows操作系统的基本概念和原理是非常重要的。
以下是一些Windows程序设计中常用的基础知识:1.Windows窗口:Windows窗口是Windows程序的基本界面单元。
每个窗口都有自己的窗口过程(WindowProcedure),用于处理窗口消息和事件。
2.控件和对话框:Windows程序中常用的GUI元素称为控件,如按钮、文本框、列表框等。
WDM驱动程序开发之读写设备寄存器:KIoRange类2009-11-09 14:05WDM驱动程序开发之读写设备寄存器:KIoRange类收藏KIoRange类:一、OverviewKIoRange类将一系列特殊的外围总线的地址映射到CPU总线的地址空间。
CPU总线上的地址即可能在CPU的I/O空间,也可能在CPU的内存空间,这取决于平台和外围总线的控制方式。
考虑到可移植性,所有对I/O周期(I/O cycle)进行译码的设备驱动程序必须用这个类对I/O的位置(location)进行正确的访问(access)。
KIoRange是KPeripheralAddress类的派生类。
一旦映射关系建立起来,驱动程序就用KIoRange类的成员函数去控制设备的I/O寄存器。
这个类提供了8位、16位和32位I/O访问控制的函数。
这些函数是以内联(in-line)函数方式来使用的,它们调用系统内相应的宏来产生依赖于平台的代码。
对I/O位置(location)进行访问的另一种备选方案是创建一个KIoRegister 的实例。
这要通过取得一个KIoRange对象的数组元素来实现。
为了访问一系列外围总线内存空间的地址,需要用KMemoryRange类。
二、Member Functions1、KIoRange - Constructor (4 forms)构造函数【函数原型】FORM 1:KIoRange( void );FORM 2: (NTDDK Only)KIoRange(INTERFACE_TYPE IntfType,ULONG BusNumber ,ULONGLONG BaseBusAddress,ULONG Count,BOOLEAN MapToSystemVirtual =TRUE);FORM 3 (WDM):KIoRange(ULONGLONG CpuPhysicalAddress,BOOLEAN InCpuIoSpace,ULONG Count,BOOLEAN MapToSystemVirtual =TRUE);FORM 4 (WDM): (NOTE: This form is deprecated as of DriverStudio version 2.0.)KIoRange(PCM_RESOURCE_LIST pTranslatedResourceList,ULONG Ordinal=0,BOOLEAN MapToSystemVirtual =TRUE);FORM 5 (WDM):KIoRange(PCM_RESOURCE_LIST pTranslatedResourceList,PCM_RESOURCE_LIST pRawResourceList,ULONG Ordinal=0,BOOLEAN MapToSystemVirtual =TRUE);【Parameters】IntfType 指定总线类型。
基于WinDriver的CPCI板卡Windows驱动程序设计作者:先登飞来源:《现代电子技术》2013年第18期摘要:为了实现在主控计算机和信号处理板之间快速通信,采用了CPCI并行总线技术。
为简化开发难度,信号处理板采用内嵌PCI模块的DSP6416数字信号处理芯片实现通信和控制功能,软件开发环境基于VC++6.0,利用WinDriver工具开发了Windows下以DLL形式封装的CPCI驱动程序。
通过实际使用验证,该驱动程序运行稳定可靠,实现了主控计算机对信号处理板的实时控制和信号处理板中结果数据向主控计算机实时上报功能。
关键词: WinDriver; Windows驱动程序; CPCI总线; VC++6.0中图分类号: TN964⁃34 文献标识码: A 文章编号: 1004⁃373X(2013)18⁃0051⁃040 引言外围设备互联(PCI)总线是一种先进的高性能局部总线,可同时支持多组外围设备[1]。
CPCI总线应用于工业和嵌入式领域,其规范改进自PCI规范,CPCI规范在电气方面兼容PCI 规范,只是在封装结构上进行了加强,CPCI板的封装结构基于IEC 60297⁃3,IEC 60297⁃4以及IEEE 1101.10定义的欧式板卡外形[2]。
既然电气特性上兼容PCI规范,因此CPCI驱动程序的设计本质就是PCI驱动程序设计。
当前Windows环境下用于PCI设备驱动开发的工具主要是DDK,DriverStudio以及WinDriver。
前两者功能强大,但是开发者需要熟知操作系统的体系结构、汇编语言和设备驱动程序结构体系方法,还需要具备丰富的驱动程序开发经验,否则可能造成软件不稳定甚至系统崩溃,另外前两者开发周期长。
而Jungo公司开发的WinDriver改变了传统的驱动程序开发方法,其整个驱动程序中的所有函数都是工作在用户态下,使开发者不需要掌握前两者所需的预备知识就可以开发出与之相媲美的程序[3]。
windows程序设计概论Windows程序设计概论Windows程序设计是指在Windows操作系统上开发和编写应用程序的过程。
随着计算机技术的不断发展,Windows操作系统成为了世界上最流行的操作系统之一,因此掌握Windows程序设计的基本知识成为了程序员的必备技能之一。
本文将从基本概念、开发工具、编程语言以及常用技术等方面介绍Windows程序设计的相关内容。
一、基本概念1.1 Windows操作系统Windows操作系统是由美国微软公司开发的一款图形化操作系统,具有用户友好的界面和丰富的功能。
它提供了一种便捷的平台,使得开发者可以利用其强大的功能来创建各种应用程序。
1.2 Windows应用程序Windows应用程序是在Windows操作系统上运行的软件程序,可以实现各种功能,如文档处理、图形处理、多媒体播放等。
通过编写代码和使用开发工具,开发者可以将自己的想法转化为实际的应用程序。
二、开发工具2.1 Visual StudioVisual Studio是微软公司推出的一款集成开发环境(IDE),提供了丰富的开发工具和功能,如代码编辑器、调试器、编译器等。
它支持多种编程语言,如C++、C#等,可以帮助开发者高效地编写和调试Windows应用程序。
2.2 .NET Framework.NET Framework是一个应用程序开发平台,提供了一系列的类库和工具,用于简化Windows应用程序的开发过程。
它支持多种编程语言,并提供了丰富的API,使得开发者可以轻松地访问操作系统的功能和资源。
三、编程语言3.1 C++C++是一种通用的编程语言,广泛用于系统级编程和高性能应用程序的开发。
它在Windows程序设计中被广泛使用,可以直接访问操作系统的底层功能,并提供了丰富的类库和工具,使得开发者可以灵活地控制和管理应用程序。
3.2 C#C#是一种面向对象的编程语言,专门用于Windows应用程序的开发。
《Windows驱动开发技术详解》之读写操作缓冲区⽅式读写操作设置缓冲区读写⽅式:读写操作⼀般是由ReadFile和WriteFile函数引起的,这⾥先以WriteFile函数为例进⾏介绍。
WriteFile要求⽤户提供⼀段缓冲区,并且说明缓冲区的⼤⼩,然后WriteFile将这段内存的数据传⼊到驱动程序中。
这种⽅法,操作系统将应⽤程序提供缓冲区数据直接复制到内核模式的地址中。
这样做,⽐较简单的解决了将⽤户地址传⼊驱动的问题,⽽缺点是需要在⽤户模式和内核模式之间复制数据,影响了效率。
在少量内存操作时,可以采⽤这种⽅法。
拷贝到内核模式下的地址由WriteFile创建的IRP的AssociatedIrp.SystemBuffer⼦域记录。
下⾯的代码演⽰了如何利⽤缓冲区⽅式读取设备,这个例⼦中,驱动程序负责向缓冲区中填⼊了数据:应⽤层调⽤ReadFile,想驱动传送⼀个读IRP请求:1int main(){2 HANDLE hDevice =3 CreateFile("\\\\.\\HelloDDK",4 GENERIC_READ | GENERIC_WRITE,50, NULL,6 OPEN_EXISTING,7 FILE_ATTRIBUTE_NORMAL,8 NULL);9if (hDevice == INVALID_HANDLE_VALUE){10 printf("Open device failed!\n");11 }12else{13 printf("Open device succeed!\n");14 }15 UCHAR buffer[10];16 ULONG ulRead;17 BOOL bRet = ReadFile(hDevice, buffer, 10, &ulRead, NULL);18if (bRet){19 printf("Read %d bytes!", ulRead);20for (int i = 0; i < (int)ulRead; i++){21 printf("%02X", buffer[i]);22 }23 printf("\n");24 }25 CloseHandle(hDevice);26 system("pause");27return0;28 }运⾏之后的结果如下:创建⼀个虚拟设备模拟⽂件读写:读、写派遣函数如下:1 NTSTATUS HelloDDKDispatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp){2 UNREFERENCED_PARAMETER(pDevObj);3 DbgPrint("Enter dispach read!\n");4 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;5 NTSTATUS status = STATUS_SUCCESS;6 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);7//得到要读取的数据的长度8 ULONG ulReadLength = stack->Parameters.Read.Length;9 ULONG ulReadOffset = (ULONG)stack->Parameters.Read.ByteOffset.QuadPart;10if (ulReadOffset + ulReadLength > MAX_FILE_LENGTH){11 status = STATUS_FILE_INVALID;12 ulReadLength = 0;13 }14else{15 memcpy(pIrp->AssociatedIrp.SystemBuffer, pDevExt->buffer + ulReadOffset, ulReadLength);16 status = STATUS_SUCCESS;17 }18 pIrp->IoStatus.Status = status;19 pIrp->rmation = ulReadLength;20//memset(pIrp->AssociatedIrp.SystemBuffer, 0x68, ulReadLength);21 IoCompleteRequest(pIrp, IO_NO_INCREMENT);22return status;23 }2425 NTSTATUS HelloDDKDispatchWrite(PDEVICE_OBJECT pDevObj, PIRP pIrp){26 UNREFERENCED_PARAMETER(pDevObj);27 NTSTATUS status = STATUS_SUCCESS;28 PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;29 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);30 ULONG ulWriteLength = stack->Parameters.Write.Length;31 ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart;32if (ulWriteOffset + ulWriteLength > MAX_FILE_LENGTH){33 status = STATUS_FILE_INVALID;34 ulWriteLength = 0;35 }36else{37 memcpy(pDevExt->buffer + ulWriteOffset, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength);38 status = STATUS_SUCCESS;39if (ulWriteLength + ulWriteOffset > pDevExt->file_length){40 pDevExt->file_length = ulWriteLength + ulWriteOffset;41 }42 }43 pIrp->IoStatus.Status = status;44 pIrp->rmation = ulWriteLength;45 IoCompleteRequest(pIrp, IO_NO_INCREMENT);4647return status;48 }再在R3添加⼊代码:1 UCHAR buffer[10];2 memset(buffer, 0x66, 10);3 ULONG ulRead;4 ULONG ulWrite;5 BOOL bRet = WriteFile(hDevice, buffer, 10, &ulWrite, NULL);6if (bRet){7 printf("Write %d bytes!\n", ulWrite);8 }910 bRet = ReadFile(hDevice, buffer, 10, &ulRead, NULL);11if (bRet){12 printf("Read %d bytes!", ulRead);13for (int i = 0; i < (int)ulRead; i++){14 printf("%02X", buffer[i]);15 }16 }17 printf("\n");运⾏,得到结果:如果我们要查询⽂件信息,没有注册IRP_MY_QUERY_INFORMATION的派遣函数时,GetFileSize会正常返回读到的⽂件的⼤⼩:但是,因为GetFileSize读取的是⽂件的⼤⼩,⽽这⾥传递的是设备对象的句柄,本来是读不到⼤⼩的,但是如果利⽤驱动对IRP进⾏修改,再返回给R3层,就可以得到了:其派遣函数代码如下:R3层添加代码:1 bRet = GetFileSizeEx(hDevice, &dwFileSize);2 printf("File size is %u\n", dwFileSize);直接⽅式读写操作与缓冲区⽅式读写设备不同,直接⽅式读写设备,操作系统会将⽤户模式下的缓冲区锁住。