驱动开发之字符串操作

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

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

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

字符串初始化

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);
相关推荐
运筹vivo@21 小时前
音频基础到ALSA框架
驱动开发·音频
爱跑马的程序员1 天前
UMS9620 展锐平台增加一个虚拟陀螺仪
驱动开发·安卓·传感器·展锐·虚拟陀螺·传感器驱动
被遗忘的旋律.1 天前
Linux驱动开发笔记(二十三)—— regmap
linux·驱动开发·笔记
比奇堡派星星1 天前
如何新加netlink
linux·驱动开发
电脑小管家1 天前
DirectX报错怎么办?快速修复游戏和软件崩溃问题
windows·驱动开发·microsoft·计算机外设·电脑
比奇堡派星星2 天前
Linux4.4使用AW9523
linux·开发语言·arm开发·驱动开发
比奇堡派星星2 天前
cmdline使用详解
linux·arm开发·驱动开发
AI时代原住民2 天前
SDD(Spec驱动开发)实战新范式:SDDAgent驱动SDD端到端开发流
驱动开发
比奇堡派星星2 天前
Linux 平台设备驱动框架详解
linux·开发语言·驱动开发
春日见3 天前
python3语法学习
linux·运维·服务器·人工智能·驱动开发