Windows驱动开发(3) - 内核模式下的字符串操作

Windows驱动开发(3) - 内核模式下的字符串操作

1、ASCII字符串和宽字符串

  char型,记录ansi字符集。每个字符一个字节。以0标志结束。在KdPrint中用%s输出。
  宽字符型,wchar_t,描述unicode字符集的字符串,每个字符两个字节,以0标志结束。通过L来体现。在KdPrint中用%S输出。

CHAR *string = "Hello";
WCHAR *string2 = L"hello";
KdPrint("%s\n", string);
KdPrint("%S\n", string2);

2、ANSI_STRING字符串和UNICODE_STRING字符串

DDK不鼓励用1)中所示的C语言字符串,因为C的字符串处理函数易导致缓冲区溢出等错误(如忘记对长度进行检查)。而鼓励用DDK自己定义的字符串。

typedef struct _STRING {
  USHORT  Length;       //字符的长度
  USHORT  MaximumLength;//整个字符缓冲区的最大长度
  PCHAR  Buffer;        //缓冲区的指针
} ANSI_STRING *PANSI_STRING;

注意STRING不是以0结束的。

typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING *PUNICODE_STRING;

%Z输出 ANSI_STRING字符串,用%wZ输出 UNICODE_STRING

UNICODE_STRING uniString;
KdPrint("%wZ", &uniString);

3、字符串初始化与销毁

3.1 使用DDK提供的相应函数

  1. 初始化ANSI_STRING
VOID RtlInitAnsiString( _Out_ PANSI_STRING DestinationString, _In_opt_ PCSZ SourceString );
  1. 初始化UNICOODE_STRING
VOID RtlInitUnicodeString( _Out_ PUNICODE_STRING DestinationString, _In_opt_ PCWSTR SourceString );
  • DestinationString:要初始化的字符串。
  • SourceString:字符串的内容。ANSI_STRING为CHAR *类型,UNICODE_STRING为WCHAR *类型。

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);
//设置字符长度
UnicodeString1.Length = 2*wcslen(wideString);
KdPrint(("UnicodeString:%wZ\n",&UnicodeString1));
//清理内存
ExFreePool(UnicodeString1.Buffer);
UnicodeString1.Buffer = NULL;
UnicodeString1.Length = UnicodeString1.MaximumLength = 0;

最后一步清理内存,可以使用DDK函数简化:
RtlFreeAnsiString
RtlFreeUnicodeString

4、字符串复制

4.1 ANSI_STRING字符串复制

VOID RtlCopyString(
  _Out_          PSTRING DestinationString,
  _In_opt_ const STRING  *SourceString
);

4.2 UNICODE_STRING字符串复制

VOID RtlCopyUnicodeString( _Inout_ PUNICODE_STRING DestinationString, _In_opt_ PCUNICODE_STRING SourceString );
  • DestinationString:目的字符串。
  • SourceString:源字符串。

5、字符串比较

5.1 ANSI_STRING字符串比较

LONG RtlCompareString(
  _In_ const STRING  *String1,
  _In_ const STRING  *String2,
  _In_       BOOLEAN CaseInSensitive
);

5.2 UNICODE_STRING字符串比较

LONG RtlCompareUnicodeString(
  _In_ PCUNICODE_STRING String1,
  _In_ PCUNICODE_STRING String2,
  _In_ BOOLEAN          CaseInSensitive
);
  • String1:要比较的第一个字符串。
  • String2:要比较的第二个字符串。
  • CaseInSensitive:是否对大小写敏感
  • 返回值:比较结果。返回0表示相等,小于0表示String1小于String2,大于0表示String1大于String2.

5.3 比较两个字符串是否相等

BOOLEAN RtlEqualString(
  _In_ const STRING  *String1,
  _In_ const STRING  *String2,
  _In_       BOOLEAN CaseInSensitive
);
BOOLEAN RtlEqualUnicodeString(
  _In_ PCUNICODE_STRING String1,
  _In_ PCUNICODE_STRING String2,
  _In_ BOOLEAN          CaseInSensitive
);
  • String1:要比较的第一个字符串。
  • String2:要比较的第二个字符串。
  • CaseInSensitive:是否对大小写敏感
  • 返回值:比较结果。返回0表示不相等,非0表示相等。

6、字符串转换成大写

6.1 ANSI_STRING字符串转换成大写

VOID RtlUpperString(
  _Inout_  PSTRING DestinationString,
  _In_     const STRING *SourceString
);
  • DestinationString:目的字符串。
  • SourceString:源字符串。

6.2 UNICODE_STRING字符串转换成大写

NTSTATUS RtlUpcaseUnicodeString(
  _Inout_ PUNICODE_STRING  DestinationString,
  _In_    PCUNICODE_STRING SourceString,
  _In_    BOOLEAN          AllocateDestinationString
);
  • DestinationString:目的字符串。
  • SourceString:源字符串。
  • AllocateDestinationString:是否为目的字符串分配内存
  • 返回值:返回转换是否成功

7、字符串与整型数字相互转换

7.1 UNICODE_STRING字符串转换成整数

NTSTATUS RtlUnicodeStringToInteger(
  _In_      PCUNICODE_STRING String,
  _In_opt_  ULONG Base,
  _Out_     PULONG Value
);
  • String:需要转换的字符串。
  • Base:转换的数的进制(2,8,10,16)。
  • Value:转换之后的数字
  • 返回值:返回转换是否成功

7.2 整数转换成UNICODE_STRING字符串

NTSTATUS RtlIntegerToUnicodeString(
  _In_     ULONG           Value,
  _In_opt_ ULONG           Base,
  _Inout_  PUNICODE_STRING String
);
  • Value:需要转换的数字
  • Base:转换的数的进制(2,8,10,16)。
  • String:转换之后的字符串。
  • 返回值:返回转换是否成功

8、ANSI_STRING字符串与UNICODE_STRING字符串相互转换

8.1 UNICODE_STRING字符串转换成ANSI_STRING字符串

NTSTATUS RtlUnicodeStringToAnsiString(
  _Inout_ PANSI_STRING     DestinationString,
  _In_    PCUNICODE_STRING SourceString,
  _In_    BOOLEAN          AllocateDestinationString
);
  • DestinationString:目的字符串。
  • SourceString:源字符串。
  • AllocateDestinationString:是否需要对被转换的字符串分配内存
  • 返回值:返回转换是否成功

8.2 ANSI_STRING字符串转换成UNICODE_STRING字符串

NTSTATUS RtlAnsiStringToUnicodeString(
  _Inout_ PUNICODE_STRING DestinationString,
  _In_    PCANSI_STRING   SourceString,
  _In_    BOOLEAN         AllocateDestinationString
);
  • DestinationString:目的字符串。
  • SourceString:源字符串。
  • AllocateDestinationString:是否需要对被转换的字符串分配内存
  • 返回值:返回转换是否成功

你可能感兴趣的:(windows,内核,驱动开发)