主要是对宽字符类型的字符串的应用,包括初始化,拷贝,比较,检索,合并等。
字符串的初始化
1.RTL_CONSTANT_STRING宏
RTL_CONSTANT_STRING宏创建一个字符串(char)或Unicode字符串(wchar_t)结构来保存一个计数字符串。
UNICODE_STRING dst = RTL_CONSTANT_STRING(L"D:\\Projects\\helloworld.c");
使用这个宏定义的时候注意,这个是const,不能释放不能修改。
2.RtlInitUnicodeString
UNICODE_STRING dst;
RtlInitUnicodeString(&dst, L"D:\\Projects\\helloworld2.c");
该方法与第一种方法一样,同样是常量无法被修改。
3.RtlInitEmptyUnicodeString
UNICODE_STRING dst;
WCHAR wcstr[128] = { 0 };
RtlInitEmptyUnicodeString(&dst, wcstr, sizeof(wcstr));
这种有自己独立的缓冲区,可以被修改,但该缓冲区在栈中,内核中栈非常小,这样会造成栈溢出,应该使用ExAllocatePool或者ExAllocatePoolTag来从堆中分配内存。
#include <ntifs.h> // 放到ntddk.h前边 否则重定义
#include <ntddk.h>
#include <intrin.h>
#include <ntstrsafe.h>
// 内存操作
void MemoryOperation() {
PCHAR pcstr;
DbgPrint("1.内存操作:\n");
// 1)申请内存
pcstr = (PCHAR)ExAllocatePoolWithTag(NonPagedPool, 1024, 'abcd');
if (pcstr == NULL) {
DbgPrint("内存分配失败\n");
return;
}
// 2)清空内存
RtlZeroMemory(pcstr, 1024);
// 3)赋值内存
strcpy(pcstr, "这是一次内存测试 strcpy赋值");
DbgPrint("%s\n", pcstr);
RtlZeroMemory(pcstr, 1024);
RtlCopyMemory(pcstr, "这是一次内存测试 RtlCopyMemory赋值",
strlen("这是一次内存测试 RtlCopyMemory赋值"));
DbgPrint("%s\n", pcstr);
// 4)释放内存
ExFreePoolWithTag(pcstr, 'abcd');
DbgPrint("**************\n");
}
// 使用宏来进行字符串初始化操作
void InitStringByRtl() {
DbgPrint("2.通过宏来进行字符串初始化操作:\n");
UNICODE_STRING us = RTL_CONSTANT_STRING(L"RTL_CONSTANT_STRING UnicodeString");
ANSI_STRING as = RTL_CONSTANT_STRING("RTL_CONSTANT_STRING AnsiString");
DbgPrint("%wZ\n", &us);
DbgPrint("%Z\n", &as);
DbgPrint("**************\n");
}
// 字符串赋值操作
void StringCopy() {
DbgPrint("3.字符串复制操作:\n");
// 1)声明目标字符串
UNICODE_STRING usDest;
ANSI_STRING asDest;
WCHAR wcstr[128] = { 0 }; // UnicodeString的缓冲区
CHAR asstr[128] = { 0 }; // AnsiString的缓冲区
// 2)初始化原字符串
UNICODE_STRING us = RTL_CONSTANT_STRING(L"UnicodeString");
ANSI_STRING as = RTL_CONSTANT_STRING("AnsiString");
// 3)初始化目标字符串(自定义缓冲区)
RtlInitEmptyUnicodeString(&usDest, wcstr, sizeof(wcstr));
RtlInitEmptyAnsiString(&asDest, asstr, sizeof(asstr));
// 4)复制目标字符串
RtlCopyUnicodeString(&usDest, &us);
RtlCopyString(&asDest, &as);
// 5)输出字符串
DbgPrint("%wZ\n", &usDest);
DbgPrint("%Z\n", &asDest);
DbgPrint("**************\n");
}
// 字符串比较操作
VOID CompareString() {
DbgPrint("4.字符串比较操作:\n");
// 1)初始化字符串
UNICODE_STRING s1 = RTL_CONSTANT_STRING(L"Hello world!");
UNICODE_STRING s2 = RTL_CONSTANT_STRING(L"Hello world!");
// 2)字符串比较
int ret = RtlCompareUnicodeString(&s1, &s2, TRUE);
// 3)输出字符串比较结果
if (ret == 0)
{
DbgPrint("s1=s2\n");
}
else if (ret < 0)
{
DbgPrint("s1<s2\n");
}
else
{
DbgPrint("s1>s2\n");
}
DbgPrint("**************\n");
}
// 字符串转换为大写操作
void UpperString() {
DbgPrint("5.将字符串转换为大写:\n");
// 1)声明并初始化字符串
UNICODE_STRING us, usDest;
RtlInitUnicodeString(&us, L"abcd");
WCHAR wcstr[128] = { 0 };
RtlInitEmptyUnicodeString(&usDest, wcstr, sizeof(wcstr));
// 2)将字符串转换为大写
RtlUpcaseUnicodeString(&usDest, &us, FALSE);
DbgPrint("转换为大写:%wZ\n", &usDest);
DbgPrint("**************\n");
}
// 字符串与数字的转换
void StringToInteger() {
DbgPrint("6.字符串与数字的转换:\n");
UNICODE_STRING us, usDest;
ULONG Value;
WCHAR wcstr[128] = { 0 };
RtlInitEmptyUnicodeString(&usDest, wcstr, sizeof(wcstr));
// 1)字符串转换为数字
RtlInitUnicodeString(&us, L"-123");
RtlUnicodeStringToInteger(&us, 10, &Value);
DbgPrint("%d\n", Value);
// 2)数字转换为字符串
RtlIntegerToUnicodeString(123, 10, &usDest);
DbgPrint("%wZ\n", &us);
DbgPrint("**************\n");
}
// 格式化输出
void FormatPrint() {
DbgPrint("7.标准化输出:\n");
// 1)初始化字符串
UNICODE_STRING str1 = RTL_CONSTANT_STRING(L"abc");
UNICODE_STRING us;
WCHAR wcstr[128] = { 0 };
RtlInitEmptyUnicodeString(&us, wcstr, sizeof(wcstr));
// 2)标准化格式输出 ntstrsafe.h
RtlUnicodeStringPrintf(&us, L"%d%wZ\n", 10, &str1);
// 3)输出
DbgPrint("%wZ", &us);
DbgPrint("**************\n");
}
// ANSI与UnicodeString之间的转换
void AnsiToUnicode() {
DbgPrint("8.ANSI与UnicodeString之间的转换:\n");
// 1)初始化Unicode字符串
UNICODE_STRING us;
WCHAR wcstr[128] = { 0 };
RtlInitEmptyUnicodeString(&us, wcstr, sizeof(wcstr));
// 2)初始化ANSI字符串
ANSI_STRING as = RTL_CONSTANT_STRING("Hello World!");
// 3)ANSI转换为Unicode
RtlAnsiStringToUnicodeString(&us, &as, FALSE);
DbgPrint("%wZ\n", &us);
DbgPrint("**************\n");
}
// 字符串检索
void IndexOfString() {
DbgPrint("9.在目标字符串中检索特定字符串:\n");
// 1)初始化Unicode字符串
UNICODE_STRING dst_str1 = RTL_CONSTANT_STRING(L"D:\\Projects\\helloworld.c");
UNICODE_STRING str = RTL_CONSTANT_STRING(L"d:");
// 2) 在字符串中搜索前缀
DbgPrint("源字符串:%wZ\n", &dst_str1);
if (RtlPrefixUnicodeString(&str,&dst_str1,FALSE))
{
DbgPrint("设置FALSE 找到 \"D:\"");
}
if (RtlPrefixUnicodeString(&str, &dst_str1, TRUE))// TRUE 设置大小写不敏感
{
DbgPrint("设置TRUE 找到 \"d:\"");
}
// 3)通配符搜索 (需引入ntifs.h)
UNICODE_STRING str2 = RTL_CONSTANT_STRING(L"*.C"); // 需要搜索的字符串要用大写形式
if (FsRtlIsNameInExpression(&str2, &dst_str1, TRUE, NULL))
{
DbgPrint("通配符 \"*.C\"搜索到 \n");
}
UNICODE_STRING str3 = RTL_CONSTANT_STRING(L"*HELLO*"); // 需要搜索的字符串要用大写形式
if (FsRtlIsNameInExpression(&str3, &dst_str1, TRUE, NULL))
{
DbgPrint("通配符 \"*HELLO*\"搜索到 \n");
}
DbgPrint("**************\n");
}
VOID DriverUnload(_In_ struct _DRIVER_OBJECT* DriverObject) {
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("%s\r\n", "驱动卸载成功");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
UNREFERENCED_PARAMETER(pRegPath);
pDriver->DriverUnload = DriverUnload;
MemoryOperation(); // 内存操作
InitStringByRtl(); // 字符串初始化操作
StringCopy(); // 字符串复制操作
CompareString(); // 字符串比较操作
UpperString(); // 字符串大写操作
StringToInteger(); // 字符串与数字的转换
FormatPrint(); // 标准化格式输出
AnsiToUnicode(); // Ansi与Unicode字符串之间的转换
IndexOfString(); // 字符串检索
return STATUS_SUCCESS;
}
UNICODE_STRING的释放
动态分配的空间需要进行释放,把buffer域空间free掉,然后指向null,将长度置0。注意不能释放常量字符串,否则会直接蓝屏。😢😢😢
ExFreePoolWithTag( String->Buffer,CTX_STRING_TAG );
String->Length = String->MaximumLength = 0;
String->Buffer = NULL;