Managed Modules and ISAPI Filters

Question:

Hello,

I have an isapi filter and a managed module. I need to put both in the same website and I need that the manage module run before the isapi filter. The sequence are: Module--->ISAPI filter. How can I do this?

Answer:

The answer really depends on the filter events that the ISAPI Filter subscribes to.

Unfortunately, no built-in IIS UI or tool displays this information since it is rarely of interest to the user.

However, you can use my tool from here to view the events that an ISAPI Filter subscribes for. To the astute reader - this filter status information is only available AFTER IIS successfully loads an ISAPI Filter (i.e. IIS successfully LoadLibrary(), GetProcAddress() the Filter DLL's GetFilterVersion() exported function, executes it for registered events, and the function returns TRUE to IIS), and depending on IIS version/mode and the type of ISAPI Filter, IIS ends up loading an ISAPI Filter at different times. The history and rationale behind the differences is an entire blog entry all to itself, but the following table is a sufficient summary for now:

IIS Version (Mode) Global Filter Loads... Site Filter Loads...
IIS4 / IIS5 / IIS5.1 On Server Startup When Configured for a Website
IIS6 (IIS5 Compatibility Mode) On Server Startup When Configured, on first request to that Website
IIS6 (Worker Process Isolation Mode) On w3wp.exe Startup When Configured, on first request to that Website
IIS7 (Classic and Integrated Modes) Same as IIS6 Worker Process Isolation Mode Same as IIS6 Worker Process Isolation Mode

It's all about Timing

Now, you may wonder WHY knowing the subscribed filter events affect the answer. As in life and most things in our four dimensional world, it's all about timing, and this situation is no exception.

ISAPI Filter triggers on various events fired by IIS throughout a request's processing, while Managed Modules trigger after only one of those events (and in IIS7 in Integrated Pipeline Mode, Managed Modules trigger on ALMOST all of the events). Thus, if you want the Managed Module to run before the ISAPI Filter, the ISAPI Filter's subscribed events must be limited to those that happen AFTER the Module triggers.

Since Modules trigger pretty late in the request processing, right before response generation and logging, and ISAPI Filters typically trigger early in the request process, to perform either custom authentication, URL rewriting, etc, it is highly likely that what you want to do is impossible on any IIS version - without knowing the exact filter events involved, I cannot be definitive.

The following is a condensed outline of how ISAPI Filter and Managed Modules triggering are ordered:

  • On IIS4, IIS5, IIS5.1, and IIS6, Managed Modules trigger between the SF_NOTIFY_AUTH_COMPLETE and SF_NOTIFY_SEND_RESPONSE filter events.
  • On IIS7 in Classic Pipeline Mode, things behave as in IIS6.
  • On IIS7 in Integrated Pipeline Mode, Managed Modules trigger in-line with all ISAPI Filter events in all Pipeline Modes (Classic and Integrated) because ISAPI Filters are actually just DLLs loaded by the "ISAPI Filter" Module, which acts as a shim to trigger appropriate ISAPI Filter events for the corresponding Module events of the Integrated Pipeline. For example, the "ISAPI Filter Module" subscribes for the OnPreBeginRequest event, which when triggered by IIS will cause it to fire the SF_NOTIFY_PREPROC_HEADERS filter event to all applicable ISAPI Filters for that URL scope.

Conclusion

In general, if your ISAPI filter does NOT subscribe to events earlier than SF_NOTIFY_SEND_RESPONSE, it would be possible for a Managed Module to execute before the ISAPI filter triggers.

You should notice some direct correlations between the Module events of the IIS7 Integrated Pipeline and a merging of the ISAPI Filter events and classic ASP.Net HttpModule events. This is intentional - that is what we meant with the name "Integrated" Pipeline! :-)

The astute reader should note that Managed Modules on IIS7 do not have access to the OnPreBeginRequest module event. Since that event is used by the "ISAPI Filter" Module to trigger the SF_NOTIFY_PREPROC_HEADERS event, this means that even in Integrated Pipeline mode, where Managed Modules trigger in-line with any other module such as the "ISAPI Filter" Module shim, a Managed Module will NOT be able to execute before an ISAPI Filter that subscribes to the SF_NOTIFY_PREPROC_HEADERS event.

Yes, there is a huge story behind why OnPreBeginRequest even exists and why Managed Modules do not have access to that event (and other such global notification events). The blurbs on MSDN simply does not do it justice...

But at long last, here is the long-winded response to it all.

Cheers!

//David