目录
0.驱动开发链表常用函数
1.代码示例
.使用驱动函数操作双向链表"><1>.使用驱动函数操作双向链表
.示例<1>实现原理"><2>.示例<1>实现原理
.结构体成员相对偏移计算(拓展)"><3>.结构体成员相对偏移计算(拓展)
0.驱动开发链表常用函数
IsListEmpty 判断链表是否为空 官方文档
InitializeListHead 初始化双向链表头 官方文档
InsertHeadList 插入链表头部 官方文档
InsertTailList 插入链表尾部 官方文档
RemoveHeadList 移除头部节点 官方文档
RemoveTailList 移除尾部节点 官方文档
RemoveEntryList 移除当前节点 官方文档
1.代码示例
<1>.使用驱动函数操作双向链表
#include
typedef struct _TEST
{
ULONG uIndex;
ULONG UTemp;
LIST_ENTRY node;
}TEST,*PTEST;
NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver)
{
DbgPrint("Driver Unloadrn");
}
VOID TestList()
{
DbgBreakPoint();
//测试结构
TEST Test[5] = { 0 };
for (size_t i = 0; i < sizeof(Test) / sizeof(Test[0]); i++)
{
Test[i].UTemp = i;
Test[i].uIndex = i;
}
//初始化链表
InitializeListHead(&Test[0].node);
//判断链表是否为空
if (IsListEmpty(&Test[0].node))
{
DbgPrint("ListEmpty rn");
}
//链表头部插入
InsertHeadList(&Test[0].node, &Test[1].node);
InsertHeadList(&Test[0].node, &Test[2].node);
//链表尾部插入
InsertTailList(&Test[0].node, &Test[3].node);
InsertTailList(&Test[0].node, &Test[4].node);
//删除头部链表
RemoveHeadList(&Test[0].node);
//删除尾部链表
RemoveTailList(&Test[0].node);
//删除当前链表
RemoveEntryList(&Test[0].node);
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
DbgPrint("Driver Load rn");
TestList();
//IRP
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
#includetypedef struct _TEST { ULONG uIndex; ULONG UTemp; LIST_ENTRY node; }TEST,*PTEST; NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver) { DbgPrint("Driver Unloadrn"); } VOID TestList() { DbgBreakPoint(); //测试结构 TEST Test[5] = { 0 }; for (size_t i = 0; i < sizeof(Test) / sizeof(Test[0]); i++) { Test[i].UTemp = i; Test[i].uIndex = i; } //初始化链表 InitializeListHead(&Test[0].node); //判断链表是否为空 if (IsListEmpty(&Test[0].node)) { DbgPrint("ListEmpty rn"); } //链表头部插入 InsertHeadList(&Test[0].node, &Test[1].node); InsertHeadList(&Test[0].node, &Test[2].node); //链表尾部插入 InsertTailList(&Test[0].node, &Test[3].node); InsertTailList(&Test[0].node, &Test[4].node); //删除头部链表 RemoveHeadList(&Test[0].node); //删除尾部链表 RemoveTailList(&Test[0].node); //删除当前链表 RemoveEntryList(&Test[0].node); } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) { DbgPrint("Driver Load rn"); TestList(); //IRP pDriver->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
1).执行初始化函数前
2).初始化函数执行后
Test[0].node.Blink = Test[0].node.Flink = &Test[0].node;
3).头部继续插入节点
当头节点上下节点都指向自身时
Test[0].node.Blink = Test[0].node.Flink = &Test[1].node;
Test[1].node.Blink = Test[1].node.Flink = &Test[0].node;
4).头部继续插入节点
Test[0].node.Flink = &Test[2].node;
Test[2].node.Blink = &Test[0].node;
Test[2].node.Flink = &Test[1].node;
Test[1].node.Blink = &Test[2].node;
5).尾部继续插入节点
Test[3].node.Flink = &Test[0].node;
Test[3].node.Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = &Test[3].node;
Test[0].node.Blink = &Test[3].node;
6).尾部继续插入节点
Test[4].node.Flink = &Test[0].node;
Test[4].node.Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = &Test[4].node;
Test[0].node.Blink = &Test[4].node;
7).头部删除节点
Test[0].node.Flink->Flink->Blink = Test[0].node.Flink->Blink;
Test[0].node.Flink->Blink->Flink = Test[0].node.Flink->Flink;
8).尾部删除节点
Test[0].node.Blink->Blink->Flink = &Test[0].node;
Test[0].node.Blink = Test[0].node.Blink->Blink;
9).移除当前节点
Test[0].node.Flink->Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = Test[0].node.Flink;
<2>.示例<1>实现原理
#include
typedef struct _TEST
{
ULONG uIndex;
ULONG UTemp;
LIST_ENTRY node;
}TEST,*PTEST;
NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver)
{
DbgPrint("Driver Unloadrn");
}
VOID TestList()
{
DbgBreakPoint();
//测试结构
TEST Test[5] = { 0 };
for (size_t i = 0; i < sizeof(Test) / sizeof(Test[0]); i++)
{
Test[i].UTemp = i;
Test[i].uIndex = i;
}
//初始化链表
Test[0].node.Blink = Test[0].node.Flink = &Test[0].node;
//链表头部插入
Test[0].node.Blink = Test[0].node.Flink = &Test[1].node;
Test[1].node.Blink = Test[1].node.Flink = &Test[0].node;
Test[0].node.Flink = &Test[2].node;
Test[2].node.Blink = &Test[0].node;
Test[2].node.Flink = &Test[1].node;
Test[1].node.Blink = &Test[2].node;
//链表尾部插入
Test[3].node.Flink = &Test[0].node;
Test[3].node.Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = &Test[3].node;
Test[0].node.Blink = &Test[3].node;
Test[4].node.Flink = &Test[0].node;
Test[4].node.Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = &Test[4].node;
Test[0].node.Blink = &Test[4].node;
//删除头部链表
Test[0].node.Flink->Flink->Blink = Test[0].node.Flink->Blink;
Test[0].node.Flink->Blink->Flink = Test[0].node.Flink->Flink;
//删除尾部链表
Test[0].node.Blink->Blink->Flink = &Test[0].node;
Test[0].node.Blink = Test[0].node.Blink->Blink;
//删除当前链表
Test[0].node.Flink->Blink = Test[0].node.Blink;
Test[0].node.Blink->Flink = Test[0].node.Flink;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg)
{
DbgPrint("Driver Load rn");
TestList();
//IRP
pDriver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
<3>.结构体成员相对偏移计算(拓展)
假设获取到结构体中链表指向且链表不是结构体首个成员时可使用下面代码获取结构体头部
#include#include typedef struct _LIST { UCHAR uchar; ULONG ulong; PLIST_ENTRY node; }LIST, * PLIST; int main() { LIST List = { 0 }; //获取成员相对于结构体首地址偏移 //OFFSET = 结构成员偏移 - 结构体首地址 ULONG u = (ULONG)&List.node - (ULONG)&List.uchar; //CONTAINING_RECORD指回结构体头部 PLIST p1 = CONTAINING_RECORd(&List.node, _LIST, node); //实现原理 //获取结构成员当前内存地址 ULONG ptr = (ULONG)&List.node; //&((_LIST*)0)->node 此步骤为结构体成员偏移量 ULONG off = (ULONG)(&((_LIST*)0)->node); p1 = (PLIST)(ptr - off); return 0; }



