免費論壇 繁體 | 簡體
Sclub交友聊天~加入聊天室當版主
分享
返回列表 发帖

内核模式下的字串操作

A、ASCII字符串和UNICODE字符串
B、ANSI_STRING字符串和UNICODE_STRING字符串
C、字符串的初始化与销毁
D、字符串复制,比较,(大小写,整数和字串)相互转换
E、ANSI_STRING字符串和UNICODE_STRING字符串相互转换
课时:25+30


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));
   
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));
   
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;


D、字符串复制,比较,(大小写,整数和字串)相互转换
RtlFreeAnsiString                                //释放
RtlFreeUnicodeString                        //释放

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";//L是扩展成宽字符
        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();

        }

===========================================

笔记:
A部分:
一般编程是有ASCII码和UNICODE码,在驱动中有专门的代码格式,类型分为CHAR和WCHAR.以37课为例新建38.h文件头,
介绍两个结构ANSI_STRING和UNICODE_STRING

测试一下字符,在WINDBG下看到了两种字符串的输出,用du显示宽字符,da只显示前面一个字符,当然也可以直接查看变量da s1,这样也会显示字符值.

添加释放字串函数,再测试一下,我们用%Z方式打印时ASCII码可以输出中文字符,UNICODE显示的是数字.用dt _ansi_string f78eec5c来查看文本结构,分别有字符长度,最大长度和字符地址.再看一下dt UNICODE_STRING f78eec64,也显示了结构.

按下来释放字串的时候出错了,因为只有在动态分配内存的时候才需要释放.

B部分:
动态分配内存ExAllocatPool就需要RtlFreeAnsiString和RtlFreeUnicodeString释放掉,用WINDBG看一下,已经正常运行了.还有字串复制,字符串比较函数,转换大写函数(注意碰到汉字则忽略掉),字符整数转换函数(其中包括转换成各进制),在转换字串的时候第三个参数我们不分配内存测试一下结果出错了,还是TRUE来分配内存吧.

最后37课时我们编写的代码需要小小的修改一下才会报出异常,最好我们是先释放掉之后然后再取指针这样报异常比较方便.

返回列表