配置WINDOWS驱动程序的开发环境走出第一步.docx
《配置WINDOWS驱动程序的开发环境走出第一步.docx》由会员分享,可在线阅读,更多相关《配置WINDOWS驱动程序的开发环境走出第一步.docx(70页珍藏版)》请在冰豆网上搜索。
![配置WINDOWS驱动程序的开发环境走出第一步.docx](https://file1.bdocx.com/fileroot1/2023-1/10/f84d0caf-e64f-4a25-b696-66ea482eeeb1/f84d0caf-e64f-4a25-b696-66ea482eeeb11.gif)
配置WINDOWS驱动程序的开发环境走出第一步
配置WINDOWS驱动程序的开发环境-走出第一步
2007-12-1018:
342601人阅读评论(5)收藏举报
一个星期前老师给我布置了一项任务:
开发我们自己设计的一块板子的PCI设备驱动,并给我指出了方向,具体说就是“三步走”战略:
(1)入门。
熟悉基于DriverStudio开发环境的设备驱动开发,同时侧面了解PCI设备驱动程序的相关知识。
(2)进阶。
运用纯DDK进行驱动开发,着重于学习别人的实例,并能熟练进行调试和修改。
(3)实战。
深入研究PCI总线标准,结合具体的电路板特性开发出一套自己的设备驱动。
现在正在入门阶段的初级,总结一下近一周以来的WINDOWS驱动程序开发学习过程中的经验:
我目前使用的开发环境是:
WINDDK/2600+VisualStudio6.0+Compuware/DriverStudio3.2
参考的主要入门书是:
《Windows2000/XPWDM设备驱动程序开发(第二版)》武安河编著
-----------------------------------------
学习中遇到的问题和解决方法:
(1)拿到附书代码,运行出了第一个驱动程序CharSample,步骤如下:
先双击代码光盘提供的注册表导入文件
Windows2K-XP.reg,然后运行DriverStudio自带的EzDriverInstaller工具,打开sys目录下的驱动安装配置文件
CharSample.inf,然后AddNewDevice,提示需要.sys驱动系统文件,找到sys/objchk/i386目录下的
CharSample.sys文件,确定后将提示TheDriverLoadedSuccessfully!
(如果报错,而且设备前带!
号,一般是因为忘记导入注册表了)
如此安装好驱动以后,就可以运行exe/objchk/i386目录下的应用程序Test_CharSample.exe进行测试了!
(2)运行成功后,重新编译时却总出现错误,编译不过去!
错误是:
fatal error LNK1181:
cannot open input file "....../DriverStudio/DriverWorks/lib/I386/checked/vdw_wdm.lib"通过网上学习和交流找到答案:
原来是因为配置开发环境时,漏掉了如下一个步骤:
编译....../Compuware/DriverStudio/DriverWorks/source目录下的工程得到vdw_wdm.lib文件!
编译时,注意用VC打开工程文件后,有两个工程,要先将VdwLibs工程设为当前ActiveProject,然后在工具栏上单击右键选择“组建”,在弹出的编译工具栏中配置一下编译平台的设置:
选择Win32WDM Checked平台(因为我们用的XP),然后编译就应该可以了,但是还有可能出现编译错误:
fatalerrorC1083:
Cannotopenincludefile:
'warning.h':
Nosuchfileordirectory
为啥呢?
因为没有选择DDK环境,此时应该在DriverStudio菜单-》DDKBuildSetting...中选择我们先前安装的DDK的目录,我安装的目录是C:
/WINDDK/2600,这样就可以编译通过了!
编译完后会在"....../DriverStudio/DriverWorks/lib/I386/checked/"目录下生成vdw_wdm.lib文件,做完这些后在去编译自己编写的驱动程序工程就不会有上面所列的错误了!
当然,也有可能会出现这样的编译错误:
fatalerrorC1051:
programdatabasefile,'....../compuware/driverstudio/driverworks/source/obj/i386/wdmchecked/vdw_wdm.pdb',hasanobsoleteformat,deleteitandrecompile
不过编译器提示的应该够清楚了,只要把连接目录下的文件删除再编译一次就可以了!
(3)用向导新建一个驱动工程,进行编译会产生如下错误:
Linking with DDK linker...
LINK :
fatal error LNK1181:
cannot open input file 'ntstrsafe.lib'
Error executing link.exe.
因为这个文件在xpddk里面是没有的,在2003ddk里面有,拷贝一个过来就可以了,或者在工程-》设置-》连接选框中把ntstrsafe.lib这个连接项去掉
结果点的时候只能点一个工程,要么在工程设置连接中无法找到ntstrsafe.lib这个库,只点driver那个工程然后再删去对那个找不到的库的连接就OK了。
这个原因主要是:
don'tknowhowtomake'D:
/WINDDK/2600/lib/wxp/i386/ntstrsafe.lib'解决办法
driverstudio产生的驱动工程都会要连接ntstrsafe.lib这个库,但实际上这个库并不存在,在Project的Settings里的Link项中去掉这个库,然后在工程中的sources文件里边,找到下面一行:
TARGETLIBS=$(DDK_LIB_PATH)/ntstrsafe.lib$(DDK_LIB_PATH)/csq.lib
直接删除即可。
DS3.2自动产生的程序报告不是有效的win32应用程序的解决方法:
使用driverstudio自带的bulid(dirverstudio->BuildwithBUILD.exe)进行进行编译即可,不要用VC带的那个build进行编译,编译驱动程序的时候好像用VC带的那个build编译还行,不过最好还是用driverstudio自带的那个build进行编译好些吧,我想。
WDM驱动程序开发之调试信息输出篇:
KTrace,KDebugOnlyTrace类
分类:
Windows驱动2008-03-2000:
121226人阅读评论(4)收藏举报
classKTrace,classKDebugOnlyTrace:
【Overview】
类KTrace提供了一种向调试器或Monitor工具输出调试内容的方法。
这个类既支持对于integers,ASCIIstrings,和Unicodestrings等数据格式的printf方式的输出,也支持某些类型的C++的输出流方式的输出,待输出的数据将被缓冲,直到被输出到Monitor。
类KDebugOnlyTrace和KTrace的工作基本相同,不同在于:
当预处理符号DBG被定义为0的时候,它将产生最简短的代码。
【Channels】
每个KTrace对象将由一个特殊的通道连接到Monitor。
这个通道是一个独特的字节流通道,只能使用能够映射到ANSI字符上的那些符号。
DBGMSG在初始化的时候创建了一个默认的通道,KTrace类在定义的时候如果在响应的通道参数上写NULL,那么它使用的就是这个默认通道。
否则就是重建一个新的通道。
通道有两种:
非中断通道和中断通道。
当处理器中断过程中需要用Trace输出信息时,必须使用中断通道,比如在IRQL>DISPATCH_LEVEL的级别上。
所有在中断通道上的操作都是在极高的中断级上完成的,目的是为了保证正确的输出次序(即Trace不会被中断)。
构造一个中断通道时需要一个指向中断对象的指针作为参数。
(请注意:
如果默认的通道被用于跟踪IRQL>DISPATCH_LEVEL级别上的调试信息,那么在KTrace构造函数中就不需要中断对象了。
此时默认通道使用的时DbgPrint服务,使它即使在ISR中断服务程序中执行也是安全的)。
【Levels】
除了通道,每个KTrace对象还有一个输出级,断点级和目标掩码。
调用者在输出时,会包含一个参数来指定输出信息的优先级。
如果这个数值大于等于这个对象的输出阈值,数据才能被输出。
方法SetOutputLevel可以设置KTrace对象的输出阈值。
类似的,当包含的优先级的值大于等于对象断点级的阈值,它就会调用DbgBreakPoint来产生一个断点。
方法SetBreakLevel可以设置KTrace对象的断点级阈值。
最后,目标掩码控制输出的对象,或者输出到调试器(Windbg或SoftICE),或者输出到Monitor。
方法SetTarget可以设置KTrace的输出设备掩码。
【成员函数介绍】
1、构造函数KTrace:
KTrace(
PCHARprefix=NULL, //由Trace输出的数据前缀,每次输出前都先输出的东西
ULONGtargetmask=TRACE_DEBUGGER|TRACE_MONITOR, //输出的目标设备,默认是两者都输出
TRACE_LEVELoutputlevel=TraceAlways,//输出级别阈值,TraceAlways是最高级别
BREAK_LEVELbreaklevel=BreakNever,//断点级别遇值,BreakNever是最低级别
PUNICODE_STRINGchannel=NULL,//输出通道,Unicodestring或KUstring,有默认通道
PKINTERRUPTintobject=NULL //中断对象,systeminterruptobject的地址或KInterrupt实例 //默认是非中断通道
);
KTrace(
PUNICODE_STRINGprefix, //前缀是UNICODE_STRING,则要明确写入参数值
ULONGtargetmask=TRACE_DEBUGGER|TRACE_MONITOR,
TRACE_LEVELoutputlevel=TraceAlways,
BREAK_LEVELbreaklevel=BreakNever,
PUNICODE_STRINGchannel=NULL,
PKINTERRUPTintobject=NULL
);
2、三个Set方法
VOIDSetTarget(ULONGtargetmask); //设置输出目标
VOIDSetOutputLevel(TRACE_LEVELnewOutputLevel);//设置输出级别阈值
VOIDSetBreakLevel(BREAK_LEVELnewBreakLevel);//设置断点级别阈值
3、重载operator<<
KTrace&operator<<(constchar*string);
KTrace&operator<<(constPWSTRstring);
KTrace&operator<<(constPUNICODE_STRINGstring);
KTrace&operator<<(constcharcharval);
KTrace&operator<<(constULONGuintval);
KTrace&operator<<(constUSHORTuintval);
KTrace&operator<<(constUCHARuintval);
KTrace&operator<<(TRACE_LEVELlevel);
KTrace&operator<<(TRACE_RADIXradix);
KTrace&operator<<(constKIrpI);
KTrace&operator<<(constULONG_PTRA64BitValue);
共有11中重载方式,需要注意:
(1)重载<<的是KTrace对象,而不是指针,所以用<<的时候如果用的是指针,则要通过指针找到它指向的对象,然后再输出。
例如:
KTrace*Tracer=new(NonPagedPool)KTrace("MyDriver");
*Tracer<<"tracingenabled/n"; //这里的*Tracer就是找到了对象
(2)上例KTrace中包含了前缀,每输出一行都要输出前缀,但是在一次输出中包含"/n"并不会导致前缀重复输出。
(3)在x86平台上,输出ULONG_PTR类型等价于输出ULONG类型,可以是一个ULONG_PTR类型的数字,也可以是任何一个普通的地址(比如PVOID),输出格式是十六进制。
4、类似C风格输出的Trace方法
VOIDTrace(
TRACE_LEVELlevel, //选择输出级别
PCHARformat, //类似于printf的格式化输出变量方式
... //若干个变量
);
输出级别是Trace方法指定的(大于等于阈值才输出),断点级别是沿用KTrace构造时或最近一次设置的值(大于等于阈值就会调用
DbgBreakPoint断点服务)。
%S可以用于没有结束符的Unicodestring,扩大格式的string不能超过256字节。
WDM驱动程序开发之设备接口篇:
CDeviceInterface和CDeviceInterfaceClass类
分类:
Windows驱动2008-03-2010:
061389人阅读评论
(1)收藏举报
CDeviceInterfaceClass,CDeviceInterface类:
【在应用程序级上使用设备接口】
DriverWorks提供了这两个类用来支持设备接口在应用程序中的访问。
这两个类的声明和实现在devintf.h中。
CDeviceInterfaceClass类封装了一个设备信息集合(set),这个set包含了所有关于一个具体类的设备接口信息。
应用程序可以使用一个CDeviceInterfaceClass类的实例来包含一个或多个CDeviceInterface类的实例。
CDeviceInterface类抽象了一个单一设备接口,它的成员函数DevicePath()可以返回一个指向设备路径名的指针,
这个指针可以作为CreateFile的参数来打开一个设备句柄。
以下是一个最基本的应用例子的模板:
externGUIDTestGuid;
HANDLEOpenByInterface(
GUID*pClassGuid,
DWORDinstance,
PDWORDpError
)
{
CDeviceInterfaceClassDevClass(pClassGuid,pError);
if(*pError!
=ERROR_SUCCESS)
returnINVALID_HANDLE_VALUE;
CDeviceInterfaceDevInterface(&DevClass,instance,pError);
if(*pError!
=ERROR_SUCCESS)
returnINVALID_HANDLE_VALUE;
cout<<"Thedevicepathis"
< < HANDLEhDev;
hDev=CreateFile(
DevInterface.DevicePath(),
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if(hDev==INVALID_HANDLE_VALUE)
*pError=GetLastError();
returnhDev;
}
一些简单的驱动测试程序可以直接使用这段代码(使用自己的GUID)。
声明GUID示例:
staticGUIDTestGuid=
{0x4747be20,0x62ce,0x11cf,{0xd6,0xa5,0x28,0xdb,0x04,0xc1,0x00,0x00}};
WDM驱动程序开发之应用程序测试篇CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle.
分类:
Windows驱动2008-03-2109:
443124人阅读评论(4)收藏举报
一、*****CreateFile*****
这个函数可以创建或打开一个对象的句柄,凭借此句柄就可以控制这些对象:
控制台对象、通信资源对象、目录对象(只能打开)、磁盘设备对象、文件对象、邮槽对象、管道对象。
函数原型:
HANDLECreateFile(
LPCTSTRlpFileName, //filename对象路径名
DWORDdwDesiredAccess, //accessmode控制模式
DWORDdwShareMode, //sharemode共享模式
LPSECURITY_ATTRIBUTESlpSecurityAttributes,//SD安全属性(也即销毁方式)
DWORDdwCreationDisposition, //howtocreate
DWORDdwFlagsAndAttributes, //fileattributes
HANDLEhTemplateFile //handletotemplatefile
);
【Parameters】
1、lpFileName
一个指向无终结符的字符串的指针,来指明要创建或打开的对象的名字。
在WindowsNT/2000/XP平台上:
如果用ANSI版本的函数,字符串长度应限制在MAX_PATH;如果用Unicode版本的函数,这个限制可以扩充到32000个Unicode字符。
在Windows95/98/Me平台上:
只能用ANSI版本的函数,字符串长度限制在MAX_PATH。
2、dwDesiredAccess
指明对象的控制模式。
一个应用程序可以包含读控制、写控制、读/写控制、设备查询控制。
这个参数的取值可以是下面这些的组合:
0 指定设备查询控制:
程序可以不访问设备就查询到设备属性。
GENERIC_READ 指定读控制,可以从对象中读取数据(指针将可以移动)。
GENERIC_WRITE 指定写控制,可以向对象中写数据(指针将可以移动)。
----------------------------------------------------------------------
另外,还可以指定下面的控制标志:
标准控制权限(16-23位掩码):
DELETE 删除对象的权限。
READ_CONTROL 从对象的安全描述符中读取信息的权限,但不包括SACL(系统访问控制列表)中的信息。
WRITE_DAC 修改对象安全描述符中的DACL(随机访问控制列表)的权限
WRITE_OWNER 修改对象安全描述符中的属主的权限
SYNCHRONIZE 同步化使用对象的权限,即可以创建一个线程等待信号量释放(但有些对象不支持这个权限)。
STANDARD_RIGHTS_REQUIRED 等价于前面四种权限的总合(通常这四种是必须具有的权限)。
STANDARD_RIGHTS_READ 一般等价于READ_CONTROL
STANDARD_RIGHTS_WRITE 一般等价于READ_CONTROL
STANDARD_RIGHTS_EXECUTE 一般等价于READ_CONTROL
STANDARD_RIGHTS_ALL 等价于前面五种权限的总合。
特殊控制权限(0-15位掩码):
SPECIFIC_RIGHTS_ALL
ACCESS_SYSTEM_SECURITY
MAXIMUM_ALLOWED
GENERIC_READ
GENERIC_WRITE
GENERIC_EXECUTE
GENERIC_ALL
注:
实质上是通过ACCESS_MASK结构体的一个双字值来设置标准权限、特殊权限和一般权限的。
3、dwShareMode
指定对象的共享模式。
如果dwShareMode==0,表示是互斥使用的。
如果CreateFile打开成功,则别的程序只能等到当前程序关闭对象句柄CloseHandle后才能在打开或使用。
使用下面这些值的组合来表示对象的共享模式:
FILE_SHARE_DELETE WindowsNT/2000/XP:
打开操作只有在删除请求发生时才能返回成功。
FILE_SHARE_READ 打开操作只有在读控制请求发生时才能返回成功。
FILE_SHARE_WRITE 打开操作只有在写控制请求发生时才能返回成功。
4、lpSecurityAttributes
一个指向SECURITY_ATTRIBUTES结构对象的指针,决定返回的句柄是否被子进程所继承。
如果lpSecurityAttributes参数为NULL,句柄就不能被子进程继承。
在WindowsNT/2000/XP平台下:
lpSecurityDescriptor这个成员指明了这个对象的安全描述符。
如果lpSecurityAttribu