UNICODE_STRING的技术总结

来源:互联网 发布:西门子编程视频 编辑:程序博客网 时间:2024/06/10 03:42

UNICODE_STRING一般是用在windows的内核驱动编程中,由于内核对安全的问题放在软件开发的首位,哪怕连一个字符串的使用都不能掉以轻心。

先看UNICODE_STRING的结构定义

typedef struct  _UNICODE_STRING {

    USHORT Length;
    USHORT MaximumLength;
    PWCH   Buffer;
} UNICODE_STRING;

可以看到这个结构体有三个成员,Length是字符串的所占的字节数,MaximumLength是字符串所能占最大字节数,Buffer则是字符串的地址,也即指针。

注意上面标注为红色的文字,Length和 MaximumLength只算字节数,而不算字符数,什么意思呢?在宽字符中,一个字符占两个字节,所以Length是字符数的2倍。MaximumLength也类似。

看下图所示:


“suq”前面加了大写的"L",表示这是一组宽字符串,利用RtlInitUnicodeString初始化usStr后,Length为3的2倍,而MaximumLength刚为6+2,因为MaximumLength要加一个为0的字符结尾。


明白了UNICODE_STRING的各个成员的意义,我们来看一下怎么对UNICODE_STRING进行初始化以及各种复制拼接的操作.

一,初始化

有三种方式可以初始化UNICODE_STRING:

1)RtlInitUnicodeString 这个函数其实是把Buffer指针指向字符串的首地址,然后对Length和 MaximumLength成员赋值为字符串的字节数

2)动态分配内存的方式初始化:

UNICODE_STRING ustr;
 ustr.Length= 0;
 ustr.MaximumLength = 120;
 ustr.Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool,120,"test");  
 这样就动态分配了一个存储空间给ustr,这样容易引起内存泄漏。

3)局部数组方式初始化:

WCHAR buf[120]=L"test";

ustr.Length=
8;
ustr.MaximumLength = 120;
ustr.Buffer =buf; 

以上是初始化UNICODE_STRING的方法,区别在于后两者可以对字符串内容进行修改,而前者不行。中间的需要动态分配内存,如果不小心容易造成内存泄漏。


二,字符串的连接

常见的就是将两个UNICODE_STRING或者将UNICODE_STRING和WCHAR_T的字符串连接起来.

首先,将两个UNICODE_STRING连接起来,调用RtlAppendUnicodeStringToString函数实现,其原型如下:
 NTSTATUS  RtlAppendUnicodeStringToString(
    IN OUT PUNICODE_STRING  Destination,
    IN PUNICODE_STRING  Source
 );
 调用该函数的原理是将两者的字符串Buffer拼接起来,同时,更新对应的Length和MaxLength域。在调用的
过程中要注意Destination的MaxLength域,若MaxLength小于Destination和Source的Length域的和的时候,该函数调用不成功,返回0xC0000023,即缓冲区溢出错误。

若将WCHAR_T字符串串接到UNICODE_STRING之后,则需要调用RtlAppendUnicodeToString,函数原型如下:
NTSTATUS  RtlAppendUnicodeToString(
IN OUT PUNICODE_STRING  Destination,
IN PCWSTR  Source
);
该函数和上面函数并没有特别多的不一致,有的资料上说即使Destination的MaxLength域为0,也可以执行RtlAppendUnicodeToString的操作,但在笔者实践中看起来是不能成功的,而且也会返回同样的0xc0000023值。

三,

0 0
原创粉丝点击