驅動自定義回調例程


前言:
熟悉驅動開發的人們都知道,在windows系統內,系統自動提供許多回調函數,比如,進程回調,模塊回調,注冊表回調,等等。但windows也提供了一些函數使得開發者也可以自定義回調。利用回調也可以實現驅動模塊間的通訊。相關函數如下:

//創建回調或者打開回調
NTSTATUS
ExCreateCallback (
    _Outptr_ PCALLBACK_OBJECT *CallbackObject,
    _In_ POBJECT_ATTRIBUTES ObjectAttributes,
    _In_ BOOLEAN Create,
    _In_ BOOLEAN AllowMultipleCallbacks
    );

//注冊回調

PVOID
ExRegisterCallback (
    _Inout_ PCALLBACK_OBJECT CallbackObject,
    _In_ PCALLBACK_FUNCTION CallbackFunction,
    _In_opt_ PVOID CallbackContext
    );

//回調通知

VOID
ExNotifyCallback (
    _In_ PVOID CallbackObject,
    _In_opt_ PVOID Argument1,
    _In_opt_ PVOID Argument2
    );

//回調例程

VOID CALLBACK_FUNC(
	_In_ PVOID CallbackContext,
	_In_ PVOID Argument1,
	_In_ PVOID Argument2);

 相關函數用法,這里不做多介紹,自行查閱msdn學習。
這里寫一個測試例子,分為sender和receiver,sender注冊回調后創建一個線程,定時的通知receiver。
receiver打開回調,注冊回調,一旦接收到通知后,把數據打印出來。

//sender

#include <ntifs.h>


#define CALLBACKNAME L"\\Callback\\driverStart"

VOID UnloadDriver(PDRIVER_OBJECT driver);

VOID MyThread(PVOID context);

BOOLEAN gbSuccess = 0;
//線程句柄
HANDLE ghThread = NULL;
//回調指針
PCALLBACK_OBJECT gpObjCallback = NULL;
KEVENT gEvent;

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING registry)
{
	UNREFERENCED_PARAMETER(registry);

	NTSTATUS status;
	OBJECT_ATTRIBUTES objAttri;
	driver->DriverUnload = UnloadDriver;
	//初始化通知事件
	KeInitializeEvent(&gEvent, SynchronizationEvent, FALSE);

	UNICODE_STRING uniCallbackName = RTL_CONSTANT_STRING(CALLBACKNAME);
	//這里必須指定OBJ_PERMANENT屬性,否則會失敗
	InitializeObjectAttributes(&objAttri, &uniCallbackName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL);

	//注冊回調對象
	status = ExCreateCallback(&gpObjCallback, &objAttri, TRUE, TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("[sysTest] ExCreateCallback error code:(0x%x).\n", status));
		return status;
	}
	//注冊成功
	gbSuccess = 1;
	//創建線程,定期發送 ExNotifyCallback
	status = PsCreateSystemThread(&ghThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, MyThread, NULL);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("[sysTest] PsCreateSystemThread error code:(0x%x).\n", status));
		return status;
	}

	status = STATUS_SUCCESS;
	return status;

}

VOID MyThread(PVOID context)
{
	UNREFERENCED_PARAMETER(context);

	NTSTATUS status;
	ULONG type = 1;
	//ULONG ulData = 0;
	PCHAR ulData = "hello";
	LARGE_INTEGER tick = { 0 };
	//時間間隔是定位2秒
	tick = RtlConvertLongToLargeInteger(-10 * 1000 * 1000 * 2);

	while (tick.QuadPart != 0)
	{
		//等待3秒
		status = KeWaitForSingleObject(&gEvent, Executive, KernelMode, FALSE, &tick);
		if (STATUS_TIMEOUT != status)
		{
			break;
		}
		//通知
		ExNotifyCallback(gpObjCallback, &type, ulData);
		KdPrint(("[sysTest] send.\n"));
	}

	KdPrint(("[sysTest] thread ended.\n"));
	PsTerminateSystemThread(STATUS_SUCCESS);
}

VOID UnloadDriver(PDRIVER_OBJECT driver)
{
	UNREFERENCED_PARAMETER(driver);
	
	KeSetEvent(&gEvent, 0, TRUE);	
	if (NULL != ghThread)
	{
		ZwWaitForSingleObject(ghThread, FALSE, NULL);
		ZwClose(ghThread);
		ghThread = NULL;
	}
	if (gbSuccess)
	{
		ObDereferenceObject(gpObjCallback);
	}

	KdPrint(("[sysTest] driver stoped.\n"));
}


//receiver

#include <ntifs.h>

#define CALLBACKNAME L"\\Callback\\driverStart"

VOID UnloadDriver(_In_ PDRIVER_OBJECT driver);
VOID CALLBACK_FUNC(
	_In_ PVOID CallbackContext,
	_In_ PVOID Argument1,
	_In_ PVOID Argument2);

PCALLBACK_OBJECT gpObjCallback = NULL;
BOOLEAN gbSuccess = 0;
PVOID gpCookie = NULL;


NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING registry)
{
	UNREFERENCED_PARAMETER(registry);
	
	driver->DriverUnload = UnloadDriver;

	NTSTATUS status;
	UNICODE_STRING uniName = RTL_CONSTANT_STRING(CALLBACKNAME);
	OBJECT_ATTRIBUTES objAttri;

	InitializeObjectAttributes(&objAttri, &uniName, OBJ_CASE_INSENSITIVE, NULL, NULL);

	status = ExCreateCallback(&gpObjCallback, &objAttri, FALSE, TRUE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("[sysRecv1] ExCreateCallback error code:(0x%x).\n", status));
		return status;
	}
	gbSuccess = 1;
	
	gpCookie = ExRegisterCallback(gpObjCallback, CALLBACK_FUNC, NULL);
	if (NULL == gpCookie)
	{
		KdPrint(("[sysRecv1] ExRegisterCallback error.\n"));
		return STATUS_UNSUCCESSFUL;
	}

	status = STATUS_SUCCESS;

	return status;
}



VOID UnloadDriver(_In_ PDRIVER_OBJECT driver)
{
	UNREFERENCED_PARAMETER(driver);

	if (NULL != gpCookie)
	{
		ExUnregisterCallback(gpCookie);
	}
	KdPrint(("[sysRecv1] Drvier unloaded.\n"));
}


VOID CALLBACK_FUNC(
	_In_ PVOID CallbackContext,
	_In_ PVOID Argument1,
	_In_ PVOID Argument2)
{
	UNREFERENCED_PARAMETER(CallbackContext);
	
	ULONG ulType;
	PCHAR ulValue;
	ulType = *(ULONG*)Argument1;
	ulValue = (PCHAR)Argument2;

	KdPrint(("[sysRecv1]:get notify ulType:(%d)\tulValue:(%s)\n", ulType, ulValue));
}

 結果如下:

 從結果分析可知是正確的,當沒有回調注冊時,即使發送通知其它驅動也收不到任何通知,當注冊回調以后,每當發送通知都可以接收到的消息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM