6.1 字符串操作
6.1.1. ASCII字符串和宽字符串
char(ASCII字符串)一个字节
wchar_t(宽字符串)两个字节
在构造字符串时使用关键字"L",编译器会自动生成所需的宽字符
wchar_t *str = L"abc";
在驱动程序开发中,DDK替换成CHAR和WCHAR
CHAR *str ="hello"';
KdPrint("%s\n",str); //注意是小写的s
WCHAR *str =L"hello"';
KdPrint("%S\n",str); //注意是大写的S
6.1.2 ANSI_STRING字符串与UNICODE_STRING字符串
DDK不鼓励使用C语言的字符串,鼓励使用DDK自定义的字符串
typedef struct _STRING{
USHORT Length;
USHORT MaximunLength;
PCHAR Buffer;
}STRING; //另一个类似
这两种字符串不是以0标志字符的结束,字符串长度依靠Length字段,最大长度是MaximunLength,而不是MaximunLength-1
6.1.3 字符初始化与销毁
ANSI_STRING字符串与UNICODE_STRING字符串使用前需要初始化。有两种办法构造这个数据结构
RtlInitAnsiString(IN OUT PANSI_STRING DestinationString, IN PCSZ SourceString );
RtlInitUnicodeString( );
初始化示例1
ANSI_STRING AnsiString1;
CHAR * string1="hello";
RtlInitAnsiString(&AnsiString1,string1);
但带来另外一个问题,如果修改string1,同时会导致AnsiString1字符发生变化。
初始化示例2
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);
ExFreePool(UnicodeString1.Buffer);
UnicodeString1.Buffer =NULL;
UnicodeString1.Length =UnicodeString1.MaximumLength =0;
6.1.4 字符串复制
(1)ANSI_STRING字符串复制函数
VOID
RtlCopyString(
IN OUT PSTRING DestinationString,
IN PSTRING SourceString OPTIONAL
);
DestinationString:目的字符串。
SourceString:源字符串。
(2)UNICODE_STRING字符串复制函数
VOID
RtlCopyUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PUNICODE_STRING SourceString
);
DestinationString:目的字符串。
SourceString:源字符串。
6.1.5 字符串比较
LONG
RtlCompareString(
IN PSTRING String1,
IN PSTRING String2,
BOOLEAN CaseInSensitive
);
String1:要比较的第一个字符串。
String2:要比较的第二个字符串。
CaseInSensitive:是否对大小写敏感。
返回值:比较结果。
LONG
RtlCompareUnicodeString(
IN PUNICODE_STRING String1,
IN PUNICODE_STRING String2,
IN BOOLEAN CaseInSensitive
);
如果函数返回值为0,表示两个字符串相等。如果小于零,则表示第一个字符串小于第二个字符串。反之,如果大于零,则代表第一个字符串大于第二个字符串。
6.1.6 字符串转化成大写
(1)ANSI_STRING字符串转化成大写。
VOID
RtlUpperString(
IN OUT PSTRING DestinationString,
IN PSTRING SourceString
);
DestinationString:目的字符串。
SourceString:源字符串。
(2)UNICODE_STRING字符串转化成大写。
NTSTATUS
RtlUpcaseUnicodeString(
IN OUT PUNICODE_STRING DestinationString OPTIONAL,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
6.1.7 字符串与整型数字相互转换
DDK提供了UNICODE_STRING字符串与整数相互转换的内核函数。
(1)将UNICODE_STRING字符串转换成整数。
这个函数是RtlUnicodeStringToInteger,其声明是:
NTSTATUS
RtlUnicodeStringToInteger(
IN PUNICODE_STRING String,
IN ULONG Base OPTIONAL,
OUT PULONG Value
);
String:需要转换的字符串。
Base:转换的数的进制(如2、8、10、16)。
Value:需要转换的数字。
返回值:指明是否转换成功。
2)将整数转换成UNICODE_STRING字符串。
这个函数RtlIntegerToUnicodeString,其声明是:
NTSTATUS
RtlIntegerToUnicodeString(
IN ULONG Value,
IN ULONG Base OPTIONAL,
IN OUT PUNICODE_STRING String
);
Value:需要转换的数字。
Base:转换的数的进制(如2、8、10、16)。
String:需要转换的字符串。
返回值:指明是否转换成功。
6.1.8 ANSI_STRING字符串与UNICODE_STRING字符串相互转换
DDK提供了ANSI_STRING字符串与UNICODE_STRING字符串相互转换的相关函数。
(1)将UNICODE_STRING字符串转换成ANSI_STRING字符串。
DDK对于这种转换提供的函数是RtlUnicodeStringToAnsiString,其声明是:
NTSTATUS
RtlUnicodeStringToAnsiString(
IN OUT PANSI_STRING DestinationString,
IN PUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
DestinationString:需要被转换的字符串。
SourceString:需要转换的源字符串。
AllocateDestinationString:是否需要对被转换的字符串分配内存。
返回值:指明是否转换成功。
(2)将ANSI_STRING字符串转换成UNICODE_STRING字符串。
DDK对于这种转换提供的函数是RtlAnsiStringToUnicodeString,其声明是:
NTSTATUS
RtlAnsiStringToUnicodeString(
IN OUT PUNICODE_STRING DestinationString,
IN PANSI_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);