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

     结果如下:

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

  • 相关阅读:
    SoapUI 使用笔记
    git 使用笔记(二)
    git 使用笔记(一)
    jquery 拓展
    hdu 1024 Max Sum Plus Plus (DP)
    hdu 2602 Bone Collector (01背包)
    hdu 1688 Sightseeing (最短路径)
    hdu 3191 How Many Paths Are There (次短路径数)
    hdu 2722 Here We Go(relians) Again (最短路径)
    hdu 1596 find the safest road (最短路径)
  • 原文地址:https://www.cnblogs.com/priarieNew/p/9759473.html
Copyright © 2011-2022 走看看