如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
Windows驱动编程基础教程前言我经常在网上遇到心如火燎的提问者。他们碰到很多工作中的技术问题,是关于驱动开发的。其实绝大部分他们碰到的“巨大困难”是被老牛们看成初级得不能再初级的问题。比如经常有人定义一个空的UNICODE_STRING,然后往里面拷贝字符串。结果无论如何都是蓝屏。也有人在堆栈中定义一个局部SPIN_LOCK,作为下面的同步用——这样用显然没有任何意义。我无法一一回答这些问题:因为往往要耐心的看他们的代码,才能很不容易的发现这些错误。而且我又不是总是空闲的,可以无休止的去帮网友阅读代码和查找初级错误。但是归根结底,这些问题的出现,是因为现在写驱动的同行越来越多,但是做驱动开发又没有比较基础的,容易读懂的资料。为此我决定从今天开始连载一篇超级入门级的教程,来解决那些最基本的开发问题。老牛们就请无视这篇教程,一笑而过了。Windows驱动编程基础教程(1.1-1.3)1.1使用字符串结构常常使用传统C语言的程序员比较喜欢用如下的方法定义和使用字符串:char*str={“myfirststring”};//ansi字符串wchar_t*wstr={L”myfirststring”};//unicode字符串size_tlen=strlen(str);//ansi字符串求长度size_twlen=wcslen(wstr);//unicode字符串求长度printf(“%s%ws%d%d”,str,wstr,len,wlen);//打印两种字符串但是实际上这种字符串相当的不安全。很容易导致缓冲溢出漏洞。这是因为没有任何地方确切的表明一个字符串的长度。仅仅用一个’\0’字符来标明这个字符串的结束。一旦碰到根本就没有空结束的字符串(可能是攻击者恶意的输入、或者是编程错误导致的意外),程序就可能陷入崩溃。使用高级C++特性的编码者则容易忽略这个问题。因为常常使用std::string和CString这样高级的类。不用去担忧字符串的安全性了。在驱动开发中,一般不再用空来表示一个字符串的结束。而是定义了如下的一个结构:tyHYPERLINK"http://www.zeroplace.cn"\t"_blank"pedefstruct_UNICODE_STRING{USHORTLength;//字符串的长度(字节数)USHORTMaximumLength;//字符串缓冲区的长度(字节数)PWSTRBuffer;//字符串缓冲区}UNICODE_STRING,*PUNICODE_STRING;以上是Unicode字符串,一个字符为双字节。与之对应的还有一个Ansi字符串。Ansi字符串就是C语言中常用的单字节表示一个字符的窄字符串。tyHYPERLINK"http://www.zeroplace.cn"\t"_blank"pedefstruct_STRING{USHORTLength;USHORTMaximumLength;PSTRBuffer;}ANSI_STRING,*PANSI_STRING;在驱动开发中四处可见的是Unicode字符串。因此可以说:Windows的HYPERLINK"http://www.zeroplace.cn"\t"_blank"内核是使用Uincode编码的。ANSI_STRING仅仅在某些碰到窄字符的场合使用。而且这种场合非常罕见。UNICODE_STRING并不保证Buffer中的字符串是以空结束的。因此,类似下面的做法都是错误的,可能会会导致HYPERLINK"http://www.zeroplace.cn"\t"_blank"内核崩溃:UNICODE_STRINGstr;…len=wcslen(str.Buffer);//试图求长度。DbgPrint(“%ws”,str.Buffer);//试图打印str.Buffer。如果要用以上的方法,必须在编码中保证Buffer始终是以空结束。但这又是一个麻烦的问题。所以,使用微软提供的Rtl系列函数来操作字符串,才是正确的方法。下文逐步的讲述这个系列的函数的使用。1.2字符串的初始化请回顾之前的UNICODE_STRING结构。读者应该可以注意到,这个结构中并不含有字符串缓冲的空间。这是一个初学者常见的出问题的来源。以下的代码是完全错误的,HYPERLINK"http://www.zeroplace.cn"\t"_blank"内核会立刻崩溃:UNICODE_STRINGstr;wcscpy(str.Buffer,L”myfirststring!”);str.Length=str.MaximumLength=wcslen(L”myfirststring!”)*sizeof(WCHAR);以上的代码定义了一个字符串并试图初始