1、UNICODE_STRING
windows內核編碼字符集採用unicode字符集,字符串處理使用UNICODE_STRING,是一個結構體,定義如下:
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
#ifdef MIDL_PASS
[size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
#else // MIDL_PASS
_Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer;
#endif // MIDL_PASS
} UNICODE_STRING;
Length 字符串長度,MaximumLength 字符串緩衝區長度,Buffer 字符串緩衝區指針變量。
2、字符串聲明與初始化
第一種方式,以局部變量方式,讓UNICODE_STRING的Buffer指向一個已聲明的WCHAR數組。
UNICODE_STRING strDest;
WCHAR dest_buf[256];
RtlInitEmptyUnicodeString(&strDest, dest_buf, 256*sizeof(WCHAR));
RtlInitEmptyUnicodeString去初始化strDest。
第二種方式,使用RtlInitUnicodeString函數去初始化一個UNICODE_STRING變量,給其複製,分配空間
UNICODE_STRING strSource;
RtlInitUnicodeString(&strSource, L"測試字符串連接");
第三種方式,動態申請空間,類似應用程序的malloc函數。
UNICODE_STRING strDest;
strDest.Length = 0;
strDest.MaximumLength = sizeof(WCHAR) * 1024;
strDest.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR)*1024, MEMTAG);
if (!strDest.Buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
3、字符串拷貝
UNICODE_STRING strSource;
RtlInitUnicodeString(&strSource, L"測試字符串連接");
KdPrint(("source is %wZ字節長度%d 最大長度%d.\n", &strSource, strSource.Length, strSource.MaximumLength));
RtlCopyUnicodeString(&strDest,&strSource);
KdPrint(("dest is %wZ 字節長度%d 最大長度%d.\n", strDest, strDest.Length, strDest.MaximumLength));
unicode格式化字符串輸出使用%wZ,ansi格式化字符串輸出使用%x
4、字符串連接
UNICODE_STRING strTmp;
RtlInitUnicodeString(&strTmp, L"this is a new string");
ntres = RtlAppendUnicodeStringToString(&strDest, &strTmp);
字符串連接使用,根據第二個參數類型而定,如果是unicode,選擇RtlAppendUnicodeStringToString,如果是ansi,選擇RtlAppendUnicodeToString。
5、字符串比較
UNICODE_STRING uCp1, uCp2;
RtlInitUnicodeString(&uCp1, L"hello a world.");
RtlInitUnicodeString(&uCp2, L"hello b world.");
LONG lRet = RtlCompareUnicodeString(&uCp1, &uCp2, TRUE);
if (lRet > 0)
{
KdPrint(("%wZ 大於 %wZ .", &uCp1, &uCp2));
}
else if(lRet < 0)
{
KdPrint(("%wZ 小於 %wZ .", &uCp1, &uCp2));
}
else
{
KdPrint(("%wZ 等於 %wZ .", &uCp1, &uCp2));
}
RtlCompareUnicodeString類似應用程序的strcmp函數,返回值爲三種值,大於0,等於0,小於0,其第三個參數表示是否大小寫敏感。
6、UNICODE_STRING與ANSI_STRING互轉
//unicode與多字節互轉
UNICODE_STRING uniTrans;
RtlInitUnicodeString(&uniTrans, L"test unicode to ansi");
ANSI_STRING ansiTrans;
RtlUnicodeStringToAnsiString(&ansiTrans, &uniTrans, TRUE);
KdPrint(("%wZ to ansi is %Z", &uniTrans, &ansiTrans));
RtlAnsiStringToUnicodeString(&uniTrans, &ansiTrans, TRUE);
KdPrint(("%Z to ansi is %wZ", &ansiTrans, &uniTrans));
7、上述測試完整代碼
#include <ntddk.h>
#define MEMTAG 'test'
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
KdPrint(("卸載驅動成功\n"));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING reg_path)
{
NTSTATUS ntres;
KdPrint(("驅動加載成功\n"));
HANDLE hPid = PsGetCurrentProcessId();
KdPrint(("當前進程id:%d\n",(int)hPid));
UNICODE_STRING strDest;
strDest.Length = 0;
strDest.MaximumLength = sizeof(WCHAR) * 1024;
strDest.Buffer = (PWCH)ExAllocatePoolWithTag(PagedPool, sizeof(WCHAR)*1024, MEMTAG);
if (!strDest.Buffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
UNICODE_STRING strSource;
RtlInitUnicodeString(&strSource, L"測試字符串連接");
KdPrint(("source is %wZ字節長度%d 最大長度%d.\n", &strSource, strSource.Length, strSource.MaximumLength));
RtlCopyUnicodeString(&strDest,&strSource);
KdPrint(("dest is %wZ 字節長度%d 最大長度%d.\n", strDest, strDest.Length, strDest.MaximumLength));
UNICODE_STRING strTmp;
RtlInitUnicodeString(&strTmp, L"this is a new string");
ntres = RtlAppendUnicodeStringToString(&strDest, &strTmp);
if (NT_SUCCESS(ntres))
{
}
else
{
KdPrint(("拼接失敗"));
}
KdPrint(("打印 %wZ 字節長度%d 最大長度%d.\n", &strDest, strDest.Length, strDest.MaximumLength));
//比較字符串
UNICODE_STRING uCp1, uCp2;
RtlInitUnicodeString(&uCp1, L"hello a world.");
RtlInitUnicodeString(&uCp2, L"hello b world.");
LONG lRet = RtlCompareUnicodeString(&uCp1, &uCp2, TRUE);
if (lRet > 0)
{
KdPrint(("%wZ 大於 %wZ .", &uCp1, &uCp2));
}
else if(lRet < 0)
{
KdPrint(("%wZ 小於 %wZ .", &uCp1, &uCp2));
}
else
{
KdPrint(("%wZ 等於 %wZ .", &uCp1, &uCp2));
}
//unicode與多字節互轉
UNICODE_STRING uniTrans;
RtlInitUnicodeString(&uniTrans, L"test unicode to ansi");
ANSI_STRING ansiTrans;
RtlUnicodeStringToAnsiString(&ansiTrans, &uniTrans, TRUE);
KdPrint(("%wZ to ansi is %Z", &uniTrans, &ansiTrans));
RtlAnsiStringToUnicodeString(&uniTrans, &ansiTrans, TRUE);
KdPrint(("%Z to ansi is %wZ", &ansiTrans, &uniTrans));
if (strDest.Buffer != NULL)
{
ExFreePool(strDest.Buffer);
strDest.Length = strDest.MaximumLength = 0;
}
pDriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}