楚狂人–驱动开发基础

本书非常适合熟悉字符串 6

1.1 使用字符串结构 6

1.2 字符串的初始化 7

1.3 字符串的拷贝 8

1.4 字符串的连接 8

1.5 字符串的打印 9

第二章 内存与链表 11

2.1内存的分配与释放 11

2.2 使用LIST_ENTRY 12

2.3 使用长长整型数据 14

2.4使用自旋锁 15

第三章 文件操作 18

3.1 使用OBJECT_ATTRIBUTES 18

3.2 打开和关闭文件 18

3.3 文件的读写操作 21

第四章 操作注册表 25

4.1 注册键的打开操作 25

4.2 注册值的读 26

4.3 注册值的写 29

第五章 时间与定时器 30

5.1 获得当前滴答数 30

5.2 获得当前系统时间 31

5.3 使用定时器 32

第六章 内核线程 35

6.1 使用线程 35

6.2 在线程中睡眠 36

6.3 使用事件通知 37

第七章 驱动与设备 41

7.1 驱动入口与驱动对象 41

7.2 分发函数与卸载函数 41

7.3 设备与符号链接 42

7.4 设备的生成安全性限制 44

7.5 符号链接的用户相关性 46

第八章 处理请求 47

8.1 IRPIO_STACK_LOCATION 47

8.2 打开与关闭的处理 48

8.3 应用层信息传入 49

8.4 驱动层信息传出 51

后记:我的闲言碎语 54

第一章 字符串

1.1 

USHORT Length; // 

USHORT Length;

USHORT MaximumLength;

PSTR Buffer;

} ANSI_STRING, *PANSI_STRING;

在驱动开发中四处可见的是… 

len = wcslen(str.Buffer); // wcscpy(str.Buffer,L”my first string!”);

str.Length = str.MaximumLength = wcslen(L”my first string!”) * sizeof(WCHAR);

以上的代码定义了一个字符串并试图初始化它的值。但是非常遗憾这样做是不对的。因为

str.Buffer = L”my first string!”;

str.Length = str.MaximumLength = wcslen(L”my first string!”) * sizeof(WCHAR);

    … …

上面代码的第二行手写的常数字符串在代码中形成了“常数”内存空间。这个空间位于代码段。将被分配于可执行页面上。一般的情况下不可写。为此,要注意的是这个字符串空间一旦初始化就不要再更改。否则可能引发系统的保护异常。实际上更好的写法如下:

 

//sizeof(L”my first string!”) – sizeof((L”my first string!”)[0]),

sizeof(L”my first string!”),

L”my first_string!” };

但是这样定义一个字符串实在太繁琐了。但是在头文件UNICODE_STRING str = RTL_CONSTANT_STRING(L“my first string!”);

这只能在定义这个字符串的时候使用。为了随时初始化一个字符串,可以使用RtlInitUnicodeString(&str,L”my first string!”);

用本小节的方法初始化的字符串,不用担心内存释放方面的问题。因为我们并没有分配任何内存。

1.3 

// RtlCopyUnicodeString(&dst,&src); // UNICODE_STRING dst; // 

// RtlCopyUnicodeString(&dst,&src); // &dst,L”my second string!”);

if(status != STATUS_SUCCESS)

{

……

}

NTSTATUS

// UNICODE_STRING dst;

NTSTATUS status;

……

// 

// dst->Buffer,L”file path = %wZ file size = %d rn”,

&file_path,file_size);

// Buffer) * sizeof(WCHAR);

RtlStringCbPrintfWKdPrint(a) DbgPrint##a

#else

KdPrint (a)

#endif

不过这样的后果是,由于L”file path = %wZ file size = %d rn”,

&file_path,file_size));

这个宏没有必要自己定义,// // (PWCHAR)ExAllocatePoolWithTag(NonpagedPool,src->Length,MEM_TAG);

if(dst.Buffer == NULL)

{

// ……

}

dst.Length = dst.MaximumLength = src->Length;

status = RtlCopyUnicodeString(&dst,&src);

ASSERT(status == STATUS_SUCCESS);

ExAllocatePoolWithTag的第一个参数NonpagedPool表明分配的内存是锁定内存。这些内存永远真实存在于物理内存上。不会被分页交换到硬盘上去。第二个参数是长度。第三个参数是一个所谓的“内存分配标记”。

内存分配标记用于检测内存泄漏。想象一下,我们根据占用越来越多的内存的分配标记,就能大概知道泄漏的来源。一般每个驱动程序定义一个自己的内存标记。也可以在每个模块中定义单独的内存标记。内存标记是随意的32位数

来源:_暮落_

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2012年9月21日
下一篇 2012年9月22日

相关推荐