《Windows内核安全与驱动开发》 3.2 内存与链表

《Windows内核安全与驱动开发》阅读笔记 -- 索引目录

《Windows内核安全与驱动开发》 3.2 内存与链表

1. 尝试生成一个链表头并将其初始化。

 

2. 尝试向内存中申请两个链表结点,并且初始化该结点,将该结点插入到链表中,其数据结构如下。

typedef struct {
    LIST_ENTRY list_entry;
    INT id;
}StuInfo,*PStuInfo;

3. 遍历“问题2”中生成的链表,并调用 DbgPrint 打印出来。

4. 将问题2中的链表清空(并释放内存),最后判断该链表是否为空。

5. 有几种删除链表结点的方法。

6. 遍历链表时,如果 LIST_ENTRY 成员不在开头,应该如何操作?


答案

1. 尝试生成一个链表头并将其初始化。

// 定义并初始化链表头
LIST_ENTRY my_list_entry;
InitializeListHead(&my_list_entry);

2. 尝试向内存中申请两个链表结点,并且初始化该结点,将该结点插入到链表中,其数据结构如下。

//
// 向内存中申请一个结点,并插入到链表中。
//
PStuInfo pStu1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo),MEN_NAME);
if (!pStu1) {
    return STATUS_INSUFFICIENT_RESOURCES;
}
pStu1->id = 123;
InsertHeadList(&my_list_entry, (PLIST_ENTRY) pStu1);

PStuInfo pStu2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo), MEN_NAME);
if (!pStu2) {
    return STATUS_INSUFFICIENT_RESOURCES;
}
pStu2->id = 456;
InsertHeadList(&my_list_entry, (PLIST_ENTRY)pStu2);

3. 遍历“问题2”中生成的链表,并调用 DbgPrint 打印出来

//
// 遍历链表
//
for (PLIST_ENTRY p = my_list_entry.Flink; p != &my_list_entry; p = p->Flink) {
    DbgPrint("%d
", ((PStuInfo)p)->id);
}

4. 将问题2中的链表清空(并释放内存),最后判断该链表是否为空。

//
// 全部删除链表
//
PLIST_ENTRY p;

while (!IsListEmpty(&my_list_entry)) {
    p = RemoveHeadList(&my_list_entry); // 获取被移除链表元素
    ExFreePool((PStuInfo)p);

}

// 判断链表是否为空
if (IsListEmpty(&my_list_entry)) {
    DbgPrint("链表已空
");
}
else {
    DbgPrint("链表未空
");
}

5. 三种方法,移除链表头(RemoveHeadList);移除链表尾(RemoveTailList);移除中间元素(RemoveEntryList)。

6. 使用一个宏 CONTAINING_RECORD.

完整代码:

 1 #include <ntifs.h>
 2 #define MEN_NAME 'abc'
 3 // 定义链表结构
 4 typedef struct {
 5     LIST_ENTRY list_entry;
 6     INT id;
 7 }StuInfo,*PStuInfo;
 8 
 9 
10 
11 //提供一个卸载函数,让程序能卸载,如果没有这个函数,驱动将不能卸载。
12 VOID UnDriver(PDRIVER_OBJECT driver)
13 {
14     KdPrint(("卸载驱动成功"));
15 }
16 //入口函数,相当于main。
17 NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
18 {
19     // 定义并初始化链表头
20     LIST_ENTRY my_list_entry;
21     InitializeListHead(&my_list_entry);
22     
23     //
24     // 向内存中申请一个结点,并插入到链表中。
25     //
26     PStuInfo pStu1 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo),MEN_NAME);
27     if (!pStu1) {
28         return STATUS_INSUFFICIENT_RESOURCES;
29     }
30     pStu1->id = 123;
31     InsertHeadList(&my_list_entry, (PLIST_ENTRY) pStu1);
32 
33     PStuInfo pStu2 = ExAllocatePoolWithTag(NonPagedPool, sizeof(StuInfo), MEN_NAME);
34     if (!pStu2) {
35         return STATUS_INSUFFICIENT_RESOURCES;
36     }
37     pStu2->id = 456;
38     InsertHeadList(&my_list_entry, (PLIST_ENTRY)pStu2);
39 
40     //
41     // 遍历链表
42     //
43     for (PLIST_ENTRY p = my_list_entry.Flink; p != &my_list_entry; p = p->Flink) {
44         DbgPrint("%d
", ((PStuInfo)p)->id);
45     }
46 
47     //
48     // 全部删除链表
49     //
50     PLIST_ENTRY p;
51 
52     while (!IsListEmpty(&my_list_entry)) {
53         p = RemoveHeadList(&my_list_entry); // 获取被移除链表元素
54         ExFreePool((PStuInfo)p);
55 
56     }
57 
58     // 判断链表是否为空
59     if (IsListEmpty(&my_list_entry)) {
60         DbgPrint("链表已空
");
61     }
62     else {
63         DbgPrint("链表未空
");
64     }
65 
66     driver->DriverUnload = UnDriver;
67     return STATUS_SUCCESS;
68 }
原文地址:https://www.cnblogs.com/onetrainee/p/11993810.html