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.
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.