一、字符串操作常用函数与结构
1、常用结构
UNICODE_STRING
ANSI_STRING
2、操作函数
RTL_CONSTANT_STRING
RtlInitUnicodeString
RtlInitEmptyString
RtlCopyUnicodeString
RtlAppendUnicodeToString
RtlStringCbPrintfW 类似swprinf,但是鉴于安全性,一般在驱动中不建议使用swprinf,
在格式化字符串打印时,鉴于安全性使用%wZ,不再使用%s和%ws
DbgPrintf 类似于prinf,但是鉴于安全性,一般在驱动中不使用prinf
为了在DEBUG下打印RELEASE中不打印,可以使用宏KdPrint,KdPrint的宏定义特殊,所以使用时需要用比较神奇的双重括号
二、内存申请与释放
1、内存申请
ExAllocatePoolWithTag
参数说明
第一个参数:
NonPagedPool 锁定内存,此内存不可被交换到硬盘上
PagePool 可分页内存
第二个参数
需要申请的内存的大小
第三个参数
分配的内存的标记,用于检测内存泄漏使用,可以多个模块重复使用同一标记,也可以一个模块使用一个标记
返回值
申请到的内存的指针
2、内存释放
ExFreePool
释放ExAllocationatePoolWithTag申请的内存,必须与ExAllocationatePoolWithTag成对存在
三、链表 -------- LIST_ENTRY
1、链表使用前需要用InitializeListhead进行初始化
LIST_ENTRY my_list;
InitializeListHead(my_list);
2、链表使用的时候可以直接放在一个结构的的第一个成员函数
eg:
typedef struct{
LIST_ENTRY list_entry;
LARGE_INTEGER data;
}MY_DATA, *PMYD_DATA;
3、链表插入
#define MEMTAG "MyTt"
PMYDATA pData = (PMYDATA)ExAllocatePoolWithTag(PagePool, sizeof(MY_DATA), MEMTAG);
if(pDATA == NULL)
{
return false;
}
InsertHeadList(&my_list, &PData);
4、链表遍历
for(p = my_list.Flink ; p != my_list.Flink; p = p->Flink)
{
PMY_DATA pData = CONTAINING_RECORD(p, MY_DATA, list_entry);
}
四、自旋锁
1、自旋锁初始化
KSPIN_LOCK my_spin_lock; 此变量一般问静态变量或者全局变量
KeInitializeSpinLock(&my_spin_lock)
2、锁定和解锁操作
KRRQL irql
KeAcquirespinLock(&my_spin_lock, &irql);
//To Do Something
KeReleaseSpinLock(&my_spin_lock,irql);
3、与链表一起使用
1)初始化
LIST_ENTRY my_list_head;
KSPIN_LOCK my_list_lock;
InitializeListHead(&my_list_head);
KeInitializeSpinLock(&my_list_lock);
2)插入数据
ExInterlockInsertHeadList 代替 InSertHeadList,替换后不再需要使用KeAcquirespinLock和KeReleaseSpinLock进行加解锁
3)删除数据
ExInterlockRemoveHeadList