zoukankan      html  css  js  c++  java
  • 驱动自定义回调例程

    前言:
    熟悉驱动开发的人们都知道,在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).
    ", 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).
    ", 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.
    "));
    	}
    
    	KdPrint(("[sysTest] thread ended.
    "));
    	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.
    "));
    }
    
    
    //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).
    ", status));
    		return status;
    	}
    	gbSuccess = 1;
    	
    	gpCookie = ExRegisterCallback(gpObjCallback, CALLBACK_FUNC, NULL);
    	if (NULL == gpCookie)
    	{
    		KdPrint(("[sysRecv1] ExRegisterCallback error.
    "));
    		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.
    "));
    }
    
    
    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)	ulValue:(%s)
    ", ulType, ulValue));
    }
    

     结果如下:

     从结果分析可知是正确的,当没有回调注册时,即使发送通知其它驱动也收不到任何通知,当注册回调以后,每当发送通知都可以接收到的消息。

  • 相关阅读:
    Java WebSocket生命周期
    软件网络总结
    js模态弹窗
    spring boot
    spring aop
    lvs分布式
    如何在大牛面前装逼
    Java学习的思考
    javase知识点
    <nginx+PHP>nginx环境下配置支持php7
  • 原文地址:https://www.cnblogs.com/priarieNew/p/9759473.html
Copyright © 2011-2022 走看看