DDK驱动开发笔记

合集下载

ddk学习中遇到的问题和解决方法

ddk学习中遇到的问题和解决方法

ddk学习中遇到的问题和解决方法/lweiyan/blog/item/8b9d22091fd8c9c73ac763f6.html2009年05月16日星期六 17:55关于Driver Studio 3.2 的安装详解经过对VC、WINDDK、Driver Studio这三个软件反复的安装,终于可以使Driver Studio能在VC环境下正常编译了。

俗话说久病成医,遇到的问题多了,自然就有了很多解决问题的方法,现在拿出来和大家一起分享一下。

1、分别安装VC、WINDDK、Driver Studio,为:VC-〉WINDDK-〉 Driver Studio。

其实顺序也可以变一下的,笔者曾试过VC-〉 Driver Studio -〉WINDDK,没问题的,但最好按建议顺序安装;2、注意安装DDK时,建议将例子等全部安装,否则Driver Studio编译时会提示缺少头文件;3、在VS2005环境下,安装Driver Studio时会有对话框弹出,单击Ignore按钮,解决办法会在后面详细说明;4、选择“DriverStudio->DDK Build Setting”,在“DDK Root Directory”选项中选入DDK目录,例如“C:\WINDDK\2600”。

为了防止每次启动VC来编译WDM时,都要设置DDK目录,可以在“控制面板”的“系统”-〉“高级”-〉“环境变量E”设置中,添加一个值为C:\WINDDK\2600的系统变量BASEDIR;5、用VC打开“…\DriverStudio\DriverWorks\source\VdwLibs.dsw”,用 Driver Studio进行编译,如果编译成功就OK了,然后可以进行驱动的开发了。

6、利用DriverWizard向导对所要开发的驱动类型进行正确配置,生成所需要的驱动工程框架。

安装DriverStudio3.2 过程中出现DSDDKEnv8.dll failed to register错误的解决方法原因:与VS2005集成时会发生此错误。

基于DDK的PCI设备驱动程序设计

基于DDK的PCI设备驱动程序设计

基于DDK的PCI设备驱动程序设计作者:赵彬,田泽,陈佳来源:《电脑知识与技术》2011年第07期摘要:该文以基于PCI9056的某项目设备板卡为例,介绍WDM驱动程序和PCI总线协议,分析利用DDK开发WDM驱动程序的主要例程,实现了识别板卡及测试板卡功能。

关键词:WDM;PCI;DDK;设备驱动程序中图分类号:TP333文献标识码:A 文章编号:1009-3044(2011)07-1534-03Designed of PCI Device Driver Based on DDKZHAO bin1, TIAN Ze1, CHEN Jia2(1.Xi'an Shiyou University, Xi'an 710065, China; 2. Xidian University, Xi'an 710072, China)Abstract: This paper takes a PCI device as an example, describes WDM drivers and PCI bus protocols. And introducing a method of WDM driver design base on DDK(Driver Development Kit), realizing identification and testing function.Key words: WDM; PCI; DDK; device driver因为某项目的需求,需要在PC机上调试一PCI设备,在Windows系统下实现主机通过PLX9056桥芯片对PCI设备的访问,但前提条件是当操作系统装载驱动程序正确的情况下。

如果驱动程序装载不正常,主机首先就不能够识别PCI设备;如果驱动程序运行不正常,用户就不能正确的访问PCI设备。

因此,PCI驱动程序是实现主机识别板卡以及正确访问设备的关键。

基于DDK的音视频编码器驱动的设计

基于DDK的音视频编码器驱动的设计

程 。通过和传统 的驱动开 发模 型相 比,得 出基于 D K的驱动模型使得驱动开发具有以下优点 :重写 的代 码量 D 更少 ;移植到不 同的平台时 ,代码改动更少 。 关键词 : 驱动开发包 ;D 6 2开发板 ;音 视频编解 码器 M4
中图分 类号 :T 9 9 N 1 .8 文献标识码 :A
p a om. lt r fห้องสมุดไป่ตู้
K yw r s die ee p r i D K) M 4 V e o d : r rdvl e’ k v o S t( D ;D 6 2E M;d vrdvlp e t i r e ee m n o
引 言
D K ( r e ee pr i 是 r T x nt m n ) 为 简 化 驱 动 程 序 开 发 ,为 T S2 D D vr vl e, Kt i D o S ) I ' ea Isu et I( s r s M 30系列
维普资讯
第2 5卷
第 3期
20 0 7年 5月
吉 林 大 学 学 报 ( 息 科 学 版) 信 Junl f inU iesy(no t nSi c dtn ora o Ji nvrt If mao c n eE io ) l i r i e i
DP S 提供的驱动程序开发套件。该套件为 T S2 M 30系列各种外围器件提供完整 的标准化驱动程序模型 , 使驱 动程序 可 以很 方便地 移植 到其他 应用 中 ,大大提 高 了驱动 程序 开 发 的效率 。D K是对 每 种 T 30 D MS2 系列 D P都提供 的芯片支持库 ( S :Ci S po i a )的补充 ,C L S C L l prL r y pu t br S 提供对外 围器件寄存器配置及 初始化 等 的低 级控 制 ,D K完全通 过 C L对外 围器件 进行 控制 。简 单地 说 ,D K建 立在 C L上层 ,所 D S D S 以用 D K来开 发驱 动程序 将更 为快捷 且可 移植性 更好 。 D

windows下虚拟串口驱动开发

windows下虚拟串口驱动开发

现在介绍在windows XP下开发虚拟串口的方法。

可以开发一个虚拟串口,将读写请求传递给USB驱动,这样就可以利用现成的串口调试工具向USB设备读取了。

1、DDK串口开发框架DDK对串口驱动提供了专门接口。

只要编写的驱动满足这些接口,并按照串口标准的命名方法,不管是真实的串口设备,还是虚拟设备,Windows操作系统都会认为这个设备是一个标准的串口设备。

用标准的串口调试工具都可以与这个设备进行通信。

1、1 串口驱动的入口函数本章的实例程序是在HelloWDM驱动的基础上修改而来,入口函数依然是DriverEntry,在DriverEntry函数中指定各种IRP的派遣函数,以及AddDevice 例程、卸载例程等。

[cpp]view plaincopy1./************************************************************************2.* 函数名称:DriverEntry3.* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象4.* 参数列表:5. pDriverObject:从I/O管理器中传进来的驱动对象6. pRegistryPath:驱动程序在注册表的中的路径7.* 返回值:返回初始化驱动状态8.*************************************************************************/9.#pragma INITCODE10.extern"C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,11. IN PUNICODE_STRING pRegistryPath)12.{13. KdPrint(("Enter DriverEntry\n"));14.15. pDriverObject->DriverExtension->AddDevice = HelloWDMAddDevice;16. pDriverObject->MajorFunction[IRP_MJ_PNP] = HelloWDMPnp;17. pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloWDMDispatchControlp;18. pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloWDMCreate;19. pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloWDMClose;20. pDriverObject->MajorFunction[IRP_MJ_READ] = HelloWDMRead;21. pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloWDMWrite;22. pDriverObject->DriverUnload = HelloWDMUnload;23.24. KdPrint(("Leave DriverEntry\n"));25.return STATUS_SUCCESS;26.}其中在AddDevice例程中,需要创建设备对象,这些都是和以前的HelloWDM驱动程序类似。

VS2005开发驱动DDK配置

VS2005开发驱动DDK配置

一准备DDK版本:Windows DDK 3790IDE:Visual Studio 2005二用DDK环境编译驱动这种编译驱动的办法是DDK文档中所提倡的办法。

此种方法需要编写一个编译脚本文件,在这个脚本中描述了DDK驱动程序的源文件、用到的lib文件和include路径名、编译输出的目录和文件名等信息。

编写此类脚本对于Windows程序员可能比较陌生,尤其是当源文件较多时,编写脚本文件可能显得更如麻烦。

在源程序的相同目录下创建两个文件makefile和Sources,这两个文件都是文本文件,内容如下。

Makefile这个文件不要修改## DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the driver components of the Windows NT DDK#!INCLUDE $(NTMAKEENV)\makefile.defSources这个文件参考实际情况修改!if "$(DDK_TARGET_OS)"=="Win2K"TARGETNAME=Passthru_2000!elseif "$(DDK_TARGET_OS)"=="WinXP"TARGETNAME= Passthru _XP!elseif "$(DDK_TARGET_OS)"=="WinNET"TARGETNAME= Passthru _03Server!endifTARGETPATH=objTARGETTYPE=DRIVERC_DEFINES=$(C_DEFINES) -DNDIS_MINIPORT_DRIVER -DNDIS_WDM=1!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"## The driver is built in the Win2K build environment#C_DEFINES=$(C_DEFINES) -DNDIS40_MINIPORT=1C_DEFINES=$(C_DEFINES) -DNDIS40=1!else## The driver is built in the XP or .NET build environment# So let us build NDIS 5.1 version.#C_DEFINES=$(C_DEFINES) -DNDIS51_MINIPORT=1C_DEFINES=$(C_DEFINES) -DNDIS51=1!endif# Uncomment the following to build for Win98/SE/WinMe# This causes several APIs that are not present in Win9X to be# ifdef'ed out.# C_DEFINES=$(C_DEFINES) -DWIN9X=1PRECOMPILED_INCLUDE=precomp.hPRECOMPILED_PCH=precomp.pchPRECOMPILED_OBJ=precomp.obj!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib \$(DDK_LIB_PATH)\ntstrsafe.lib!elseTARGETLIBS=$(DDK_LIB_PATH)\ndis.lib!endifUSE_MAPSYM=1INCLUDES=SOURCES=\miniport.c \passthru.c \passthru.rc \protocol.c \PTEXTEND.C \filter.c前7行说明此驱动的名称,这里用到了宏来控制不同操作系统版本的编译所需的文件,$(DDK_TARGET_OS)是从外面的命令行传递进来的。

基于WINDOWS DDK的USB键盘驱动开发

基于WINDOWS DDK的USB键盘驱动开发








…Leabharlann …一美展. 。 I
基  ̄' W I N DOW S DD K的 USB键 盘 驱 动 开 发
江西赣 州农 业学校 卢晓娟 陈根生
【 摘要】U S B 接 口具有方便快速 等优 点, 已经发展成为一种 比较普遍 的计 算机 与外设 的接口。基于微软w i n d o ws 统D DK,本 文介 绍了一种非标准U S B 键盘  ̄w i n d o w s 设 备 驱 动程序的开发过程与方法 。 【 关键 词】设备驱动 ;驱动开发包 ;非标准键 盘
1 . 引言
w i n m a i n 函数 的控制 下执行 ,驱动 程序不 存在
U S B 总线 的成功 关键 是使用 户感 到 了使 用 这样 的 函数 ,而 只是 一个 由I / 0 管理 组件 根据 U S B 设备 的方便 。即插 即用 ( P n P ) 概念的使用 使 需要 调用 的子例 程 的集合 ,i / 0 管理 组件 根据 某 些硬 件的 安装过 程得 到 了简 化 。U S B 规范 中 不 同的情 况调用 驱动程序 中不同的例程 。构成 指 出,适合迁 移 ̄U S B I . 1 上 的硬 件限定于那 些 内核模 式驱动程序 的主要例程 包括 :初 始化和 / o 系 统服务 调度 例程 ,数据 传输 低 速到 中速 的外设 ,包括键盘 ,鼠标等 。即这 清 除例程 ,i 些 设备 的数据 传输速率低 于1 2 M b / s e c ,并且 能 例程和 资源 回调例程 ,下面 是一个基本 的驱动
通 过单一 的P c 接 口被 系统软件识 别。现在标 准 例程架构 : e x t e r n” C” 的u s b 键盘 设备只 需要 遵循一些h i d 设备 的协 议 N T S T A T U S 就 可 以被 w i n d o w s 操 作系 统 自动 识别无 需设备 制造 商开发驱 动程序 ,但 有些键盘 带有特殊 功 D ri v e r E nt r Y( I N P D RI V E R — O B J EC T

Windows驱动开发入门

Windows驱动开发入门

接触windows驱动开发有一个月了,感觉Windows驱动编程并不像传说中的那么神秘。

为了更好地为以后的学习打下基础,记录下来这些学习心得,也为像跟我一样致力于驱动开发却苦于没有门路的菜鸟朋友们抛个砖,引个玉。

我的开发环境:Windows xp 主机+ VMW ARE虚拟机(windows 2003 server系统)。

编译环境:WinDDK6001.18002。

代码编辑工具:SourceInsight。

IDE:VS2005/VC6.0。

调试工具:WinDBG,DbgView.exe, SRVINSTW.EXE上面所有工具均来自互联网。

对于初学者,DbgView.exe和SRVINSTW.EXE是非常简单有用的两个工具,一定要装上。

前者用于查看日志信息,后者用于加载驱动。

下面从最简单的helloworld说起吧。

Follow me。

驱动程序的入口函数叫做DriverEntry(PDRIVER_OBJECT pDriverObj,PUNICODE_STRING pRegisgryString)。

两个参数,一个是驱动对象,代表该驱动程序;另一个跟注册表相关,是驱动程序在注册表中的服务名,暂时不用管它。

DriverEntry 类似于C语言中的main函数。

它跟main的差别就是,main完全按照顺序调用的方法执行,所有东西都按照程序员预先设定的顺序依次发生;而DriverEntry则有它自己的规则,程序员只需要填写各个子例程,至于何时调用,谁先调,由操作系统决定。

我想这主要是因为驱动偏底层,而底层与硬件打交道,硬件很多都是通过中断来与操作系统通信,中断的话就比较随机了。

但到了上层应用程序,我们是看不到中断的影子的。

说到中断,驱动程序中可以人为添加软中断,__asm int 3或者Int_3();前者是32位操作系统用的,后者是64位用的。

64位驱动不允许内嵌汇编。

下面是我的一个helloworld的源码:注意第16行的宏。

Windows驱动程序开发环境配置

Windows驱动程序开发环境配置

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、添加该项完毕后,选择您的控制面板,就可以看到新添加进来的项了。

USB ddk驱动

USB ddk驱动

通常驱动程序的调试都是用ddk在cmd中完成的。

这部分我暂时略过。

下面先介绍如何设置vc++6.0在Visual Studio 6.0集成环境中开发设备驱动程序的方法。

在Windows上,Windows DDK提供的开发环境是基于命令行的,操作起来极为不便,而Visual Studio 6.0给我们提供了非常友好易用的集成环境,让我们有如虎添翼之感。

那么,能否利用Visual Studio的集成环境来开发驱动程序呢?答案是可以的。

通过对Visual Studio集成环境的简单设置,创建好自己的驱动开发集成环境就可以了。

1,第一:安装Vc++6.0,我装的是英文版,中文版应该也可以,不过我没试。

第二:安装winXP DDK,注意,安装目录中间不能有空格,比如D:\Program Files不行,我直接装在了D盘,装完后设置环境变量DDKROOT为安装目录D:\WINDDK\2505。

2,创建一个目录,作为开发目录,我是利用<<PCI设备开发宝典>>的光盘中的工程文件PCI9052Demo,直接考到E盘,所以,工作目录下是E:\PCI9052Demo3,工作目录下创建一个批处理文件MakeDrvr.bat,内容如下:@echo offif "%1"=="" goto usageif "%3"=="" goto usageif not exist %1\bin\setenv.bat goto usagecall %1\bin\setenv %1 %4%2cd %3build -b -w %5 %6 %7 %8 %9goto exit:usageecho usage MakeDrvr DDK_dir Driver_Drive Driver_Dir free/checked [build_options] echo eg MakeDrvr %%DDKROOT%% F: %%WDMWorkshop%% free -cef:exit解释以下:1% 是DDK_dir,也就是ddk的安装目录2% 是Driver_Drive,是你工作目录所在的盘符,这里是E:3% 是Driver_Dir,是你工作目录的路径,这里是E:\PCI9052Demo4% 是编译模式,checked表示调试模式,free表示发行模式,这里是出问题的地方,后面再说。

ntddk

ntddk

用NT DDK开发协议驱动程序王大伟杨凯锋胡熠洪佩琳摘要:本文针对基于Windows NT平台的协议驱动程序的开发方法进行讨论,并给出一个开发实例进行具体说明。

关键词:协议驱动程序、DDK、NDIS一.协议驱动程序简介微软公司为Windows系列平台上的网络驱动程序开发者专门制定了NDIS规范(Network Driver Interface Specification)。

根据NDIS规范,Windows NT平台上的网络驱动程序主要有三类:网卡驱动程序、中介协议驱动程序和上层协议驱动程序。

网络驱动程序的层次结构参见参考文献【1】。

网卡驱动程序位于驱动程序层次的最底层,它直接管理硬件,屏蔽底层物理硬件的细节,向上层驱动程序提供一个抽象的服务接口。

协议驱动程序加载在网卡驱动程序之上,利用网卡驱动程序提供的服务实现各种网络协议的功能。

协议驱动程序可以在其上边界实现TDI(Transport Driver Interface)接口为网络用户提供服务。

譬如分配分组,从用户应用程序把数据拷贝到分组中,然后调用NDIS提供的函数把分组发送给下层驱动程序。

它在下边界提供一个协议接口,接收并解释从下层驱动程序接收到的分组。

微软公司为开发者编写驱动程序提供了DDK(Device DriverKit)工具包。

根据不同的平台分为NT DDK和Windows 95 DDK。

在DDK中,包含了依据NDIS规范开发网络驱动程序的工具。

关于DDK的介绍,以及用DDK开发驱动程序的步骤参见参考文献【1】。

二.协议驱动程序的结构协议驱动程序包括驱动程序对象和驱动程序所提供的入口函数集合。

一个协议驱动程序必须绑定到小端口网卡驱动程序或者中介驱动程序(此时相当于一个虚拟的小端口网卡驱动程序)之上,它可以绑定到一个或者多个底层驱动程序之上。

协议驱动程序在其下边界提供一系列的ProtocolXxx接口函数,并通过NDIS发送和接收网络分组。

vs2015 驱动程序开发实例

vs2015 驱动程序开发实例

vs2015 驱动程序开发实例标题:VS2015驱动程序开发实例驱动程序是一种特殊的软件,用于与硬件设备进行通信和控制。

在Visual Studio 2015(简称VS2015)中,开发人员可以使用驱动程序开发工具包(DDK)来创建驱动程序。

本文将通过一个实例来介绍在VS2015中进行驱动程序开发的步骤和注意事项。

第一步:准备开发环境在开始编写驱动程序之前,我们需要准备好开发环境。

首先,确保已经安装了VS2015,并选择合适的开发模块。

接下来,下载并安装驱动程序开发工具包(DDK)。

安装完成后,打开VS2015,创建一个新的驱动程序项目。

第二步:编写驱动程序代码在VS2015中,我们可以使用C或C++语言来编写驱动程序。

根据硬件设备的特性和功能需求,我们可以选择合适的编程语言。

编写驱动程序的关键是了解设备的工作原理和通信协议。

根据设备文档和开发者手册,我们可以开始编写驱动程序的代码。

第三步:构建和调试驱动程序在编写完驱动程序代码后,我们需要进行构建和调试。

在VS2015中,我们可以使用调试工具来检查代码的正确性和执行过程。

通过设置断点,我们可以逐步调试代码,并查看变量的值和函数的返回结果。

如果发现错误,我们可以根据调试信息进行修改和优化。

第四步:测试和部署驱动程序在完成构建和调试后,我们需要进行测试和部署。

测试主要是验证驱动程序是否能够正常运行,并与硬件设备进行正确的通信和控制。

通过编写测试用例和模拟不同的工作场景,我们可以全面测试驱动程序的性能和稳定性。

一旦通过测试,我们可以将驱动程序部署到目标设备中,让其正式投入使用。

总结在VS2015中进行驱动程序开发需要准备好开发环境,编写代码,构建调试,测试部署等多个步骤。

通过合理的组织和安排,开发人员可以高效地完成驱动程序的开发工作。

驱动程序的开发是一项复杂而重要的任务,需要充分理解硬件设备和通信协议,同时注重代码的质量和性能。

希望本文能够帮助读者更好地理解和掌握VS2015驱动程序开发的技术和方法。

vs2012 ddk驱动设置

vs2012 ddk驱动设置

vs2012与wdk驱动编程中编译环境设置(此例驱动在win7下要重启系统)1、新建项目向导中选择“空项目”如下图,然后点击完成。

2、在菜单“视图”里面选择“属性管理器”如下图:3、点击“配置管理器”(此工具在“工具箱”中“标准”)如下图:4、在弹出的的对话框中点击“活动解决方案配置”下拉菜单点“新建”,名字随便为了有意义在这取个名字“WdkDriver”如下图:5、设置“WdkDriver”为当前活动状态,如下图:6、设置“解决方案属性”,点击菜单“项目”“属性”设置如下图:A、选项“常规”设置如下图:B、“VC++目录”设置如下图:(inc文件夹下面有3个文件夹“api”“ddk”“crt”,lib下面“win7”“i386”(我用的是win7系统32位)C、“C++”设置如下图:1、“常规”设置:2、“优化”选择“禁用/od”3、“预处理器”选择“预处理器定义”输入如下内容“WIN32=100;_X86_=1;DBG=1;%(PreprocessorDefinitions)”4、“代码生成”选5、“高级”选择“调用约定”中选择“_stdcall/Gz”D、“链接器”设置如下图:1、“常规”设置2、“输入”选择“附加依赖项”输入如下内容“ntoskrnl.lib Hal.lib;wdm.lib;wdmsec.lib;wmilib.lib;ndis.lib;MSVCRT.LIB;LIBCMT.LIB“忽略所有默认库”中选择“是(/NODEFAULTLIB)”其他选项为空3、“清单文件”选择“生成清单”中选择“否(/MANIFEST:NO)”;“启用帐户控制(UAC)”中选择“否(/MANIFESTUAC:NO)”4、“系统”选择“子系统”中选择“本机(/SUBSYSTEM:NATIVE)”;“堆栈保留大小”“4194304”;“堆栈提交大小”“4096”;“驱动程序”中选择“驱动程序(/Driver)”5、“所有选项”参考WINDOWS 7 配置驱动开发环境vs2012+WDK7.6__脚本百事通设置以上属性后可以加入源文件编译事例:WdkDriver.h#pragma once#ifdef _cplusplusextern"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 WdkUnload(IN PDRIVER_OBJECT pDriverObject);NTSTATUS WdkDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);事例 WdkDriver.cpp#include"WdkDriver.h"#pragma INITCODE //指出下面函数加载到INIT内存区,加载完成后退出NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING RegistryPath) {NTSTATUS status;KdPrint(("Enter DriverEntry\n"));//注册其他入口程序pDriverObject->DriverUnload = WdkUnload;pDriverObject->MajorFunction[IRP_MJ_CREATE] = WdkDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_CLOSE] = WdkDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_WRITE] = WdkDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_READ] = WdkDispatchRoutine;//创建驱动设备对象status = CreateDevice(pDriverObject);KdPrint(("DriverEntry end\n")); //宏,调试版(Checked版)用DbgPrint()代替,发行版(Free版)不执行任何操作.//类似MFC中的TRACE()return status;}//创建设备#pragma INITCODENTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject){NTSTATUS status;PDEVICE_OBJECT pDevObj;PDEVICE_EXTENSION pDevExt;//创建设备名称UNICODE_STRING devName;RtlInitUnicodeString(&devName,L"\\Device\\MyWdkDevice");//创建设备status = IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN, //设备为独占设备,只能被一个应用程序使用0,TRUE,&pDevObj);if(!NT_SUCCESS(status))return status;//填充PDEVICE_EXTENSION结构,得到设备自定义信息pDevObj->Flags |= DO_BUFFERED_IO;pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;pDevExt->pDevice = pDevObj;pDevExt->ustrDeviceName = devName;//创建符号链接,此符号指向真正的设备名称UNICODE_STRING symLinkName;RtlInitUnicodeString(&symLinkName,L"\\??\\WdkApp");pDevExt->ustrSymLinkName = symLinkName;status = IoCreateSymbolicLink(&symLinkName,&devName);if(!NT_SUCCESS(status)){IoDeleteDevice(pDevObj);return status;}return STATUS_SUCCESS;}//卸载设备#pragma PAGEDCODEvoid WdkUnload(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);IoDeleteDevice(pDevExt->pDevice);}}//事务函数,对设备的具体操作#pragma PAGEDCODENTSTATUS WdkDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp){KdPrint(("Enter WdkDispatchRoutine\n"));NTSTATUS status = STATUS_SUCCESS;//完成IRPpIrp->IoStatus.Status = status;pIrp->rmation = 0;IoCompleteRequest(pIrp,IO_NO_INCREMENT);KdPrint(("Leave WdkDispatchRoutine"));return status;}。

基于WINDOWS DDK的USB键盘驱动开发

基于WINDOWS DDK的USB键盘驱动开发

基于WINDOWS DDK的USB键盘驱动开发
卢晓娟;陈根生
【期刊名称】《电子世界》
【年(卷),期】2013(000)010
【摘要】USB接口具有方便快速等优点,已经发展成为一种比较普遍的计算机与外设的接口。

基于微软windows系统DDK,本文介绍了一种非标准USB键盘的windows设备驱动程序的开发过程与方法。

【总页数】2页(P83-84)
【作者】卢晓娟;陈根生
【作者单位】江西赣州农业学校;江西赣州农业学校
【正文语种】中文
【相关文献】
1.基于VxWorks的USB键盘驱动开发研究 [J], 白丽;任恩恩;朱娜敏
2.基于DDK的USB接口WDM驱动开发 [J], 邓玖根;张正荣;胡松;唐小萍
3.Windows CE下USB设备流驱动开发与设计 [J], 慕晓蕾
4.基于DDK的PCI总线数据交互驱动开发 [J], 段晗晗;
5.用DDK开发Windows USB驱动程序 [J], 杨成
因版权原因,仅展示原文概要,查看原文内容请购买。

使用CodeBlocks进行驱动开发

使用CodeBlocks进行驱动开发

使用CodeBlocks进行Windows驱动开发CodeBlocks是一款轻量级的编程开发工具,相对于动辄好几G的VC++来说,可以说好上太多了。

那么,对于驱动开发方面,如何使用CodeBlocks进行开发?本文介绍一种在Win7 x86环境下进行配置的方法。

1、在安装好WinDDK(版本:7600.16385.1,记下此安装的目录,此例的安装目录在E 盘)之后打开CodeBlocks,在界面中依次单击菜单:“Settings”→“Complier...”,打开如下图所示的界面。

首先选择一个编译器的配置,如:Microsoft Visual C++ 2010,单击“Copy”,输入新的配置的名称,这里我们配置一个x86环境下的编译器。

为编译器取一个名字:Microsoft Visual C++ Driver x86,确定之后在“Compiler settings”中钩选“__stdcall calling convention [/Gz]”。

由于我们设置的是x86环境下的编译器,所以在“#define”中设置一个“_X86_”,其它环境的编译器设置方法与此类似。

如果不知道如何设置,将此项留空,在编译时会有错误提示,可以根据错误提示进行输入。

2、设置链接时链接的lib文件,如下图所示:3、为编译器、链接器及资源编译器设置查找目录:设置编译器(Comliler)编译时的搜寻头文件目录如下图:设置链接器(Linker)的搜寻头文件目录如下图所示:设置资源编译器(Resource Compiler)的搜索头文件目录如下图所示(也可以不设置):4、设置编译器、链接器及资源编译器的安装目录,如下图:5、设置链接参数:依次打开“Other settings”→“Advanced options…”,在“Commands”页的“Command”中选择“Link object files to native executable”,在“Command line macro”中输入如下参数:$linker /nologo /subsystem:native /driver /entry:DriverEntry /RELEASE $libdirs /out:$exe_output $libs $link_objects $link_resobjects确定之后,退出compiler settings设置。

ddk教程-driver

ddk教程-driver

初学驱动开发书籍介绍一、总述 (2)1.1分类 (2)1.2 目的 (2)1.3 开发环境的建造 (2)1.4 编写驱动程序的原则 (3)1.5 计算机已知的挑选原则 (3)1.6 购买方式 (3)二、推荐的书目 (4)2.1 《C程序设计》 (4)2.2 《Windows 2000内部揭密》 (5)2.3 《Microsoft Windows 驱动程序模型设计》 (5)三、一般驱动开发书籍 (7)3.1 Windows 2000设备驱动程序设计指南(原书第2版) (7)3.2 WINDOWS NT与WINDOWS 2000设备驱动及开发 (8)3.3 WINDOWS WDM设备驱动程序开发指南 (8)3.4 Windows设备驱动程序(VxD与WDM)开发实务 (9)四、相关推荐书目 (10)4.1 Windows核心编程 (10)4.2 LINUX设备驱动程序(第二版) (11)五、烂书曝光 (12)5.1 Microsoft Windows 2000驱动程序设计指南 (12)5.2 VC++.NET开发驱动程序详解——Windows 2000/XP (13)六、后记 (14)一、总述1.1分类驱动程序按操作系统平台可分为两大类:Windows 系列与 Linux/Unix系统。

而在Windows平台中又包含两大类:VxD(Virtual X Device)与WDM(Windows Driver Model),前者运行于Windows 3.1/95/98/ME,后者运行于Windows 98/ME/2000/XP。

Windows NT4.0平台上的KMD驱动程序仅比WDM少了能量管理与即插即用功能而矣。

当然,在Windows 2000平台上的驱动程序除WDM外,还有文件系统驱动、NDIS(Network Driver Interface Specific)驱动等等其它类型的驱动程序,但在下面的书籍推荐与介绍中我们将主要围绕WDM进行。

DriverWorks简明教程

DriverWorks简明教程

DriverW orks简明教程1.学会使用向导很多人不喜欢向导,可是一个从应用开发转做驱动开发的人可能更容易接受这种方式,但在今天我不打算使用过多的向导,而是手工写驱动代码,只是使用了DriverW orks的包装类,使用MFC可以反过来使我的SDK技术长进不少,那同样的使用DriverW orks我相信同样可以使我们的DDK技术得到锻炼.首先使用DDK Build Settings启动V isual C++ 6.01.1 点击DriverStudio工具栏上的Launch DriverWizard按钮,选择New Project中的"Start a New Driver Project"1.2 向导会自动选中DDK Source/makefile和V isual Studio 6,在Project Name里输入"hello"后点下一步1.3 project type页中选择"Kernel Mode Service"点下一步1.4 IRP Handlers页中把所有自动勾上的请求都去掉,因为我们要手工写DriverW orks代码以加深印象.点下一步1.5 在Additional页里把自动勾上的Generate SoftICE NMS file in custom build step去掉.点下一步1.6 预览工程,并点击完成:Project Summary For kruglinskiProject Name = helloProject Location = D:\W orkspace\helloProject Type = NT1.8 空的工程框架就会生成完毕.此时直接编译会出错,也许是DriverStudio的一个Bug,只要把sources中的:TARGETLIBS=$(DDK_LIB_PA TH)\ntstrsafe.lib$(DDK_LIB_PA TH)\csq.lib这一行去掉就可以编译通过了,让我们编试一下,一定感觉很不错吧!2.拨开云雾见日出2.1 现在我们要做的是清理掉所有会让我们眼花的东东(一大堆向导生成的代码),只留下编译环境,我喜欢在V isual Studio里直接编译的感觉,很讨厌总是看到那个黑黑的Build Console.切换到FileV iew初图,把除了makefile和sources文件以外的其它文件全部删除,然后我们只复制hello.dsp,sources和makefile三个文件到一个单独的文件夹helloworld里.选择File-Close W orkspace关闭刚向导出来的工程,再把copy出来的hello.dsp拖到V isual Studio 6中打开(这时会自动生成一个hello.dsw).2.2 现在要正式开工了,按Ctrl+N在Files页选择C++ Source File,在File栏里输入hello.cpp在hello.cpp里首先要#include "vdw.h" ,因为我们要用的DriverW orks包装类的头文件都由该文件包括.这里需要注意的是在#include "vdw.h"前应该加入一句#define VDW_MAIN因为DriverW orks的帮助文件里这样说(懒得译了,将就着看吧!!)Symbol VDW_MAIN must be #define'd in exactly one source module of the driver, generally the module that implements the driver class. If, as is true for most drivers, there is more than one source module, do not #define VDW_MAIN in any other modules. The definition must precede #include . The purpose of this symbol is to control the inclusion of certain source files in the DriverW orks library. These source files must be compiled in the context of the driver being built.2.3 我们定义一个驱动对象类,它派生自KDriver,必须提供一个纯虚函数DriverEntry的实现:class MyDriver:public KDriver{SAFE_DESTRUCTORS;public:virtual NTSTA TUS DriverEntry(PUNICODE_STRING RegistryPath);};DECLARE_DRIVER_CLASS(MyDriver,NULL)NTSTA TUS MyDriver::DriverEntry(IN PUNICODE_STRING RegistryPath){DbgPrint("Hello KMD world!");return STA TUS_SUCCESS;}这里还有一个DECLARE_DRIVER_CLASS(MyDriver,NULL)要注意,再copy一段帮助文档上的内容:One module of the driver must invoke macro DECLARE_DRIVER_CLASS. This macro actually inserts a small function that the framework calls during initialization. The function creates an instance of the driver class.现在已经可以编译成sys,用我的小工具Driver Logicl Tester可以测试一下效果,可以看到输出了一行"hello KMD W orld!",我想需要解释一下KDriver,KDriver是驱动对象,按照DriverW orks对象模型里的观念,一个驱动程序里至少要包括一个驱动对象,这个驱动对象可以包括一个或多个设备对象,Ring3的应用程序可以通过设备对象来于驱动程序交互.后面我会做简单的演示.3.打开潘多拉魔盒上面演示的东东其实本上没有多大实际的用处,当然可以在riverEntry里添加一个调用门让Ring3的应用程序有机会使用调用门进入Ring0.所以我们必须要做到可以控制驱动程序执行指定的代码完成指定的任务.3.1 设备对象与KDevice在DriverW orks里KDevice和KPnpDeivce做为设备对象类的抽像,因为这里想演示的是KMD而不是WDM,所以我在这里只使用KDevice,KPnpDeivce以后有空再说.在#define VDW_MAIN后#include "vdw.h"前加上以下几行:#define DRIVER_FUNCTION_DEVICE_CONTROL#define DRIVER_FUNCTION_CREA TE#define DRIVER_FUNCTION_CLOSE#define DRIVER_FUNCTION_CLEANUP当需要覆盖设备或是驱动对象基类的某个函数时,需要在include 之前定义这些宏.原因不要问,文档上要求这样做那就这样做咯.具体的可以查看DriverW orks源代码,这四个是设备对象要用到的,可以对应看下面的代码.现在我们实现一个设备对象的派生类MyDevice,它将负责与上层的驱动测试工具做交互.class MyDevice : public KDevice{public:SAFE_DESTRUCTORS;MyDevice();~MyDevice();DEVMEMBER_DISPA TCHERS;};DriverW orks帮助文档里说到如果没有SAFE_DESTRUCTORS这个宏,Unload例将工作的不太正常,所以不用问那么照做就是.而DEVMEMBER_DISPA TCHERS宏的功能是自动的定义所有的派遣函数,如果Create,Close,Cleanup...等.然后分别实现前面#define的那几个派遣函数:NTSTA TUS MyDevice::Create(KIrp I)DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS MyDevice::Close(KIrp I){DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS MyDevice::DeviceControl(KIrp I){DbgPrint(__FUNCTION__":IRP %p,CodeCode=%d\n", I,I.IoctlCode());rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS MyDevice::CleanUp(KIrp I)DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}3.2 构造一个设备对象在DriverEntry里创建这个设备对象,其实非常简单,只是调用一个new运算符函数.NTSTA TUS MyDriver::DriverEntry(PUNICODE_STRING RegistryPath){NTSTA TUS status = STATUS_SUCCESS;DbgPrint(__FUNCTION__"RegistryPath:%S\n",RegistryPath->Buff er);MyDevice* pDevice = new (L"HelloDevice",FILE_DEVICE_UNKNOWN,L"HelloDevice",0,DO_DIRECT_IO)MyDevice();if (pDevice == NULL){status = STA TUS_INSUFFICIENT_RESOURCES;}else{status = pDevice->ConstructorStatus();//读取设备对象构造后的状态if (!NT_SUCCESS(status)){delete pDevice;}elseDbgPrint(__FUNCTION__"Created HelloDevice!\n");}return status;}我想需要解释一下这个new运算符,它是KDevice的重载动算符,我使用的原型是:void* __cdecl operator new(size_t n,PCWSTR DeviceName,DEVICE_TYPE Type,PCWSTR LinkName=NULL,ULONG Characteristics=0,ULONG DeviceFlags=DO_BUFFERED_IO);这个new运算符函数的comment说到:// This is the form of new that allocates the storage for the class instance in// the system device object extension.在设备对象扩展里分配并存储类实例,我看了一下它的源代码在kfilter.cpp中,它会调用一个叫__construct的函数,而__construct函数会调用IoCreateDevice创建一个驱动设备对象(注意不是DriverW orks设备对象类),并分配一个大小为n(在这里是n=sizeof(MyDevice))的设备扩展用来存储这个设备对象类(包括它的数据成员,感觉确实是很方便啊!),并调用IoCreateSymbolLink在\DosDevice\创建一个符号链接供Ring3程序使用,我想LinkName使用一个GUID字符串更合适一些.呵呵!其实不需要把代码跟到这里看,只不过了解一些底下的东东也好,但我很赞成潘爱民老师所说的,做应用开发尽可能不要去读软件开发商提供的类库源代码.只看参考手册能够用的很熟练很巧就行了.所以我只看D.j.Kruglinski的Inside VC++而从不去看什么深入浅出MFC,我的MFC照样用的很好,也可以理解那些MFC底层如何实现,其实深入浅出MFC里的东西,Inside VC++里只用了几页纸就讲的非常清楚了,呵呵!话扯远了.也许每个人学习的思想和方法不一样.再搬出我的小工具,测试一下.可以看到我们写的几个函数都被调用到了,每按一下"IoControl"按钮,DeviceControl函数就会被调用.4.输入与输出4.1 简单的KMD与上层应用同步方法我想有了前面的基础,做输出输出已经不是什么难事,可以在DeviceIoControl里做,也可以在Read和Write派遣函数里做,不过我想通常的做法是,驱动创建一个同步事件,使用DriverW orks的KEvent对象,并使用这个成员函数原型进行初使化:VOID Initalize(KUstring& Name,EVENT_TYPE type);第一个参数可以填以\BaseNamedObjects\为前缀的事件对象名,后一个参数可以是SynchronizationEvents(同步事件)或是NotificationEvents(通知事件),然后Ring3的程序可以用CreateEvent打开这个对象,W aitForSingleObject做同步.当有数据时上层的程序会在第一时间得到通知.一般设备对象会添加几个容器成员,像前面分析的,它们会被会配并存储在设备扩展里,当然容器要使用的堆内存会是从PagedPool 或是NonPagedPool里分配出来的,一些常用的容器如KList,KLockableFifo,KInterlockedList...等等.这样,数据的排队和存储解决后,就是在派遣函数中处理它们了,或是从上层收到并存入容器,或是从容器里摘除并返回到上层.4.2 IO控制代码一般使用一个叫做CTL_CODE的宏来定义IO控制代码,在每个派遣函数有一个KIrp类型的参数,它也IRP请求包的包装类,KIrp::IoctlCode函数返回控制代码的引用,也就是说我们可以读也可以改写控制代码.通常在DeviceIoControl里根据不同的控制代码做不同的动作.类似于这样:NTSTA TUS MyDevice::DeviceControl(KIrp I){switch (I.IoctlCode()){case CTRL_SETUP_HOOK:.............break;case CTRL_REMOVE_HOOK:.............break;default:status = STA TUS_INV ALID_DEVICE_REQUEST;break;}...}而输入输出缓冲及大小分别由,KIrp::IoctlBuffer,KIrp::IoctlInputBufferSize和KIrp::IoctlOutputBufferSize来获得.这只是Buffered IO方式,还有Direct IO方式有空再说!完整的程序代码,我更喜欢看面向对象的代码结构,呵呵!//hello.cpp:#define VDW_MAIN#define DRIVER_FUNCTION_DEVICE_CONTROL#define DRIVER_FUNCTION_CREA TE#define DRIVER_FUNCTION_CLOSE#define DRIVER_FUNCTION_CLEANUP#define DRIVER_FUNCTION_UNLOAD#include "vdw.h"class MyDriver : public KDriver{SAFE_DESTRUCTORSpublic:virtual NTSTA TUS DriverEntry(PUNICODE_STRING RegistryPath);virtual VOID Unload(VOID);};DECLARE_DRIVER_CLASS(MyDriver,NULL)class MyDevice : public KDevice{public:SAFE_DESTRUCTORS;MyDevice();~MyDevice();DEVMEMBER_DISPA TCHERS};MyDevice::~MyDevice(){}MyDevice::MyDevice() :KDevice(){if (!NT_SUCCESS(m_ConstructorStatus)){DbgPrint(__FUNCTION__": Failed to create device MyDevice"); return;}}NTSTA TUS MyDevice::Create(KIrp I){DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;NTSTA TUS MyDevice::Close(KIrp I){DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS MyDevice::DeviceControl(KIrp I){DbgPrint(__FUNCTION__":IRP %p,CodeCode=%d\n", I,I.IoctlCode());rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS MyDevice::CleanUp(KIrp I){DbgPrint(__FUNCTION__":IRP %p\n", I);rmation() = 0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;VOID MyDriver::Unload(VOID){KDriver::Unload();}NTSTA TUS MyDriver::DriverEntry(PUNICODE_STRING RegistryPath){NTSTA TUS status = STATUS_SUCCESS;DbgPrint(__FUNCTION__"RegistryPath:%S\n",RegistryPath->Buff er);MyDevice* pDevice = new (L"HelloDevice",FILE_DEVICE_UNKNOWN,L"HelloDevice",0,DO_DIRECT_IO)MyDevice();if (pDevice == NULL){status = STA TUS_INSUFFICIENT_RESOURCES;else{status = pDevice->ConstructorStatus();if (!NT_SUCCESS(status)){delete pDevice;}elseDbgPrint(__FUNCTION__"Created HelloDevice!\n");}return status;}到现在为止,如果你是已经可以很熟练的用DDK写驱动肯定觉得这一切会有点繁琐,但这仅仅是开始,驱动的工程越大,代码量越多时使用DriverW orks表现出的效率会越明显.可以类比像MFC 与SDK玩玩DriverW orks(二)-读写数据这两天怎么老想玩DriverW orks今天抽了一个小时写个小驱动练习一下KIrp和KMemory配合访问三种IO方式中的数据.KIrp是对IRP请求对象的包装,它有很多成员函数用于操作IRP结构.1.Buffered IO:在Buffered IO方式中IO管理器会分配一块堆内存然后把用户态缓冲区数据copy进来再传给驱动程序,而输出时IO管理器会把堆内存中的数据copy回用户态缓冲区.我们使用下面这样的代码来得到输入/输出缓冲区和大小KIrp I;....ULONG inputSize = I.IoctlInputBufferSize();ULONG outputSize = I.IoctlOutputBufferSize();PVOID inputBuffer = I.IoctlBuffer();PVOID outputBuffer = I.IoctlBuffer();一目了然吧!我想要介绍一下这几个函数,但你实际上可以跳过下面的一小段因为用DriverW orks根本用不着知道这些细节.IoctlBuffer,IoctlInputBufferSize,IoctlOutputBufferSize函数实现非常简单:inline PVOID& KIrp::IoctlBuffer(void){return m_Irp->AssociatedIrp.SystemBuffer;}inline ULONG& KIrp::IoctlOutputBufferSize(EStackLocation s) {V alidateStackLocation(s);if (s == CURRENT)return IoGetCurrentIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.OutputBufferLength;elsereturn IoGetNextIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.OutputBufferLength;}inline ULONG& KIrp::IoctlInputBufferSize(EStackLocation s) {V alidateStackLocation(s);if (s == CURRENT)return IoGetCurrentIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.InputBufferLength;elsereturn IoGetNextIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.InputBufferLength;}在IoctlOutputBufferSize和IoctlInputBufferSize中S有一个默认参数CURRENT,上面的代码就是这样调用它们的.可以看到其实是对IO_STACK_LOCATION结构直接的操作.2.Direct IO:Direct IO方式中IO管理器分将用户态缓冲区映射到核心态(地址不一样,但其实是一块内存),并锁定内存不要分页机制将内存交换到外存中.然后IO管理器将缓冲区在核心态的的地址传给驱动程序.Direct IO的分成METHOD_IN_DIRECT和METHOD_OUT_DIRECT2.1 在METHOD_IN_DIRECT中我们使用这样的代码来访问缓冲区及大小KIrp I;....KMemory Mem(I.Mdl());PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG writeSize = I.WriteSize();ULONG bytesSent = 0;2.2 在METHOD_OUT_DIRECT中要像这样来访问缓冲区及大小KIrp I;....KMemory Mem(I.Mdl());PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG readSize = I.ReadSize();ULONG bytesRead = 0;I.Mdl函数是这样实现的:inline PMDL& KIrp::Mdl(void){return m_Irp->MdlAddress;}它直接返回IRP结构的MdlAddress字段,而MapToSystemSpace 的实现代码是这样的:inline PVOID KMemory::MapToSystemSpace(void){return GetSystemAddressForMdl(m_pMdl);}它调用下面这个函数,这里我不太明白为什么不直接调用MmGetSystemAddressForMdlinline PVOID GetSystemAddressForMdl(PMDL pMdl){CSHORT canFail; // original fail flag in MDLif(!(pMdl->MdlFlags &(MDL_MAPPED_TO_SYSTEM_V A | MDL_SOURCE_IS_NONPAGED_POOL))) {// get the current fail flagcanFail = (CSHORT)(pMdl->MdlFlags & MDL_MAPPING_CAN_FAIL);// set 'mapping can fail' so we don't bugcheck// if MmMapLockedPages failspMdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;// try to map the bufferpMdl->MappedSystemV a =(PVOID)(((ULONG_PTR)MmMapLockedPages(pMdl, KernelMode)) |MmGetMdlByteOffset(pMdl));// set the original flag back in the MDLif(!canFail) {pMdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;}}return pMdl->MappedSystemV a;}3 Neither IO:在Neither IO,IO管理器直接把用户态的缓冲区地址和大小传给驱动,不做任何处理.这是很危险的,通常情况下,我们需要写一些小的助手驱动以进入Ring0或是调用一些底层功能,如果可以肯定驱动的派遣函是运行在被动级并且在我们自己指定程序的进程上下文里,那么用用这种方式也无所谓.除此以外尽可能不用这样的IO方式.通常需要使用这样的代码来访问缓冲区和大小: KIrp I;....ULONG inputSize = I.IoctlInputBufferSize();ULONG outputSize = I.IoctlOutputBufferSize();PVOID inputBuffer = I.IoctlType3InputBuffer();PVOID outputBuffer = erBuffer();IoctlType3InputBuffer和UserBuffer的实现代码:inline PVOID& KIrp::IoctlType3InputBuffer(EStackLocation s) {V alidateStackLocation(s);if (s == CURRENT)return IoGetCurrentIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.Type3InputBuffer;elsereturn IoGetNextIrpStackLocation(m_Irp)->Parameters.DeviceIoControl.Type3InputBuffer;}inline PVOID& KIrp::UserBuffer(void){return m_Irp->UserBuffer;}4. 现在可以总结一下,根据这些我们可以学到在DDK层面上应该怎么操作这些IO方式中的缓冲区:4.1 在驱动的派遣函数中可以使用IoGetCurrentIrpStackLocation 得到IO_STACK_LOCATION可以根据它的Control字段确定是什么派遣函数(因为可以将多个派遣函数地址指向一个派遣函数来处理多个请求).在Control等于IRP_MJ_DEVICE_CONTROL 时来要根据DeviceIoControl的子字段IoControlCode来确定是什么控制代码.4.2 对于Buffered IO和Neither IO可以使用它的DeviceIoControl 字段和三个子字段来访问缓冲区和大小参数:typedef struct _IO_STACK_LOCA TION {....union {...struct {ULONG OutputBufferLength;ULONG InputBufferLength;ULONG IoControlCode;PVOID Type3InputBuffer;} DeviceIoControl;...}....} IO_STACK_LOCA TION, *PIO_STACK_LOCA TION;4.3 对于Direct IO则要使用MmGetSystemAddressForMdl来将IRP结构的MdlAddress(内存描述表)字段映射到内核地址空间并锁定,得到一个内核空间地址才能进一步操作.Direct IO方式中的输入输出大小参数由IO_STACK_LOCA TION的Read.Length和Write.Length指示typedef struct _IO_STACK_LOCA TION {....union {...struct {ULONG Length;ULONG Key;LARGE_INTEGER ByteOffset;} Read;struct {ULONG Length;ULONG Key;LARGE_INTEGER ByteOffset;} Write;...}....} IO_STACK_LOCA TION, *PIO_STACK_LOCA TION;说不看库源代码的又忍不住开始分析,呵呵!其实可以把DriverW orks的对象类搞清楚怎么用就可以了.如果是想顺便把自己的DDK开发能力也提高一下的话,库的源代码也可以参考.有了昨天的DriverW orks基本介绍,我想下面的代码应该不是很难懂吧!//Interface.h#ifndef __INTERFACE_H__#define __INTERFACE_H__#define DEVICE_NAME L"IoDemoDevice"#define FILE_DEVICE_IODEMO 0x8000#define IOCTL_DO_BUFFERED_IO \CTL_CODE(FILE_DEVICE_IODEMO,0x800,METHOD_BUFFE RED,FILE_ANY_ACCESS)#define IOCTL_DO_DIRECT_IN \CTL_CODE(FILE_DEVICE_IODEMO,0x801,METHOD_IN_DIRECT,FILE_ANY_ACCESS)#define IOCTL_DO_DIRECT_OUT \CTL_CODE(FILE_DEVICE_IODEMO,0x802,METHOD_OUT_DI RECT,FILE_ANY_ACCESS)#define IOCTL_DO_NEITHER_IO \CTL_CODE(FILE_DEVICE_IODEMO,0x803,METHOD_NEITHE R,FILE_ANY_ACCESS)#endif//IODemo.cpp#define VDW_MAIN#define DRIVER_FUNCTION_UNLOAD#define DRIVER_FUNCTION_CREA TE#define DRIVER_FUNCTION_CLOSE#define DRIVER_FUNCTION_CLEANUP#define DRIVER_FUNCTION_DEVICE_CONTROL#include "vdw.h"#include "Interface.h"class IoDemoDriver:public KDriver{SAFE_DESTRUCTORS;public:virtual NTSTA TUS DriverEntry(IN PUNICODE_STRING RegistryPath);virtual VOID Unload();};DECLARE_DRIVER_CLASS(IoDemoDriver,NULL)class IoDemoDevice:public KDevice{SAFE_DESTRUCTORS;public:IoDemoDevice();DEVMEMBER_DISPA TCHERS;};IoDemoDevice::IoDemoDevice():KDevice(){if (!NT_SUCCESS(m_ConstructorStatus)){DbgPrint(__FUNCTION__": Failed to create device MyDevice"); return;}}NTSTA TUS IoDemoDevice::Create(KIrp I){DbgPrint(__FUNCTION__":IRP 0x%08X\n",I); rmation()=0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS IoDemoDevice::Close(KIrp I){DbgPrint(__FUNCTION__":IRP 0x%08X\n",I); rmation()=0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS IoDemoDevice::CleanUp(KIrp I) {DbgPrint(__FUNCTION__":IRP 0x%08X\n",I); rmation()=0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS IoDemoDevice::DeviceControl(KIrp I) {DbgPrint(__FUNCTION__":IRP 0x%08X\n",I);switch(I.IoctlCode()){case IOCTL_DO_BUFFERED_IO:{DbgPrint(__FUNCTION__":IOCTL_DO_BUFFERED_IO\n",I); ULONG inputSize = I.IoctlInputBufferSize();ULONG outputSize = I.IoctlOutputBufferSize();PVOID inputBuffer = I.IoctlBuffer();PVOID outputBuffer = I.IoctlBuffer();//显示出传进来的字符串if(inputSize)DbgPrint("inputBuffer:%s",(char*)inputBuffer);//返回一个字符串char chDoBufferedIO[]="DO_BUFFERED_IO";strncpy((char*)outputBuffer,chDoBufferedIO,outputSize);rmation()=strlen(chDoBufferedIO);}break;case IOCTL_DO_DIRECT_IN:{DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_IN\n",I);KMemory Mem(I.Mdl());PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG writeSize = I.WriteSize();ULONG bytesSent = 0;if(writeSize)DbgPrint("pBuffer:%s",(char*)pBuffer);rmation()=0;}break;case IOCTL_DO_DIRECT_OUT:{DbgPrint(__FUNCTION__":IOCTL_DO_DIRECT_OUT\n",I); KMemory Mem(I.Mdl());PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace(); ULONG readSize = I.ReadSize();ULONG bytesRead = 0;if(readSize){char chDirectOut[]="DO_DIRECT_OUT";strncpy((char*)pBuffer,chDirectOut,readSize);rmation()=strlen(chDirectOut);}}break;case IOCTL_DO_NEITHER_IO:{DbgPrint(__FUNCTION__":IOCTL_DO_NEITHER_IO\n",I); ULONG inputSize = I.IoctlInputBufferSize();ULONG outputSize = I.IoctlOutputBufferSize();PVOID inputBuffer = I.IoctlType3InputBuffer();PVOID outputBuffer = erBuffer();//显示出传进来的字符串if(inputSize)DbgPrint("inputBuffer:%s",(char*)inputBuffer);//返回一个字符串char chDoNeitherIo[]="DO_NEITHER_IO";strncpy((char*)outputBuffer,chDoNeitherIo,outputSize);rmation()=strlen(chDoNeitherIo);}break;default:rmation()=0;plete(STA TUS_INV ALID_DEVICE_REQUEST);return STA TUS_INV ALID_DEVICE_REQUEST;}plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS IoDemoDriver::DriverEntry(IN PUNICODE_STRING RegistryPath){NTSTA TUS status = STATUS_SUCCESS;DbgPrint(__FUNCTION__":RegistryPath:%S\n",RegistryPath->Buf fer);IoDemoDevice* pDevice = new (DEVICE_NAME,FILE_DEVICE_UNKNOWN,DEVICE_NAME,0,DO_DIRECT_IO)IoDemoDevice();if (pDevice == NULL){status = STA TUS_INSUFFICIENT_RESOURCES;}else{status = pDevice->ConstructorStatus();if (!NT_SUCCESS(status)){delete pDevice;}elseDbgPrint(__FUNCTION__":Created IoDemoDevice!\n"); }return status;}VOID IoDemoDriver::Unload(){DbgPrint(__FUNCTION__);KDriver::Unload();}最后可以用我的小工具测试一下,Load驱动后可以点Content 按钮编辑数据包,也可以查看驱动返回的数据,显示方式是十六进制,注意根据IO控制代码的定义选择不同的Method,DeviceId 和ControlCode组合方式.个人感觉这个小工具还是比较好用的,呵呵!玩玩DriverW orks(三)-串行化IO请求周末实在不太想写我的数据库程序,又花了一个小时练习了一下DriverW orks里的排队IO请求模型,其实这和DDK中的模型基本上是一样的,因为参考了Programming the Microsoft Windows Driver Model里的一些代码,并且少看了DriverW orks关于排队IO的一句话,我还得到了一个BSOD,不过这个BSOD让我注意到了帮助文档上我没有注意到的地方,呵呵!废话不多说,来一个段代码!#define VDW_MAIN#define DRIVER_FUNCTION_UNLOAD#define DRIVER_FUNCTION_CREA TE#define DRIVER_FUNCTION_CLEANUP#define DRIVER_FUNCTION_CLOSE#define DRIVER_FUNCTION_READ#define DRIVER_FUNCTION_WRITE#define DRIVER_FUNCTION_STARTIO#define DRIVER_FUNCTION_DEVICE_CONTROL#include "vdw.h"//Begin Device Code/////////////////////////////////////////////////////// class CQueueDevice:public KDevice{SAFE_DESTRUCTORS;public:CQueueDevice();NTSTA TUS ComplateIrp(KIrp I);DEVMEMBER_DISPA TCHERS;DEVMEMBER_CANCELIRP(CQueueDevice,CancelIo);NTSTA TUS SerialRead(KIrp I);NTSTA TUS SerialWrite(KIrp I);NTSTA TUS SerialIoControl(KIrp I);};CQueueDevice::CQueueDevice():KDevice(L"CQueueDevice",FILE _DEVICE_UNKNOWN,L"CQueueDevice",0,DO_DIRECT_IO) {if(!NT_SUCCESS(ConstructorStatus())){DbgPrint(__FUNCTION__":Failed to Create Device\n");}}NTSTA TUS CQueueDevice::ComplateIrp(KIrp I){rmation()=0;plete(STA TUS_SUCCESS);return STA TUS_SUCCESS;}NTSTA TUS CQueueDevice::Create(KIrp I) {DbgPrint(__FUNCTION__"\n");return ComplateIrp(I);}NTSTA TUS CQueueDevice::CleanUp(KIrp I) {DbgPrint(__FUNCTION__"\n");return ComplateIrp(I);}NTSTA TUS CQueueDevice::Close(KIrp I) {DbgPrint(__FUNCTION__"\n");return ComplateIrp(I);NTSTA TUS CQueueDevice::DeviceControl(KIrp I) {DbgPrint(__FUNCTION__"\n");//排队并设置取消例程return QueueIrp(I,LinkTo(CancelIo));}NTSTA TUS CQueueDevice::Read(KIrp I){DbgPrint(__FUNCTION__"\n");//排队并设置取消例程return QueueIrp(I,LinkTo(CancelIo));}NTSTA TUS CQueueDevice::Write(KIrp I){DbgPrint(__FUNCTION__"\n");。

基于WINDOWSDDK的USB键盘驱动开发

基于WINDOWSDDK的USB键盘驱动开发

基于WINDOWSDDK的USB键盘驱动开发【摘要】USB接口具有方便快速等优点,已经发展成为一种比较普遍的计算机与外设的接口。

基于微软windows系统DDK,本文介绍了一种非标准USB 键盘的windows设备驱动程序的开发过程与方法。

【关键词】设备驱动;驱动开发包;非标准键盘1.引言USB总线的成功关键是使用户感到了使用USB设备的方便。

即插即用(PnP)概念的使用使某些硬件的安装过程得到了简化。

USB规范中指出,适合迁移到USB1.1上的硬件限定于那些低速到中速的外设,包括键盘,鼠标等。

即这些设备的数据传输速率低于12Mb/sec,并且能通过单一的PC接口被系统软件识别。

现在标准的usb键盘设备只需要遵循一些hid设备的协议就可以被windows操作系统自动识别无需设备制造商开发驱动程序,但有些键盘带有特殊功能,所以需要设备驱动程序。

b软件系统简介USB设备对于USB系统来说是一个端点的集合,端点被分成组,一组端点实现一个接口,如图1所示。

设备端点和主机软件之间利用管道进行数据交互。

设备驱动程序就是通过这些接口和管道与设备进行通信的。

USB数据传输就是指发生在主机软件和USB设备上特定端点(endpoint)之间的数据交互,一个设备可以具有若干管道(pipe)。

一般情况下,一个管道中数据传输与其他管道中的数据传输是相互独立的。

这种发生在管道中的数据流动共有4种基本类型:(1)控制传输,一般发生在设备枚举阶段(2)块传输,一般用于usb disk(3)中断传输,一般用于键盘鼠标类设备(4)流传输,一般用于语音视频流设备USB设备驱动程序都必须使用这些管道和接口来管理设备,而不是直接通过内存或I/O端口来存取来管理。

3.Windows驱动程序的工作原理3.1 Windows驱动程序基本架构驱动程序与应用程序的最大差别在于驱动程序的架构。

应用程序从头到尾都在main或者winmain函数的控制下执行,驱动程序不存在这样的函数,而只是一个由I/O管理组件根据需要调用的子例程的集合,I/O管理组件根据不同的情况调用驱动程序中不同的例程。

【驱动笔记1】第一个驱动程序

【驱动笔记1】第一个驱动程序

【驱动笔记1】第一个驱动程序学习各种高级外挂制作技术,马上去百度搜索"魔鬼作坊",点击第一个站进入,快速成为做挂达人。

驱动程序的开发,向来是令人感到有所畏惧的,可能很多人像我一样,看了很久却还是一头雾水,不得其门而入。

我们今天就通过一个简单的程序来使读者学会初步的驱动程序开发。

在开发Windows驱动程序之前,我们需要首先安装DDK,Win98及其以前的VxD我们就不要再考虑了;Windows2000DDK也比较老了点,很少有人使用了,微软最新的WDK貌似都不支持2000了;在本文中假设我们已经安装了Win XP DDK或2003DDK(2003会包括XP)。

驱动开发通常有两种环境,一种是使用任意文本编辑器来编写代码,然后通过编写makefile 和sources文件在WinDDK的命令行环境下使用build命令编译;另一种方法是使用各种各样的方法以图可以利用IDE的环境来搭建驱动框架,比如使用驱动向导文件或一些小工具,我经常使用的是EasySys这个小工具。

废话不多说了,假设我们已经通过EasySys生成了一个驱动框架,现在我们就向里面添加代码。

下面我们编写了一个函数,它的作用是根据形参来创建一个文件,形参中给出了将要被创建的文件完整路径。

(注意,以下程序有许多错误,具体请看后面的讲解)BOOL CreateFileTest(IN PUNICODE_STRING FileName){BOOL bRet=FALSE;HANDLE hFile=NULL;NTSTATUS status;IO_STATUS_BLOCK Io_Status_Block;//初始化文件路径OBJECT_ATTRIBUTES obj_attrib;InitializeObjectAttributes(&obj_attrib,&FileName,OBJ_CASE_INSENSITIVE| OBJ_KERNEL_HANDLE,NULL,NULL);//创建文件status= ZwCreateFile(hFile,GENERIC_ALL,NULL,Io_Status_Block,NULL,FILE_ATTRIBUTE_NORMA L,FILE_SHARE_READ,FILE_CREATE,FILE_NON_DIRECTORY_FILE| FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);if(Io_Status_rmation!=FILE_CREATED){bRet=FALSE;}else{bRet=TRUE;}if(hFile){ZwClose(hFile);}return bRet;}当我们激动地编译上述程序时,却很郁闷地发现编译器报出了十几个错误,不要急,这是大多数新手都必须要跨过的一个坎儿。

windows内核驱动开发的英文书籍

windows内核驱动开发的英文书籍

windows内核驱动开发的英文书籍Windows内核驱动开发是一个相对专业和复杂的主题,涉及底层系统设计和编程。

英文书籍通常具有更全面的知识和更快的更新速度,所以我会推荐一些英文书籍。

以下是一些与Windows内核驱动开发相关的英文书籍:
1. "Windows Kernel Programming" by Alex Ionescu
- 这本书是Windows内核驱动开发领域非常经典的书籍,涵盖了从基础知识到高级技术的全面内容。

2. "The Windows Internals Book" by Mark Russinovich and David A. Solomon
- 这本书深入探讨了Windows操作系统的内部工作原理,适合对底层系统有深入了解的读者。

3. "Microsoft Windows Driver Kit (WDK)"
- 这是一个由微软官方提供的开发套件,其中包含大量的文档、示例和工具,用于帮助开发者编写Windows内核驱动。

4. "Driver Development Kit (DDK)"
- 这是另一个由微软提供的开发套件,用于编写Windows内核驱动和设备驱动。

请注意,这些书籍可能需要一些高级的编程和系统知识才能完全理解。

如果你对这些主题还不熟悉,可能需要先从更基础的书籍或在线教程开始学习。

同时,由于操作系统和开发技术不断发展和更新,这些书籍的内容也可能已经有所变化或更新,所以建议查看最新的版本。

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

DDK驱动开发笔记1、windows驱动分为NT式驱动和WDM式驱动,前者为非即插即用,后者为即插即用驱动。

需要头文件分别为NTDDK.h和WDM.h2、驱动的入口函数均为extern "C" NTSTA TUS DriverEntry(IN PDRIVER_OBJECTpDriverObject, IN PUNICODE_STRING pRegistryPath),它由I/O管理器负责调用,前参数为传递进来的驱动对象,后参数为Unicode字符串,指向此驱动的注册表。

3、驱动程序向windows的I/O管理器注册一些回调函数,回调函数是由程序员定义的函数,由操作系统负责调用,只要把地址告诉操作系统即可如:pDriverObject->DriverUnload=HelloDDKUnload;4、使用CreateDevice函数创建驱动设备对象如:CreateDevice(pDriverObject);返回NTSTATUS类型5、KdPrint是一个宏,用于打印输出信息,在Checked中会使用DbgPrint代替,在Free版本中无效果,用法和TRACE一致。

6、Windows的设备管理是使用线性链表进行管理,每一个节点记录了设备对象的地址,每次要对指定驱动进行操作,就必须先遍历设备对象链表。

7、设备对象函数NextDevice域记录下一个设备对象的地址,IoDeleteDevice用于删除设备对象如:IoDeleteDevice(pDevExt->pDevice),IoDeleteSymbolicLink用于删除设备符号链接。

8、DDK环境编译驱动源程序,需要使用两个自己创建的脚本makefile和Sources,最好使用二进制文本格式,makefile的内容固定为:!INCLUDE $(NTMAKEENV)\makefile.def。

sources文件记录了驱动的名称、驱动类型、编译输出目录、include目录、指定源文件。

编译好的文件会再工程目录的objchk_wxp_x86\i386文件夹里生成.sys文件。

9、对于使用其他编译环境,只能使用VS编译环境,vc6编译环境只能支持到win2000的DDK。

10、配置VS+DDK+DDKWizard:11、使用DriverMonitor安装驱动,对于NT驱动,在设备管理器中默认是隐藏的(可更改),本软件用于测试驱动。

12、WDM中使用AddDevice回调函数创建设备对象并由PNP(即插即用plug and play)管理器调用,然后设置对IRP_MJ_PNP的IRP(I/O Request Packages)的回调函数,对PNP的IRP处理是WDM和NT驱动的重大区别之一。

在WDM程序中,大部分卸载工作放在对IRP_MN_REMOVE_DEVICE的IRP的处理函数中处理。

13、在WDM的驱动程序中,创建设备对象需要驱动程序向系统注册一个称作AddDevice的例程,由PNP调用如:NTSTATUS HelloAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject); 对象->AddDevice=HelloAddDevice;14、WDM驱动的安装需要使用INF文件安装,其中编译的时候其Sources文件有所不同。

要安装WDM驱动,要先为驱动程序编写一个inf文件,该文件描述了驱动的操作硬件设备信息和驱动的一些信息,并存放在源文件的同一目录下。

Inf的信息是提供给SDK使用的。

15、安装WDM驱动,由于该驱动是一个虚拟设备,因此需要使用添加硬件的方式使用inf安装。

快速安装的话可以使用DriverStudio的EzDriverInstaller工具直接安装。

16、Windows系统的设计思想采用CS架构,内核到硬件之间使用HAL(硬件抽象层)作为过渡。

Native API穿越了用户层和内核层。

为能将其他操作系统程序移植到windows上才采用了子系统的设计模式。

17、Windows API分为三类:USER函数(窗口控件)、GDI函数(绘图)、KERNEL函数(其他有关内核操作的一些进程、线程之类的操作)。

在运行应用程序的时候,系统都会把这三种DLL装载到内存中(user32.dll\gdi32.dll\kernel.dll)。

user32和gdi32模块是在内核模式下实现的,所以图形效率非常高。

18、除了WIN32其他子系统都不是WINDOWS的纯正系统。

有OS/2子系统(苹果)、POSIX子系统(UNIX),WOW子系统(是使低bit的win程序在高bit的win上运行)、VDW子系统(Virtual DOS Machine),但这些系统都要调用win32的特定api才能运行,属于一个虚拟机概念。

19、Windows API是调用Native API的,对应的函数都是在API函数前加Nt,如NtCreateFile(由I/O管理器调用),Native API是用户模式通往内核模式的大门,它通过软件中断方式进入内核模式,并调用内核的系统服务。

Native API没有文档,适当时候可以使用,不推荐。

20、Windows规定,将4G的虚拟内存分成两部分,0~0x7fffffff为用户模式地址,以上为内核模式地址。

21、I/O管理器,用来发出IO请求,让用户发出的IO请求独立与设备,使用IRP的请求形式,把操作的参数内容存进缓冲区再读到内存中,IRP被传递到具体的设备驱动程序中,驱动程序完成IRP并返回到用户程序中,实际上,I/O管理器担当着用户模式代码和设备驱动程序之间的接口。

22、配置管理程序,它用来记录计算机软硬件的配置信息,使用叫“注册表”的数据库保存数据,驱动程序根据表中信息进行加载操作。

23、内核为执行组件提供最基本的支持,负责提供进程和线程的调度,通过自旋锁(spinlock)提供多CPU同步支持。

功能:对内核对象的支持、对线程的调度、对多处理器同步的支持、中断处理函数的支持、对错误陷阱的支持、对其他硬件特殊功能的支持。

24、Windows与微内核:微内核可以看做是组件化内核,每个组件都独立运行,降低模块间的耦合性,单一内核是可以看做所有组件都与一个中央内核有联系而存在高耦合性,linux就是典型的单内核系统。

Windows是单内核与微内核并存的系统(由user32和gdi32可以由内核模式实现说明)。

25、Windows为了简化对不同设备的操作,实现对不同设备的统一接口,将所有设备以普通文件看待,都用操作文件的办法去操作设备。

26、DbgView可以用于监听内核和win32上层程序的调试信息(免费)。

比WinDbg好用。

27、设备驱动程序的动态加载由服务控制管理程序(server control manage,SCM)系统组件完成,其实就是修改注册表实现。

操作是四个步骤:为NT驱动创建新的服务、开启此项服务、关闭此项服务、删除N T驱动所创建的服务。

28、SCM函数:A、SC_HANDLE OpenSCManager(…):打开SCM管理器用于SCM的初始化B、B OOL CloseServiceHandle(…):关闭SCM管理器用于SCM的清除工作C、S C_HANDLE CreateService(…):创建SCM管理器句柄,或说创建服务,所有操作都基于此进行D、SC_HANDLE OpenService(…):打开服务E、BOOL ControlService(…):控制服务,发送控制码进行操作服务。

29、使用VC提供的一个附加工具GUIDGEN.exe可以产生一组新的GUID,工具在Microsoft Visual Studio\Common\Tools里。

30、驱动对象DRIVER_OBJECT由I/O管理器负责加载,由DriverEntry对其进行初始化。

Typedef struct _DRIVER_OBJECT{…};驱动对象可以对应多个设备对象,在系统中是使用链表存储驱动对象。

31、设备对象DEVICE_OBJECT,在系统中使用链表存储设备对象。

在驱动程序中尽量避免全局变量的使用,因为全局变量设计不容易同步问题,可以将全局变量存放在设备扩展里。

32、设备扩展:设备对象记录“通用”设备的信息,而另外一些“特殊”信息记录在设备扩展里。

设备扩展由程序员指定内容和大小,由I/O管理器创建并保存在非分页内存中。

在驱动程序中,尽量避免使用全局函数,因为全局函数往往导致函数的不可重入性。

重入性指在多线程的程序中,多个函数并行运行,函数的运行结果不会根据函数的调用先后顺序而导致不同。

解决的办法是,将全局变量以设备扩展的形式存储,并加以适当的同步保护措施。

由于设备扩展是驱动程序专用的,它的结构必须在驱动程序的头文件中定义。

33、设备扩展定义:在设备扩展仲,记录以上几个信息,以备其他回调函数或者派遣函数使用。

使用的时候,只需从驱动设备中获取,类似以下代码:34、WinObj.exe和DeviceTree.exe用于观察驱动对象和设备对象。

它由windows内核专家编写。

35、WDM模型中完成一个设备的操作,至少有PDO和FDO两个设备对象共同完成,两者的关系是附加与“被附加”的关系。

WDM程序负责创建FDO,PDO由总线驱动创建,FDO创建后被附加到PDO上。

当FDO附加在PDO上的时候,PDO设备对象的子域AttachedDevice会记录FDO的位置。

PDO被称作底层\下层驱动,FDO被称作高层\上层驱动。

通过函数IoAttachDeviceToDeviceStack实现FDO附加到PDO上。

36、内存管理37、要指定某个例程和某个全局变量是载入分页内存还是非分页内存,需要做如下定义:#define PAGEDCODE code_seg(“PAGE”)#define LOCKEDCODE code_seg()#define INITCODE code_seg(“INIT”)#define PAGEDCODE data_seg(“PAGE”)#define LOCKEDCODE data_seg()#define INITCODE data_seg(“INIT”)如果将某个函数载入到分页内存中,我们需要在函数的实现中加入代码:#pragma PAGEDCODEVOID SomeFunction(){PAGED_CODE();//内容}PAGED_CODE宏会检验函数是否运行低于DISPATCH_LEVEL的中断请求级,等于或高于这个请求级将产生一个断言用来防止蓝屏。

相关文档
最新文档