Hello !
We can allocate extra create parameters from lookaside list.
Let’s consider next scenario:
Fltregisterfilter - now we have valid pflt_filter.
FltInitExtraCreateParameterLookasideList
Fltstartfiltering
At each pre-create allocate ecp from lookaside list and attach to callback data
So far so good.
Now I want to unload my filter.
I need to call FltDeleteExtraCreateParameterLookasideList.
However there can still be create operations in progress with my attached ecp - io manager will try to free them to deleted lookaside list.
I can’t call FltDeleteExtraCreateParameterLookasideList after fltunregisterfilter because we need valid filter to delete lookaside list.
So it’s look like I can use ECPs from lookaside list only in fltcreatefileex2 calls - in that case I know when all creates that use lookaside ECPs finished and I won’t start new creates after I decide to unload.
However here https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/fltkernel/nf-fltkernel-fltallocateextracreateparameterfromlookasidelist it is said “ Drivers must free all ECP context structures and lookaside lists they create before unloading. However, if a file system or file system filter driver attaches an ECP to an existing or newly-created ECP_LIST while processing an IRP_MJ_CREATE request, this ECP is automatically cleaned up when the IRP completes.”
So it seems lookaside ECPs can be attached to callback data.
Am I missing something? Is it possible to somehow drain all creates that have lookaside ECPs attached ?
The rules around ECPs are Byzantine and in particular SRV isn’t very good at cleaning up after itself.
Frankly I think I once understood them (the rules) but I was probably mistaken.
The only guarantee I have found is to remove them yourself in post create.
This becomes problematic if if you are wanting to have an ECP survive reparse - but that just needs special handling.
Thank you Rod !
Good to know about srv.
Guess I just won’t attach lookaside ECPs to callback data.
I have always worked under the assumption that FltMgr keeps my PFLT_FILTER referenced until after my filter unload callback. if it doesn’t then we’re all doomed as it’s pretty much impossible to solve your problem.
For my sanity I just put a breakpoint in an unload routine. Here’s the PFLT_FILTER at the start of unload:
1: kd> !fltkd.fltobj ffff9605e1920010 1
FLT_OBJECT: ffff9605e1920010 [02000000] Filter
RundownRef : 0x0000000000000002 (1)
PointerCount : 0x00000002
PrimaryLink : [ffff9605dfb5d020-ffff9605de4c3020]
And here it is after FltUnregisterFilter:
1: kd> !fltkd.fltobj ffff9605e1920010 1
FLT_OBJECT: ffff9605e1920010 [02000003] Filter DRAINING ZOMBIED
RundownRef : 0x0000000000000001 (0) drained
PointerCount : 0x00000001
PrimaryLink : [ffff9605dfb5d020-ffff9605de4c3020]
And putting a breakpoint on the last pointer count:
1: kd> dt FLTMGR!_FLT_OBJECT ffff9605e1920010
+0x000 Flags : 0x2000003 (No matching name)
+0x004 PointerCount : 1
+0x008 RundownRef : _EX_RUNDOWN_REF
+0x010 PrimaryLink : _LIST_ENTRY [ 0xffff9605`dfb5d020 - 0xffff9605`de4c3020 ]
+0x020 UniqueIdentifier : _GUID {765d6ad3-000a-0000-6117-0700065a72e9}
1: kd> ba w4 ffff9605e1920010+4
1: kd> g
Breakpoint 2 hit
FLTMGR!FltpObjectPointerDereference+0x1f:
fffff802`f403b193 cmp eax,1
1: kd> kc
# Call Site
00 FLTMGR!FltpObjectPointerDereference
01 FLTMGR!FltpDoUnloadFilter
02 FLTMGR!FltpMiniFilterDriverUnload
03 nt!IopLoadUnloadDriver
04 nt!ExpWorkerThread
05 nt!PspSystemThreadStartup
06 nt!KiStartSystemThread
So, you’re safe to still use the PFLT_FILTER pointer after unregister and before you return from unload.
Thank you very much Scott !
I always assumed that pflt_filter should be considered invalid after fltunregisterfilter. Same way as any other object can’t be used after obdereferenceobject. But now I see why this is a special case.
Thank you very much again.