cwinapiwfpwindows-driver

devcon status returns 39 after installing wfp kernel driver


I am trying to write a simple windows filtering platform kernel driver to add some filters. I used the VS2019 Kernel Driver project template and added code to create the driver and device. This works fine and I was able to see the WPP logs and the devcon status returns success. But as soon as I add any WFP code to the driver, devcon says the install was successful, but the devcon status command returns 39. I searched in google, but was not really able to come up with a solution. WPP tracing also does not seem to work after adding WFP code.

The only line of code related to WFP is the CloseEngine call in the driver unload. If I remove that line, the driver installs successfully and I don't see any errors in the devcon status command.

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 File =>

;
; 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"

Not sure what I am missing. Any help would be appreciated.


Solution

  • There were 2 problems in my code.

    1 - For a callout driver, the driver class in the inf file has to be WFPCALLOUTS and the Class GUID in the inf file has to be {57465043-616C-6C6F-7574-5F636C617373}. In addition that are a few sections of the INF file that are not applicable for callout drivers. Referred microsoft inspect callout driver code.

    2 - Linking user mode libraries in the callout driver does not work. I was trying to use some methods in Fwpuclnt.lib which is a user mode library.