三、字符串操作

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;
}

8、測試結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章