Windows 内核驱动字符串操作

在 Windows 内核开发中,字符串并非像 C 中使用的是一个 \0 结尾的字符数组,取而代之的是一个结构体,该结构体储存了指向字符的指针和字符的长度。因为没有了 \0,很多 C 语言库函数也无法使用了,但不用担心,Windows 提供了很多操作这种字符串的函数。见如下示例:

初始化、拷贝、拼接字符串

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
      // 使用字符串常量初始化字符串
      UNICODE_STRING src;
      RtlInitUnicodeString(&src, L "Hello My First Driver..\r\n");

      // 用一个缓冲区初始化字符串
      UNICODE_STRING dst;
      WCHAR dst_buf[256];
      RtlInitEmptyUnicodeString(&dst, dst_buf, 256 * sizeof( WCHAR));

      // Copy 字符串
      RtlCopyUnicodeString(&dst, &src);
      DbgPrint("src = %wZ\r\ndst = %wZ\r\n", &src, &dst);

      // Append 字符串
      RtlAppendUnicodeToString(&dst, L "Yes I'm Fine...\r\n");
      DbgPrint("Append String dst = %wZ\r\n", &dst);

      driver->DriverUnload = DriverUnload;
      return STATUS_SUCCESS;
}

实现类 C 语言函数 sprintf

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
      WCHAR dst_buf[512] = { 0 };
      UNICODE_STRING dst;
      NTSTATUS status;
      UNICODE_STRING file_path =
             RTL_CONSTANT_STRING(L "\\??\\c:\\winddk\\7600.16385.1\\inc\\cifs.h" );
      USHORT file_size = 1024;

      RtlInitEmptyUnicodeString(&dst, dst_buf, 512 * sizeof( WCHAR));

      // 实现类 sprintf 的功能
      status = RtlStringCbPrintfW(
            dst. Buffer,
            512 * sizeof( WCHAR),
            L "file path = %wZ file size = %d \r\n",
            &file_path, file_size);
      dst.Length = wcslen(dst.Buffer) * sizeof(WCHAR);

      DbgPrint("dst = %wZ\r\n", &dst);

      driver->DriverUnload = DriverUnload;
      return STATUS_SUCCESS;
}

动态分配内存储存字符串

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
      NTSTATUS status;
      UNICODE_STRING dst = { 0 };
      UNICODE_STRING src = RTL_CONSTANT_STRING(L "Hello My First Driver...\r\n");

      // 根据 src 长度给 dst 分配内存
      dst.Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool, src.Length, MEM_TAG);
      if (NULL == dst.Buffer)
      {
             status = STATUS_INSUFFICIENT_RESOURCES;
      }

      // 指定 dst 字符串的长度
      dst.Length = dst.MaximumLength = src.Length;
      // 拷贝字符串
      RtlCopyUnicodeString(&dst, &src);

      // 包装一层 DbgPrint,让其只在 Debug 模式下打印
      KdPrint(("ExAllocatePoolWithTag: dst = %wZ\r\n", &dst));

      // 释放内存并将字符串指向 NULL,长度置为 0
      ExFreePool(dst.Buffer);
      dst.Buffer = NULL;
      dst.Length = dst.MaximumLength = 0;

      driver->DriverUnload = DriverUnload;
      return status;
}

发表评论