How to load kmdf driver (wfp/inspect) on system boot.

Krzysztof wrote:

I wrote simple kmdf driver (wfp/inspect). This driver is located in:
%WinDir%\System32\Drivers\Inspect.sys
I can load this driver using: net start inspect.

Which means you already had to create a Services registry key for it. 
Forgive the obvious question, but did you actually run this INF file? 
Have you checked the registry key to make sure the StartType actually
got changed?

Peter_Viscarola wrote:

> @Tim_Roberts said:
>
> (empty message)
Tim? Do you realize that you posted an empty message?

It wasn’t empty when I sent it.  Hmm.  I have “digital signing” enabled
by default.  The old OSR mailing lists rejected anything with an
attachment.  I thought this one was just ignoring it, but maybe it’s not.

Hello,

Yes I have run this INF file. I can see there is a valid entry in Regedit:

I tried to change value of StartType of 0 and 1 but there is no changes. Inspect.sys isn’t load while sysytem boots.

At this point I’m wondering. I have a driver file in System32\drivers\Inspect.sys. I can load this driver using “net start inspect”.
I have also (above) entry in Regedit. There should be no problem with loading this driver on boot, however there is.
Can you please point out where problem might exist?

Krzysiek

I have also found (in ntbtlog) this entry:
BOOTLOG_LOADED \SystemRoot\system32\DRIVERS\Inspect.sys

however it didn’t indicate, that driver was loaded. In fact I can see, that it is not.

Krzysiek

There should be no problem with loading this driver on boot, however there is.
Can you please point out where problem might exist

Hmmmmmmm… Do you know if DriverEntry is called?

Ignoring the INF file, the only thing I see that’s questionable is the BootFlags entry. Why do you have this set to 0x01? Would that not indicate that this driver should be loaded at boot only when the system is booted from the network??

Aside from that… Could the probelm be that you’re missing the leading slash in your ImagePath. it should be \SystemRoot\System32\drivers.…

Peter

Hi,

Yes, DriverEntry is called:

Also I have remove BootFlag and fix path:

but still Windows doesn’t load driver on boot.

Krzysiek

Krzysztof wrote:

Hello,

Yes I have run this INF file. I can see there is a valid entry in Regedit:

I tried to change value of StartType of 0 and 1 but there is no changes. Inspect.sys isn’t load while sysytem boots.

At this point I’m wondering. I have a driver file in System32\drivers\Inspect.sys. I can load this driver using “net start inspect”.

I have also (above) entry in Regedit. There should be no problem with loading this driver on boot, however there is.

I assume you realize that “net start” actually uses the Services entry
in the registry to find the driver.  “net load inspect” loads the
service called inspect.  It doesn’t simply load “inspect.sys” by
filename.  What I’m trying to say is that the registry already had to be
set up.

Can you please point out where problem might exist?

Have you checked the logs?  Have you attached a debugger to see if
you’re getting loaded and unloaded?  I know the rules for boot start
drivers have changed over the years.  I think they actually demote some
boot start drivers if it looks like you’re not doing anything. There may
be web articles about that.

If driverentry was called then your driver was loaded and then perhaps
failed at driverentry. Use a debugger to find out what happened.

Mark Roddy

Hi,

At this point I manage to run debugger. Here’s results:


Microsoft (R) Windows Debugger Version 10.0.17134.1 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.


Waiting for pipe \.\pipe\vpcdebug
Waiting to reconnect…
Connected to Windows 10 17134 x64 target at (Wed Sep 26 14:55:37.674 2018 (UTC + 2:00)), ptr64 TRUE
Kernel Debugger connection established.
Symbol search path is: srv*
Executable search path is:
Windows 10 Kernel Version 17134 MP (1 procs) Free x64
Built by: 17134.1.amd64fre.rs4_release.180410-1804
Machine Name:
Kernel base = 0xfffff8026d805000 PsLoadedModuleList = 0xfffff8026dbbf1f0
System Uptime: 0 days 0:00:00.000
nt!DebugService2+0x5:
fffff8026d9a4fe5 cc int 3<br> kd> bu Inspect!DriverEntry<br> kd> ed nt!Kd_DEFAULT_Mask 0x8<br> kd> g<br> minio\security\base\lsa\security\driver\asyncsspi.cxx - SspiInitAsyncInterface IOINIT: Built-in driver \Driver\hwpolicy failed to initialize with status - 0xC000025E KDTARGET: Refreshing KD connection Breakpoint 0 hit Inspect!DriverEntry: fffff807e22c54c0 4889542410 mov qword ptr [rsp+10h],rdx
0: kd> t
Inspect!DriverEntry+0x1a:
fffff807e22c54da 48c744244000000000 mov qword ptr [rsp+40h],0 0: kd> t Inspect!DriverEntry+0x23: fffff807e22c54e3 488d0dc6910000 lea rcx,[Inspect! ?? ::FNODOBFM::string' (fffff807e22ce6b0)]
0: kd> t
nt!DbgPrint:
fffff8026d900730 4c8bdc mov r11,rsp 0: kd> t nt!DbgPrint+0x3: fffff8026d900733 49894b08 mov qword ptr [r11+8],rcx
0: kd> t
nt!DbgPrint+0x7:
fffff8026d900737 49895310 mov qword ptr [r11+10h],rdx 0: kd> t nt!DbgPrint+0xb: fffff8026d90073b 4d894318 mov qword ptr [r11+18h],r8
0: kd> t
nt!DbgPrint+0xf:
fffff8026d90073f 4d894b20 mov qword ptr [r11+20h],r9 0: kd> t nt!DbgPrint+0x13: fffff8026d900743 4883ec38 sub rsp,38h
0: kd> t
nt!DbgPrint+0x17:
fffff8026d900747 ba65000000 mov edx,65h 0: kd> t nt!DbgPrint+0x1c: fffff8026d90074c c644242801 mov byte ptr [rsp+28h],1
0: kd> t
nt!DbgPrint+0x21:
fffff8026d900751 498d4310 lea rax,[r11+10h] 0: kd> t nt!DbgPrint+0x25: fffff8026d900755 4c8bc9 mov r9,rcx
0: kd> t
nt!DbgPrint+0x28:
fffff8026d900758 488d0d01ea0a00 lea rcx,[nt! ?? ::FNODOBFM::string’ (fffff802`6d9af160)]
0: kd> g
[Inspect] DriverEntry start
[Inspect] AddToBuffer: allocated bufferHelper.tab_buffer (192000 bytes) !
[Inspect] WdfDeviceCreate 4.
[Inspect] MonitorCtlDriverInit.
[Inspect] WdfIoQueueCreate.
[Inspect] TLInspectRegisterCallouts
[Inspect] DriverEntry error. Driver cannot be started!
[Inspect] DriverEntry Exit.


Below is my DriverEntry code:


Function_class(DRIVER_INITIALIZE)
IRQL_requires_same
NTSTATUS
DriverEntry(
In DRIVER_OBJECT* driverObject,
In UNICODE_STRING* registryPath
)
{
NTSTATUS status;
WDF_DRIVER_CONFIG config;
PWDFDEVICE_INIT pInit = NULL;

DbgPrint("[Inspect] DriverEntry start\n");

InitList();

InitializeListHead(&gFlowList);
KeInitializeSpinLock(&gFlowListLock);

// Request NX Non-Paged Pool when available
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);

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

status = WdfDriverCreate(
	driverObject,
	registryPath,
	WDF_NO_OBJECT_ATTRIBUTES,
	&config,
	&driver
);

if (!NT_SUCCESS(status))
{
	goto Exit;
}

pInit = WdfControlDeviceInitAllocate(driver, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL);

if (!pInit)
{
	DbgPrint("[Inspect] WdfControlDeviceInitAllocate FAILED!\n");

	status = STATUS_INSUFFICIENT_RESOURCES;
	goto Exit;
}

status = MonitorEvtDeviceAdd(pInit);

status = FwpsInjectionHandleCreate(
	AF_UNSPEC,
	FWPS_INJECTION_TYPE_TRANSPORT,
	&gInjectionHandle
);

if (!NT_SUCCESS(status))
{
	goto Exit;
}

KeInitializeSpinLock(&gConnListLock);

KeInitializeEvent(
	&gWorkerEvent,
	NotificationEvent,
	FALSE
);

gWdmDevice = WdfDeviceWdmGetDeviceObject(device);

status = TLInspectRegisterCallouts(gWdmDevice);

if (!NT_SUCCESS(status))
{
	goto Exit;
}

NT_ASSERT(NT_SUCCESS(status));

Exit:
if (!NT_SUCCESS(status))
{
DbgPrint(“[Inspect] DriverEntry error. Driver cannot be started!\n”);

	if (gEngineHandle != NULL)
	{
		TLInspectUnregisterCallouts();
	}
	if (gInjectionHandle != NULL)
	{
		FwpsInjectionHandleDestroy(gInjectionHandle);
	}
}

DbgPrint("[Inspect] DriverEntry Exit.\n");

return status;

};

My first question is: why I can load this driver by myself (net start inspect) and it can’t be done while system boot?
Ofcourse, now I can see why, but I don’t understand.

I assume, there is a problem with WdfDriverCreate() function. It should return STATUS_SUCCESS but it doesn’t.
Can I use:

DbgPrint(“[Inspect] WdfDriverCreate status returns: %s”, status);

to check what this function returns?

Maybe someone sees an obvious mistake?
Please help me with track down this issue.

Krzysiek

Krzysztof wrote:

At this point I manage to run debugger. Here’s results:

My first question is: why I can load this driver by myself (net start inspect) and it can’t be done while system boot?
Ofcourse, now I can see why, but I don’t understand.
I assume, there is a problem with WdfDriverCreate() function. It should return STATUS_SUCCESS but it doesn’t.

Why do you assume that?  The trace shows that you got past
WdfDriverCreate and called WdfIoQueueCreate (which is not here) and
TLInspectRegisterCallouts.

The source code doesn’t match your trace, so it’s a little hard to be
sure.  The implication is that TLInspectRegisterCallouts failed. In the
code as you presented it, that would be a natural result, because
“device” is undefined.  Where is “device” created?

Hello,

You are right. While using debugger I noticed that a problem exist here:

    gWdmDevice = WdfDeviceWdmGetDeviceObject(device);

status = TLInspectRegisterCallouts(gWdmDevice);

if (!NT_SUCCESS(status))
{
	goto Exit; <-- debugger enters here
}

Answering to your question, I have:
WDFDEVICE device;
And here is TLInspectRegisterCallouts:
NTSTATUS TLInspectRegisterCallouts( _Inout_ void* deviceObject ) { NTSTATUS status = STATUS_SUCCESS; FWPM_SUBLAYER TLInspectSubLayer;
BOOLEAN engineOpened = FALSE;
BOOLEAN inTransaction = FALSE;

DbgPrint("[Inspect] TLInspectRegisterCallouts\n");

FWPM_SESSION session = { 0 };

session.flags = FWPM_SESSION_FLAG_DYNAMIC;

status = FwpmEngineOpen(
	NULL,
	RPC_C_AUTHN_WINNT,
	NULL,
	&session,
	&gEngineHandle
);
if (!NT_SUCCESS(status))
{
	goto Exit;
}
engineOpened = TRUE;

status = FwpmTransactionBegin(gEngineHandle, 0);
if (!NT_SUCCESS(status))
{
	goto Exit;
}
inTransaction = TRUE;

RtlZeroMemory(&TLInspectSubLayer, sizeof(FWPM_SUBLAYER));

TLInspectSubLayer.subLayerKey = TL_INSPECT_SUBLAYER;
TLInspectSubLayer.displayData.name = L"Transport Inspect Sub-Layer";
TLInspectSubLayer.displayData.description =
	L"Sub-Layer for use by Transport Inspect callouts";
TLInspectSubLayer.flags = 0;
TLInspectSubLayer.weight = 0; // must be less than the weight of 
							  // FWPM_SUBLAYER_UNIVERSAL to be
							  // compatible with Vista's IpSec
							  // implementation.

status = FwpmSubLayerAdd(gEngineHandle, &TLInspectSubLayer, NULL);
if (!NT_SUCCESS(status))
{
	goto Exit;
}

if (!AddAleClassifyCallouts(
	&FWPM_LAYER_INBOUND_MAC_FRAME_NATIVE, 
	&TL_INSPECT_INBOUND_MAC_FRAME_NATIVE,
	deviceObject,
	&calloutInboundMacFrameNative,
           NULL
))
{
	goto Exit;
}
if (!AddAleClassifyCallouts(
	&FWPM_LAYER_OUTBOUND_MAC_FRAME_NATIVE, 
	&TL_INSPECT_OUTBOUND_MAC_FRAME_NATIVE,
	deviceObject,
	&calloutOutboundMacFrameNative,
	NULL
))
{
	goto Exit;
}

status = FwpmTransactionCommit(gEngineHandle);
if (!NT_SUCCESS(status))
{
	goto Exit;
}
inTransaction = FALSE;

Exit:
if (!NT_SUCCESS(status))
{
if (inTransaction)
{
FwpmTransactionAbort(gEngineHandle);
Analysis_assume_lock_not_held(gEngineHandle);
}
if (engineOpened)
{
FwpmEngineClose(gEngineHandle);
gEngineHandle = NULL;
}
}

return status;

}

Can you help me with track this issue?

Krzysiek

Use the debugger and debug prints to “track this issue”. Asking this board to do that by code inspection is sort of silly. If you get to the cause of the failure in driver entry and you don’t understand why that is happening, then you have a question that you can ask here and get a reasonable answer.

Hi,

First of all I’m sorry for my obvious questions. This is my first kernel-mode driver and I’m trying to
understand why and how these things works. Again, sorry if I’m bothering with simple tasks (for me they are not simple).


I have put DbgPrint inside TLInspectRegisterCallouts function in place where I’m testing !NT_SUCCESS(status), like this:


status = FwpmEngineOpen(
NULL,
RPC_C_AUTHN_WINNT,
NULL,
&session,
&gEngineHandle
);
if (!NT_SUCCESS(status))
{
DbgPrint(“[Inspect] FwpmEngineOpen Failed\n”);
goto Exit;
}


I have put DbgPrint in each if (!NT_SUCCESS(status)). Of course with coresponding function name inside DbgPrint.


So far I can see (in debugger):


[Inspect] DriverEntry start
[Inspect] AddToBuffer: allocated bufferHelper.tab_buffer (192000 bytes) !
[Inspect] WdfDriverCreate status returns: (null)[Inspect] WdfDeviceCreate 4.
[Inspect] MonitorCtlDriverInit.
[Inspect] WdfIoQueueCreate.
Breakpoint 0 hit
Inspect!TLInspectRegisterCallouts:
fffff80e`460d69f0 48894c2408 mov qword ptr [rsp+8],rcx
0: kd> g
[Inspect] TLInspectRegisterCallouts
[Inspect] FwpmEngineOpen Failed
[Inspect] DriverEntry error. Driver cannot be started
[Inspect] DriverEntry Exit.


At this point, I can see there is a problem in FwpmEngineOpen(). So in TLInspectRegisterCallouts I’m jumping to
the:


status = FwpmEngineOpen(
NULL,
RPC_C_AUTHN_WINNT,
NULL,
&session,
&gEngineHandle
);


Since status !=NT_SUCCESS so I’m jumping to DriverEntry:

gWdmDevice = WdfDeviceWdmGetDeviceObject(device);
status = TLInspectRegisterCallouts(gWdmDevice);


and this leads me to:


Exit:
if (!NT_SUCCESS(status))
{
DbgPrint(“[Inspect] DriverEntry error. Driver cannot be started!\n”);

	if (gEngineHandle != NULL)
	{
		TLInspectUnregisterCallouts();
	}
	if (gInjectionHandle != NULL)
	{
		FwpsInjectionHandleDestroy(gInjectionHandle);
	}
}

DbgPrint("[Inspect] DriverEntry Exit.\n");

return status;

};


Below is debugger output:


[Inspect] DriverEntry start
[Inspect] AddToBuffer: allocated bufferHelper.tab_buffer (192000 bytes) !
[Inspect] WdfDriverCreate status returns: (null)[Inspect] WdfDeviceCreate 4.
[Inspect] MonitorCtlDriverInit.
[Inspect] WdfIoQueueCreate.
Breakpoint 0 hit
Inspect!TLInspectRegisterCallouts:
fffff8076d6569f0 48894c2408 mov qword ptr [rsp+8],rcx 0: kd> t Inspect!TLInspectRegisterCallouts+0x2c: fffff8076d656a1c c744243400000000 mov dword ptr [rsp+34h],0
0: kd> t
Inspect!TLInspectRegisterCallouts+0x34:
fffff8076d656a24 c644243100 mov byte ptr [rsp+31h],0 0: kd> t Inspect!TLInspectRegisterCallouts+0x39: fffff8076d656a29 c644243000 mov byte ptr [rsp+30h],0
0: kd> t
Inspect!TLInspectRegisterCallouts+0x3e:
fffff8076d656a2e 488d0dab7c0000 lea rcx,[Inspect! ?? ::FNODOBFM::string’ (fffff8076d65e6e0)] 0: kd> p [Inspect] TLInspectRegisterCallouts Inspect!TLInspectRegisterCallouts+0x4a: fffff8076d656a3a 488d842490000000 lea rax,[rsp+90h]
0: kd> p
Inspect!TLInspectRegisterCallouts+0x5e:
fffff8076d656a4e c78424b000000001000000 mov dword ptr [rsp+0B0h],1 0: kd> p Inspect!TLInspectRegisterCallouts+0x69: fffff8076d656a59 488d05d8380100 lea rax,[Inspect!gEngineHandle (fffff8076d66a338)] 0: kd> p Inspect!TLInspectRegisterCallouts+0x90: fffff8076d656a80 837c243400 cmp dword ptr [rsp+34h],0
0: kd> p
Inspect!TLInspectRegisterCallouts+0x97:
fffff8076d656a87 488d0d827c0000 lea rcx,[Inspect! ?? ::FNODOBFM::string’ (fffff8076d65e710)] 0: kd> p [Inspect] FwpmEngineOpen Failed Inspect!TLInspectRegisterCallouts+0xa3: fffff8076d656a93 e9f0040000 jmp Inspect!TLInspectRegisterCallouts+0x598 (fffff8076d656f88) 0: kd> p Inspect!TLInspectRegisterCallouts+0x598: fffff8076d656f88 837c243400 cmp dword ptr [rsp+34h],0
0: kd> p
Inspect!TLInspectRegisterCallouts+0x59f:
fffff8076d656f8f 0fb6442430 movzx eax,byte ptr [rsp+30h] 0: kd> p Inspect!TLInspectRegisterCallouts+0x5b4: fffff8076d656fa4 0fb6442431 movzx eax,byte ptr [rsp+31h]
0: kd> p
Inspect!TLInspectRegisterCallouts+0x5d4:
fffff8076d656fc4 8b442434 mov eax,dword ptr [rsp+34h] 0: kd> p Inspect!TLInspectRegisterCallouts+0x5d8: fffff8076d656fc8 488b8c24e0000000 mov rcx,qword ptr [rsp+0E0h]
0: kd> p
Inspect!DriverEntry+0x168:
fffff8076d655628 89442430 mov dword ptr [rsp+30h],eax 0: kd> p Inspect!DriverEntry+0x16c: fffff8076d65562c 837c243000 cmp dword ptr [rsp+30h],0
0: kd> p
Inspect!DriverEntry+0x173:
fffff8076d655633 eb34 jmp Inspect!DriverEntry+0x1a9 (fffff8076d655669)
0: kd> p
Inspect!DriverEntry+0x1a9:
fffff8076d655669 837c243000 cmp dword ptr [rsp+30h],0 0: kd> p Inspect!DriverEntry+0x1b0: fffff8076d655670 488d0d49950000 lea rcx,[Inspect! ?? ::FNODOBFM::string' (fffff8076d65ebc0)]
0: kd> p
[Inspect] DriverEntry error. Driver cannot be started!
Inspect!DriverEntry+0x1bc:
fffff8076d65567c 48833db44c010000 cmp qword ptr [Inspect!gEngineHandle (fffff8076d66a338)],0
0: kd> p
Inspect!DriverEntry+0x1cb:
fffff8076d65568b 48833d9d4c010000 cmp qword ptr [Inspect!gInjectionHandle (fffff8076d66a330)],0
0: kd> p
Inspect!DriverEntry+0x1d5:
fffff8076d655695 488b0d944c0100 mov rcx,qword ptr [Inspect!gInjectionHandle (fffff8076d66a330)]
0: kd> p
Inspect!DriverEntry+0x1e1:
fffff8076d6556a1 488d0d58950000 lea rcx,[Inspect! ?? ::FNODOBFM::string’ (fffff8076d65ec00)] 0: kd> p [Inspect] DriverEntry Exit. Inspect!DriverEntry+0x1ed: fffff8076d6556ad 8b442430 mov eax,dword ptr [rsp+30h]
0: kd> p
Inspect!DriverEntry+0x1f1:
fffff807`6d6556b1 4883c478 add rsp,78h

Maybe I have a problem with gEngineHandle? In my code I have defined it as:

HANDLE gEngineHandle;

Krzysiek

What’s the status that FwpmEngineOpen is failing with?

Just walk through the code in the debugger… look at the returned status value. Or, DbgPrint the returned status.

A quick search (GIYF) returned this link, to a question on FwpmEngineOpen failing here in NTDEV long ago. Mayhaps this is your issue?

Peter

Krzysztof wrote:

First of all I’m sorry for my obvious questions. This is my first kernel-mode driver and I’m trying to
understand why and how these things works. Again, sorry if I’m bothering with simple tasks (for me they are not simple).

I have put DbgPrint inside TLInspectRegisterCallouts function in place where I’m testing !NT_SUCCESS(status), like this:

status = FwpmEngineOpen(
NULL,
RPC_C_AUTHN_WINNT,
NULL,
&session,
&gEngineHandle
);
if (!NT_SUCCESS(status))
{
DbgPrint(“[Inspect] FwpmEngineOpen Failed\n”);
goto Exit;
}

That doesn’t tell you anything.  You need to get in the habit of
printing the error code.  At this point, you never print the error code
any where in your driver, so you have no clue why the API is failing.

    DbgPrint(“[Inspect] FwpmEngineOpen failed, %08x\n”, status );

I have put DbgPrint in each if (!NT_SUCCESS(status)). Of course with coresponding function name inside DbgPrint.

But not the status code.  Your “Check Engine” light is on, but you’re
trying to fix it without ever checking the engine status codes.

0: kd> p
Inspect!TLInspectRegisterCallouts+0x5d4:
fffff8076d656fc4 8b442434 mov eax,dword ptr [rsp+34h]
0: kd> p
Inspect!TLInspectRegisterCallouts+0x5d8:
fffff8076d656fc8 488b8c24e0000000 mov rcx,qword ptr [rsp+0E0h]
0: kd> p
Inspect!DriverEntry+0x168:
fffff8076d655628 89442430 mov dword ptr [rsp+30h],eax
0: kd> p
Inspect!DriverEntry+0x16c:
fffff8076d65562c 837c243000 cmp dword ptr [rsp+30h],0

Even here, where you return to DriverEntry, if you had taken the simple
step of looking at the value of rax, you would have seen the status code.

Are you building the “Debug” build?  That skipped over an awful lot of
lines.

Maybe I have a problem with gEngineHandle?

Guessing at random is NOT a successful engineering strategy.  Until you
know what is failing and WHY it is failing, you’re not debugging. 
You’re just poking it with a stick.

I haven’t been really following this thread but I am sure that FwpmEngineOpen requires the BFE service to be running. I “solved” this by using an install app to set the filters up.

Bill Wandel

Hi,

Thanks for answers. I can see, that FwpmEngineOpen returns:

[Inspect] FwpmEngineOpen returns (hex): c0020035

so it’s EPT_NT_CANT_PERFORM_OP, The operation cannot be performed.

I have read linked thread https://community.osr.com/discussion/269426
and also this thread https://social.msdn.microsoft.com/Forums/en-US/5eff55e6-cb28-4726-ba16-2e245bb55d03/fwpmengineopen-returns-eptntcantperformop-when-wfp-callout-driver-is-started-with

Can you please share some examples on how to use FwpmBfeStateSubscribeChanges or shed some light on how I can
do this?

@Bill_Wandel, Can you write more about your solution?

Krzysiek

Can you please share some examples on how to use FwpmBfeStateSubscribeChanges

C’mon dude… You have Google, right?

The first result when you Google the name of the function is the WDK docs for the function. The second is the H file where the function is declared. And the third result is an example from the WDK showing how to use this function.

We all wanna help. We do. But PLEASE… do your homework. Or, you know, hire somebody to write your driver.

Peter

If you use an installer you can specify filters that take affect when the driver first loads and filters that take affect when BFE is started. Check the documentation for FwpmFilterAdd. Your installer sets up the filters and callouts. Your driver connects to these callouts.
If you have an installer program you will need an uninstall program.

Bill Wandel

While boot state , the kernel filter engine may be not initialized yet. So, what should you is registering a callback with FwpmBfeStateSubscribeChanges in which you can open filter engine . You can find this in WDK WFPSample.