驱动开发之字符串操作

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

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

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

字符串初始化

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);
相关推荐
Freak嵌入式16 小时前
MicroPython LVGL基础知识和概念:GUI 的扩展接口
ide·驱动开发·嵌入式·gui·lvgl·micropython·upypi
月亮给我抄代码1 天前
Superpowers —— 让 AI 编程代理具备工程化开发能力
驱动开发·ai编程·codex·claude code·opencode·superpowers
Tom·Ge1 天前
告别“猜谜式编程”!详解规范驱动开发(SDD)在企业AI开发中的最佳实践
人工智能·驱动开发
s09071362 天前
ZYNQ7000 AXI DMA 接收中断(S2MM_introut)全解析:从硬件原理到Linux驱动开发
linux·驱动开发·dma·zynq
路溪非溪2 天前
如何使用sysfs来排查驱动问题
linux·arm开发·驱动开发
路溪非溪2 天前
如何使用procfs来排查问题
linux·arm开发·驱动开发
青桔柠薯片2 天前
Linux 设备驱动开发环境构建与系统启动机制剖析
linux·arm开发·驱动开发·imx6ull
Clarence Liu2 天前
langchain源码研究 - deepagents设计思想学习
人工智能·驱动开发·学习·langchain
2601_949695592 天前
笔记本电脑怎么连接无线网WiFi?【2026最新完整版教程】
驱动开发·电脑
somi72 天前
ARM-驱动-03 Linux 字符设备驱动开发
linux·arm开发·驱动开发·自用