前言:为什么字符串在驱动里是"危险操作"
在用户态,操作字符串随便乱写基本不会让程序直接崩溃;
但在内核态:写错直接蓝屏!
字符串初始化
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);