Windows驱动程序框架理解_经典入门

合集下载

驱动基础知识.

驱动基础知识.

驱动程序对象
• DeviceObject(PDEVICE_OBJECT) 指向一 个设备对象链表,每个设备对象代表一个设备。 I/O管理器把多个设备对象连接起来并维护这 个域。非WDM驱动程序的DriverUnload函数 利用这个域来遍历设备对象列表,以便删除其 中的设备对象。WDM驱动程序没有必要使用 这个域。 FastIoDispatch(PFAST_IO_DISPATCH)指 向一个函数指针表,这些函数是由文件系统和 网络驱动程序输出的。 DriverStartIo(PDRIVER_STARTIO)指向驱动 程序中处理串行I/O请求的函数,I/O管理器自 动为驱动程序串行化多个I/O请求。 DriverUnload (PDRIVER_UNLOAD)指向驱 动程序中的清除函数。 MajorFunction (array of PDRIVER_DISPATCH)是一个函数指针表, 指向存在于驱动程序中的二十多种IRP处理函 数。
Windows 驱动基础知识
Windows NT5.0 System Structure
应用程序 Window 32 API调用 Win32子系统
用户模式
内核模式 I/O管理器 转递IRP给驱动程序派遣函数 设备驱动程序 HAL调用 硬件抽象层 平台相关操作 硬件 系统服务接口
FindNextFile function operation process
应用程序调用 Kernel32.dll中 的FindNextFile Kernel32.dll中 的FindNextFile
Ntdll.dll中的 NtQueryDirectory SYSTEM 或 INT 2E 用户模式 内核模式
KiSystemService
Ntoskrnl.exe中的 NtQueryDirectoryFile

WinPcap所涉及的Windows驱动基础知识(三)

WinPcap所涉及的Windows驱动基础知识(三)

深度剖析WinPcap之(三)——所涉及的Windows驱动基础知识1.1 Windows驱动的基础知识本节主要描述在WinPcap的NPF中经常使用一些编写Windows驱动程序所需掌握的部分基础知识,以便于后面的理解。

1.1.1 驱动对象(DRIVER_OBJECT)每个驱动程序都有唯一的驱动对象与之对应,该驱动对象在驱动程序被加载时由内核的对象管理程序所创建。

驱动对象用DRIVER_OBJECT数据结构表示,它作为驱动程序的一个实例被内核加载,对一个驱动程序内核I/O管理器只加载一个实例。

驱动对象数据结构在wdm.h文件中的定义如下。

typedef struct _DRIVER_OBJECT {CSHORT Type;CSHORT Size;/**DeviceObject为每个驱动程序所创建的一个或多个设备对象链表,*Flags提供一个扩展的标识定位驱动对象*/PDEVICE_OBJECT DeviceObject;ULONG Flags;/*下列各成员字段描述驱动程序从哪儿被加载*/PVOID DriverStart;ULONG DriverSize;PVOID DriverSection;PDRIVER_EXTENSION DriverExtension;/**DriverName成员被错误日志线程用来*确定一个I/O请求越界的驱动名称*/UNICODE_STRING DriverName;/*指向注册表中硬件信息的路径*/PUNICODE_STRING HardwareDatabase;/**如果驱动支持“fast I/O”,*就指向一个“fast I/O”的派遣函数数组*/PFAST_IO_DISPATCH FastIoDispatch;/**描述该特定驱动的入口点。

*主函数(major function)派遣函数表必须是对象最后的成员,*因此它仍然是可扩展的*/PDRIVER_INITIALIZE DriverInit;PDRIVER_STARTIO DriverStartIo;PDRIVER_UNLOAD DriverUnload;PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];} DRIVER_OBJECT;typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT;下面分别描述驱动对象中驱动程序可访问的成员。

Windows 驱动程序开发指导说明书

Windows 驱动程序开发指导说明书

课程内容驱动基本概念介绍驱动核心代码分析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应用程序的基本结构

Windows应用程序的基本结构

Windows程序的特点
大致说来windows编程有两种方法: a.windows c方式(SDK),SDK编程就是直接调用windows 的API进行编程; b.c++方式:即对SDK函数进行包装,如VC的MFC,BCB的 OWL等。MFC把这些API封闭起来,共有一百多个类组成. API,全称application program interface,意思是应用程序编 程接口(说起API并不仅仅指windows而言, windows支持 的API叫winapi)。winapi就是应用程序和windows之间通讯 的一个编程界面。windows提供了上千个API函数,以方便程 序员来编写应用程序。
WinMain函数的功能
WinMain函数 功 能 注册窗口类,建立窗口及执行必要的初始化 进入消息循环,根据接受的消息调用相应的处理过程 当消息循环检索到WM_QUIT时终止程序运行
三个基本的组成部分:函数说明、初始化和消息循环 WinMain函数说明
注意!Win是多任务管理的 ,同一应用程序的多个窗口 可能会同时存,Win系统对每 个窗口的执行称为一个实例, WinMain函数的说明如下: 并用一个实例句柄来唯一标 识 int WINAPI WinMain
HDC 设备环境句柄 HCURSOR 光标句柄 HFONT 字体句柄 HPEN 画笔句柄 HBRUSH 画刷句柄
Windows程序的特点
窗口句柄: 系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息 时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都 会有自己的窗口过程,所以用户的输入就会被正确的处理。 所有的命名采用了匈牙利表示法。如消息的前缀使用msg.句柄使用h. 函数使用fn等。 Windows程序则至少两个主程序, 一个是WinMain(), int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state );

驱动基础知识

驱动基础知识

设备驱动程序种类
虚拟设备驱动程序,被用于仿真 16位MS-DOS应用程序 用户模式驱动程序 子系统打印机驱动程序,把与设备无关 的图形请求转译成与打印相关的命令
文件系统驱动程序,接受针对文件操作的请求
内核模式驱动程序
即插即用驱动程序,与硬件一起工作,结合了 电源和PNP管理器
非即插即用驱动程序,
文件系统驱动程序和磁盘驱动程序的分层结构
应用程序调用 Kernel32.dll中 的FindNextFile Kernel32.dll中 的FindNextFile
Ntdll.dll中的 NtQueryDirectory SYSTEM 或 INT 2E 用户模式 内核模式
KiSystemService
Ntoskrnl.exe中的 NtQueryDirectoryFile
环境子系统或DLL
1 NtWriteFile(file_handle, char_buffer)
系统服务
2 在一个文件中指定的偏移处 写入数据
文件系统驱动程序 I/O管理器 3 将相对于文件的字节偏移转 译成相对于卷的字节偏移, 并调用下一个驱动程序
磁盘驱动程序
4 调用驱动程序以便在相对于 卷的字节偏移处写数据 5 将相对于卷的字节偏移转译 成物理位置的磁盘偏移,并 传送数据
驱动程序对象
• DeviceObject(PDEVICE_OBJECT) 指向一 个设备对象链表,每个设备对象代表一个设备。 I/O管理器把多个设备对象连接起来并维护这 个域。非WDM驱动程序的DriverUnload函数 利用这个域来遍历设备对象列表,以便删除其 中的设备对象。WDM驱动程序没有必要使用 这个域。 FastIoDispatch(PFAST_IO_DISPATCH)指 向一个函数指针表,这些函数是由文件系统和 网络驱动程序输出的。 DriverStartIo(PDRIVER_STARTIO)指向驱动 程序中处理串行I/O请求的函数,I/O管理器自 动为驱动程序串行化多个I/O请求。 DriverUnload (PDRIVER_UNLOAD)指向驱 动程序中的清除函数。 MajorFunction (array of PDRIVER_DISPATCH)是一个函数指针表, 指向存在于驱动程序中的二十多种IRP处理函 数。

第17讲 Windows程序设计基础

第17讲 Windows程序设计基础

1. 2.
主菜单 弹出式菜单
菜单类
在.NET类库中,定义了一个非常庞大的基础类, 以供用户在各种编程中使用。在这些类中,有几个专 为用户编写菜单程序所用的类,通过使用这几个类, 你可以设计出自己想要的任何菜单。下面主要介绍三 个类:
1. 2. 3.
MenuStrip ContextMenuStrip ToolStripMenuItem
Windows应用程序框架
Windows程序运行机制 Windows程序设计是一种事件驱动方式的程 序设计模式。在程序提供给用户的界面中有许 多可操作的可视对象。用户从所有可能的操作 中任意选择,被选择的操作会产生某些特定的 事件,这些事件发生后将会向程序中的某些对 象发出消息,然后这些对象调用相应的消息处 理函数来完成特定的操作。
1.
在“工具箱”中双击ToolTip为窗体添加一个ToolTip, 此时窗体上所有控件的属性里都多了一个“toolTip1 上的ToolTip”属性,它可使控件与toolTip1关联起来 以创建工具提示。
高级控件
本节主要讲述以下几个主要高级控件的应用: NumericUpDown控件 ProgressBar控件 ListView控件 TreeView控件 Splitter控件 TabControl控件
ListView(列表视图)
ListView用列表的形式显示一组数据,每条数据都 是一个ListItem类型的对象。通常使用ListView来显示 对数据库的查询结果,Windows系统中的文件浏览器就 是一个ListView控件。 【例】ListView控件应用 View属性表示显示数据的视图模式,它包含如下4个选项:
Windows程序运行机制 2、事件驱动程序运行 事件指的是独立的偶发的事情,在计算机中,可以 通过单击鼠标、单击按钮、操作键盘产生事件,也可以 通过程序的控制而产生,甚至可以由另一个窗口的操作 产生。 在Windows程序中,可以对相应的事件编写对应 的响应函数,当该事情发生时,响应函数就会被调用。

windows文件核心驱动结构简介、FileMon例程简介、开发注意要点

windows文件核心驱动结构简介、FileMon例程简介、开发注意要点

本帖子是《注册表实时监控拦截》的下篇,也是本系列的最后一篇。

主要讲述如何自己动手做一个在windows系统下的文件操作拦截的小驱动。

利用本驱动,可以实现对本机的所有文件操作请求进行实时监视、拦截,可以完全保护文件系统,在此基础上的进行深入开发后,可以做到文件加密、病毒防护等功能。

本帖子分三个部分:windows文件核心驱动结构简介、FileMon例程简介、开发注意要点。

一、windwos文件核心驱动结构简介在windows操作系统中(NT以上版本),规定了一套严格的文件操作请求处理流程,总体结构如下图:在图中上部分有一条虚线,这是“用户态”软件和“核心驱动”的分界线(用户态软件可以理解为普通的、可见的软件,如各类exe类型的软件)。

当用户态软件需要操作文件时,则发出文件操作请求,然后统一发送给系统的I/O管理器,I/O管理器把这个操作请求依次向下传递给“文件系统驱动”、“磁盘驱动”等,后者执行真正的文件操作。

上图是在本机上进行文件操作的流程,那么在访问网络上的文件,则处理流程如下:可以看到,在目标计算机(即文件所处的计算机)上,文件操作请求同样经过了“本地文件系统”和“磁盘驱动”,在这一点上,两者没有区别。

那么,如果我们要自己做一个文件的驱动,应该放在什么位置?下图给出了详细的“自定义驱动”的插入位置:图中以深色表示的部分,即留给用户可以插入“自定义驱动”的位置,可以看到,新插入的驱动和系统的驱动是“串接”在一起的。

所以,所有的文件操作均会通过“自定义驱动”(当然了,如果有人又开发了另外一个驱动,并插入到你所开发的驱动的下面,然后不通过正规的文件驱动而是直接发送消息到下层他的驱动,这样是拦截不到的)。

此时,你可以在你的驱动中很悠闲地处理这些请求,而且想啥时候丢弃、修改这些文件请求,那是全凭自己的心情了。

二、FileMon例程简介在了解了windows文件核心驱动的大致结构后,我们可以动手来试试了。

WindowsDriverFoundationWindows驱动程序基础

WindowsDriverFoundationWindows驱动程序基础

Windows Driver FoundationWDF简介WDFSTA TUS DioEvtDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit){// ...//// Initialize our idle policy//WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings,IdleCannotWakeFromS0);status = WdfDeviceUpdateS0IdleSettings(device, &idleSettings);if (!NT_SUCCESS(status)) {DbgPrint("WdfDeviceUpdateS0IdleSettings failed 0x%0x ", status);return status;}return(status);}WDF亮点WDF亮点主要是针对新的 PnP/Power 模型的进一步优化和调整、可放弃的驱动创建(例如在 Longhorn 中可以中断并放弃 IRP_MJ_CREA TE 操作)、新的存储架构、灵活的任务请求队列(支持串行、并行和定制任务分发)、以及一些其他细节方面的改进。

在驱动模型方面,WDF 使用一些新的类型驱动 WDM 的相应类型,并做了一定的扩展:WDF 类型 WDM 类型WDFDRIVER DRIVER_OBJECTWDFDEVICE DEVICE_OBJECTWDFREQUEST IRPWDFQUEUE DPC 队列WDFINTERRUPT ISR & DPCforISRDriverEntry 在 WDF 中只负责 WDFDRIVER 类型对象的初始化和构造工作,将设备的管理完全丢到 DioEvtDeviceAdd 函数中,由 WDF 框架在合适的时候调用。

Windows驱动程序框架理解_经典入门

Windows驱动程序框架理解_经典入门

标题: 【原创】Windows驱动程序框架windows驱动程序入门比较坑爹一点,本文旨在降低入门的门槛。

注:下面的主要以NT式驱动为例,部分涉及到WDM驱动的差别会有特别说明。

首先,肯定是配置好对应的开发环境啦,不懂的就百度下吧,这里不再次描述了。

在Console控制台下,我们的有一个入口函数main;在Windows图形界面平台下,有另外一个入口函数Winmain。

我们只要在这入口函数里面调用其他相关的函数,程序就会按照我们的意愿跑起来了。

在我们用IDE开发的时候,也许你不会发现这些细微之处是如何配置出来的,一般来说我们也不用理会,因为在新建工程的时候,IDE已经帮我们把编译器(Compiler)以及连接器(Linker)的相关参数设置好,在正式编程的时候,我们只要按照规定的框架编程就行了。

同样,在驱动程序也有一个入口函数DriverEntry,这并不是一定的,但这是微软默认的、推荐使用的。

在我们配置开发环境的时候我们有机会指定入口函数,这是链接器的参数/entry:"DriverEntry"。

入口函数的声明代码:DriverEntry主要是对驱动程序进行初始化工作,它由系统进程(System)创建,系统启动的时候System系统进程就被创建了。

驱动加载的时候,系统进程将会创建新的线程,然后调用执行体组件中的对象管理器,创建一个驱动对象(DRIVER_OBJECT)。

另外,系统进程还得调用执行体组件中的配置管理程序,查询此驱动程序在注册表中对应项。

系统进程在调用驱动程序的Driv erEntry的时候就会将这两个值传到pDriverObject和pRegistryPath。

接下来,我们介绍下上面出现的几个数据结构:typedef LONG NTSTATUS在驱动开发中,我们应习惯于用NTSTATUS返回信息,NTSTATUS各个位有不同的含义,我们可以也应该用宏NT_SUCCESS来判断是否返回成功。

C编程第二章Windows应用程序框架精品PPT课件

C编程第二章Windows应用程序框架精品PPT课件
第二讲:Windows应用程序框架
e-mail:
联系方式:
北京源智天下科技有限公司
课程内容安排
• Windows应用程序设计基础 • MFC应用程序框架 • MFC应用程序框架说明 • 综合练习 • 思考和习题
北京源智天下科技有限公司
1-2
联系方式:
Windows应用程序设计基础
• Windows程序设计是一种完全不同于传统的DOS方式 的程序设计方法,其内部运行原理是一种事件驱动方式 的程序设计模式,主要是基于消息的。当用户需要完成 某种功能时会调用操作系统的某种支持,然后操作系统 将用户的需要包装成消息,并投递到消息队列中,最后 应用程序从消息队列中取得消息并进行响应,其流程如 图2-1所示。
北京源智天下科技有限公司
1-14
联系方式:
CHelloWorldView类和CHelloWorldDoc类
CHelloWorldView类的基类为CView,而CHelloWorldDoc 类的基类为CDocument。之所以把CHelloWorldView类 和CHelloWorldDoc类一起介绍是因为这两个类是密切相 关的。
程序员
API
Windows应用程序
北京源智天下科技有限公司
1-4
联系方式:
句柄
• 在Windows编程中读者将频繁接触到一个称为句柄( HANDLE)的概念。Windows程序中产生的任何资源(要 占用某一块或大或小的内存),如图标、光标、窗口和应用 程序的实例(已加载到内存运行中的程序)等。操作系统每 产生一个这样的资源时,都要将它们放入相应的内存,并为 这些内存指定一个唯一的标识号。这个标识号即是该资源的 句柄。
用户 1-13

C++第三十三篇--研究一下Windows驱动开发(一)内部构造介绍

C++第三十三篇--研究一下Windows驱动开发(一)内部构造介绍

C++第三⼗三篇--研究⼀下Windows驱动开发(⼀)内部构造介绍因为⼯作原因,需要做⼀些与⽹卡有关的测试,其中涉及到了驱动这⼀块的知识,虽然程序可以运⾏,但是不搞清楚,⼼⾥总是不安,觉得没理解清楚。

因此想看⼀下驱动开发。

查了很多资料,看到有⼈推荐Windows驱动开发技术详解这本书,因此本篇⽂章也是基于这本书进⾏学习的。

有些图⽚也是按照书上⾃⼰画的。

Windows操作系统⽰意图⾸先,需要下载相应的⼯具,将环境搭建起来,VS和WDK,由于我已经安装了VS2017,所以需要找对应版本的WDK()。

如果想要查OS的版本,可以WIN+R输⼊winver就可以看到OS的版本了,⽼版本对应链接:安装好了后就需要写⼀下程序了,参考链接:Windows架构简图Win32⼦系统将API函数转化为Native API函数。

在Native API接⼝中,已经没有了⼦系统的概念,它将这种调⽤转化为系统服务函数的调⽤。

其中,Native API穿过了⽤户模式和内核模式的界⾯,达到了内核模式。

系统服务函数通过I/O管理器将消息传递给驱动程序。

在内核模式下,执⾏体组件提供了⼤量的内核函数供驱动程序调⽤。

内核主要负责进程、线程的调度情况。

驱动程序通过硬件抽象层与具体硬件进⾏操作。

Windows API分为三类,分别是USER函数、GDI函数和KERNEL函数。

》USER函数:这类函数管理窗⼝、菜单、对话框和控件。

》GDI函数:这类函数在物理设备商执⾏绘图操作。

》KERNEL函数:这类函数管理⾮GUI资源,例如:进程、线程、⽂件和同步服务等。

可以发现Windows系统⽬录中有对应的三个系统⽂件,分别是USER32.dll、GDI32.dll和KERNEL32.dll。

这三个⽂件提供了以上三类API的接⼝。

当应⽤程序加载的时候,操作系统出了将应⽤程序加载到内存中,同时将以上三个DLL⽂件加载到内存中。

1、Native API⼤部分Win32⼦系统的API,都通过Native API实现的。

Windows应用程序的基本结构ppt课件

Windows应用程序的基本结构ppt课件

LPSTR lpCmdLine,
// command
line
int nCmdShow
// show state
);
精选课件ppt
16
Windows程序的特点
另一个是窗口过程函数WndProc,它的函数原型为: long FAR PASCAL WndProc(HWND hWnd,WORD message,WORD wParam,LONG lParam);
窗口函数与回调函数: 在Windows中,应用程序通过要求Windows完成指定操作, 而承担这项通信任务的API函数就是Windows的相应窗口函数 WndProc。应用程序不直接调用任何窗口函数,而是等待 Windows调用窗口函数,请求完成任务或返回信息。为保证 Windows调用这个窗口函数,这个函数必须先向Windows登 记,然后在Windows实施相应操作时回调,所以窗口函数又称 为回调函数。WndProc是一个主回调函数,Windows至少有 一个回调函数。典型的回调函数有窗口过程、对话框过程和钩 子函数。实际上,也许有不止一个的窗口过程。例如,每一个 不同的窗口类都有一个与之相对应的窗口过程。
精选课件ppt
13
句柄是什么?
在Win32里,句柄是指向一个无值型对象(void *)的指针, 是一个4字节长的数据”。句柄并不是一个真正意义上的指针。 从结构上看,句柄的确是一个指针,尽管它没有指向用于存储 某个对象的内存位置,而实际上句柄指向的是一个包含了对该 对象进行的引用的位置。我们天气热摇扇子的时候只要抓住扇 柄便可以控制整个扇子的运动了,在程序中也差不多是这个意 思。通常一个句柄就可以传递我们所要做的事情。有经验的开 发者肯定清楚,编写程序总是要和各种句柄打交道的,句柄是 系统用来标识不同对象类型的工具,如窗口、菜单等,这些东 西在系统中被视为不同类型的对象,用不同的句柄将他们区分 开来。

Windows 8 应用框架理解

Windows 8 应用框架理解

Windows 8 应用框架理解Windows操作系统之所以风靡世界,是因为其“易学易用”,从用户的角度出发,让数以万计的非IT人员使用计算机实现娱乐,工作等目的。

Windows8继承Windows桌面的优点,同时提供一种新的用户体验模式-Windowsstore风格。

换句话说,Windows8操作系统存在两种不同风格的应用。

本篇将介绍Windows8应用框架以及开发工具的使用。

理解Windows8应用框架正如前文所说,Windows8具有两个不同风格的应用,Windowsstore应用和传统Windows桌面应用。

两种风格应用使用不同的UI引擎,不同的服务和工具,以及不同的API.但是,都运行在同一个Windows8操作系统内核下。

我们简单对比一下两种应用:Windowsstore应用传统Windows桌面应用Windowsstore应用增加触控操作,独特的手势操作,提高用户体验性传统桌面应用主要操作模式是基于鼠标和键盘操作应用应用开发基于.NetFrameworkWindows8API应用开发基于Win32API,或者NetFrameworkWindowsstore应用不推荐大量使用对话框进行人机交互,而推荐使用页面导航的模式进行交互,这种方式更象使用浏览器前进后退的功能进行交互。

传统应用以对话框为主要人机交互方式在部署方面,用户不需要了解应用安装文件等信息,仅需要在Windowsstore下载安装即可。

在部署方面,传统桌面应用需要一定的安装和注册流程Windows8传统桌面应用框架Windows8传统桌面应用可以根据分为三类,分别是Win32应用,.Net应用和HTML应用。

1.Win32应用主要开发语言为C,C++或VB。

该应用被直接编译为CPU代码运行在Win32API上,其用户界面实现必须使用GDI或者GDI+。

应用主要开发语言为C#,。

该应用被编译为中间语言(IL),然后再被转换为CPU代码运行在CLR(CommonLanguageRuntime)环境。

第2章 Windows程序的基本框架

第2章  Windows程序的基本框架

符串都被封装在一个TEXT宏中。通常不必将所有字符串都
封装在TEXT宏中,除非想将你的程序中的字符串转换为 Unicode字符集。MessageBox的第四个参数可以是在
WINUSER.H中定义的一组以前缀MB_开始的常数的组合,
例如MB_ICONINFORMATION | MB_OKCANCEL。
处理函数的结构如下:
2.3.3 详细研究三种消息及其处理 ① WM_CREATE 窗口消息处理函数接收的第一个消息是WM_CREATE。 在WinMain ()中调用CreateWindow()时,Windows将做一些 它必须做的工作,包括发出WM_CREATE消息。具体做法
是,调用WndProc(),将第一个参数设定为窗口句柄,第二
2.2.3 显示窗口
在CreateWindow()调用之后,Windows内部已经建立了 这个窗口。这就是说,Windows已经配置了一块内存,用来 保存在CreateWindow()调用中指定窗口的全部信息和一些其 它信息,而Windows稍后依据窗口句柄找到这些信息。 然而,光是这样子,窗口并不会出现在显示器上。还 需要调用的函数是:
例如,可以这样创建一个窗口:
HWND hwnd = CreateWindow (szAppName, // window class name
TEXT ( "The Hello Program"),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
// window caption
(1) 表头文件
在每个用C/C++编写的Windows程序的开头都以一个预 处理命令开始: #include <windows.h> windows.h是主要的包含文件,其中包括大约800个API

从一篇文章入门Windows驱动程序(一)

从一篇文章入门Windows驱动程序(一)

从一篇文章入门Windows驱动程序(一)作者:Kr0net预估稿费:300RMB投稿方式:发送邮件至linwei#,或登陆网页版在线投稿0x1 背景笔者在学习中发现,关于Windows驱动编程的文章多不胜数,但是其中很多文章的内容繁杂不便于了解与学习,缺少对内容精准的概括与总结,所以本片文章将对Windows驱动编程进行一次总结性介绍。

文章将分为两个部分,分别是对NT驱动和WDM驱动的介绍,同时为了读者能够更好地学习Windows驱动编程,在文章开头将先介绍在内核模式下编程的基础知识。

0x2 相关基础(内核相关)a.内核模式和用户模式内核模式和用户模式是操作系统的两种运行级别。

内核模式:操作系统的核心代码运行在特权模式下。

与之相对应的,应用程序运行在非特权模式下为用户模式。

我们都知道在用户模式下,一个进程拥有windows专供的句柄表和虚拟地址空间,形象一点来说就是windows为进程提供了一个密闭的个人房间(这个房间位于低32位的内存空间里,用户空间),进程可以在房间里自行其是二不会干扰到其他的进程。

在内核模式下,所有的代码都共享一个房间(位于高32位的内存空间里,内核空间),这个房间受到硬件的保护,ring0层的代码才可以访问这个内存空间,ring3层的代码想访问这个内存空间时,一般都需要操作系统提供的入口(int 0x2e、iret组合或者sysenter、sysexit组合)来让CPU进入内核。

学习这部分内容的时候,可能可能会有一个疑问,那么什么是实模式、保护模式?(笔者一开始的时候将这四种模式混淆)实际上与用户模式和内核模式不同,实模式和保护模式是另外一种概念了。

实模式和保护模式是内存的两种形式,二者最大的区别是寻址范围,保护模式是32位内存寻址,可以访问4G的内存空间,实模式是20位寻址,只能访问1M的内存空间,另外保护模式保证进程间的地址空间不会冲突,也就是一个进程没有办法访问另外一个进程地址空间的数据。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

标题: 【原创】Windows驱动程序框架windows驱动程序入门比较坑爹一点,本文旨在降低入门的门槛。

注:下面的主要以NT式驱动为例,部分涉及到WDM驱动的差别会有特别说明。

首先,肯定是配置好对应的开发环境啦,不懂的就百度下吧,这里不再次描述了。

在Console控制台下,我们的有一个入口函数main;在Windows图形界面平台下,有另外一个入口函数Winmain。

我们只要在这入口函数里面调用其他相关的函数,程序就会按照我们的意愿跑起来了。

在我们用IDE开发的时候,也许你不会发现这些细微之处是如何配置出来的,一般来说我们也不用理会,因为在新建工程的时候,IDE已经帮我们把编译器(Compiler)以及连接器(Linker)的相关参数设置好,在正式编程的时候,我们只要按照规定的框架编程就行了。

同样,在驱动程序也有一个入口函数DriverEntry,这并不是一定的,但这是微软默认的、推荐使用的。

在我们配置开发环境的时候我们有机会指定入口函数,这是链接器的参数/entry:"DriverEntry"。

入口函数的声明代码:DriverEntry主要是对驱动程序进行初始化工作,它由系统进程(System)创建,系统启动的时候System系统进程就被创建了。

驱动加载的时候,系统进程将会创建新的线程,然后调用执行体组件中的对象管理器,创建一个驱动对象(DRIVER_OBJECT)。

另外,系统进程还得调用执行体组件中的配置管理程序,查询此驱动程序在注册表中对应项。

系统进程在调用驱动程序的Driv erEntry的时候就会将这两个值传到pDriverObject和pRegistryPath。

接下来,我们介绍下上面出现的几个数据结构:typedef LONG NTSTATUS在驱动开发中,我们应习惯于用NTSTATUS返回信息,NTSTATUS各个位有不同的含义,我们可以也应该用宏NT_SUCCESS来判断是否返回成功。

代码:NTSTAUS的编码意义:其中Ser是Serviity的缩写,代表严重程度。

00:成功01:信息10:警告11:错误C是Customer的缩写,代表自定义的位。

Facility:设备位Code:设备的状态代码。

根据这定义编码,还有补码的概念,那么只要是错误的时候,最高位就是1,NTSTATUS的值就是负数,所以可以大于零来判断,但无论如何都希望读者用NT_SUCCESS宏来判断是否成功,因为这可能在以后会有所改动,即使这么多年来都一直沿用着。

同样的,微软也为我们定义了其他几个判断宏:代码:有了之前的介绍,这三个相信不说大家也能领会了。

但最常用的还是NT_SUCCESS。

我们继续说其他的两个数据结构,先说PUNICODE_STRING吧,P代表这是一个指针类型,指向一个UNICODE_STRING结构。

宽字符串结构体(UNICODE_STRING)代码:其中,ØLength:Unicode字符串当前的字符长度。

注意不是字节数,每个Unicode字符占用两个字节。

ØMaximumLength:该Unicode字符串的最大容纳长度。

ØBuffer:Unicode字符串的缓冲地址。

UNICODE_STRING是Windows驱动开发里面经常用到的一个结构,用Length来标记字符串的长度而不再用\0来表示结束。

可以用RtlInitUnicodeString来对其初始化,但这里的pRegistryPath是直接由创建驱动程序的线程传进来的参数,如果在接下来仍需要用到该值,最好是使用RtlCopyUnicodeString函数将其值另外保存下来,因为这个字符串并不是长期存在的,DriverEn try函数返回的时候可能就会被销毁了。

PDRIVER_OBJECT,P代表这是一个指针类型,指向一个驱动对象(DRIVER_OBJECT),每个驱动程序都有一个驱动对象。

这是一个半透明的数据结构,微软没有公开它的完全定义,只是有提到几个成员,但我们依旧可以通过WinDbg看到它的定义,只是不同的系统可能会存在不同的结构。

不过我另外在WDK的头文件WDM.h里面发现了它的定义:驱动对象(DRIVER_OBJECT)代码:这里提下几个比较重要的字段,ØDeviceObject:指向由此驱动创建的设备对象。

每个驱动程序都会有一个或多个的设备对象。

其中,每个设备对象都会有一个指针指向下一个设备对象,这在我们介绍设备对象的时候再继续说。

ØDriverName:驱动的名字,该字符串一般为\Driver\[驱动程序名称]。

ØHardwareDatabase:记录设备的硬件数据库键名。

该字符串一般为"\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services \[服务名]"。

ØFastIoDispatch:指向快速I/O函数入口,是文件驱动中用到的排遣函数。

ØDriverStartIo:记录StartIo例程的函数地址,用于串行化操作。

ØDriverUnload:指定驱动卸载时所用的回调函数地址。

ØMajorFunction:这是一个函数指针数组,每个指针指向的是一个函数,该函数就是处理相应IRP的排遣函数,数组的索引值与IRP_MJ_XXX相对应。

我们已经了解了DriverEntry函数头的那个数据结构了,但这还不够,在DriverEntry里,我们主要是对驱动程序进行初始化,这就涉及到其他的一些数据结构了,下面我们继续逐一地介绍。

设备对象(DEVICE_OBJECT)代码:这里只对几个比较重要的字段进行说明:ØDriverObject:指向创建此设备对象的驱动程序对象。

同属于一个驱动程序的设备对象指向的是同一个驱动对象。

ØNextObject:指向同一个驱动程序创建的下一个设备对象。

同一个驱动对象可以创建若干个设备对象,每个设备对象根据N extDevice来连成一个链表,最后一个设备对象的NextDevice域为NULL。

ØAttachedDevice:指向附加到此设备对象之上的最近设备对象。

这里需要理解分层驱动程序的概念。

ØDeviceExtension:指向设备的扩展对象。

每个设备都会指定一个设备扩展对象,这个数据结构由驱动程序开发者自行定义,可以用来记录一些与设备相关的一些信息,同时应尽量避免使用全局变量,将数据存放在设备扩展里,具有很大的灵活性。

ØCurrentIrp:在使用StartIO例程的时候,该成员指向的是当前IRP结构。

ØFlags:指定了该设备对象的标记。

下面列出了常用的几个标记:ØDeviceType:指定设备的类型。

一般在开发虚拟设备时,选择FILE_DEVICE_UNKNOW。

其他的请自行参考WDK文档。

ØStackSize:在多层驱动情况下,驱动与驱动之间会形成类似堆栈的结构,称之为设备栈。

IRP会依次从最高层传递到最底层。

StackSize描述的就是该层数。

最底层的设备层数为1。

ØAlignmentRequirement:在进行大容量传输的时候,往往需要进行内存对齐,以保证传输速度。

请使用类似FILE_XXX_AL IGNMENT的方式进行赋值。

下面给大家展示一下DriverEntry的最基本框架:代码:这是用C++写的,所以必要的地方加上了extern“C”,否则会引起一些错误,这是因为C++与C在进行名称粉碎的时候处理得不一样,C++这个改进主要是为了实现一些高级功能,比如多态。

虽然加上extern “C”会有点麻烦,但可以用上C++那些功能,个人觉得也有所值。

如果用C,直接忽略上面的extern “C”。

NTDDK.h是NT式驱动需要加载的头文件,如果是WDM式驱动,那么加载的是WDM.h#define INITCODE code_seg("INIT")定义一个宏,#prama INITCODE还原后就是#pramacode_seg(“INIT”),表示接下来的代码加载到INIT内存区域中,成功加载后,可以退出内存。

对于DriverEntry这种一次性的函数而言,这是最适合的选择,可以节省内存。

函数结束后需要显式地切换回来,如:#prama LOCKEDCODE。

同样,PAGECODE表示分页内存,作用是将此部分代码放入分页内存中运行,在里面的代码切换进程上下文时可能会被换回分页文件。

LOCKEDCODE表示默认内存,也就是非分页内存,里面的代码常驻内存。

IRQL处于DISPATCH_LEVEL或者以上的等级,必须处于非分页内存里面。

同理,对于数据段也有同样的机制,于是有了PAGEDATA、LOCKEDDATA、INITDATA。

KdPrint是一个宏,在调试版本(Checked)里面(具备DBG宏定义),有代码:而在正式版本(Free)里面,KdPrint被定义为空。

所以可以用来作为调试输出。

但注意Kdprint后面是两层括号,用法与C语言运行库的printf差不多。

pDriverObject->DriverUnload = UnloadRoutine;将卸载例程函数告诉驱动对象,驱动对象在前面已经有定义,这里不做深入讨论。

pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine;注册排遣例程。

Windows是消息驱动,而驱动程序是IRP驱动的,I/O管理器将发送到驱动的“消息”封装在IRP里面,驱动程序也将结果告诉IRP。

类似windows的消息机制,对于不同的“消息”,驱动程序需要注册不同的处理例程来区别对待,当然也可以放在同一个例程里面,然后用sw itch语句来区别对待,但当处理过程比较长的时候,会比较凌乱。

IRP_MJ_CREATE是当RING3应用程序在使用CreateFile函数建立与驱动程序的通信通道时所激活的。

IRP_MJ_READ是ReadFile,IRP_MJ_WRITE是WriteFile,而IRP_MJ_CLOSE是CloseHandle关闭文件句柄的时候产生的。

小知识:对于WDM式驱动,仍需要注册AddDevice例程,pDriverObject->DriverExtension->AddDevice = WDMAddDeviceRou tine,设备对象的初始化将在AddDevice里面进行而不是DriverEntry。

另外还需要注册IRP_MJ_PNP排遣函数。

相关文档
最新文档