//
// 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);