typedef struct _UNICODE_STRING {
USHORT Length; //有效字符串的长度(字节数)
USHORT MaximumLength; //字符串的最大长度(字节数)
PWSTR Buffer; //指向字符串的指针
}UNICODE_STRING,*PUNICODE_STRING;
注意事项:
1.Buffer指向的字符串不以'\0'为结束符,其长度大小仅取决于Length的大小(Length<=MaximumLength)。
2.不建议使用wcscp、wcscmp等函数对Buffer进行操作,因为这些函数默认处理以'\0'结尾的字符串,可能缺漏。
3.因为Length和MaximumLength均为USHORT,占2个字节,所以MaximumLength和Length的范围是[0,65535]。
4.MaximumLength和Length表示的是字节数,是字符数的2倍。
5.Buffer指针必须指向有效内存!
1.
UNICODE_STRING test={0};//填0初始化
WCHAR* buf=L"I am buf";//定义宽字节字符串
RtlInitUnicodeString(&test,buf);//初始化
首先所有成员均被置0。
接着RtlInitUnicodeString做了3件事:
1.将Buffer指针指向静态常量区的字符串"I am buf"(更改指针,非深拷贝,指向常量区所以不能使用
RtlCopyUnicodeString、RtlAppendUnicodeToString等函数直接对其操作,否则可能引发蓝屏)。
2.修改Length为wcslen(buf)*sizeof(WCHAR)。
3.修改MaximumLength为(wcslen(buf)+1)*sizeof(WCHAR)。
2.
UNICODE_STRING test;
DECLARE_CONST_UNICODE_STRING(test,L"I am buf");
UNICODE_STRING test=RL_CONSTANT_STRING(L"first:Hello ,my salary!");
将buffer指针指向宽字符串常量,具体操作和上面描述的一致。同样需要注意指向的字符串位于常量区。
3.
UNICODE_STRING test={0};//填0初始化
WCHAR buf[9]=L"I am buf";//定义宽字节字符串
test.Buffer=buf;
test.Length=sizeof(buf);
test.MaximumLength=sizeof(buf);//wcslen(L"I am buf")*sizeof(WCHAR);
4.
UNICODE_STRING test = {0};
ULONG Length = (wcslen(L"I am Buf") + 1)*sizeof(WCHAR);
test.Buffer = ExAllocatePoolWithTag(PagedPool, 64*sizeof(WCHAR), 'ALAL');//注意这里不是双引号
if (ustrTest.Buffer == NULL)
{
return;
}
RtlZeroMemory(test.Buffer, 64*sizeof(WCHAR));
wcscpy(test.Buffer, L"I am Buf");//拷贝
test.Length = Length;
test.MaximumLength = 64*sizeof(WCHAR);
ExFreePool(test.Buffer);//释放内存
通过堆区申请内存并拷贝字符串至Buffer来初始化。
代码中的ExAllocatePoolWithTag可用ExAllocatePool函数代替但不推荐这样做,因为在WDM.H(NTDDK.H)中声明了内存分配函数无条件受预处理宏POOL_TAGGING控制(POOL_TAGGING被无条件的定义)。因此,即便是调用的ExAllocatePool函数,实际执行的却是:ExAllocatePoolWithTag,其加入的标签为"mdW",指明是WDM的内存块。若强行关闭POOL_TAGGING宏再去调用ExAllocatePool,实际执行的依然是ExAllocatePoolWithTag,带标签"enoN"。因此,建议在分配内存时,直接调用ExAllocatePoolWithTag并加上一个自定义的标签,同时也方便调试时辨认并定位。
RtlAppenUnicodeToString(&uStr,str);//将str拼接至uStr
2.str是WCHAR*类型,字符串以'\0'结尾。
RtlAppendUnicodeStringToString(&uStr1,&uStr2);//uStr2拼接至uStr1尾部
这种拼接的2个参数uStr1和uStr2均为UNICODE_STRING类型。
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1, L"Hello World");
//初始化 UnicodeString2
UNICODE_STRING UnicodeString2 = { 0 };
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE;
//将初始化 UnicodeString2 拷贝到 UnicodeString1
RtlCopyUnicodeString(&UnicodeString2, &UnicodeString1);
//分别显示 UnicodeString1 和 UnicodeString2
DbgPrint("UnicodeString1:%wZ\n", &UnicodeString1);
DbgPrint("UnicodeString2:%wZ\n", &UnicodeString2);
//销毁 UnicodeString2
//注意!!UnicodeString1 不用销毁
RtlFreeUnicodeString(&UnicodeString2);
-----来自张帆<//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1, L"Hello World");
//初始化 UnicodeString2
UNICODE_STRING UnicodeString2;
RtlInitUnicodeString(&UnicodeString1, L"Hello");
if (RtlEqualUnicodeString(&UnicodeString1, &UnicodeString2, TRUE))//最后一个参数含义为是否无视大小写
DbgPrint("UnicodeString1 and UnicodeString2 are equal\n");
else
DbgPrint("UnicodeString1 and UnicodeString2 are NOT equal\n");
}
-----来自张帆<//ANSI_STRING 字符串与 UNICODE_STRING 字符串相互转换
VOID StringConverTest()
{
//(1)将 UNICODE_STRING 字符串转换成 ANSI_STRING 字符串
//初始化 UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"Hello World");
ANSI_STRING AnsiString1;
NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1,&UnicodeString1,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("Conver succussfully!\n"));
KdPrint(("Result:%Z\n",&AnsiString1));
}
else
{
KdPrint(("Conver unsuccessfully!\n"));
}
//销毁 AnsiString1
RtlFreeAnsiString(&AnsiString1);
//(2)将 ANSI_STRING 字符串转换成 UNICODE_STRING 字符串
//初始化 AnsiString2
ANSI_STRING AnsiString2;
RtlInitString(&AnsiString2,"Hello World");
UNICODE_STRING UnicodeString2;
nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2,&AnsiString2,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("Conver succussfully!\n"));
KdPrint(("Result:%wZ\n",&UnicodeString2));
}
else
{
KdPrint(("Conver unsuccessfully!\n"));
}
//销毁 UnicodeString2
RtlFreeUnicodeString(&UnicodeString2);
}
//UNICODE_STRINGz 转换为 CHAR*
//输入 UNICODE_STRING 的指针,输出窄字符串,BUFFER 需要已经分配好空间
VOID UnicodeToChar(PUNICODE_STRING dst, char *src)
{
ANSI_STRING string;
RtlUnicodeStringToAnsiString(&string,dst, TRUE);
strcpy(src,string.Buffer);
RtlFreeAnsiString(&string);
}
//WCHAR*转换为 CHAR*
//输入宽字符串首地址,输出窄字符串,BUFFER 需要已经分配好空间
VOID WcharToChar(PWCHAR src, PCHAR dst)
{
UNICODE_STRING uString;
ANSI_STRING aString;
RtlInitUnicodeString(&uString,src);
RtlUnicodeStringToAnsiString(&aString,&uString,TRUE);
strcpy(dst,aString.Buffer);
RtlFreeAnsiString(&aString);
}
//CHAR*转UNICODE_STRING
VOID CharToUnicode(PCHAR src,PUNICODE_STRING dst)
{
ANSI_STRING aString;
RtlInitAnsiString(&aString,src);
RtlAnsiStringToUnicodeString(dst,&aString,FALSE);
}
//CHAR*转 WCHAR*
//输入窄字符串首地址,输出宽字符串,BUFFER 需要已经分配好空间
VOID CharToWchar(PCHAR src, PWCHAR dst)
{
UNICODE_STRING uString;
ANSI_STRING aString;
RtlInitAnsiString(&aString,src);
RtlAnsiStringToUnicodeString(&uString,&aString,TRUE);
wcscpy(dst,uString.Buffer);
RtlFreeUnicodeString(&uString);
}
-----来自张帆<