What notifications are delivered to IIS7 native modules

Here is the output of getmreg tool for all the modules listed under <system.webServer/globalModules> section in IIS7 full install. This tells what notifications are delivered to native modules shipped with IIS7.

1. UriCacheModule – getmreg.exe %windir%\system32\inetsrv\cachuri.dll
Global notifications
GL_CACHE_CLEANUP
GL_CACHE_OPERATION
GL_CONFIGURATION_CHANGE

2. FileCacheModule – getmreg.exe %windir%\system32\inetsrv\cachfile.dll
Global notifications
GL_CACHE_CLEANUP
GL_CACHE_OPERATION
GL_FILE_CHANGE

3. TokenCacheModule – getmreg.exe %windir%\system32\inetsrv\cachtokn.dll
Global notifications
GL_CACHE_CLEANUP
GL_CACHE_OPERATION

4. HttpCacheModule – getmreg.exe %windir%\system32\inetsrv\cachhttp.dll
Global notifications
GL_CACHE_CLEANUP
GL_CONFIGURATION_CHANGE
GL_FILE_CHANGE
Request notifications
RQ_BEGIN_REQUEST

RQ_RESOLVE_REQUEST_CACHE
RQ_UPDATE_REQUEST_CACHE
RQ_SEND_RESPONSE

5. DynamicCompressionModule – getmreg.exe %windir%\system32\inetsrv\compdyn.dll
Request notifications
RQ_SEND_RESPONSE
POST_RQ_RELEASE_REQUEST_STATE

6. StaticCompressionModule – getmreg.exe %windir%\system32\inetsrv\compstat.dll

Request notifications
RQ_MAP_REQUEST_HANDLER
RQ_RELEASE_REQUEST_STATE
 
7. DefaultDocumentModule – getmreg.exe %windir%\system32\inetsrv\defdoc.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
 
8. DirectoryListingModule – getmreg.exe %windir%\system32\inetsrv\dirlist.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
 
9. ProtocolSupportModule – getmreg.exe %windir%\system32\inetsrv\protsup.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
RQ_SEND_RESPONSE
 
10. HttpRedirectionModule – getmreg.exe %windir%\system32\inetsrv\redirect.dll
Request notifications
RQ_MAP_REQUEST_HANDLER
 
11. ServerSideIncludeModule – getmreg.exe %windir%\system32\inetsrv\iis_ssi.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
 
12. StaticFileModule – getmreg.exe %windir%\system32\inetsrv\static.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
 
13. AnonymousAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authanon.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
Setting priority for request notifications
RQ_AUTHENTICATE_REQUEST
LOW
 
14. CertificateMappingAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authcert.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
 
15. UrlAuthorizationModule – getmreg.exe %windir%\system32\inetsrv\urlauthz.dll
Request notifications
RQ_AUTHORIZE_REQUEST
 
16. BasicAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authbas.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
RQ_SEND_RESPONSE
 
17. WindowsAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authsspi.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
RQ_SEND_RESPONSE
 
18. DigestAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authmd5.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
RQ_SEND_RESPONSE
 
19. IISCertificateMappingAuthenticationModule – getmreg.exe %windir%\system32\inetsrv\authmap.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
 
20. IpRestrictionModule – getmreg.exe %windir%\system32\inetsrv\iprestr.dll
Request notifications
RQ_BEGIN_REQUEST
 
21. RequestFilteringModule – getmreg.exe %windir%\system32\inetsrv\modrqflt.dll
Request notifications
RQ_BEGIN_REQUEST
 
22. CustomLoggingModule – getmreg.exe %windir%\system32\inetsrv\logcust.dll
Request notifications
RQ_LOG_REQUEST
 
23. CustomErrorModule – getmreg.exe %windir%\system32\inetsrv\custerr.dll
Request notifications
RQ_SEND_RESPONSE
Setting priority for request notifications
RQ_SEND_RESPONSE
HIGH
 
24. HttpLoggingModule – getmreg.exe %windir%\system32\inetsrv\loghttp.dll
Request notifications
RQ_SEND_RESPONSE
 
25. TracingModule – getmreg.exe %windir%\system32\inetsrv\iisetw.dll
Global notifications
GL_TRACE_EVENT
 
26. FailedRequestsTracingModule – getmreg.exe %windir%\system32\inetsrv\iisfreb.dll
Request notifications
RQ_BEGIN_REQUEST
Global notifications
GL_PRE_BEGIN_REQUEST
GL_TRACE_EVENT
 
27. RequestMonitorModule – getmreg.exe %windir%\system32\inetsrv\iisreqs.dll
Request notifications
RQ_BEGIN_REQUEST
RQ_END_REQUEST
Global notifications
GL_RSCA_QUERY
 
28. IsapiModule – getmreg.exe %windir%\system32\inetsrv\isapi.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
RQ_SEND_RESPONSE
Global notifications
GL_CONFIGURATION_CHANGE
 
29. IsapiFilterModule – getmreg.exe %windir%\system32\inetsrv\filter.dll
Request notifications
RQ_AUTHENTICATE_REQUEST
RQ_AUTHORIZE_REQUEST
RQ_MAP_PATH
RQ_SEND_RESPONSE
Global notifications
GL_PRE_BEGIN_REQUEST
 
30. CgiModule – getmreg.exe %windir%\system32\inetsrv\cgi.dll
Request notifications
RQ_EXECUTE_REQUEST_HANDLER
Global notifications
GL_STOP_LISTENING
GL_CONFIGURATION_CHANGE
 
31. ConfigurationValidationModule – getmreg.exe %windir%\system32\inetsrv\validcfg.dll
Request notifications
RQ_BEGIN_REQUEST
 
32. ManagedEngine – getmreg.exe %windir%\Microsoft.NET\Framework\v2.0.50727\webengine.dll
Global notifications
GL_APPLICATION_RESOLVE_MODULES
GL_APPLICATION_STOP
GL_THREAD_CLEANUP

-Kanwal-

Tool to find native module’s pipeline events registration (source code)

//
// Filename – getmreg.cxx 
// Build this as an executable.
// Keep this exe and module dll
// in the same folder
//
// Run using "getmreg.exe <path to module>"
//
// This tool uses hostable web core functionality
// of IIS7. So this will only run on machine with
// IIS7 installed. You don’t need to have w3svc running.
//

#include <stdio.h>
#include <windows.h>
#include "httpserv.h"
#include "hwebcore.h"

HRESULT
WriteContentToConfigFile(
    HANDLE hConfigFile,
    DWORD dwPort,
    PCSTR pszModulePath
);

extern
"C"
INT
__cdecl
wmain(
    INT argc,
    __in_ecount(argc) PCWSTR argv[]
)
{
    //
    // Introduction
    //
    wprintf(L"GetMReg: Prints event registration information of native modules.\r\n");
    wprintf(L" Author: Kanwaljeet Singla\r\n\r\n");

   
HRESULT hr = S_OK;
    DWORD dwErr = 0;
    DWORD dwSize = 0;

    if(argc != 2)
    {
        wprintf(L"Usage: getmreg <path to native module>\r\nAborting\r\n");
        goto finished;
    }
   
    //
    // Set the module path in an environment variable
    // which module can read
    //
    if(SetEnvironmentVariable(
            L"MODULEPATH",
            argv[1]) == FALSE)
    {
        wprintf(L"Call to SetEnvironmentVariable failed\r\nAborting\r\n");
        goto finished;
    }

    //
    // Build path to hwebcore.dll using GetSystemDirectory
    //
    HINSTANCE hHWebCore = NULL;
    PWSTR pszSystemDir = NULL;
   
    dwSize = GetSystemDirectory(pszSystemDir, 0);
    if(dwSize == 0)
    {
        wprintf(L"Call to GetSystemDirectory failed\r\nAborting\r\n");
        goto finished;
    }

    pszSystemDir = (PWSTR)malloc((dwSize + 1)* sizeof(WCHAR));
    if(pszSystemDir == NULL)
    {
        wprintf(L"Out of memory error\r\nAborting\r\n");
        goto finished;
    }

    if(GetSystemDirectory(pszSystemDir, dwSize + 1) == 0)
    {
        wprintf(L"Call to GetSystemDirectory gave unexpected error\r\nAborting\r\n");
        goto finished;
    }

    PWSTR hwebcore = (PWSTR)malloc(MAX_PATH * sizeof(WCHAR));
    if(hwebcore == NULL)
    {
        wprintf(L"Out of memory error\r\nAborting\r\n");
        goto finished;

    }


    if(wcslen(pszSystemDir) > MAX_PATH – 22)
    {
        wprintf(L"hwebcore.dll path larger than MAX_PATH\r\nAborting\r\n");
        goto finished;
    }

 

 

    wcscat(hwebcore, L"\\inetsrv\\hwebcore.dll");
   
    //
    // Load hwebcore.dll
    //
    hHWebCore = LoadLibraryEx(hwebcore, NULL, 0);
    if(hHWebCore == NULL)
    {
        wprintf(L"Could not load hwebcore.dll\r\nAborting\r\n");
        goto finished;
    }
    //
    // Get entry point WebcoreActivate and WebcoreShutdown
    //
    PFN_WEB_CORE_ACTIVATE pfnWebcoreActivate = NULL;
    PFN_WEB_CORE_SHUTDOWN pfnWebcoreShutdown = NULL;

    pfnWebcoreActivate = (PFN_WEB_CORE_ACTIVATE)GetProcAddress(
        hHWebCore,
        WEB_CORE_ACTIVATE_DLL_ENTRY);

    pfnWebcoreShutdown = (PFN_WEB_CORE_SHUTDOWN) GetProcAddress(
        hHWebCore,
        WEB_CORE_SHUTDOWN_DLL_ENTRY
        );

    if(pfnWebcoreActivate == NULL ||
       pfnWebcoreShutdown == NULL)
    {
        wprintf(L"Didn’t get WebcoreActivate or WebcoreShutdown entry points\r\nAborting\r\n");
        goto finished;
    }

    //
    // Get current process path
    //
    PSTR pszHelperModulePath = NULL;
    pszHelperModulePath = (PSTR)malloc(MAX_PATH * sizeof(CHAR));
    dwSize = GetModuleFileNameA(NULL,
        pszHelperModulePath,
        MAX_PATH);

    if(dwSize == 0)
    {
        wprintf(L"Call to GetModuleFileNameA failed\r\nAborting\r\n");
        goto finished;
    }

    //
    // Get the folder and add GetMRegModule.dll to build module path
    //
    PSTR pszLastSlash = strrchr(pszHelperModulePath, ‘\\’);

    *(pszLastSlash + 1) = 0;

    if(strlen(pszHelperModulePath) > MAX_PATH – 18)
    {
        wprintf(L"GetMRegModule.dll path larger than MAX_PATH\r\nAborting\r\n");
        goto finished;
    }

 

    strcat(pszHelperModulePath, "GetMRegModule.dll");

    //
    // Create config file in temp folder
    // Ports starting from 31212 will be tried if
    // WebcoreActivate fails with error 0x80070038
    //

    DWORD dwPort = 31212;
    PWSTR pszTempPath = NULL;
    dwSize = GetTempPath(0, pszTempPath);

    if(dwSize == 0)
    {
        wprintf(L"Call to GetTempPath failed\r\nAborting\r\n");
        goto finished;
    }

    pszTempPath = (PWSTR)malloc((dwSize + 1)* sizeof(WCHAR));
    if(pszTempPath == NULL)
    {
        wprintf(L"Out of memory error\r\nAborting\r\n");
        goto finished;
    }

    if(GetTempPath(dwSize + 1, pszTempPath) == 0)
    {
        wprintf(L"Call to GetTempPath gave unexpected error\r\nAborting\r\n");
        goto finished;
    }

    PWSTR configPath = (PWSTR)malloc(MAX_PATH * sizeof(WCHAR));
    wcscpy(configPath, pszTempPath);
    wcscat(configPath, L"getmreg.config");
   
    //
    // CREATE_ALWAYS overwrite existing file
    //
createconfig:
    HANDLE hConfigFile = CreateFile(configPath,
        GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if(hConfigFile == NULL)
    {
        wprintf(L"Couldn’t create file\r\nAborting\r\n");
        goto finished;
    }

    hr = WriteContentToConfigFile(
        hConfigFile,
        dwPort,
        pszHelperModulePath);
    if(FAILED(hr))
    {
        goto finished;
    }

    if(hConfigFile != NULL)
    {
        CloseHandle(hConfigFile);
        hConfigFile = NULL;
    }

    //
    // Call WebcoreActivate which should call RegisterModule of the module
    //
    hr = pfnWebcoreActivate(configPath, L"", L"GETMREG");
    if(FAILED(hr))
    {
        wprintf(L"Call to webcore activate failed %d\r\n", hr);
        if(hr == 0x80070038)
        {
            wprintf(L"Trying different port\r\n");
            dwPort++;
            goto createconfig;
        }
        else
        {
            wprintf(L"Aborting\r\n");
            goto finished;
        }
    }

    //
    // Call WebcoreShutdown
    //
    hr = pfnWebcoreShutdown(1);
    if(FAILED(hr))
    {
        wprintf(L"Call to webcore shutdown failed\r\n");
        wprintf(L"Aborting\r\n");
        goto finished;
    }

finished:
    //
    // Unload hwebcore.dll
    //
    if(hHWebCore != NULL)
    {
        FreeLibrary(hHWebCore);
        pfnWebcoreActivate = NULL;
        pfnWebcoreShutdown = NULL;
        hHWebCore = NULL;
    }

    //
    // free allocated string buffers
    //
    if(pszSystemDir != NULL)
    {
        free(pszSystemDir);
        pszSystemDir = NULL;
    }

    if(hwebcore != NULL)
    {
        free(hwebcore);
        hwebcore = NULL;
    }

    if(pszHelperModulePath != NULL)
    {
        free(pszHelperModulePath);
        pszHelperModulePath = NULL;
    }

    if(pszTempPath != NULL)
    {
        free(pszTempPath);
        pszTempPath = NULL;
    }

    if(configPath != NULL)
    {
        free(configPath);
        configPath = NULL;
    }
   
    //
    // Close file handles
    //
    if(hConfigFile != NULL)
    {
        CloseHandle(hConfigFile);
        hConfigFile = NULL;
    }

    return 0;
}   // wmain

HRESULT
WriteContentToConfigFile(
    IN HANDLE hConfigFile,
    IN DWORD dwPort,
    IN PCSTR pszModulePath
)
{
    HRESULT hr = S_OK;
    PCSTR pszConfigContent1 =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
        "\r\n"
        "<configuration>\r\n"
        "\r\n"
        "    <configSections>\r\n"
        "        <sectionGroup name=\"system.applicationHost\">\r\n"
        "            <section name=\"applicationPools\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"customMetadata\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"listenerAdapters\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"log\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"sites\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"webLimits\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "        </sectionGroup>\r\n"
        "\r\n"
        "        <sectionGroup name=\"system.webServer\">\r\n"
        "            <section name=\"asp\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"caching\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"cgi\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"defaultDocument\" overrideModeDefault=\"Allow\" />\r\n"
        "            <section name=\"directoryBrowse\" overrideModeDefault=\"Allow\" />\r\n"
        "            <section name=\"globalModules\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"handlers\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"httpCompression\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"httpErrors\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"httpLogging\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"httpProtocol\" overrideModeDefault=\"Allow\" />\r\n"
        "            <section name=\"httpRedirect\" overrideModeDefault=\"Allow\" />\r\n"
        "            <section name=\"httpTracing\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"isapiFilters\" allowDefinition=\"MachineToApplication\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"modules\" allowDefinition=\"MachineToApplication\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"odbcLogging\" overrideModeDefault=\"Deny\" />\r\n"
        "            <sectionGroup name=\"security\">\r\n"
        "                <section name=\"access\" overrideModeDefault=\"Deny\" />\r\n"
        "                <section name=\"applicationDependencies\" overrideModeDefault=\"Deny\" />\r\n"
        "                <sectionGroup name=\"authentication\">\r\n"
        "                    <section name=\"anonymousAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                    <section name=\"basicAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                    <section name=\"clientCertificateMappingAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                    <section name=\"digestAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                    <section name=\"iisClientCertificateMappingAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                    <section name=\"windowsAuthentication\" overrideModeDefault=\"Deny\" />\r\n"
        "                </sectionGroup>\r\n"
        "                <section name=\"authorization\" overrideModeDefault=\"Deny\" />\r\n"
        "                <section name=\"ipSecurity\" overrideModeDefault=\"Deny\" />\r\n"
        "                <section name=\"isapiCgiRestriction\" allowDefinition=\"AppHostOnly\" overrideModeDefault=\"Deny\" />\r\n"
        "                <section name=\"requestFiltering\" overrideModeDefault=\"Deny\" />\r\n"
        "            </sectionGroup>\r\n"
        "            <section name=\"serverRuntime\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"serverSideInclude\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"staticContent\" overrideModeDefault=\"Deny\" />\r\n"
        "            <sectionGroup name=\"tracing\">\r\n"
        "                <section name=\"traceFailedRequests\" overrideModeDefault=\"Deny\" />\r\n"
        "                <section name=\"traceProviderDefinitions\" overrideModeDefault=\"Deny\" />\r\n"
        "            </sectionGroup>\r\n"
        "            <section name=\"urlCompression\" overrideModeDefault=\"Deny\" />\r\n"
        "            <section name=\"validation\" overrideModeDefault=\"Allow\" />\r\n"
        "        </sectionGroup>\r\n"
        "    </configSections>\r\n"
        "\r\n"
        "    <configProtectedData>\r\n"
        "        <providers>\r\n"
        "            <add name=\"IISWASOnlyRsaProvider\" type=\"\" description=\"Uses RsaCryptoServiceProvider to encrypt and decrypt\" keyContainerName=\"iisWasKey\" cspProviderName=\"\" useMachineContainer=\"true\" useOAEP=\"false\" />\r\n"
        "        </providers>\r\n"
        "    </configProtectedData>\r\n"
        "\r\n"
        "    <system.applicationHost>\r\n"
        "\r\n"
        "        <applicationPools>\r\n"
        "            <add name=\"MyAppPool\" />\r\n"
        "        </applicationPools>\r\n"
        "\r\n"
        "        <listenerAdapters>\r\n"
        "            <add name=\"http\" />\r\n"
        "        </listenerAdapters>\r\n"
        "\r\n"
        "        <sites>\r\n"
        "            <site name=\"My Web Site\" id=\"31212\">\r\n"
        "                <application path=\"/\">\r\n"
        "                    <virtualDirectory path=\"/\" physicalPath=\"%systemdrive%\\inetpub\\wwwroot\\\" />\r\n"
        "                </application>\r\n"
        "                <bindings>\r\n"
        "                    <binding protocol=\"http\" bindingInformation=\"*:";
   
    PCSTR pszConfigContent2 =
        ":\" />\r\n"
        "                </bindings>\r\n"
        "            </site>\r\n"
        "            <applicationDefaults applicationPool=\"MyAppPool\" />\r\n"
        "            <virtualDirectoryDefaults allowSubDirConfig=\"true\" />\r\n"
        "        </sites>\r\n"
        "\r\n"
        "    </system.applicationHost>\r\n"
        "\r\n"
        "    <system.webServer>\r\n"
        "\r\n"
        "        <globalModules>\r\n"
        "            <add name=\"GetMRegModule\" image=\"";

   
PCSTR pszConfigContent3 =
        "\" />\r\n"
        "        </globalModules>\r\n"
        "\r\n"
        "    </system.webServer>\r\n"
        "\r\n"
        "</configuration>\r\n";

   
//
    // Put port number in the config string
    //
    PSTR pszPort = NULL;
    pszPort = (PSTR)malloc(6 * sizeof(CHAR));
    _itoa(dwPort, pszPort, 10);
   
   PSTR pszConfigContent = NULL;
    pszConfigContent = (PSTR)malloc(
        strlen(pszConfigContent1) +
        strlen(pszPort) +
        strlen(pszConfigContent2) +
        strlen(pszModulePath) +
        strlen(pszConfigContent3) + 1);

    strcpy(pszConfigContent, pszConfigContent1);
    strcat(pszConfigContent, pszPort);
    strcat(pszConfigContent, pszConfigContent2);
    strcat(pszConfigContent, pszModulePath);
    strcat(pszConfigContent, pszConfigContent3);

    //
    // Write the contents to the temp config file
    //
    DWORD cbBytes;
    if(WriteFile(
        hConfigFile,
        pszConfigContent,
        strlen(pszConfigContent),
        &cbBytes,
        NULL) == 0)
    {
        wprintf(L"No bytes written to config file\r\nAborting\r\n");
        hr = E_FAIL;
        goto finished;
    }

finished:
    if(pszPort != NULL)
    {
        free(pszPort);
        pszPort = NULL;
    }
    if(pszConfigContent != NULL)
    {
        free(pszConfigContent);
        pszConfigContent = NULL;
    }

 

 
}
 

 

 

// Build this as a library and export RegisterModule
// Keep the name as GetMRegModule.dll (or change the name
// in other executable accordingly
//

#include "httpserv.h"
#include "http.h"
#include <stdio.h>
 class MyRegistrationProvider : IHttpModuleRegistrationInfo
{
public:
    MyRegistrationProvider(
        IHttpModuleRegistrationInfo *pModuleInfo
    )
    {
        _pModuleInfo    = pModuleInfo;
        _pModuleFactory = NULL;
        _pGlobalModule  = NULL;
    }

    ~MyRegistrationProvider()
    {
        if(_pModuleFactory != NULL)
        {
            _pModuleFactory->Terminate();
        }

        if(_pGlobalModule != NULL)
        {
            _pGlobalModule->Terminate();
        }
    }

    PCWSTR
    GetName(
        VOID
    ) const
    {
        return _pModuleInfo->GetName();
    }

    HTTP_MODULE_ID
    GetId(
        VOID
    ) const
    {
        return _pModuleInfo->GetId();
    }

    HRESULT
    SetRequestNotifications(
        IN IHttpModuleFactory * pModuleFactory,
        IN DWORD                dwRequestNotifications,
        IN DWORD                dwPostRequestNotifications
    )
    {
        //
        // Print request notifications
        //
        _pModuleFactory = pModuleFactory;
        wprintf(L"Request notifications\r\n");
        PrintRequestNotifications(dwRequestNotifications, dwPostRequestNotifications);
        wprintf(L"\r\n");

        //
        // Blindly return S_OK. We don’t actually want to
        // the notifications
        //
        return S_OK;
    }

    HRESULT
    SetGlobalNotifications(
        IN CGlobalModule *      pGlobalModule,
        IN DWORD                dwGlobalNotifications
    )
    {
        //
        // Print global notifications
        //
        _pGlobalModule = pGlobalModule;
        wprintf(L"Global notifications\r\n");
        PrintGlobalNotifications(dwGlobalNotifications);
        wprintf(L"\r\n");

        //
        // Blindly return S_OK
        //
        return S_OK;
    }

    HRESULT
    SetPriorityForRequestNotification(
        IN DWORD                dwRequestNotification,
        IN PCWSTR               pszPriority
    )
    {
        //
        // Print request notification priority information
        //
        wprintf(L"Setting priority for request notifications\r\n");
        PrintRequestNotifications(dwRequestNotification, 0);
        wprintf(L"%s\r\n", pszPriority);
        wprintf(L"\r\n");

        //
        // Blindly return S_OK
        //
        return S_OK;
    }

    HRESULT
    SetPriorityForGlobalNotification(
        IN DWORD                dwGlobalNotification,
        IN PCWSTR               pszPriority
    )
    {
        //
        // Print global notification priority information
        //
        wprintf(L"Setting priority for request notifications\r\n");
        PrintGlobalNotifications(dwGlobalNotification);
        wprintf(L"%s\r\n", pszPriority);
        wprintf(L"\r\n");

        //
        // Blindly return S_OK
        //
        return S_OK;
    }

private
:
    IHttpModuleRegistrationInfo * _pModuleInfo;
    IHttpModuleFactory          * _pModuleFactory;
    CGlobalModule               * _pGlobalModule;

    VOID PrintRequestNotifications(
        DWORD dwRequestNotifications,
        DWORD dwPostRequestNotifications
    );

    VOID PrintGlobalNotifications(
        DWORD dwGlobalNotifications
    );
};

VOID MyRegistrationProvider::PrintRequestNotifications(
    DWORD dwRequestNotifications,
    DWORD dwPostRequestNotifications
)
{
    DWORD count = 0;
    PCWSTR rnNames[16] = {
        L"RQ_BEGIN_REQUEST",
        L"RQ_AUTHENTICATE_REQUEST",
        L"RQ_AUTHORIZE_REQUEST",
        L"RQ_RESOLVE_REQUEST_CACHE",
        L"RQ_MAP_REQUEST_HANDLER",
        L"RQ_ACQUIRE_REQUEST_STATE",
        L"RQ_PRE_EXECUTE_REQUEST_HANDLER",
        L"RQ_EXECUTE_REQUEST_HANDLER",
        L"RQ_RELEASE_REQUEST_STATE",
        L"RQ_UPDATE_REQUEST_CACHE",
        L"RQ_LOG_REQUEST",
        L"RQ_END_REQUEST",
        L"RQ_MAP_PATH",
        L"RQ_READ_ENTITY",
        L"RQ_SEND_RESPONSE",
        L"RQ_CUSTOM_NOTIFICATION"
    };

    //
    // Print request registration information
    //
    for(DWORD i = 0; i <= 11; i++)
    {
        count = (1 << i);
        if((dwRequestNotifications & count) != 0)
        {
            wprintf(L"%s\r\n", rnNames[i]);
        }
    }

    //
    // Print asynchronous request registration information
    //
    for(DWORD i = 0; i <= 3; i++)
    {
        count = (1 << (31 – i));
        if((dwRequestNotifications & count) != 0)
        {
            wprintf(L"%s\r\n", rnNames[12 + i]);
        }
    }

    //
    // Print POST request registration information
    //
    for(DWORD i = 0; i <= 11; i++)
    {
        count = (1 << i);
        if((dwPostRequestNotifications & count) != 0)
        {
            wprintf(L"POST_%s\r\n", rnNames[i]);
        }
    }

    //
    // Print asynchronous POST request registration information
    //
    for(DWORD i = 0; i <= 3; i++)
    {
        count = (1 << (31 – i));
        if((dwPostRequestNotifications & count) != 0)
        {
            wprintf(L"POST_%s\r\n", rnNames[12 + i]);
        }
    }
}

VOID MyRegistrationProvider::PrintGlobalNotifications(
    DWORD dwGlobalNotifications
)
{
    DWORD count = 0;
    PCWSTR gnNames[16] = {
        L"",
        L"GL_STOP_LISTENING",
        L"GL_CACHE_CLEANUP",
        L"",
        L"GL_CACHE_OPERATION",
        L"GL_HEALTH_CHECK",
        L"GL_CONFIGURATION_CHANGE",
        L"GL_FILE_CHANGE",
        L"GL_PRE_BEGIN_REQUEST",
        L"GL_APPLICATION_START",
        L"GL_APPLICATION_RESOLVE_MODULES",
        L"GL_APPLICATION_STOP",
        L"GL_RSCA_QUERY",
        L"GL_TRACE_EVENT",
        L"GL_CUSTOM_NOTIFICATION",
        L"GL_THREAD_CLEANUP"
    };

    //
    // Print global registration information
    //
    for(DWORD i = 0; i <= 15; i++)
    {
        count = (1 << i);
        if((dwGlobalNotifications & count) != 0)
        {
            wprintf(L"%s\r\n", gnNames[i]);
        }
    }
}

HRESULT
RegisterModule(
    DWORD                           dwServerVersion,
    IHttpModuleRegistrationInfo *   pModuleInfo,
    IHttpServer *                   pGlobalInfo
)
{
    HRESULT hr = S_OK;

    //
    // Load another module
    //
    HINSTANCE hModule = NULL;
    PWSTR pszModulePath = NULL;
    DWORD dwSize = 0;

    //
    // Get the size of the buffer to be allocated
    //
    dwSize = GetEnvironmentVariable(
        L"MODULEPATH",
        pszModulePath,
        0);

    if(dwSize == 0)
    {
        wprintf(L"Environment variable MODULEPATH should point to module\r\n");
        goto finished;
    }

    //
    // Allocate buffer and call again
    //
    pszModulePath = (PWSTR)malloc(dwSize * sizeof(WCHAR));
    if(GetEnvironmentVariable(
        L"MODULEPATH",
        pszModulePath,
        dwSize) == 0)
    {
        wprintf(L"Error getting environment variable MODULEPATH\r\n");
        goto finished;
    }

    wprintf(L"Registration information for module %s\r\n\r\n", pszModulePath);

    //
    // Load the module whose registrations need to be found
    //
    hModule = LoadLibraryEx(
        pszModulePath,
        NULL,
        0);

    if(hModule == NULL)
    {
        wprintf(L"Couldn’t load module\r\n");
        wprintf(L"Aborting\r\n");
        goto finished;
    }

    //
    // Get RegisterModule entry point
    //
    PFN_REGISTERMODULE  pfnRegisterModule;
    pfnRegisterModule = (PFN_REGISTERMODULE)GetProcAddress(hModule, "RegisterModule" );

    if(pfnRegisterModule == NULL)
    {
        wprintf(L"RegisterModule entry point not found\r\n");
        wprintf(L"Aborting\r\n");
        goto finished;
    }

    //
    // Call register module now
    //
    MyRegistrationProvider * pRegProvider = new MyRegistrationProvider(pModuleInfo);

    hr = pfnRegisterModule(
        dwServerVersion,
        (IHttpModuleRegistrationInfo *)pRegProvider,
        pGlobalInfo);

    if(FAILED(hr))
    {
        wprintf(L"RegisterModule returned error\r\n");
        goto finished;
    }

finished:
    if(pRegProvider != NULL)
    {
        delete pRegProvider;
        pRegProvider = NULL;
    }

    if(hModule != NULL)
    {
        FreeLibrary(hModule);
        hModule = NULL;
    }

    if(pszModulePath != NULL)
    {
        free(pszModulePath);
        pszModulePath = NULL;
    }

    return S_OK;
}

Use attached GetMRegInstall.zip containing GetMRegInstall.exe to install the program.

-Kanwal

//
// Filename – module.cxx
//

 

    return hr;

    wcscpy(hwebcore, pszSystemDir);

 

Sample forms authentication test in C#

This sample test is doing the following:
1. Sending request to a page which requires forms authentication. This results in 302 to login page.
2. Send request to login page.
3. Parse response from 2 and create response entity containing username/password to be used in next post request to login page.
4. Do a POST to login page. If successful this should return a 302 with Set-Cookie and location header.
5. Send request to location pointed to in last response (this is original page we requested in 1) with request cookie as returned in 4. Expect 200.

using System;
using System.IO;
using System.Net;

namespace FormsAuthTest
{
    class Program
    {
        static void Main(string[] args)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            StreamReader sr = null;

            String originalUri = "http://localhost/default.aspx";

            System.Diagnostics.ConsoleTraceListener trace =
                    new System.Diagnostics.ConsoleTraceListener();

            //
            // Request page protected by forms authentication.
            // This request will get a 302 to login page
            //
            trace.Write("Requesting : " + originalUri);
            request = (HttpWebRequest)WebRequest.Create(originalUri);
            request.AllowAutoRedirect = false;

            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.Found)
            {
                trace.Write("Response: 302 ");
                trace.WriteLine(response.StatusCode);
            }
            else
            {
                trace.Fail("Response status is " + response.StatusCode + ". Expected was Found");
            }

           
//
            // Get the url of login page from location header
            //
            String locationHeader = response.GetResponseHeader("Location");
            trace.WriteLine("Location header is " + locationHeader);
            trace.WriteLine("");

           
//
            // Request login page
            //
            String loginPageUrl = "http://localhost" + locationHeader;
            Console.WriteLine("Requesting " + loginPageUrl);
            request = (HttpWebRequest)WebRequest.Create(loginPageUrl);
            request.AllowAutoRedirect = false;

            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                trace.Write("Response: 200 ");
                trace.WriteLine(response.StatusCode);
            }
            else
            {
                trace.Fail("Response status is " + response.StatusCode + ". Expected was OK");
            }

            trace.WriteLine("Parsing login page to create post message");
            trace.WriteLine("");

            sr = new StreamReader(response.GetResponseStream());
            String loginResponse = sr.ReadToEnd();
            sr.Close();

           
String
eventTargetVar = "__EVENTTARGET=";
            String eventTargetValue = "";

           
String
eventArgumentVar = "__EVENTARGUMENT=";
            String eventArgumentValue = "";

           
String
viewStateVar = "__VIEWSTATE=";
            String viewStateSearchString = "name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\"";
            int viewStateStartIndex = loginResponse.IndexOf(viewStateSearchString);
            loginResponse = loginResponse.Substring(viewStateStartIndex + viewStateSearchString.Length);
            String viewStateValue = Uri.EscapeDataString(
                                                           loginResponse.Substring(0, loginResponse.IndexOf("\" />"))
                                                       );
            loginResponse = loginResponse.Substring(loginResponse.IndexOf("\" />"));

           
String
 lcSearchStr = "input name=";
            int lcSearchIndex = 0;

            //
            // Look for logon control id
            // Use any valid username and password

            //
            lcSearchIndex = loginResponse.IndexOf(lcSearchStr);
            loginResponse = loginResponse.Substring(lcSearchIndex + lcSearchStr.Length + 1);
            String userNameVar = Uri.EscapeDataString(
                                                       loginResponse.Substring(0, loginResponse.IndexOf("\""))
                                                   ) + "=";
            String userNameValue = "Alice";

            lcSearchIndex = loginResponse.IndexOf(lcSearchStr);
            loginResponse = loginResponse.Substring(lcSearchIndex + lcSearchStr.Length + 1);
            String passwordVar = Uri.EscapeDataString(
                                                       loginResponse.Substring(0, loginResponse.IndexOf("\""))
                                                    ) + "=";
            String passwordValue = "alice123";

            lcSearchStr = "type=\"submit\" name=";
            lcSearchIndex = loginResponse.IndexOf(lcSearchStr);
            loginResponse = loginResponse.Substring(lcSearchIndex + lcSearchStr.Length + 1);
            String loginButtonVar = Uri.EscapeDataString(
                                                           loginResponse.Substring(0, loginResponse.IndexOf("\""))
                                                       ) + "=";
            String loginButtonValue = "Log+In";

           
String
eventValidationVar = "__EVENTVALIDATION=";
            String eventValSearchString =
                "name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\" value=\"";
            int eventValStartIndex = loginResponse.IndexOf(eventValSearchString);
            loginResponse = loginResponse.Substring(eventValStartIndex + eventValSearchString.Length);
            String eventValidationValue =
                Uri.EscapeDataString(
                    loginResponse.Substring(0, loginResponse.IndexOf("\" />"))
                );

            String postString = eventTargetVar + eventTargetValue;
            postString += "&" + eventArgumentVar + eventArgumentValue;
            postString += "&" + viewStateVar + viewStateValue;
            postString += "&" + userNameVar + userNameValue;
            postString += "&" + passwordVar + passwordValue;
            postString += "&" + loginButtonVar + loginButtonValue;
            postString += "&" + eventValidationVar + eventValidationValue;

           
//
            // Do a POST to login.aspx now
            // This should result in 302 with Set-Cookie header
            //
            Console.WriteLine("POST request to http://localhost" + locationHeader);
            request = (HttpWebRequest)WebRequest.Create("http://localhost" + locationHeader);
            request.AllowAutoRedirect = false;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] requestData = encoding.GetBytes(postString);
            request.ContentLength = requestData.Length;

           
Stream
requestStream = request.GetRequestStream();
            requestStream.Write(requestData, 0, requestData.Length);
            requestStream.Close();

            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.Found)
            {
                trace.Write("Response: 302 ");
                trace.WriteLine(response.StatusCode);
            }
            else
            {
                trace.Fail("Response status is " + response.StatusCode + ". Expected was Found");
            }

            locationHeader = response.GetResponseHeader("Location");
            trace.WriteLine("Location header is " + locationHeader);
            String cookie = response.GetResponseHeader("Set-Cookie");
            trace.WriteLine("Set-Cookie header is " + cookie);
            trace.WriteLine("");

           
//
            // Send request to originalUri with the cookie
            // We should be able to see originalUri contents
            //
            trace.WriteLine("Requesting http://localhost" + locationHeader + " with cookie");
            request = (HttpWebRequest)WebRequest.Create("http://localhost" + locationHeader);
            request.AllowAutoRedirect = false;
            request.Headers.Add(HttpRequestHeader.Cookie, cookie);

            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                trace.Write("Response: 200 ");
                trace.WriteLine(response.StatusCode);
            }
            else
            {
                trace.Fail("Response status is " + response.StatusCode + ". Expected was OK");
            }
            trace.WriteLine("");

            trace.WriteLine("Contents of " + originalUri);
            trace.WriteLine("");

            sr = new StreamReader(response.GetResponseStream());
            trace.WriteLine(sr.ReadToEnd());
            sr.Close();
        }
    }
}

Above sample is requesting aspx content. You can remove precondition from FormsAuthentication module on your server and use the same code to request non-aspx content as well.

Kanwal