【Window内核编程】——UNICODE_STRING,ANSI_STRING和PCHAR

来源:互联网 发布:什么叫大数据思维 编辑:程序博客网 时间:2024/05/21 11:23

【我的】Window驱动开发——UNICODE_STRING,ANSI_STRING和PCHAR

作者:zcr214 时间:2016/4/15

 

Windows驱动开发最常接触的就是指针了,各种类型的地址很容易搞晕,绝大多数的API需要的参数都是UNICODE_STRING的指针类型的,当我们自己要使用它的时候,多少会有些麻烦,需要借助ANSI_STRING和PCHAR才能转换到我们更熟悉的String字符串的处理,这里大致梳理一下。

1.     数据结构定义

UNICODE_STRING的结构定义如下:

typedefstruct_UNICODE_STRING

{

   USHORTLength;

   USHORTMaximumLength;

   PWSTRBuffer;

}UNCODE_STRING,*PUNICODE_STRING;

 

ANSI_STRING的结构定义如下:

typedefstruct_STRING

{

   USHORTLength;

   USHORTMaximumLength;

   PSTRBuffer;

}ANSI_STRING,*PANSI_STRING;

 

可以看到,除了字符串Buffer的类型不同之外,二者的结构大致相同,这里要区分的是,UNICODE字符串采用宽字符指针,ANSI字符串采用窄字符指针,也就是平时常用的CHAR*。

2.    UNICODE_STRING初始化

UNICODE_STRING结构只包含一个指针,而且不包含字符串缓冲的空间,在实际使用中,它也不保证Buffer指针指向的字符串是以空字符结尾的,所以对于新手来说,对UNICODE_STRING的处理特别需要小心,只要出错,很可能导致系统崩溃了。(已经蓝屏无数次,在风中凌乱ing……)

   UNICODE_STRINGustr={0};

   wcscpy(ustr.Buffer, L"this is unicode_string");

   ustr.Length=ustr.MaximumLength=

      wcslen(L"this is unicode_string")*sizeof(WCHAR);

       第一行把ustr清空,意味着Buffer也为0,而第二行直接使用wcscopy()函数向Buffer拷贝宽字符串,因为没有指派缓冲区,引发空指针异常,就会立即蓝屏。

所以初始化UNICODE_STRING的时候,需要开发者为Buffer指定一个缓冲区。

例如:

   UNICODE_STRINGustr={0};

   WCHARstrBuf[128]={0};

   ustr.Buffer=strBuf;

   wcscpy(ustr.Buffer, L"thisis unicode_string");

   ustr.Length=ustr.MaximumLength=

      wcslen(L"thisis unicode_string")*sizeof(WCHAR);

或者:

   UNICODE_STRINGustr;

   ustr.Buffer=L"thisis unicode_string";

   ustr.Length=ustr.MaximumLength=

      wcslen(L"thisis unicode_string")*sizeof(WCHAR);

这两种方式是正确的。当然,WDK提供了一个API来简化这个步骤,所以推荐直接使用这个API,它是这样的:

   UNICODE_STRINGustr={0};

   RtlInitUnicodeString(&ustr, L"this is unicode_string");

 

3.    UNICODE_STRING拷贝与连接

拷贝:目标的UNICODE_STRING要有足够的缓冲区长度,否则会拷贝不完整,这是一个很容易造成隐藏的错误,所以需要提前分配足够的缓冲区长度。

   UNICODE_STRINGustr={0};

   WCHARstrBuf[256]={0};

   UNICODE_STRINGsrcstr=RTL_CONSTANT_STRING(L"this is unicode_string");

   //初始化一个空串

   RtlInitEmptyUnicodeString(&ustr,strBuf,256*sizeof(WCHAR));

   //拷贝

   RtlCopyUnicodeString(&ustr,&srcstr);

连接:目标的UNICODE_STRING依然要保证有足够的缓冲区长度。

NTSTATUSstatus=

RtlAppendUnicodeToString(&ustr, L"this is cat string");

返回状态值,成功则返回STATUS_SUCCESS,失败返回一个错误码。

 

4.     转换为PCHAR

在C语言中,常用的String的操作显然都是Char *类型的,而UNICODE_STRING是宽字符的,所以需要将其转换为窄字符串。

先将其转换为ANSI_STRING类型,再通过Buffer提取出来即可。

   ANSI_STRINGansi={0};

   CHARansiBuf[256]={0};

   //初始化一个ANSI_STRING

   RtlInitEmptyAnsiString(&ansi,ansiBuf,256*sizeof(CHAR));

   //转换

   RtlUnicodeStringToAnsiString(&ustr,&ansi,TRUE);

   PCHARstring=ansi.Buffer;

 

 

 

 

 

0 0
原创粉丝点击