Creating a Native Module for IIS7

To extend the server, IIS7 provides a new (C++) native core server API, which replaces ISAPI filter and extension API from previous IIS releases. The new API features object-oriented development with an intuitive object model, provides more control over request processing, and uses simpler design patterns to help you write robust code. Please visit Developing a Native Module for IIS7 for more information about this sample.

NOTE: The IIS7 native (C++) server API is declared in the Platform SDK httpserv.h header file.  You must obtain this SDK and register it with Visual Studio in order to compile this module.

A native module is a Windows DLL that contains an the following:

  1. RegisterModule exported function.  This function is responsible for creating a module factory, and registering the module for one or more server events.

    This function is implemented in main.cpp.
  2. Implementation of the module class inheriting from the CHttpModule base class.  This class is provides the main functionality of your module.

    This class is declared in mymodule.h, with method implementations in mymodule.cpp.
  3. Implementation of the module factory class implementing the IHttpModuleFactory interface.  The class is responsible for creating instances of your module.

    This class is declared and implemented in mymodulefactory.h.

0. Prerequisites

In order to compile the module, you will need to install the Windows Platform SDK that contains the required IIS header files. 

After installing the SDK
, you will need to register the SDK with Visual Studio 2005.  You can do this via Start > Programs > Microsoft Windows SDK > Visual Studio Registration > Register Windows SDK Directories with Visual Studio.

1. Implement RegisterModule entrypoint

A native module must export the RegisterModule function.  This function will be invoked by the server when the module DLL is loaded, so that your DLL can register for the required server events, and provide a mechanism for the server to create instances of your module class.

__stdcall
HRESULT RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pHttpServer );

This function is implemented for you in the main.cpp source file. 

It does the following:

  1. Create module factory.  This is an instance of your CMyModuleFactory class that implements the IHttpModuleFactory inteface:

    // step 2: create module factory
    pFactory = new CMyHttpModuleFactory();

  2. Register module factory for desired server events.  This registers the module factory for one or more server events that occur during request processing.  The server will use the factory to create an instance of your module class for each request, and call the appropriate event handler method on your module instance for each of the requested events:

    // step 3: register for server events
    // TODO: register for more server events here
    hr = pModuleInfo->SetRequestNotifications( pFactory,
    /* module factory */
                                               RQ_ACQUIRE_REQUEST_STATE, /* server event mask */
                                               0 /* server post event mask */ );

    The server event mask is a bit mask of one or more request processing event names declared in
    httpserv.h:

    //
    // Request deterministic notifications
    //

    // request is beginning

    #define RQ_BEGIN_REQUEST 0x00000001
    // request is being authenticated
    #define RQ_AUTHENTICATE_REQUEST 0x00000002
    // request is being authorized
    #define RQ_AUTHORIZE_REQUEST 0x00000004
    // satisfy request from cache
    #define RQ_RESOLVE_REQUEST_CACHE 0x00000008
    // map handler for request
    #define RQ_MAP_REQUEST_HANDLER 0x00000010
    // acquire request state
    #define RQ_ACQUIRE_REQUEST_STATE 0x00000020
    // pre-execute handler
    #define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040
    // execute handler
    #define RQ_EXECUTE_REQUEST_HANDLER 0x00000080
    // release request state
    #define RQ_RELEASE_REQUEST_STATE 0x00000100
    // update cache
    #define RQ_UPDATE_REQUEST_CACHE 0x00000200
    // log request
    #define RQ_LOG_REQUEST 0x00000400
    // end request
    #define RQ_END_REQUEST 0x00000800

    //
    // Request non-deterministic notifications
    //


    // custom notification
    #define RQ_CUSTOM_NOTIFICATION 0x10000000
    // send response
    #define RQ_SEND_RESPONSE 0x20000000
    // read entity
    #define RQ_READ_ENTITY 0x40000000
    // map a url to a physical path
    #define RQ_MAP_PATH 0x80000000

    The post event mask is a bit mask of the same events, allowing to subscribe to the post events for each of the specified events.

2. Implement module factory class

The server requires a module factory class in order to obtain instances of your module.  The factory class must implement the IHttpModuleFactory interface declared in the httpserv.h Windows SDK header file.

This factory is implemented for you in the mymodulefactory.h header file.

The GetHttpModule method of the factory class is called at the beginning of each request in order to obtain an instance of your module.  The typical implementation simply returns a new instance of your module class:

class CMyHttpModuleFactory : public IHttpModuleFactory
{
public:
    virtual HRESULT GetHttpModule( OUT CHttpModule **ppModule, IN IModuleAllocator * )
    { 
        ...
        pModule = new CMyHttpModule(); 
        ...
        *ppModule = pModule; 
        ...
    } 

    virtual void Terminate() { }
}

The Terminate method of the factory class is called during the shutdown of the worker process, before your module DLL is unloaded.  It typically releases any resources you may have initialized inside the RegisterModule function.

3. Implement module class

The module class inherits from the CHttpModule base class, which defines an event handler method for each of the server events discussed earlier.  When the server executes each event during the processing of a request, it will invoke the associated event handler method on each of the module instances that have registered for that event. 

This class is declared in the mymodule.h header file, and its event handler methods are implemented in the mymodule.cpp source file.

In order to provide processing for each server event, the module class MUST override the corresponding method.  The signature of each event handler method is the following:

REQUEST_NOTIFICATION_STATUS On<EVENT NAME>( IN IHttpContext * pHttpContext, IN OUT IHttpEventProvider * pProvider );

Where <EVENT NAME> is one of the server events we listed earlier.  For example, the module in this project initially overrides only the OnAcquireRequestState method since we register only for the RQ_ACQUIRE_REQUEST_STATE event:

class CMyHttpModule : public CHttpModule
{
public:

    // Implementation of the AcquireRequestState event handler method.
    REQUEST_NOTIFICATION_STATUS OnAcquireRequestState( IN IHttpContext * pHttpContext, IN OUT IHttpEventProvider * pProvider );

    // TODO: override additional event handler methods below.
};


The implementation of this method provides the module functionality desired for processing the request in the appropriate pipeline stage.  This project provides a dummy implementation in the mymodule.cpp source file.

4. Deploy the module to the server

After you have compiled your module, you need to deploy it on the server.  You can do that by compiling the module, and then copying IIS7NativeModule.dll (and the IIS7NativeModule.pdb debugging symbols file if desired) to any location on the machine running IIS7.

You can install your module on the server by running the following command from an Elevated command line prompt:

%systemroot%\system32\inetsrv\APPCMD.EXE install module /name:MyModule /image:<FULL PATH TO DLL>

Where <FULL_PATH_TO_DLL> is the full path to the module DLL file.

You can also install your module using the IIS7 Administration Tool. After installation, your module will be loaded and enabled in all application pools on the server.  To learn ore about installing modules, and selecting modules to execute on your server and for specific applications, please visit www.iis.net.

Congratulations!

You have succesfully built and deployed your own IIS7 module.  To learn more about building IIS7 modules, and to download sample modules, be sure to visit www.iis.net.