首页 > 系统编程 > Windows 内核字符串
2019
05-24

Windows 内核字符串


UNICODE_STRING 结构

Unicode 字符串的结构定义如下

typedef struct _UNICODE_STRING {
    USHORT Length;            // 字符串长度(Byte)
    USHORT MaxiumLength;    // 字符缓冲区长度(Byte)
    PWSTR Buffer;            // 字符串缓冲区
} UNICODE_STRING, *PUNICODE_STRING

需要注意的是 UNICODE_STRING 结构中的缓冲区 Buffer 并不一定保证是以 ‘\0’ 空字符结束的,所以最好不要使用传统的字符串函数对其进行操作


内核字符串相关的 API

这里笔者写出一些常用的内核字符串的 API,关于字符串的初始化、拷贝、连接(追加)和格式化输出。

字符串的初始化

  • RTL_CONSTANT_STRING 宏

此宏用于根据显式指定的字符串来初始化一个 UNICODE_STRING 字符串

  #include <ntdef.h>
  UNICODE_STRING str = RTL_CONSTANT_STRING(L"this is my string");

需要注意的是 RTL_CONSTANT_STRING 宏只能用于 UNICODE_STRING 结构变量的定义式。

  • RtlInitUnicodeString 函数

此函数用于根据显式指定的字符串来初始化一个 UNICODE_STRING 字符串

  UNICODE_STRING str;
  RtlInitUnicodeString(&str, L"this is my string");
  • RtlInitEmptyString 函数

此函数用于根据指定的缓冲区空间来初始化一个 UNICODE_STRING 空字符串,与前两者不同之处在于,此函数将需要分配额外的内存缓冲区空间(在栈上或者在堆上)

  UNICODE_STRING str;
  WCHAR buff[256];    // 定义缓冲区空间,256 * sizeof(WCHAR) 共 512 字节

  // 使用自定义的缓冲区空间 buff 来初始化字符串 str,第三个参数即缓冲区空间大小(字节数)
  RtlInitEmptyString(&str, buff, 256 * sizeof(WCHAR));

字符串的拷贝

  • RtlCopyUnicodeString 函数

此函数用于将源字符串拷贝至目标字符串(当然,这里说的是深拷贝)

  UNICODE_STRING dest_str;
  WCHAR dest_buff[256];    // 定义缓冲区空间,256 * sizeof(WCHAR) 共 512 字节

  // 用显式指定的字符串来初始化源字符串
  UNICODE_STRING src_str = RTL_CONSTANT_STRING(L"this is source string");

  // 把目标字符串初始化为缓冲区为 dest_buff 的空字符串,大小为 256 * sizeof(WCHAR)
  RtlInitEmptyString(&dest_str, dest_buff, 256 * sizeof(WCHAR));
  RtlCopyUnicodeString(&dest_str, &src_str); // 字符串拷贝

需要注意的是,使用 RtlCopyUnicodeString 函数拷贝字符串的时候,如果目标字符串的缓冲区最大长度小于源字符串的长度,拷贝时字符串将被截短,这取决于目标字符串的缓冲区最大长度。

字符串的连接(追加)

  • RtlAppendUnicodeToString 函数

此函数用于将显式指定的字符串追加到目标 UNICODE_STRING 字符串的末尾,在如下示例代码中,dest_str 是 UNICODE_STRING 结构,函数第二个参数即显式指定的源字符串

  NTSTATUS status; // NTSTATUS 枚举

  // 如果成功,将返回 STATUS_SUCCESS,缓冲区不够则返回 STATUS_BUFFER_TOO_SMALL
  status = 
      RtlAppendUnicodeToString(&dest_str, L"this is a string which you want to append");
  • RtlAppendUnicodeStringToString 函数

此函数用于将源 UNICODE_STRING 字符串追加到目标 UNICODE_STRING 字符串的末尾,在如下示例代码中,dest_str 与 src_str 都是 UNICODE_STRING 结构

  NTSTATUS status; // NTSTATUS 枚举

  // 如果成功,将返回 STATUS_SUCCESS,缓冲区不够则返回 STATUS_BUFFER_TOO_SMALL
  status = 
      RtlAppendUnicodeToString(&dest_str, &src_str);

字符串的格式化输出

  • RtlStringCbPrintfW 函数
  #include <ntstrsafe.h>

  // 暂且把缓冲区定义在栈中
  WCHAR dest_buff[512] = { 0 };
  UNICODE_STRING dest;
  NTSTATUS status;        // NTSTATUS 枚举

  /* ...... */

  // 字符串初始化为指定缓冲区为 buff 的空字符串,缓冲区长度为 512 * sizeof(WCHAR)
  RtlInitEmptyString(&dest, dest_buff, 512 * sizeof(WCHAR));

  // 调用 RtlStringCbPrintfW 函数进行字符串格式化输出,其中 filepath 是个 UNICODE_STRING 结构
  // 使用格式化符 %wZ 可以直接打印出 UNICODE_STRING 结构的字符串
  status = 
      RtlStringCbPrintfW(dest.Buffer, 512 * sizeof(WCHAR), 
                         L"file path = %wZ, file size = %d \r\n", 
                         &file_path, file_size);

  // 这里调用 wcslen 函数没有问题,因为 RtlStringCbPrintfW 打印的字符串以 '\0' 结束
  dest.Length = wcslen(dest.Buffer) * sizeof(WCHAR); // 字节数

RtlStringCbPrintfW 函数需要包含 ntstrsafe.h 头文件,链接的时候需要链接库 ntsafestr.lib。

如果在目标缓冲区空间不足的情况下,此函数将对字符串进行截短,并返回 STATUS_BUFFER_OVERFLOW。


打赏 赞(2)
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

最后编辑:
作者:Yenyu
Yenyu
编程爱好者

Windows 内核字符串》有 5 条评论

  1. 头像 匿名 说:

    背后这个线条可以弄成跟鼠标连接的

     

  2. 头像 Donk 说:

    测试一下啦

  3. 头像 xiaowen 说:

    来大佬这打个卡

留下一个回复

你的email不会被公开。