It’s for sure got something to do with the way I manage contexts , struggling to spot it
I call FltAllocateContext in post create and if successful , save it in a custom list using the following function
{
AutoLock<Mutex> locker(ContextsListMutex);
PContextToDelete New = (PContextToDelete)ExAllocatePoolWithTag(NonPagedPool, sizeof(ContextToDelete), TAG);
if (!New)
return false;
New->Context = (DWORD64)context;
New->Next = nullptr;
if (!ContextsToDelete)
{
ContextsToDelete = New;
return true;
}
PContextToDelete current = ContextsToDelete;
while (current->Next != nullptr)
{
current = (PContextToDelete)current->Next;
}
current->Next = (LIST_ENTRY*)New;
return true;
} ```
On unload I call the following
{
AutoLock<Mutex> locker(ContextsListMutex);
if (ContextsToDelete)
{
PContextToDelete current = ContextsToDelete;
PContextToDelete temp = nullptr;
while (current != nullptr)
{
temp = current;
current = (PContextToDelete)current->Next;
ExFreePoolWithTag(temp, TAG);
}
}
} ```
and for every call the increments the reference count (FltGetStreamHandleContext in my case) I construct the following object :
AutoContext AutoHandleContx(HandleContx);
{
public:
AutoContext(PFLT_CONTEXT Context) : m_context_ptr(Context) {};
~AutoContext() { FltReleaseContext(m_context_ptr); };
private:
PFLT_CONTEXT m_context_ptr;
}; ```
ideally initial reference by FltAllocateContext is dereferenced in pre / post close , for example
PreClose(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
)
{
pHandleContext HandleContx = nullptr;
NTSTATUS status = FltGetStreamHandleContext(FltObjects->Instance, FltObjects->FileObject, reinterpret_cast<PFLT_CONTEXT*>(&HandleContx));
if (!NT_SUCCESS(status))
return FLT_PREOP_SUCCESS_NO_CALLBACK;
// auto release get reference
AutoContext AutoHandleContxGet(HandleContx);
// no write occured , no need to evaluate
if (HandleContx->FirstPreWrite)
{
contexts::RemoveContextFromList(HandleContx);
ExFreePoolWithTag(HandleContx->FileName.Buffer, TAG);
FltReleaseContext(HandleContx);
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
// pass handle context pointer to post close
*CompletionContext = HandleContx;
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
but in case the minifilter unloads before close has taken place the context is released through the list of contexts , anyone sees something I dont ?
usually it unloads cleanly but every once in a while it hangs and requires restart