安装 wfp 内核驱动程序后 devcon status returns 39

devcon status returns 39 after installing wfp kernel driver

我正在尝试编写一个简单的 windows 过滤平台内核驱动程序来添加一些过滤器。我使用了 VS2019 内核驱动程序项目模板并添加了代码来创建驱动程序和设备。这工作正常,我能够看到 WPP 日志和 devcon 状态 returns 成功。但是只要我向驱动程序添加任何 WFP 代码,devcon 就会说安装成功,但是 devcon 状态命令 returns 39。我在 google 中搜索,但并没有真正能够想出一个解法。添加 WFP 代码后 WPP 跟踪似乎也不起作用。

与WFP相关的唯一一行代码是驱动程序卸载中的CloseEngine调用。如果我删除该行,驱动程序安装成功并且我在 devcon status 命令中看不到任何错误。

Driver.c =>

/*++

Module Name:

    driver.c

Abstract:

    This file contains the driver entry points and callbacks.

Environment:

    Kernel-mode Driver Framework

--*/

#include "driver.h"
#include "driver.tmh"
#include <fwpmk.h>

PDEVICE_OBJECT gDeviceObject;
HANDLE gEngineHandle;

VOID
MyCalloutUnload(
    IN WDFDRIVER DriverObject
)
{
    // TODO : Memory cleanups
    // - Unregister callouts?
    // - Free any allocated memory
    UNREFERENCED_PARAMETER(DriverObject);
    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    if (gEngineHandle != NULL)
    {
        FwpmEngineClose(gEngineHandle); // If I comment this line, there are no problems with the driver
        gEngineHandle = NULL;
    }
    
}

//NTSTATUS
//FilterByApplication()
//{
//    NTSTATUS status = STATUS_SUCCESS;
//    FWPM_SESSION session = { 0 };
//
//    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");
//
//    do
//    {
//        session.flags = FWPM_SESSION_FLAG_DYNAMIC;
//        status = FwpmEngineOpen(
//            L"MyCalloutDriver",
//            RPC_C_AUTHN_WINNT,
//            NULL,
//            &session,
//            &gEngineHandle
//        );
//
//        if (!NT_SUCCESS(status))
//        {
//            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "FwpmEngineOpen failed %!STATUS!", status);
//            break;
//        }
//
//    } while (FALSE);
//
//    return status;
//}

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDFDRIVER driver;
    WDFDEVICE device;
    PWDFDEVICE_INIT pInit = NULL;

    //
    // Initialize WPP Tracing
    //
    WPP_INIT_TRACING(DriverObject, RegistryPath);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Register a cleanup callback so that we can call WPP_CLEANUP when
    // the framework driver object is deleted during driver unload.
    //
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.EvtCleanupCallback = MyCalloutDriver1EvtDriverContextCleanup;

    WDF_DRIVER_CONFIG_INIT(&config, WDF_NO_EVENT_CALLBACK);
    config.DriverInitFlags |= WdfDriverInitNonPnpDriver;
    config.EvtDriverUnload = MyCalloutUnload;

    do
    {
        status = WdfDriverCreate(DriverObject,
            RegistryPath,
            &attributes,
            &config,
            &driver
        );

        if (!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDriverCreate failed %!STATUS!", status);
            break;
        }

        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Driver created successfully!");

        pInit = WdfControlDeviceInitAllocate(driver, &SDDL_DEVOBJ_KERNEL_ONLY);

        if (!pInit)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfControlDeviceInitAllocate failed %!STATUS!", status);
            break;
        }

        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Control Device Initialized Successfully!");

        WdfDeviceInitSetDeviceType(pInit, FILE_DEVICE_NETWORK); // Set the device type as a network device

        // If a device object's FILE_DEVICE_SECURE_OPEN characteristic is set, 
        // the system applies the device object's security descriptor to 
        // all file open requests in the device's namespace. 
        WdfDeviceInitSetCharacteristics(pInit, FILE_DEVICE_SECURE_OPEN, FALSE);

        // The FILE_AUTOGENERATED_DEVICE_NAME is only used for PDOs. What does this do??
        WdfDeviceInitSetCharacteristics(pInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE);

        status = WdfDeviceCreate(&pInit, WDF_NO_OBJECT_ATTRIBUTES, &device);
        if (!NT_SUCCESS(status))
        {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "WdfDeviceCreate failed %!STATUS!", status);
            break;
        }

        TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "Device created successfully!");

        // The system will not send I/O requests or Windows Management Instrumentation (WMI) 
        // requests to a control device object unless the driver has called WdfControlFinishInitializing.
        WdfControlFinishInitializing(device);

        // Get the Device Object
        gDeviceObject = WdfDeviceWdmGetDeviceObject(device);

    } while (FALSE);
    

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Exit");
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_DRIVER, "Failed %!STATUS!", status);
        WPP_CLEANUP(DriverObject);
    }
    return status;
}

VOID
MyCalloutDriver1EvtDriverContextCleanup(
    _In_ WDFOBJECT DriverObject
    )
/*++
Routine Description:

    Free all the resources allocated in DriverEntry.

Arguments:

    DriverObject - handle to a WDF Driver object.

Return Value:

    VOID.

--*/
{
    UNREFERENCED_PARAMETER(DriverObject);

    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "%!FUNC! Entry");

    //
    // Stop WPP Tracing
    //
    WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
}

INF 文件 =>

;
; MyCalloutDriver1.inf
;

[Version]
Signature="$WINDOWS NT$"
Class=System ; TODO: specify appropriate Class
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid
Provider=%ManufacturerName%
CatalogFile=MyCalloutDriver1.cat
DriverVer= ; TODO: set DriverVer in stampinf property pages
PnpLockdown=1

[DestinationDirs]
DefaultDestDir = 12
MyCalloutDriver1_Device_CoInstaller_CopyFiles = 11

[SourceDisksNames]
1 = %DiskName%,,,""

[SourceDisksFiles]
MyCalloutDriver1.sys  = 1,,
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames

;*****************************************
; Install Section
;*****************************************

[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$

[Standard.NT$ARCH$]
%MyCalloutDriver1.DeviceDesc%=MyCalloutDriver1_Device, Root\MyCalloutDriver1 ; TODO: edit hw-id

[MyCalloutDriver1_Device.NT]
CopyFiles=Drivers_Dir

[Drivers_Dir]
MyCalloutDriver1.sys

;-------------- Service installation
[MyCalloutDriver1_Device.NT.Services]
AddService = MyCalloutDriver1,%SPSVCINST_ASSOCSERVICE%, MyCalloutDriver1_Service_Inst

; -------------- MyCalloutDriver1 driver install sections
[MyCalloutDriver1_Service_Inst]
DisplayName    = %MyCalloutDriver1.SVCDESC%
ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
StartType      = 3               ; SERVICE_DEMAND_START
ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
ServiceBinary  = %12%\MyCalloutDriver1.sys

;
;--- MyCalloutDriver1_Device Coinstaller installation ------
;

[MyCalloutDriver1_Device.NT.CoInstallers]
AddReg=MyCalloutDriver1_Device_CoInstaller_AddReg
CopyFiles=MyCalloutDriver1_Device_CoInstaller_CopyFiles

[MyCalloutDriver1_Device_CoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"

[MyCalloutDriver1_Device_CoInstaller_CopyFiles]
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll

[MyCalloutDriver1_Device.NT.Wdf]
KmdfService =  MyCalloutDriver1, MyCalloutDriver1_wdfsect
[MyCalloutDriver1_wdfsect]
KmdfLibraryVersion = $KMDFVERSION$

[Strings]
SPSVCINST_ASSOCSERVICE= 0x00000002
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer name
DiskName = "MyCalloutDriver1 Installation Disk"
MyCalloutDriver1.DeviceDesc = "MyCalloutDriver1 Device"
MyCalloutDriver1.SVCDESC = "MyCalloutDriver1 Service"

不确定我错过了什么。任何帮助将不胜感激。

我的代码中有 2 个问题。

1 - 对于标注驱动程序,inf 文件中的驱动程序 class 必须是 WFPCALLOUTS,inf 文件中的 Class GUID 必须是 {57465043-616C-6C6F-7574 -5F636C617373}。此外,INF 文件的一些部分不适用于标注驱动程序。参考 microsoft inspect callout driver code.

2 - 在标注驱动程序中链接用户模式库不起作用。我试图在 Fwpuclnt.lib 中使用一些方法,这是一个用户模式库。