Windows内核模式下的字符串操作

电子常识

2573人已加入

描述

  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.2、另外一种方法是程序员自己申请内存,并初始化内存,当不用字符串时

  需要回收字符串占用的内存

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

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分