IRP_MJ_CREATE - IRQL of Pre and Post Handlers?

> I believe Tony talked about IRP completion which can happen at IRQL <=
DISPATCH_LEVEL.

Now i believe too.

Let’s refocus this:
I need to call a few passive level only routines in PRE create. As such, if
this can ever be called at anything other than passive, I absolutely must
defer in the case where this happens only very rarely as reliability trumps
performance for my use case. I hate to put code in here that will never
execute, but it appears there is a conflict in the community knowledge base
where one says only passive level and another says it can be greater than
in the rare case. Is my reading comprehension so lacking? The MSDN
documentation is explicit about the Post Create, but is ambiguous on the
Pre, perhaps that is the ultimate source of the confusion.

On Monday, October 31, 2016, Anatoly Mikhailov wrote:

> > I believe Tony talked about IRP completion which can happen at IRQL <=
> DISPATCH_LEVEL.
> >
> Now i believe too.
>
>
> — NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis,
> WDF, Windows internals and software drivers! Details at To unsubscribe,
> visit the List Server section of OSR Online at

Tony was talking about postcreate. Hypothetically it can be called above
PASSIVE_LEVEL. But in practice this is rather rare. As for precreate, it is
always called at PASSIVE_LEVEL.

1 нояб. 2016 г. 7:06 AM пользователь “Jesse Conn”
написал:

> Let’s refocus this:
> I need to call a few passive level only routines in PRE create. As such,
> if this can ever be called at anything other than passive, I absolutely
> must defer in the case where this happens only very rarely as reliability
> trumps performance for my use case. I hate to put code in here that will
> never execute, but it appears there is a conflict in the community
> knowledge base where one says only passive level and another says it can be
> greater than in the rare case. Is my reading comprehension so lacking? The
> MSDN documentation is explicit about the Post Create, but is ambiguous on
> the Pre, perhaps that is the ultimate source of the confusion.
>
> On Monday, October 31, 2016, Anatoly Mikhailov
> wrote:
>
>> > I believe Tony talked about IRP completion which can happen at IRQL <=
>> DISPATCH_LEVEL.
>> >
>> Now i believe too.
>>
>>
>> — NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis,
>> WDF, Windows internals and software drivers! Details at To unsubscribe,
>> visit the List Server section of OSR Online at
>
> — NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis,
> WDF, Windows internals and software drivers! Details at To unsubscribe,
> visit the List Server section of OSR Online at

Let’s talk purely in terms of the I/O Manager and leave Filter Manager our
of it for the moment.

The *only* way to generate an IRP_MJ_CREATE request in Windows is to call
ZwCreateFile*. ZwCreateFile will build an IRP and send it to the dispatch
entry point of the target driver. ZwCreateFile does not change the IRQL as
part of the call. According to the ZwCreateFile documentation:

“Callers of ZwCreateFile must be running at IRQL = PASSIVE_LEVEL and
with special kernel APCs enabled.”

Therefore, by design Windows sends IRP_MJ_CREATE requests at PASSIVE_LEVEL.

Filter Manager abstracts out the dispatching of the IRP and calls you at
your PreCreate callback when it receives the IRP. FltMgr does not change the
IRQL, thus your PreCreate callback is called at PASSIVE_LEVEL.

If a driver raises the IRQL and calls ZwCreateFile, they’re hosed. If a
higher altitude minifilter changes the IRQL in PreCreate and doesn’t restore
it, they’re hosed. Trying to defend against this sort of thing leads to
madness. A driver could send me invalid arguments, or call me at a bad IRQL,
or corrupt my data structures, or do any other sorts of horrid things. Yes,
my customers will come to ME with the problems that arise, but that’s life
in the fast lane (and a scan for other third party drivers is usually my
first step in analysis). Note that Verifier should catch these types of
problems and blame the offending driver, so you have that at least.

Going back to IRP talk, if I want to post-process the create IRP I need to
set a completion routine and send it along. When the target driver is done
with the IRP, I get called back at my completion routine at IRQL <=
DISPATCH_LEVEL.

FltMgr *always* synchronizes the call between PreCreate and PostCreate. What
this means is that if the lower driver pends the request, FltMgr will block
in thread context and then call your PostCreate routine when the lower
filter is done. FltMgr does not change the IRQL, thus you are called in
PostCreate at IRQL PASSIVE_LEVEL.

*Building your own create IRP with IoAllocateIrp was never supported and is
a tremendously bad idea these days

-scott
OSR
@OSRDrivers

“Anatoly Mikhailov” wrote in message
news:xxxxx@ntfsd…

Tony was talking about postcreate. Hypothetically it can be called above
PASSIVE_LEVEL. But in practice this is rather rare. As for precreate, it is
always called at PASSIVE_LEVEL.

1 нояб. 2016 г. 7:06 AM пользователь “Jesse Conn”
написал:
Let’s refocus this:
I need to call a few passive level only routines in PRE create. As such, if
this can ever be called at anything other than passive, I absolutely must
defer in the case where this happens only very rarely as reliability trumps
performance for my use case. I hate to put code in here that will never
execute, but it appears there is a conflict in the community knowledge base
where one says only passive level and another says it can be greater than in
the rare case. Is my reading comprehension so lacking? The MSDN
documentation is explicit about the Post Create, but is ambiguous on the
Pre, perhaps that is the ultimate source of the confusion.

On Monday, October 31, 2016, Anatoly Mikhailov wrote:

> I believe Tony talked about IRP completion which can happen at IRQL <=
> DISPATCH_LEVEL.
>
Now i believe too.

— NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis, WDF,
Windows internals and software drivers! Details at To unsubscribe, visit the
List Server section of OSR Online at
— NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis, WDF,
Windows internals and software drivers! Details at To unsubscribe, visit the
List Server section of OSR Online at

A+! Many thanks for putting it all in context start to finish.

I appreciate all the feedback. I inherited a mess of an undocumented mini
filter driver, which was obviously a copy paste recompile til it compiled
design that was littered with huge architectural problems and “random blue
screens we don’t understand”… I’ve been doing a careful redesign, one
that is hopefully much more maintainable. Thanks for filling in the
knowledge gaps :slight_smile:

On Tuesday, November 1, 2016, Scott Noone wrote:

> Let’s talk purely in terms of the I/O Manager and leave Filter Manager our
> of it for the moment.
>
> The only way to generate an IRP_MJ_CREATE request in Windows is to call
> ZwCreateFile*. ZwCreateFile will build an IRP and send it to the dispatch
> entry point of the target driver. ZwCreateFile does not change the IRQL as
> part of the call. According to the ZwCreateFile documentation:
>
> “Callers of ZwCreateFile must be running at IRQL = PASSIVE_LEVEL and
> with special kernel APCs enabled.”
>
> Therefore, by design Windows sends IRP_MJ_CREATE requests at PASSIVE_LEVEL.
>
> Filter Manager abstracts out the dispatching of the IRP and calls you at
> your PreCreate callback when it receives the IRP. FltMgr does not change
> the IRQL, thus your PreCreate callback is called at PASSIVE_LEVEL.
>
> If a driver raises the IRQL and calls ZwCreateFile, they’re hosed. If a
> higher altitude minifilter changes the IRQL in PreCreate and doesn’t
> restore it, they’re hosed. Trying to defend against this sort of thing
> leads to madness. A driver could send me invalid arguments, or call me at a
> bad IRQL, or corrupt my data structures, or do any other sorts of horrid
> things. Yes, my customers will come to ME with the problems that arise, but
> that’s life in the fast lane (and a scan for other third party drivers is
> usually my first step in analysis). Note that Verifier should catch these
> types of problems and blame the offending driver, so you have that at least.
>
> Going back to IRP talk, if I want to post-process the create IRP I need to
> set a completion routine and send it along. When the target driver is done
> with the IRP, I get called back at my completion routine at IRQL <=
> DISPATCH_LEVEL.
>
> FltMgr always synchronizes the call between PreCreate and PostCreate.
> What this means is that if the lower driver pends the request, FltMgr will
> block in thread context and then call your PostCreate routine when the
> lower filter is done. FltMgr does not change the IRQL, thus you are called
> in PostCreate at IRQL PASSIVE_LEVEL.
>
> *Building your own create IRP with IoAllocateIrp was never supported and
> is a tremendously bad idea these days
>
> -scott
> OSR
> @OSRDrivers
>
> “Anatoly Mikhailov” wrote in message
> news:xxxxx@ntfsd…
>
> Tony was talking about postcreate. Hypothetically it can be called above
> PASSIVE_LEVEL. But in practice this is rather rare. As for precreate, it is
> always called at PASSIVE_LEVEL.
>
>
> 1 нояб. 2016 г. 7:06 AM пользователь “Jesse Conn”
> написал:
> Let’s refocus this:
> I need to call a few passive level only routines in PRE create. As such,
> if this can ever be called at anything other than passive, I absolutely
> must defer in the case where this happens only very rarely as reliability
> trumps performance for my use case. I hate to put code in here that will
> never execute, but it appears there is a conflict in the community
> knowledge base where one says only passive level and another says it can be
> greater than in the rare case. Is my reading comprehension so lacking? The
> MSDN documentation is explicit about the Post Create, but is ambiguous on
> the Pre, perhaps that is the ultimate source of the confusion.
>
> On Monday, October 31, 2016, Anatoly Mikhailov
> wrote:
>
>
> I believe Tony talked about IRP completion which can happen at IRQL <=
>> DISPATCH_LEVEL.
>>
>> Now i believe too.
>
>
>
> — NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis,
> WDF, Windows internals and software drivers! Details at To unsubscribe,
> visit the List Server section of OSR Online at
> — NTFSD is sponsored by OSR MONTHLY seminars on crash dump analysis,
> WDF, Windows internals and software drivers! Details at To unsubscribe,
> visit the List Server section of OSR Online at
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

Pre-Create is called in the context of the I/O Manager operation (so IopParseDevice or IopParseFile calls filter manager, which calls your mini-filter.)

Thus, it is at IRQL == PASSIVE_LEVEL with special kernel APCs enabled (filter manager doesn’t change this). The I/O Manager does not ensure that completion routines (“post create”) are called at passive level - this is a specific feature of Filter Manager.

It’s possible other drivers could violate these restrictions, but then they’re broken as they have not “played by the rules”. If you try to write code to defend against this level of malfunction, you will drive yourself insane.

Tony
OSR

The fact that ZwCreateFile must be called at passive level (*and* with special kernel APCs enabled) is not germane to the IRQL of the completion routine, though. Thus, as I said, it is almost always called at passive level but it is not safe to assume that is the case.

Mini-filters, however, have the added functionality provided by Filter Manager - it handles this case and ensures that the post create function is invoked at passive level, with special kernel APCs enabled. In addition, it also guarantees that it is in the original thread context.

Tony
OSR