- 注册时间
 - 2010-7-27
 
- 最后登录
 - 2017-6-3
 
- 在线时间
 - 3 小时
 
 
 
 
 
编程入门 
  
	- 魔鬼币
 - 512 
 
 
 
 | 
 
 
内核模式下的字符串操作 
 
1、ASCII字符串和宽字符串 
在驱动程序开发中,DDK将char和wchar_t类别,替换成CHAR和WCHAR类别 
驱动程序中用KdPrint打印ASCII字符串和宽字符串: 
打印ASCII字符串 
 
CHAR *string = "Hello"; 
KdPrint("%s\n", string); 
打印宽字符串 
 
WCHAR *string = L"Hello"; 
KdPrint("%S\n", string); 
2、ANSI_STRING字符串与UNICODE_STRING字符串 
2.1、ANSI_STRING字符串: 
 
typedef struct _STRING 
{ 
    USHORT Length; 
    USHORT MaximumLength; 
    PCHAR Buffer; 
}STRING; 
typedef STRING ANSI_STRING; 
typedef PSTRING PANSI_STRING; 
 
typedef STRING OEM_STRING; 
typedef PSTRING POEM_STRING; 
复制代码 
这个数据结构对ASCII字符串进行了封装 
Length:字符的长度 
MaximumLength:整个字符串缓冲区的最大长度 
Buffer:缓冲区的指针 
注意:和标准的字符不同,STRING字符串不是以0标志字符的结束。字符长度依靠 
Length字段。在标准C中的字符串中,如果缓冲区长度是N,那么只能容纳N-1个字 
符的字符串,这是因为要留一个字节存储NULL。而在STRING字符串中,缓冲区的大小 
MaximumLength,最大的字符串长度可以是MaximumLength,而不是MaximumLength-1 
 
2.2、UNICODE_STRING字符串: 
 
typedef struct _UNICODE_STRING 
{ 
    USHORT Length; 
    USHORT MaxmumLength; 
    PWSTR Buffer; 
} UNICODE_STRING; 
Length:字符的长度,单位是字节。如果是N个字符,那么Length等于N的2倍 
MaximumLength:整个字符串缓冲区的最大长度,单位也是字节 
Buffer:缓冲区的指针 
 
2.3、KdPrint打印ANSI_STRING字符串与UNICODE_STRING字符串 
打印ANSI_STRING字符串: 
 
ANSI_STRING ansiString; 
//省去对ansiString初始化 
KdPrint("%Z\n", &ansiString); 
打印UNICODE_STRING字符串: 
UNICODE_STRING uniString; 
//省去对uniString初始化 
KdPrint("%wZ\n", &uniString); 
 
3、字符串的初始化与销毁 
3.1、方法一使用DDK提供了相应的函数 
 
/************************************************************************ 
* 函数名称:RtlInitAnsiString 
* 功能描述:初始化ANSI_STRING字符串 
* 参数列表: 
        DestinationString:要初始化的ANSI_STRING字符 
        SourceString:字符串的内容 
* 返回 值:VOID 
*************************************************************************/ 
VOID RtlInitAnsiString( 
    IN OUT PANSI_STRING DestinationString, 
    IN PCSZ SourceString) 
 
使用方法: 
 
ANSI_STRING AnsiString1; 
CHAR* string1 = "hello"; 
RtlInitAnsiString(&AnsiString1,string1);  
 
/************************************************************************ 
* 函数名称:RtlInitUnicodeString 
* 功能描述:初始化UNICODE_STRING字符串 
* 参数列表: 
        DestinationString:要初始化的UNICODE_STRING字符 
        SourceString:字符串的内容 
* 返回 值:VOID 
*************************************************************************/ 
VOID RtlInitUnicodeString( 
    IN OUT PANSI_STRING DestinationString, 
    IN PCSZ SourceString) 
复制代码 
使用方法: 
 
UNICODE_STRING UniString1; 
CHAR* string1 = "hello"; 
RtlInitUnicodeString(&UniString1,string1);  
这中办法是将AnsiString1中的Buffer等于string1指针。这种初始化的优点是 
操作简单,用完后不用清理内存。但带来另外一个问题,如果修改string1,同时 
会导致AnsiString1字符串发生变化 
 
ANSI_STRING AnsiString1; 
CHAR* string1 = "hello"; 
//初始化ANSI_STRING字符串 
RtlInitAnsiString(&AnsiString1,string1);  
KdPrint(("AnsiString1:%Z\n", &AnsiString1));//打印hello 
//改变string1 
string1[0]='H'; 
string1[1]='E'; 
string1[2]='L'; 
string1[3]='L'; 
string1[4]='o'; 
//改变string1,AnsiString1同样会导致变化 
KdPrint(("AnsiString1:%Z\n", &AnsiString1));//打印HELLO 
 
3.1、另外一种方法是程序员自己申请内存,并初始化内存,当不用字符串时 
需要回收字符串占用的内存 
 
 
#define BUFFER_SIZE 1024 
UNICODE_STRING UnicodeString1 = {0}; 
//设置缓冲区大小 
UnicodeString1.MaximumLength = BUFFER_SIZE; 
//分配内存 
UnicodeString1.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE); 
WCHAR* wideString = L"hello"; 
//设置字符串长度,因为是宽字符,所以是字符长度的2倍 
UnicodeString1.Length = 2 * wcslen(wideString); 
//保证缓冲区足够大,否则程序终止 
ASSERT(UnicodeString1.MaximumLength >= UnicodeString1.Length); 
//内存赋值 
RtlCopyMemory(UnicodeString1.Buffer, wideString, UnicodeString1.Length); 
 
KdPrint(("UnicodeString:%wZ\n", &UnicodeString1)); 
 
//清理内存 
ExFreePool(UnicodeString1.Buffer); 
UnicodeString1.Buffer = NULL; 
UnicodeString1.Length = UnicodeString1.MaximumLength = 0; 
 
清理内存,DDK同样给出了简化函数分别是 
 
RtlFreeAnsiString 
RtlFreeUnicodeString 
这两个函数内部调用了ExFreePool去回收内存 
 
4、字符串复制 
 
/************************************************************************ 
* 函数名称:RtlCopyString 
* 功能描述:ANSI_STRING字符串复制 
* 参数列表: 
        DestinationString:目的字符串 
        SourceString:源字符串 
* 返回 值:VOID 
*************************************************************************/ 
VOID RtlCopyString( 
    IN OUT PSTRING DestinationString, 
    IN PSTRING SourceString OPTIONAL); 
 
/************************************************************************ 
* 函数名称:RtlCopyUnicodeString 
* 功能描述:UNICODE_STRING字符串复制 
* 参数列表: 
        DestinationString:目的字符串 
        SourceString:源字符串 
* 返回 值:VOID 
*************************************************************************/ 
VOID RtlCopyUnicodeString( 
    IN OUT PUNICODE_STRING DestinationString, 
    IN PUNICODE_STRING SourceString OPTIONAL); 
 
使用方法: 
 
//初始化UnicodeString1 
UNICODE_STRING UnicodeString1; 
RtlInitUnicodeString(&UnicodeString1, L"Hello World"); 
 
//初始化UnicodeString2 
UNICODE_STRING UnicodeString2 = {0}; 
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE); 
UnicodeString2.MaximumLength = BUFFER_SIZE; 
 
//将初始化UnicodeString1复制到UnicodeString2 
RtlCopyUnicodeString(&UnicodeString2, &UnicodeString1); 
 
//分别显示UnicodeString1和UnicodeString2 
KdPrint(("UnicodeString1%wZ\n", &UnicodeString1)); 
KdPrint(("UnicodeString2%wZ\n", &UnicodeString2)); 
 
//销毁UnicodeString2 
//注意UnicodeString1不用销毁 
RtlFreeUnicodeString(&UnicodeString2); 
  
 
 5、字符串比较 
 
/************************************************************************ 
* 函数名称:RtlCompareString 
* 功能描述:ANSI_STRING字符串比较 
* 参数列表: 
        String1:要比较的第一个字符串 
        String2:要比较的第二个字符串 
        CaseInSensitive:是否对大小写敏感 
* 返回 值:比较结果 
        如果函数返回值为0,表示两个字符串相等 
        如果小于0,则表示第一个字符串小于第二个字符串 
        如果大于0,则表示第一个字符串大于第二个字符串 
*************************************************************************/ 
LONG RtlCompareString( 
    IN PSTRING String1, 
    IN PSTRING String2, 
    IN BOOLEAN CaseInSensitive); 
 
/************************************************************************ 
* 函数名称:RtlCompareUnicodeString 
* 功能描述:UNICODE_STRING字符串比较 
* 参数列表: 
        String1:要比较的第一个字符串 
        String2:要比较的第二个字符串 
        CaseInSensitive:是否对大小写敏感 
* 返回 值:比较结果 
        如果函数返回值为0,表示两个字符串相等 
        如果小于0,则表示第一个字符串小于第二个字符串 
        如果大于0,则表示第一个字符串大于第二个字符串 
*************************************************************************/ 
LONG RtlCompareUnicodeString( 
    IN PUNICODE_STRING String1, 
    IN PUNICODE_STRING String2, 
    IN BOOLEAN CaseInSensitive); 
 
如何使用RtlCompareUnicoodeString函数 
 
UNICODE_STRING UnicodeString2; 
RtlInitUnicodeString(&UnicodeString2, L"Hello"); 
//判断字符串是否相等 
if(RtlEqualUnicodeString(&UnicodeString1, &UnicodeString2, TRUE)) 
{ 
    KdPrint(("UnicodeString1 and UnicodeString2 are equal\n")); 
} 
else 
{ 
    KdPrint(("UnicodeString1 and UnicodeString2 are NOT equal\n")); 
} 
 
 
6、字符串转化成大写 
 
/************************************************************************ 
* 函数名称:RtlUpperString 
* 功能描述:UNICODE_STRING字符串转化成大写 
* 参数列表: 
        DestinationString:目的字符串 
        SourceString:源字符串 
* 返回 值:VOID 
*************************************************************************/ 
VOID RtlUpperString( 
    IN OUT PSTRING DestinationString, 
    IN PSTRING SourceString); 
 
/************************************************************************ 
* 函数名称:RtlUpperString 
* 功能描述:UNICODE_STRING字符串转化成大写 
* 参数列表: 
        DestinationString:目的字符串 
        SourceString:源字符串 
        AllocateDesttinationString:是否为目的字符串分配内存 
* 返回 值:VOID 
*************************************************************************/ 
NTSTATUS RtlUpcaseUnicodeString( 
    IN OUT PUNICODE_STRING DestinationString OPTIONAL, 
    IN PCUNICODE_STRING SourceString, 
    IN BOOLEAN AllocateDesttinationString); 
 
 
如何使用RtlUpcaseUnicodeString函数 
 
 
//初始化UnicodeString1 
UNICODE_STRING UnicodeString1; 
RtlInitUnicodeString(&UnicodeString1, L"Hello World"); 
//变化钱 
KdPrint(("UnicodeString1:%wZ\n", &UnicodeString1)); 
//转换成大写 
RtlUpcaseUnicodeString(&UnicodeString1,&UnicodeString2,FALSE); 
//变化后 
KdPrint(("UnicodeString1:%wZ\n", &UnicodeString1)); 
复制代码 
  
 
 7、字符串与整型数字相互转换 
 
/************************************************************************ 
* 函数名称:RtlUnicodeStringToInteger 
* 功能描述:UNICODE_STRING字符串转化成整型数字 
* 参数列表: 
        String:需要转化的字符串 
        Base:转换的数的进制(2,8,10,16) 
        Value:需要转换的数字 
* 返回 值:指明是否转换成功 
*************************************************************************/ 
NTSTATUS RtlUnicodeStringToInteger( 
IN PUNICODE_STRING String, 
IN ULONG Base OPTIONAL, 
OUT PULONG Value); 
 
/************************************************************************ 
* 函数名称:RtlIntegerToUnicodeString 
* 功能描述:UNICODE_STRING字符串转化成整型数字 
* 参数列表: 
        Value:需要转化的数字 
        Base:转换的数的进制(2,8,10,16) 
        String:需要转换的字符串 
* 返回 值:指明是否转换成功 
*************************************************************************/ 
NTSTATUS RtlIntegerToUnicodeString( 
IN ULONG Value, 
IN ULONG Base OPTIONAL, 
OUT PUNICODE_STRING  String); 
 
  
 
字符串与整型数字相互转换的实例 
 
//(1)字符串转换成数字 
//初始化UnicodeString1 
UNICODE_STRING UnicodeString1; 
RtlInitUnicodeString(&UnicodeString1, L"-100"); 
 
ULONG lNumber; 
NTSTATUS nStatus = RtlUnicodeStringToInteger(&UnicodeString1, 10, &lNumber); 
if( NT_SUCCESS(nStatus) ) 
{ 
    KdPrint(("Conver To Integer successfullu!\n")); 
    KdPrint(("Result:%d\n", lNumber)); 
} 
else 
{ 
    KdPrint(("Conver to integer unsuccessfully!\n")); 
} 
 
//(2)数字转换成字符串 
//初始化UnicodeString2 
UNICODE_STRING UnicodeString2; 
UnicodeString2.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE); 
UnicodeString2.MaximumLength = BUFFER_SIZE; 
nStatus = RtlIntegerToUnicodeString(200, 10, &UnicodeString2); 
 
if( NT_SUCCESS(nStatus) ) 
{ 
    KdPrint(("Conver to string successfuall!\n")); 
    KdPrint(("Result:%wZ\n", &UnicodeString2)); 
} 
else 
{ 
    KdPrint(("Conver to string unsuccessfully!\n")); 
} 
 
//注销UniocdeString2 
//注意:UnicodeString1不用销毁 
RtlFreeUnicodeString(&UniocdeString2); 
  
 
  
 
 8、ANSI_STRING字符串与UNICODE_STRING字符串相互转换 
 
/************************************************************************ 
* 函数名称:RtlUnicodeStringToAnsiString 
* 功能描述:将UNICODE_STRING字符串转化成ANSI_STRING字符串 
* 参数列表: 
        DestinationString:需要转化的字符串 
        SourceString:需要转换的原字符串 
        AllocateDesctinationString:是否需要对被转换的字符串分配内存 
* 返回 值:指明是否转换成功 
*************************************************************************/ 
NTSTATUS RtlUnicodeStringToAnsiString( 
INT OUT PANSI_STRING DestinationString, 
IN PUNICODE_STRING SourceString, 
IN BOOLEAN AllocateDesctinationString); 
 
/************************************************************************ 
* 函数名称:RtlAnsiStringToUnicodeString 
* 功能描述:将ANSI_STRING字符串转化成UNICODE_STRING字符串 
* 参数列表: 
        DestinationString:需要转化的字符串 
        SourceString:需要转换的原字符串 
        AllocateDesctinationString:是否需要对被转换的字符串分配内存 
* 返回 值:指明是否转换成功 
*************************************************************************/ 
NTSTATUS RtlAnsiStringToUnicodeString( 
INT OUT PUNICODE_STRING DestinationString, 
IN PANSI_STRING SourceString, 
IN BOOLEAN AllocateDesctinationString); 
复制代码 
  
 
ANSI_STRING字符串与UNICODE_STRING字符串的相互转换 
 
复制代码 
//(1)将UNICODE_STRING字符串转换成ANSI_STRING字符串 
//初始化UnicodeString1 
UNICODE_STRING UnicodeString1; 
RtlInitUnicodeString(&UnicodeString1, L"Hello World"); 
 
ANSI_STRING AnsiString1; 
NTSTATUS nStatus = RtlUnicodeStringToAnsiString(&AnsiString1, &UnicodeString1, TRUE); 
if( NT_SUCCESS(nStatus) ) 
{ 
    KdPrint(("Conver successfully!\n")); 
    KdPrint(("Result:%Z\n", &AnsiString1)); 
} 
else 
{ 
    KdPrint(("Conver unsuccessfully\n")); 
} 
 
//销毁AnsiString1 
RtlFreeAnsiString(&AnsiString1); 
 
//(2)将ANSI_STRIN字符串转换成GUNICODE_STRING字符串 
//初始化AnsiString2 
ANSI_STRING AnsiString2; 
RtlInitString(&AnsiString2, "Hello World"); 
UNICODE_STRING UnicodeString2; 
nStatus = RtlAnsiStringToUnicodeString(&UnicodeString2, &AnsiString2, TRUE); 
 
if( NT_SUCCESS(nStatus) ) 
{ 
    KdPrint(("Conver successfully!\n")); 
    KdPrint(("Result:%Z\n", &UnicodeString2)); 
} 
else 
{ 
    KdPrint(("Conver unsuccessfully\n")); 
} 
 
//销毁UnicodeString2 
RtlFreeUnicodeString(&UnicodeString2); 
 |   
 
 
 
 |