2016年8月23日星期二

获取WFP的Bfe的State及相关

/*
起因:系统启动的时候FwpmEngineOpen0返回c0020035即EPT_NT_CANT_PERFORM_OP ,意思是:The operation cannot be performed.(服务器终结点无法运行操作)。
所以:有此文。

文件名:BfeState.C

测试要点和心得:
1.FwpmBfeStateGet0在系统启动的时候返回值是FWPM_SERVICE_STOPPED。
2.FwpmBfeStateGet0在正常驱动加载的时候返回值是FWPM_SERVICE_RUNNING。
3.只有在系统启动的时候会调用FwpmBfeStateSubscribeChanges的回调函数。两次,第一次是FWPM_SERVICE_START_PENDING,后来FWPM_SERVICE_RUNNING。
4.在正常的驱动加载时,不会调用FwpmBfeStateSubscribeChanges的回调函数。
5.所以FwpmBfeStateGet可判断驱动是否在系统启动的时候运行/加载。
...,更多的你想吧,如:启动的时候如何完美的获取EngineHandle。
6.驱动卸载和关机时是没有反应的,可以注册电源事件的监控看看。
7.在系统启动时,从加载驱动到FwpmBfeStateSubscribeChanges的回调函数被调用,这一段时间是很长的:前者很早,后者已经有启动画面了。

WDK说明:
A callout driver calls the FwpmBfeStateSubscribeChanges0 function to register a callback function that is called whenever there is a change to the state of the filter engine.
A callout driver cannot open a session to the filter engine unless the filter engine is currently running.
A callout driver can use the FWPM_SERVICE_RUNNING notification to open a session to the filter engine so that it can make calls to the other Windows Filtering Platform management functions.
Similarly, a callout driver can use the FWPM_SERVICE_STOP_PENDING notification to perform any cleanup before the filter engine is stopped.

A callout driver can retrieve the current state of the filter engine at any time by calling the FwpmBfeStateGet0 function.

A callout driver must deregister the callback function by calling the FwpmBfeStateUnsubscribeChanges0 function before the callout driver can be unloaded.

made by correy
made at 2016.08.23
http://correy.webs.com
*/

#pragma once

#include <ntifs.h>
#include <Fwpsk.h>
#include <windef.h>
#include <initguid.h> //静态定义UUID用的,否则:error LNK2001。
#include <Fwpmk.h>
#include <Ntstrsafe.h>
#include <ndis.h>
#include <Wsk.h>
#include <ipmib.h>
#include <netpnp.h>
#include <ntintsafe.h>

#pragma warning(disable:4047)
#pragma warning(disable:4028)

#define TAG 'test' //test

PDEVICE_OBJECT gDeviceObject;

HANDLE gEngineHandle;
HANDLE gChangeHandle;


VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
    NTSTATUS status;
    UNICODE_STRING uniWin32NameString;
 
    FwpmBfeStateUnsubscribeChanges0(gChangeHandle);

    if (gEngineHandle)
    {
        FwpmEngineClose0(gEngineHandle);
    }

    RtlInitUnicodeString( &uniWin32NameString, L"\\DosDevices\\hpm" );
    IoDeleteSymbolicLink( &uniWin32NameString );

    IoDeleteDevice(gDeviceObject);// Delete the device object
}


VOID NTAPI SubscriptionBFEStateChangeCallback(IN OUT void  *context, IN FWPM_SERVICE_STATE  newState)
//VOID SubscriptionBFEStateChangeCallback(_Inout_ VOID* pContext, _In_ FWPM_SERVICE_STATE bfeState)
/**
   Purpose:  Callback, invoked on BFE service state change, which will get or release a handle to the engine.
   MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF550062.aspx
   测试心得:
   1.操作系统启动的时候先来FWPM_SERVICE_START_PENDING,后来FWPM_SERVICE_RUNNING。
   2.正常的启动是不会走这里的。
*/
{
    NTSTATUS status;
    FWPM_SESSION0 session = {0};

    switch(newState)
    {
    case FWPM_SERVICE_RUNNING:
        //调用FwpmEngineOpen获取EngineHandle。
        KdPrint(("FWPM_SERVICE_RUNNING.\n",__LINE__));

        session.flags = FWPM_SESSION_FLAG_DYNAMIC;
        status = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &gEngineHandle);
        ASSERT(NT_SUCCESS(status));

        break;
    case FWPM_SERVICE_STOP_PENDING://要走这里,还得做一些小动作。
        //调用FwpmEngineClose释放EngineHandle。
        KdPrint(("FWPM_SERVICE_RUNNING.\n",__LINE__));
        break;
    case FWPM_SERVICE_STOPPED:
        KdPrint(("FWPM_SERVICE_STOPPED.\n",__LINE__));//系统启动的时候会是这个。
        break;
    case FWPM_SERVICE_START_PENDING :
        KdPrint(("FWPM_SERVICE_START_PENDING.\n",__LINE__));//操作系统启动的时候会有这个。
        break;
    }
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    UNICODE_STRING  ntUnicodeString;
    UNICODE_STRING  ntWin32NameString;

    KdBreakPoint();

    DriverObject->DriverUnload = Unload;

    RtlInitUnicodeString( &ntUnicodeString, L"\\Device\\hpm");
    NtStatus = IoCreateDevice(DriverObject, 0, &ntUnicodeString, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &gDeviceObject);
    if (!NT_SUCCESS(NtStatus))
    {
        return NtStatus;
    }

    RtlInitUnicodeString( &ntWin32NameString, L"\\DosDevices\\hpm" );
    NtStatus = IoCreateSymbolicLink(&ntWin32NameString, &ntUnicodeString );
    if (!NT_SUCCESS(NtStatus))
    {
        IoDeleteDevice( gDeviceObject );
        return NtStatus;
    }

    SubscriptionBFEStateChangeCallback(NULL, FwpmBfeStateGet0());//这个可判断驱动是否在系统的启动状态。

    NtStatus = FwpmBfeStateSubscribeChanges0(gDeviceObject, SubscriptionBFEStateChangeCallback, NULL, &gChangeHandle);
    if (!NT_SUCCESS(NtStatus))
    {
        IoDeleteSymbolicLink( &ntWin32NameString );
        IoDeleteDevice(gDeviceObject);
        return NtStatus;
    }

    return NtStatus;
}

没有评论:

发表评论