Windows内核函数(1) - 字符串处理函数
1.ASCII字符串和宽字符串
打印一个ASCII字符串:
CHAR*string="Hello";
KdPrint(("%s\n",string));//s为小写
打印一个宽字符字符串
WCHAR*string=L"Hello";
KdPrint(("%S\n",string));//s为大写
2.ANSI_STRING字符串与UNICODE_STRING字符串
ANSI_STRING:
typedefstruct_STRING{
USHORTLength;
USHORTMaximumLength;
PCHARBuffer;
}ANSI_STRING*PANSI_STRING;
UNICODE_STRING:
typedefstruct_UNICODE_STRING{
USHORTLength;
USHORTMaximumLength;
PWSTRBuffer;
}UNICODE_STRING*PUNICODE_STRING;
打印ANSI_STRING
ANSI_STRINGansiString;
//省略对ansiString的初始化
KdPrint(("%Z\n",&ansiString));//注意是大写的Z
打印UNICODE_STRING
UNICODE_STRINGunicodeString;
//省略对unicodeString的初始化
KdPrint(("%wZ",&unicodeString));//注意是小写的w和大写的Z
3.字符串的初始化与销毁
(1)方法一是使用DDK提供的相应的函数。
初始化ANSI_STRING字符串:VOID
RtlInitAnsiString(
INOUTPANSI_STRINGDestinationString,
INPCSZSourceString
);初始化UNICODE_STRING字符串VOID
RtlInitUnicodeString(
INOUTPUNICODE_STRINGDestinationString,
INPCWSTRSourceString
);使用方法(以ANSI_STRING为例):
ANSI_STRINGansiString;
CHAR*string="Hello";
RtlInitAnsiString(&ansiString,string);
注意:
这种方法是将ANSI_STRING结构体中的Buffer指针等于string指针。
这种初始化的优点是操作简单,用完后不用清理内存。但是带来另外一个问题,如果修改string,同时会导致ansiString字符串发生变化。
(2)方法2是程序员自己申请内存,并初始化内存,当不用字符串时,需要回收字符串占用的内存。
示例代码:
#pragmaINITCODE
VOIDTestUnicodeString()
{
KdPrint(("1.利用DDK函数进行初始化UNICODE_STRING!\n"));
UNICODE_STRINGustrTest1;
WCHAR*wstring=L"Hello";
//用DDK宏进行初始化
RtlInitUnicodeString(&ustrTest1,wstring);
KdPrint(("%wZ",&ustrTest1));
KdPrint(("2.自己初始化UNICODE_STRING!\n"));
UNICODE_STRINGustring2={0};
//设置缓冲区大小
ustring2.MaximumLength=BUFFER_SIZE;
//申请内存
ustring2.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
WCHAR*string2=L"hello";
//两倍字符的长度
ustring2.Length=2*wcslen(string2);
RtlCopyMemory(ustring2.Buffer,string2,ustring2.Length);
KdPrint(("%wZ",&ustring2));
//清理内存
ExFreePool(ustring2.Buffer);
ustring2.Buffer=NULL;
ustring2.Length=ustring2.MaximumLength=0;
//RtlFreeUnicodeString(&ustring2);
}
对于最后一步清理内存,DDK给出了简化函数,分别是RtlFreeAnsiString和RtlFreeUnicodeString,这两个函数内部调用了ExFreePool去回收内存。
所以最后的三行代码也可替换成最后的一行注释代码。
4.字符串复制
ANSI_STRING字符串复制函数VOID
RtlCopyString(
INOUTPSTRINGDestinationString,
INPSTRINGSourceStringOPTIONAL
);UNICODE_STRING字符串复制函数VOID
RtlCopyUnicodeString(
INOUTPUNICODE_STRINGDestinationString,
INPUNICODE_STRINGSourceString
);示例代码:
#pragmaINITCODE
voidTestCopy()
{
//初始化string1
UNICODE_STRINGstring1;
RtlInitUnicodeString(&string1,L"fuckzq");
//初始化string2
UNICODE_STRINGstring2;
string2.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
string2.MaximumLength=BUFFER_SIZE;
string2.Length=string1.Length;
//开始复制
RtlCopyUnicodeString(&string2,&string1);
KdPrint(("%wZ\n",&string1));
KdPrint(("%wZ\n",&string2));
//销毁string2。
//注意:string1不用销毁
RtlFreeUnicodeString(&string2);
}
5.字符串比较
ANSI_STRING比较函数LONG
RtlCompareString(
INPSTRINGString1,
INPSTRINGString2,
BOOLEANCaseInSensitive//是否对大小写敏感
);BOOLEAN
RtlEqualString(
INPSTRINGString1,
INPSTRINGString2,
INBOOLEANCaseInSensitive
);UNICODE_STRING比较函数LONG
RtlCompareUnicodeString(
INPUNICODE_STRINGString1,
INPUNICODE_STRINGString2,
INBOOLEANCaseInSensitive
);BOOLEAN
RtlEqualUnicodeString(
INCONSTUNICODE_STRING*String1,
INCONSTUNICODE_STRING*String2,
INBOOLEANCaseInSensitive
);示例代码:
#pragmaINITCODE
VOIDTestCmpSting()
{
UNICODE_STRINGstring1;
RtlInitUnicodeString(&string1,L"fuckyouzq");
UNICODE_STRINGstring2;
string2.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
string2.MaximumLength=BUFFER_SIZE;
RtlCopyUnicodeString(&string2,&string1);
if(RtlCompareUnicodeString(&string1,&string2,TRUE)==0)
{
KdPrint(("1.相等\n"));
}
if(RtlEqualUnicodeString(&string1,&string2,TRUE))
{
KdPrint(("相等!\n"));
}
else
{
KdPrint(("不相等\n"));
}
}
6.字符串转化成大写
ANSI_STRING:VOID
RtlUpperString(
INOUTPSTRINGDestinationString,
INPSTRINGSourceString
);UNICODE_STRING:NTSTATUS
RtlUpcaseUnicodeString(
INOUTPUNICODE_STRINGDestinationStringOPTIONAL,
INPCUNICODE_STRINGSourceString,
INBOOLEANAllocateDestinationString//是否为目的字符串分配内存
);注意:DDK虽然提供了转化成大写的函数,但是却没有提供转化为小写的函数。
示例代码:
#pragmaINITCODE
VOIDTestUpperString()
{
UNICODE_STRINGstring1;
RtlInitUnicodeString(&string1,L"HelloWorld");
KdPrint(("%wZ\n",&string1));
UNICODE_STRINGstring2;
//RtlUpcaseUnicodeString最后一个参数为TRUE,表示为目标字符串分配内存,因此我们不需要手动分配了。
RtlUpcaseUnicodeString(&string2,&string1,TRUE);
KdPrint(("%wZ\n",&string2));
//目标字符串和源字符串可以是同一个字符串
RtlUpcaseUnicodeString(&string1,&string1,FALSE);
KdPrint(("%wZ\n",&string1));
RtlFreeUnicodeString(string2);
}
7.字符串与整形数字相互转换
将UNICODE_STRING字符串转换成整数NTSTATUS
RtlUnicodeStringToInteger(
INPUNICODE_STRINGString,//字符串
INULONGBaseOPTIONAL,//转换的数的进制
OUTPULONGValue//转换后的数字
);将整数转换成UNICODE_STRINGNTSTATUS
RtlIntegerToUnicodeString(
INULONGValue,
INULONGBaseOPTIONAL,
INOUTPUNICODE_STRINGString
);示例代码:
VOIDTestStringToInt()
{
UNICODE_STRINGstring1;
RtlInitUnicodeString(&string1,L"-100");
ULONGi;
NTSTATUSstatus=RtlUnicodeStringToInteger(&string1,10,&i);
if(!NT_SUCCESS(status))
{
KdPrint(("转换失败!\n"));
}
else
{
KdPrint(("%d",i));
}
UNICODE_STRINGstring2={0};
string2.Buffer=(PWSTR)ExAllocatePool(PagedPool,BUFFER_SIZE);
string2.MaximumLength=BUFFER_SIZE;
status=RtlIntegerToUnicodeString(200,10,&string2);
if(!NT_SUCCESS(status))
{
KdPrint(("转换失败!\n"));
}
else
{
KdPrint(("%wZ\n",&string2));
}
RtlFreeUnicodeString(&string2);
}
8.ANSI_STRING和UNICODE_STRING字符串相互转换
UNICODE_STRING转换为ANSI_STRING字符串NTSTATUS
RtlUnicodeStringToAnsiString(
INOUTPANSI_STRINGDestinationString,
INPUNICODE_STRINGSourceString,
INBOOLEANAllocateDestinationString
);ANSI_STRING转为UNICODE_STRING字符串NTSTATUS
RtlAnsiStringToUnicodeString(
INOUTPUNICODE_STRINGDestinationString,
INPANSI_STRINGSourceString,
INBOOLEANAllocateDestinationString
);示例代码:
#pragmaINITCODE
VOIDTestStringToString()
{
UNICODE_STRINGunicodeString;
RtlInitUnicodeString(&unicodeString,L"fuckyou!\n");
ANSI_STRINGansiString;
NTSTATUSstatus=RtlUnicodeStringToAnsiString(&ansiString,&unicodeString,TRUE);//为ansiString分配内存
if(NT_SUCCESS(status))
{
KdPrint(("%Z",&ansiString));
}
//销毁ansiString
RtlFreeAnsiString(&ansiString);
}
更多驱动编程文章http://mzf2008.blog.163.com/blog/static/3559978620101112115510592/