驱动开发之字符串操作

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

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

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

字符串初始化

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);
相关推荐
盛世宏博智慧档案2 小时前
智慧档案平台驱动开发实战:恒湿消毒净化一体机 Modbus-RTU 协议解析
驱动开发·恒湿机
Herbert_hwt3 小时前
OpenSpec 实战演练:从“猜数字”到“暗黑模式”的规范驱动开发之旅
驱动开发
码农小旋风3 小时前
SDD规范驱动开发:AI时代的软件工程新范式
人工智能·驱动开发·软件工程
幼儿园蛋小黑9 小时前
DHT11 温湿度传感器驱动与 I2C 子系统驱动开发详解
驱动开发
zbyyd9 小时前
Linux 驱动开发实战:从手写 LED 字符设备驱动到设备树
linux·驱动开发
昌原的儿子LEO9 小时前
嵌入式 Linux I2C 驱动开发核心知识总结:设备树与 platform 架构全解析
linux·驱动开发·架构
gwf2169 小时前
常见驱动问题定位与解决:设备识别、性能不达预期、CQ错误码 —— 资深RDMA驱动调试排错指南
驱动开发·linux内核·性能调优·rdma·故障排查·mlx5·irdma
万物智能信息科技11 小时前
气体传感器MQ-2芯片驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
驱动开发·嵌入式硬件·华为·开源·harmonyos
硅基手札13 小时前
【I2C 技术系列 11】I2C Linux 驱动框架
linux·驱动开发·stm32·单片机·嵌入式硬件·mcu·计算机外设
碧海银沙音频科技研究院13 小时前
炬芯ATS3089智能手表烧录方法
人工智能·驱动开发·嵌入式硬件·算法