驱动开发之字符串操作

前言:为什么字符串在驱动里是"危险操作"

在用户态,操作字符串随便乱写基本不会让程序直接崩溃;

但在内核态:写错直接蓝屏!

字符串初始化

cpp 复制代码
typedef struct _UNICODE_STRING {
    USHORT Length;         // 当前使用的字节数(注意是字节,不是字符)
    USHORT MaximumLength;  // Buffer 最大可使用的字节数
    PWSTR  Buffer;         // 指向 wchar_t 字符数组(UTF-16)
} UNICODE_STRING, *PUNICODE_STRING;


typedef struct _ANSI_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PCHAR  Buffer;
} ANSI_STRING, *PANSI_STRING;
cpp 复制代码
// ===========================
// UNICODE_STRING 示例
// ===========================

// RtlInitUnicodeString 只是初始化结构,不会分配内存或拷贝字符串
UNICODE_STRING uStr1;
RtlInitUnicodeString(&uStr1, L"unicode_string!");

// 注意:Length 单位是"字节",不是字符个数
DbgPrint("(mydriver) Unicode.Length = %d, Buffer = %wZ\n",
         uStr1.Length, &uStr1);


// ===========================
// ANSI_STRING 示例
// ===========================

// 同理,RtlInitAnsiString 也不会分配内存
ANSI_STRING aStr1;
RtlInitAnsiString(&aStr1, "ansi_string!");

// %Z 打印 ANSI_STRING,%wZ 打印 UNICODE_STRING
DbgPrint("(mydriver) Ansi.Length = %d, Buffer = %Z\n",
         aStr1.Length, &aStr1);

拷贝字符串

cpp 复制代码
// =============================================
// 示例:Unicode 与 ANSI 字符串拷贝
// =============================================

// 1. 定义源字符串
	UNICODE_STRING uStrSrc;
	ANSI_STRING    aStrSrc;

	RtlInitUnicodeString(&uStrSrc, L"unicode_string_test");
	RtlInitAnsiString(&aStrSrc, "ansi_string_test");

	// 2. 定义目标字符串缓冲区(必须自己提供内存)
	WCHAR uniBuffer[64];   // 64 WCHAR = 128 字节
	CHAR  ansiBuffer[64];  // 64 CHAR

	UNICODE_STRING uStrDst;
	ANSI_STRING    aStrDst;

	// 3. 初始化"空字符串结构体"
	//    这一步会:
	//    - Length = 0
	//    - MaximumLength = sizeof(buffer)
	//    - Buffer = buffer 指针
	RtlInitEmptyUnicodeString(&uStrDst, uniBuffer, sizeof(uniBuffer));
	RtlInitEmptyAnsiString(&aStrDst, ansiBuffer, sizeof(ansiBuffer));

	// 4. 执行字符串拷贝
	//    注意:这两个函数不做边界检查,如果源字符串比目标大 → 蓝屏
	RtlCopyUnicodeString(&uStrDst, &uStrSrc);
	RtlCopyString(&aStrDst, &aStrSrc);

	// 输出结果
	DbgPrint("(mydriver) ------- 字符串拷贝示例 -------\n");
	DbgPrint("(mydriver) Unicode  Length = %d, MaximumLength = %d, Buffer = %wZ\n", uStrDst.Length, uStrDst.MaximumLength, &uStrDst);
	DbgPrint("(mydriver) ANSI     Length = %d, MaximumLength = %d, Buffer = %Z\n", aStrDst.Length, aStrDst.MaximumLength,  &aStrDst);

字符串比较

cpp 复制代码
// =============================================
// 示例:Unicode 与 ANSI 字符串比较
// =============================================

// 1. 初始化 Unicode 字符串
	UNICODE_STRING uStr1;
	UNICODE_STRING uStr2;

	// RtlInitUnicodeString 仅初始化结构体,不分配内存
	RtlInitUnicodeString(&uStr1, L"Unicode_Test");
	RtlInitUnicodeString(&uStr2, L"unicode_test");

	// 2. 初始化 ANSI 字符串
	ANSI_STRING aStr1;
	ANSI_STRING aStr2;

	RtlInitAnsiString(&aStr1, "Ansi_Test");
	RtlInitAnsiString(&aStr2, "ansi_test");

	// ---------------------------------------------
	// Unicode 字符串比较
	// ---------------------------------------------
	if (
		RtlCompareUnicodeString(
			&uStr1,
			&uStr2,
			TRUE   // 第三个参数:
				   // TRUE  = 大小写不敏感比较(忽略大小写)
				   // FALSE = 大小写敏感比较
		) == 0    // 返回值 == 0 表示两个字符串完全相等
		)
	{
		DbgPrint("(mydriver) uStr1 == uStr2 (Unicode比较)\n");
	}
	else
	{
		DbgPrint("(mydriver) uStr1 != uStr2 (Unicode比较)\n");
	}

	// ---------------------------------------------
	// ANSI 字符串比较
	// ---------------------------------------------
	if (
		RtlCompareString(
			&aStr1,
			&aStr2,
			TRUE   // 第三个参数:
				   // TRUE  = 大小写不敏感比较
				   // FALSE = 大小写敏感比较
		) == 0    // 返回值 == 0 表示两个字符串完全相等
		)
	{
		DbgPrint("(mydriver) aStr1 == aStr2 (ANSI比较)\n");
	}
	else
	{
		DbgPrint("(mydriver) aStr1 != aStr2 (ANSI比较)\n");
	}

Unicode ↔ ANSI,相互转换

cpp 复制代码
// =============================================
// 示例:UNICODE_STRING 与 ANSI_STRING 相互转换
// =============================================

// 1. 准备源字符串
UNICODE_STRING uStrSrc;
ANSI_STRING    aStrSrc;

RtlInitUnicodeString(&uStrSrc, L"Unicode_String_Test");
RtlInitAnsiString(&aStrSrc,    "Ansi_String_Test");

// 2. 定义目标字符串(注意:此时不需要自己分配 Buffer)
UNICODE_STRING uStrDst;
ANSI_STRING    aStrDst;

// ---------------------------------------------
// Unicode → ANSI
// ---------------------------------------------
//
// 第三个参数说明:
// TRUE  :由系统分配目标字符串的 Buffer
//         转换成功后,必须调用 RtlFreeAnsiString 释放
// FALSE :调用者自己提供 Buffer(必须提前初始化 ANSI_STRING)
//
RtlUnicodeStringToAnsiString(
    &aStrDst,
    &uStrSrc,
    TRUE      // 由系统分配内存
);

// ---------------------------------------------
// ANSI → Unicode
// ---------------------------------------------
RtlAnsiStringToUnicodeString(
    &uStrDst,
    &aStrSrc,
    TRUE      // 由系统分配内存
);

// 输出转换结果
DbgPrint("(mydriver) -------- 字符串转换 --------\n");
DbgPrint("(mydriver) Unicode  Length = %hu, Buffer = %wZ\n",
         uStrDst.Length, &uStrDst);
DbgPrint("(mydriver) ANSI     Length = %hu, Buffer = %Z\n",
         aStrDst.Length, &aStrDst);

// 3. 释放由系统分配的字符串 Buffer
RtlFreeUnicodeString(&uStrDst);
RtlFreeAnsiString(&aStrDst);
相关推荐
XD7429716361 小时前
科技早报晚报|2026年5月2日:Spec 驱动开发、空口隔离交付与时序预测 Copilot,今天最值得跟进的 3 个机会
驱动开发·科技·copilot·开源项目·科技新闻·开发者工具
神一样的老师13 小时前
【兆易创新GD32VW553开发板试用】红外遥控接入天气时钟实战
驱动开发·单片机·嵌入式硬件
charlie11451419119 小时前
嵌入式Linux驱动开发——新字符设备驱动 API 概览
linux·运维·驱动开发
莎士比亚的文学花园1 天前
Linux驱动开发(4)——总线驱动
驱动开发
智者知已应修善业1 天前
【用一片74LS139和一片74Ls00,设计带高电平有效使能输入端的3线-8线译码器】2023-10-16
驱动开发·经验分享·笔记·硬件架构·硬件工程
Ghost Face...2 天前
LS2K PCIe驱动开发全链路解析
驱动开发
Joseph Cooper2 天前
Linux Power Management 子系统:从 suspend/resume 到 Runtime PM、PM QoS
linux·驱动开发·linux kernel·嵌入式linux·电源管理
d111111111d2 天前
移植MQTT到STM32
驱动开发
码踏樱花2 天前
navicat17安装包和破解
驱动开发
senijusene3 天前
基于 MX6UL 的 DHT11 温湿度传感器 驱动开发
驱动开发