驱动开发之字符串操作

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

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

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

字符串初始化

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);
相关推荐
世微 如初3 天前
AP5125大功率LED恒流驱动实战:地摊灯项目从原理图到调试笔记
驱动开发·芯片·led电源驱动·降压恒流ic
ScilogyHunter3 天前
Zephyr串口驱动开发及构建完全指南
驱动开发·uart·zephyr
_Emma_3 天前
【DRM&Graphic】Linux图形与显示框架
linux·驱动开发·图形渲染·显示器
董厂长3 天前
Loop Engineering:停止手动提示,开始设计自动提示的系统
大数据·人工智能·驱动开发·llm
Saniffer_SH4 天前
【高清视频】Gen6 服务器还没到,Gen6 SSD 怎么测?Emily 现场演示三种测试环境
人工智能·驱动开发·测试工具·缓存·fpga开发·计算机外设·压力测试
暮云星影4 天前
全志linux开发屏幕适配(二)`HDMI`驱动适配说明
linux·arm开发·驱动开发
charlie1145141914 天前
嵌入式Linux驱动开发——从轮询到中断
linux·开发语言·驱动开发·嵌入式
暮云星影4 天前
瑞芯微rk3566开发FIT Secure Boot
linux·arm开发·驱动开发·安全
暮云星影4 天前
全志linux开发 USB接口设置
linux·arm开发·驱动开发
sukalot5 天前
windows显示驱动开发-CCD DDI的其它技术
windows·驱动开发