IIS Modules (2/6)


IIS modules written in C++ are implemented by deriving from the CHttpModule class. The CHttpModule class has several virtual functions that correspond to the different stages of the request lifecycle.

A factory class derived from IHttpModuleFactory must also be provided. It provides the method that the IIS server will call to create a new instance of the module: HRESULT GetHttpModule(OUT CHttpModule** ppModule, IN IModuleAllocator* pAllocator).

The code is packaged in a DLL that must export the HRESULT __stdcall RegisterModule(DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pGlobalInfo) function. That function will be called by the IIS server to get an instance of the module factory and the list of events the module wishes to get notified about.

A "Hello World!" Module

We will need an example to illustrate the next topics so let's create the traditional "Hello World!" application in the form of a module that will display a web page with "Hello World!" on it.

File: IISHelloWorldModuleFactory.h

#define _WINSOCKAPI_
#include <httpserv.h>    // for IHttpModuleFactory

class IISHelloWorldModuleFactory : public IHttpModuleFactory
    HRESULT GetHttpModule(OUT CHttpModule** ppModule, IN IModuleAllocator* pAllocator);
    void Terminate();

File: IISHelloWorldModuleFactory.cpp
#include "IISHelloWorldModuleFactory.h"
#include "IISHelloWorldModule.h"

HRESULT __stdcall RegisterModule(DWORD dwServerVersion,
    IHttpModuleRegistrationInfo * pModuleInfo,
    IHttpServer * pGlobalInfo)
    return pModuleInfo->SetRequestNotifications(new IISHelloWorldModuleFactory(),
        RQ_BEGIN_REQUEST, 0);

HRESULT IISHelloWorldModuleFactory::GetHttpModule(OUT CHttpModule** ppModule,
                                                  IN IModuleAllocator* pAllocator)
    *ppModule = new(std::nothrow) IISHelloWorldModule();
    if (*ppModule == nullptr)
    return S_OK;

void IISHelloWorldModuleFactory::Terminate()
    delete this;
File: IISHelloWorldModule.h

#define _WINSOCKAPI_
#include <httpserv.h>    // for CHttpModule
#include <string>

class IISHelloWorldModule : public CHttpModule
    REQUEST_NOTIFICATION_STATUS OnBeginRequest(IN IHttpContext* pHttpContext,
        IN IHttpEventProvider* pProvider);

    void writeResponse(IHttpContext* pHttpContext, const std::string& text);

File: IISHelloWorldModule.cpp
#include "IISHelloWorldModule.h"

REQUEST_NOTIFICATION_STATUS IISHelloWorldModule::OnBeginRequest(IN IHttpContext* pHttpContext,
    IN IHttpEventProvider* pProvider)
    writeResponse(pHttpContext, "Hello World!");

void IISHelloWorldModule::writeResponse(IHttpContext* pHttpContext,
                                        const std::string& text)
    HTTP_DATA_CHUNK dataChunk;
    dataChunk.DataChunkType = HttpDataChunkFromMemory;
    dataChunk.FromMemory.pBuffer = (void*)text.c_str();
    dataChunk.FromMemory.BufferLength = text.size();
    DWORD cbSent;
    pHttpContext->GetResponse()->WriteEntityChunks(&dataChunk, 1, false, false, &cbSent);
If you create a 32-bit module it will probably not be loaded successfully if you keep the default settings for the application pool on 64-bit versions of IIS.
/EXPORT:RegisterModule to linker command line

blog comments powered by Disqus

Copyright(c) 2006-2017 Xavier Leclercq | Privacy policy

Contact Us