1、
内核模式下的字串操作
A、ASCII字符串和UNICODE字符串
B、ANSI_STRING字符串和UNICODE_STRING字符串
C、字符串的初始化与销毁
D、字符串复制,比较,(大小写,整数和字串)相互转换
E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换
【A00:50】
“
A、ASNI字符串和UNICODE字符串
在C语言中,有ANSI和UNICODE 两个不同字串类型。
char* s1="abc"; //CHAR * s1="abc"; 61
KdPrint(("%x,%s\n",s1,s1));
wchar_t * s2=L"abc"; //WCHAR * s2=L"abc";00 61
KdPrint(("%x,%S\n",s2,s2));
”
【A01:45】
“
B、ANSI_STRING字符串和UNICODE_STRING字符串
在C语言中,传统的char和wchar_t类型的字符串在使用过程中,很容易出现缓冲区溢出错误,从而导致整个系统的崩溃。一般由于程序员没有对字串长度进行校验造成的。
所以在DDK中 提供了2个带字串长度的类型 ANSI_STRING和UNICODE_STRING
ANSI_STRING s1 ; //CHAR Length MaxLength PCHAR
KdPrint(("%x, %Z\n",s1,s1));
UNICODE_STRING s2 //WCHAR * = PWSTR
KdPrint(("%x, %wZ\n",s2,s2));
”
【A02:22】ANSI_STRING 包含了 Length(长度)、MaxLength(最大长度)、PCHAR(字串的缓冲区)
【A02:55】驱动里 用 CHAR代替char,WCHAR代替wchar_t
【A03:20】UNICODE_STRING 也包含了 Length(长度)、MaxLength(最大长度)、PCHAR(字串的缓冲区)
ZC: 确定是 PCHAR?不是 PWCHAR之类的?见【A05:08】处,是PWSTR
【A03:33】第37课 代码为例
【A03:45】37.h ==> 复制 ==> 38.h
【A03:55】用vs2003打开
【A04:25】写测试代码
【A04:37】ZC: 注释掉的代码 照样能够 右击-->转到定义 ?
【A04:45】ntdef.h ZC: 这个是 STRING 的结构,并非 ANSI_STRING,2者是一样的?
【A05:08】ntdef.h ==> UNICODE_STRING,可以看到 这里的指针项 是 PWSTR(并非PCHAR)
【A06:08】
“
C、字符串的初始化与销毁
在使用ANSI_STRING和UNICODE_STRING这2个类型的字串时都需要对其进行初始化 和销毁
RtlInitAnsiString RtlInitString(&s1,"abc"); //%Z
RtlInitUnicodeString(&s2,L"abc");// %wZ
AnsiString1.Buffer="AnsiString1字符串";
AnsiString1.Length=strlen( AnsiString1.Buffer);
AnsiString1.MaximumLength=BUFFER_SIZE;
UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
UnicodeString1.Length=wcslen(UnicodeString1.Buffer)*2;
UnicodeString1.MaximumLength = BUFFER_SIZE;
RtlFreeAnsiString
RtlFreeUnicodeString
”
【A06:15】如果我们是手工初始化的话,需要调用 RtlFreeAnsiString、RtlFreeUnicodeString,对它进行销毁
【A06:28】如果使用 RtlInitAnsiString / RtlInitString / RtlInitUnicodeString 初始化 ANSI_STRING / UNICODE_STRING,就不需要调用 RtlFreeAnsiString、RtlFreeUnicodeString,对它进行销毁
ZC: 何为 手动/手工 初始化 ANSI_STRING / UNICODE_STRING?如何 手动/手工 初始化 ANSI_STRING / UNICODE_STRING?
【A06:51】这个方式 就是 手动/手工 初始化 ANSI_STRING / UNICODE_STRING :
“
AnsiString1.Buffer="AnsiString1字符串";
AnsiString1.Length = strlen( AnsiString1.Buffer);
AnsiString1.MaximumLength = BUFFER_SIZE;
UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
UnicodeString1.Length = wcslen(UnicodeString1.Buffer)*2;
UnicodeString1.MaximumLength = BUFFER_SIZE;
”
【A07:03】测试
【A07:20】直接复制这一段
“
#define BUFFER_SIZE 1024
#pragma INITCODE
VOID CharTest()
{
KdPrint(("Char字串测试--Start \n"));
PCHAR s1="abc11"; //CHAR ANSI
KdPrint(("%x, %s\n", s1, s1));
PWSTR s2=L"abc11"; //WCHAR UNICODE // PWSTR ==> WCHAR*
KdPrint(("%x, %S\n", s2, s2));
KdPrint(("Char字串测试--End \n"));
_asm int 3
}
”
【A08:46】虚拟机中测试
【A09:05】开 WInDBG
【A09:30】WinDBG命令 "da ba045380",显示 ANSI字符串的内容(ba045380: ANSI字符串起始地址)
【A09:35】WinDBG命令 "du ba045390",显示 宽字符串的内容(ba045390: 宽字符串起始地址)
【A09:41】WinDBG命令 "da ba045390",只显示了 宽字符串的 第1个字符
【A09:51】WinDBG命令 "db ba045390",显示 宽字符串的 二进制内容(按byte来显示的)
【A10:41】第1个字 包含有汉字的话,显示还会不准确
【A11:20】(这里是断下的状态)通过变量来查看,WinDBG命令 "da s1"
2、
D、字符串复制,比较,(大小写,整数和字串)相互转换
RtlCopyUnicodeString
RtlEqualUnicodeString
RtlUpcaseUnicodeString
RtlUnicodeStringToInteger
RtlIntegerToUnicodeString
E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换
RtlUnicodeStringToAnsiString
RtlAnsiStringToUnicodeString
//----------------------www.yjxsoft.com------------------郁金香灬技术
//文件名 "38.h"
#define BUFFER_SIZE 1024
#pragma INITCODE
VOID CharTest()
{
KdPrint(("Char字串测试--Start \n"));
PCHAR s1="abc11"; //CHAR ANSI
KdPrint(("%x,%s\n",s1,s1));
PWSTR s2=L"abc11"; //WCHAR UNICODE //PWSTR
KdPrint(("%x,%S\n",s2,s2));
KdPrint(("Char字串测试--End \n"));
_asm int 3
}
//ANSI_STRING
//UNICODE_STRING
//字符串初始化测试
#pragma INITCODE
VOID StringInitTest()
{
KdPrint(("初始化字串测试--Start \n"));
ANSI_STRING AnsiString1={0};
UNICODE_STRING UnicodeString1={0};
AnsiString1.Buffer="AnsiString1字符串";
AnsiString1.Length=strlen( AnsiString1.Buffer);
AnsiString1.MaximumLength=BUFFER_SIZE;
UnicodeString1.Buffer = L"3333333333333333333322222222221111112";
UnicodeString1.Length=wcslen(UnicodeString1.Buffer)*2;
UnicodeString1.MaximumLength = BUFFER_SIZE;
//方法2 用RTL函数初始化
//初始化ANSI_STRING字符串
//RtlInitAnsiString(&AnsiString1,"AnsiString1字符串");
//RtlInitUnicodeString(&UnicodeString1,L"3333333333333333333322222222221111112");
//打印ASCII字符用 %Z
KdPrint(("%x AnsiString1: %Z\n",&AnsiString1, &AnsiString1));
//打印UNICODE字符用 %wZ 中文字符会被截断
KdPrint(("%x UnicodeString1:%wZ\n",&UnicodeString1,&UnicodeString1));
KdPrint(("初始化字串测试--END \n"));
__asm int 3
}
//D、字符串复制,比较,(大小写,整数和字串)相互转换
#pragma INITCODE
VOID StringCopyTest()
{
KdPrint(("-------------------字串复制测试开始---------------D \n"));
//初始化UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");
//初始化UnicodeString2
UNICODE_STRING UnicodeString2={0};
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE;
//将初始化UnicodeString1拷贝到UnicodeString2
RtlCopyUnicodeString(&UnicodeString2,&UnicodeString1);
//分别显示UnicodeString1和UnicodeString2
KdPrint(("字串1:%wZ\n",&UnicodeString1));
KdPrint(("字串2:%wZ\n",&UnicodeString2));
//销毁UnicodeString2
//注意!调用过RtlInitUnicodeString 初始化的字串!UnicodeString1不用销毁,
//RtlFreeUnicodeString(&UnicodeString1); 加上此行会蓝屏
RtlFreeUnicodeString(&UnicodeString2);
KdPrint(("-------------------字串复制测试结束--------------- \n"));
}
//字符串比较测试
#pragma INITCODE
VOID StringCompareTest()
{ KdPrint(("\n-------------------字串比较测试 开始--------------- \n"));
//初始化UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");
//初始化UnicodeString2
UNICODE_STRING UnicodeString2;
RtlInitUnicodeString(&UnicodeString2,L"UnicodeString2");
KdPrint(("%wZ 和,%wZ",&UnicodeString1,&UnicodeString2));
if (RtlEqualUnicodeString(&UnicodeString1,&UnicodeString2,TRUE)) //第三个参数 表示区分大小写
{
KdPrint(("UnicodeString1 和 UnicodeString2 相等\n"));
}
else
{
KdPrint(("UnicodeString1 和 UnicodeString2 不相等\n"));
}
KdPrint(("\n-------------------字串比较测试 结束--------------- \n"));
}
//字符串变大写测试
#pragma INITCODE
VOID StringToUpperTest()
{
KdPrint(("\n-------------------字串转大写测试 开始--------------- \n"));
//初始化UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1—Aabc");
//变化前
KdPrint(("UnicodeString1 初值:%wZ\n",&UnicodeString1));
//变大写
RtlUpcaseUnicodeString(&UnicodeString1,&UnicodeString1,FALSE);
//变化后
KdPrint(("UnicodeString1 转换大写后:%wZ\n",&UnicodeString1));
KdPrint(("\n-------------------字串转大写测试 结束--------------- \n"));
}
//字符串与整型相互转化测试
#pragma INITCODE
VOID StringToIntegerTest()
{
KdPrint(("\n-------------------字串转整数测试 开始--------------- \n"));
//(1)字符串转换成数字
//初始化UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"-100");
ULONG lNumber;
KdPrint(("待转换字串%wZ \n",&UnicodeString1));
NTSTATUS nStatus = RtlUnicodeStringToInteger(&UnicodeString1,10,&lNumber);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("转换整数成功 结果=%d !\n",lNumber));
}
else
{
KdPrint(("转换整数 失败\n"));
}
//(2)数字转换成字符串
//初始化UnicodeString2
UNICODE_STRING UnicodeString2={0};
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
UnicodeString2.MaximumLength = BUFFER_SIZE;
nStatus = RtlIntegerToUnicodeString(200,10,&UnicodeString2);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("转换字串成功! 结果:%wZ\n",&UnicodeString2));
}
else
{
KdPrint(("转换字串 失败!\n"));
}
//销毁UnicodeString2
//注意!调用过RtlInitUnicodeString 初始化的字串!UnicodeString1不用销毁,
//RtlFreeUnicodeString(&UnicodeString1); 加上此行会蓝屏
RtlFreeUnicodeString(&UnicodeString2);
KdPrint(("\n-------------------字串转整数测试 结束--------------- \n"));
}
//E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换
//ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试
#pragma INITCODE
VOID StringConverTest()
{
KdPrint(("\n-------------------ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试 开始--------------- \n"));
//(1)将UNICODE_STRING字符串转换成ANSI_STRING字符串
//初始化UnicodeString1
UNICODE_STRING UnicodeString1;
RtlInitUnicodeString(&UnicodeString1,L"UnicodeString1");
ANSI_STRING AnsiString1;
NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1,&UnicodeString1,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("RtlUnicodeStringToAnsiString 转换成功 结果=%Z\n",&AnsiString1));
}
else
{
KdPrint(("RtlAnsiStringToUnicodeString 转换失败 !\n"));
}
//销毁AnsiString1
RtlFreeAnsiString(&AnsiString1);
//(2)将ANSI_STRING字符串转换成UNICODE_STRING字符串
//初始化AnsiString2
ANSI_STRING AnsiString2;
RtlInitString(&AnsiString2,"AnsiString2");
UNICODE_STRING UnicodeString2;
nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2,&AnsiString2,TRUE);
if ( NT_SUCCESS(nStatus))
{
KdPrint(("RtlAnsiStringToUnicodeString转换成功 结果=%wZ\n",&UnicodeString2));
}
else
{
KdPrint(("RtlAnsiStringToUnicodeString字串转换失败!\n"));
}
//销毁UnicodeString2
RtlFreeUnicodeString(&UnicodeString2);
KdPrint(("\n-------------------ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试 结束--------------- \n"));
}
VOID StringTestAll()
{
//Char类字符串测试
CharTest();
//字串初始化测试
StringInitTest();
//字符串拷贝测试
StringCopyTest();
//字符串比较测试
StringCompareTest();
//字符串变大写测试
StringToUpperTest();
//字符串与整型相互转化测试
StringToIntegerTest();
//ANSI_STRING字符串与UNICODE_STRING字符串相互转换测试
StringConverTest();
}