typedef struct _UNICODE_STRING {
USHORT Length;//字节数,不是字符数 一定要* sizeof(WCHAR)
USHORT MaximumLength;//字节数,不是字符数 一定要* sizeof(WCHAR)
PWSTR Buffer;//非零结尾,中间也可能含有零
} UNICODE_STRING, *PUNICODE_STRING;
//常用函数
RtlInitUnicodeString(&uStr1, str1);//注意 这个函数并不是将str1拷贝到uStr1.buffer 而是将buffer指向str1 所以如果这个buffer是程序员为它分配的 那么不能释放 也不能为它分配 一是BSOD 二是内存泄露
RtlCopyUnicodeString(&uStr1, &uStr2);//需要注意这里copy uStr1的buffer必须自己分配 如果后面跟着的是常量
RtlAppendUnicodeToString(&uStr1, str1);//注意 uStr1的buffer必须自己分配
RtlAppendUnicodeStringToString(&uStr1, &uStr2);//注意 uStr1的buffer必须自己分配
RtlCompareUnicodeString(&uStr1, &uStr2, TRUE/FALSE);//比较 TRUE 指定大小写
RtlAnsiStringToUnicodeString(&uStr1, &aStr1, TRUE/FALSE);// TRUE 指定buffer系统分配 如果是TRUE 则用后需要调用RtlFreeUnicodeString
RtlFreeUnicodeString(&uStr1);
这些函数调用时系统会自动检测是否超过buffer 相对来说安全一些
#include <ntstrsafe.h>
RtlUnicodeStringInit(&uStr1, str1);
RtlUnicodeStringCopy(&uStr1, &uStr2);
RtlUnicodeStringCat(&uStr1, &uStr2);
#define NTSTRSAFE_UNICODE_STRING_MAX_CCH (0xffff / sizeof(wchar_t)) (32767个字符)
快速初始化一个UnicodeString字符串
DECLARE_CONST_UNICODE_STRING(ustrTest,L”Hello, world!”);
//这个等同于
UNICODE_STRING ustrTest = {0};
WCHAR *szHello = L”Hello, world!”;
RtlInitUnicodeString(&ustrTest, szHello);
//Length:wcslen(szHello)*sizeof(WCHAR)
//MaximumLength:(wcslen(szHello)+1)*sizeof(WCHAR);
初始化方式:栈上buffer
UNICODE_STRING ustrTest = {0};
WCHAR szHello[512] = L”Hello, world!”;
//Length:wcslen(szHello)*sizeof(WCHAR)
//MaximumLength:(wcslen(szHello)+1)*sizeof(WCHAR);
RtlInitUnicodeString(&ustrTest, szHello);
或者
UNICODE_STRING ustrTest = {0};
WCHAR szHello[512] = L”Hello, world!”;
ustrTest.Buffer = szHello;
ustrTest.Length = wcslen(L”hello,world!”)*sizeof(WCHAR);
ustrTest.MaximumLength = sizeof(szHello);
初始化方式:堆上buffer
UNICODE_STRING ustrTest = {0};
ULONG ulLength = (wcslen(L"Hello world") + 1)*sizeof(WCHAR);
ustrTest.Buffer = ExAllocatePoolWithTag(PagedPool, MAX_PATH*sizeof(WCHAR), 'POCU');
if (ustrTest.Buffer == NULL)
{
return;
}
RtlZeroMemory(ustrTest.Buffer, MAX_PATH*sizeof(WCHAR));
wcscpy(ustrTest.Buffer, L"Hello, world");//必须使用内存拷贝类函数
ustrTest.Length = ulLength;
ustrTest.MaximumLength = MAX_PATH*sizeof(WCHAR);
DbgPrint("%wZ\n", &ustrTest);
ExFreePool(ustrTest.Buffer);//这样释放就没有问题啦
下个这个演示了UnicodeString的一个蓝屏
UNICODE_STRING ustrTest = {0};
ustrTest.Buffer = ExAllocatePoolWithTag(PagedPool,
(wcslen(L"Nice to meet u") + 1)*sizeof(WCHAR), 'POCU');
if (ustrTest.Buffer == NULL)
{
return;
}
RtlZeroMemory(ustrTest.Buffer, (wcslen(L"Hello, world") + 1)*sizeof(WCHAR));
RtlInitUnicodeString(&ustrTest, L”Hello, world”);//这个时候userTest.buffer指向了hello wolrd的地址 导致了内存泄露 在下面调用ExFree的时候还会蓝屏
DbgPrint("%wZ\n", & ustrTest);
ExFreePool(ustrTest.Buffer); //蓝屏 释放常量区内存
UNICODE_STRING常见问题
计算length的时候,少了*sizeof(WCHAR)
计算字符数的时候,少了/sizeof(WCHAR)
使用了wcscmp/wcscpy等函数操作
更长远的说,缓冲大小长度问题,就是驱动容易出错的问题
WCHAR wszPath[MAX_PATH];
MAX_PATH? MAX_PATH 在windows上是260 在linux是256
sizeof(wszPath)或者MAX_PATH*sizeof(WCHAR) 这才是字符长度
MAX_PATH*2? 也是可以的
使用Copy Append时目标的buffer不是自行分配的 必定失败 如下:
RtlInitUnicodeString(&uStr1, L"hello"); //直接将L"hello"字符串的指针赋给了uStr.Buffer;
RtlInitUnicodeString(&uStr2, L"Goodbye");
DbgPrint("%ws\n", L"hello world");
DbgPrint("uStr1=%wZ\n", &