|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
sink.cxx
Abstract:
IIS Services IISADMIN Extension Unicode Metadata Sink.
Author:
Michael W. Thomas 16-Sep-97
--*/ #include <cominc.hxx>
#include "w3ssl_config.hxx"
//extern HANDLE hevtDone;
#define REG_FP_LOAD_VALUE "NewFPWebCmdLine"
#define REG_FP_UNLOAD_VALUE "DelFPWebCmdLine"
CSvcExtImpIMDCOMSINK::CSvcExtImpIMDCOMSINK( IMDCOM * pcCom): m_dwRefCount(1), m_pcCom(pcCom) { }
CSvcExtImpIMDCOMSINK::~CSvcExtImpIMDCOMSINK() { }
HRESULT CSvcExtImpIMDCOMSINK::QueryInterface( REFIID riid, void **ppObject) { if ( ppObject == NULL ) { return E_INVALIDARG; }
*ppObject = NULL;
if (riid==IID_IUnknown || riid==IID_IMDCOMSINK_W) { *ppObject = (IMDCOMSINKW *) this; } else { return E_NOINTERFACE; }
AddRef(); return NO_ERROR; }
ULONG CSvcExtImpIMDCOMSINK::AddRef() { DWORD dwRefCount; dwRefCount = InterlockedIncrement((long *)&m_dwRefCount); return dwRefCount; }
ULONG CSvcExtImpIMDCOMSINK::Release() { DWORD dwRefCount; dwRefCount = InterlockedDecrement((long *)&m_dwRefCount); if (dwRefCount == 0) { delete this; }
return dwRefCount; }
#define SCHEMA_PATH_PREFIX IIS_MD_ADSI_SCHEMA_PATH_W L"/"
HRESULT STDMETHODCALLTYPE CSvcExtImpIMDCOMSINK::ComMDSinkNotify( METADATA_HANDLE , DWORD dwMDNumElements, MD_CHANGE_OBJECT __RPC_FAR pcoChangeList[ ]) { DWORD i; DWORD j;
for (i = 0; i < dwMDNumElements; i++) { if (((pcoChangeList[i].dwMDChangeType | MD_CHANGE_TYPE_SET_DATA) != 0) &&
//
// If this is a schema change, then don't do anything
//
(_wcsnicmp(pcoChangeList[i].pszMDPath, SCHEMA_PATH_PREFIX, ((sizeof(SCHEMA_PATH_PREFIX) / sizeof(WCHAR)) - 1)) != 0)) { for (j = 0; j < pcoChangeList[i].dwMDNumDataIDs; j++) { switch (pcoChangeList[i].pdwMDDataIDs[j]) { case MD_FRONTPAGE_WEB: { RegisterFrontPage( pcoChangeList[i].pszMDPath ); break; }
case MD_SERVER_COMMAND: { ProcessCommand(pcoChangeList[i].pszMDPath, MD_SERVER_COMMAND, MD_SERVER_COMMAND_START ); break; }
case MD_APPPOOL_COMMAND: { ProcessCommand(pcoChangeList[i].pszMDPath, MD_APPPOOL_COMMAND, MD_APPPOOL_COMMAND_START); break; }
case MD_GLOBAL_STANDARD_APP_MODE_ENABLED: { W3SSL_CONFIG::AdjustHTTPFilterImagePath(); break; }
default: ;
//
// No specific action for this command
//
} } } } return S_OK; }
#define REG_KEY_W3SVC_VROOTS TEXT("SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters\\Virtual Roots")
#define REG_KEY_MSFTPSVC_VROOTS TEXT("SYSTEM\\CurrentControlSet\\Services\\MSFTPSVC\\Parameters\\Virtual Roots")
HRESULT STDMETHODCALLTYPE CSvcExtImpIMDCOMSINK::ComMDEventNotify( DWORD dwMDEvent) { DWORD err;
if (dwMDEvent == MD_EVENT_MID_RESTORE) { //
// Blow away registry VRoots so they won't be brought back to life
//
err = RegDeleteKey(HKEY_LOCAL_MACHINE, REG_KEY_W3SVC_VROOTS); if ( err != ERROR_SUCCESS ) { DBGINFOW((DBG_CONTEXT, L"[ComMDEventNotify] (%x) Couldn't remove W3SVC VRoot key\n", err )); }
err = RegDeleteKey(HKEY_LOCAL_MACHINE, REG_KEY_MSFTPSVC_VROOTS); if ( err != ERROR_SUCCESS ) { DBGINFOW((DBG_CONTEXT, L"[ComMDEventNotify] (%x) Couldn't remove MSFTPSVC VRoot key\n", err )); }
}
//
// Sync up the user accounts with those from the metabase
//
UpdateUsers( TRUE );
return S_OK; }
//
// This must be in a non-Unicode file so that registry reads on Win95 work.
//
VOID CSvcExtImpIMDCOMSINK::RegisterFrontPage( LPWSTR pszPath) { HRESULT hr = S_OK; HKEY hkey = NULL; CHAR buff[255]; CHAR cmd[512]; CHAR achPath[512]; LPSTR pszOp; DWORD cbBuff = sizeof( buff ); DWORD dwType; DWORD dwValue = 0; DWORD dwRequiredDataLen; HRESULT hresReturn; METADATA_RECORD mdrData;
MD_SET_DATA_RECORD_EXT(&mdrData, MD_FRONTPAGE_WEB, METADATA_NO_ATTRIBUTES, ALL_METADATA, DWORD_METADATA, sizeof(DWORD), (PBYTE)&dwValue)
hresReturn = m_pcCom->ComMDGetMetaData(METADATA_MASTER_ROOT_HANDLE, pszPath, &mdrData, &dwRequiredDataLen);
if (FAILED(hresReturn)) { if (hresReturn != MD_ERROR_DATA_NOT_FOUND) { DBGINFOW((DBG_CONTEXT, L"[RegisterFrontPage] GetData Failed, return code = %X\n", hresReturn)); } } else { DBGINFOW(( DBG_CONTEXT, L"[RegisterFrontPage] Value - %d, Path - %S\n", dwValue, pszPath ));
//
// PREFIX
// ComMDGetMetaData should not return success without setting the data
// value pointed to by dwValue. I'm not sure if PREFIX is incapable of
// recognizing the extra level of indirection or if there is some path
// that I missed in reviewing ComMDGetMetaData. I'm going to shut down
// this warning, but I'll open an issue with the PREFIX guys.
//
/* INTRINSA suppress = uninitialized */ pszOp = dwValue ? REG_FP_LOAD_VALUE : REG_FP_UNLOAD_VALUE;
if ( !RegOpenKeyExA( HKEY_LOCAL_MACHINE, REG_FP_PATH, 0, KEY_READ, &hkey ) && !RegQueryValueExA( hkey, pszOp, NULL, &dwType, (BYTE *) buff, &cbBuff )) {
if ( WideCharToMultiByte( CP_ACP, 0, pszPath, -1, achPath, sizeof(achPath), NULL, NULL ) == 0 ) { DBGINFOW((DBG_CONTEXT, L"Failed to convert path to Ansi, error = %d\n", GetLastError() )); } else {
//
// FrontPage cannot handle trailing slash, so remove it.
// Need to restore as this is not a local copy of path.
//
DWORD dwPathLen = (DWORD)strlen(achPath);
DBG_ASSERT(achPath[dwPathLen - 1] == '/');
achPath[dwPathLen - 1] = '\0';
if ( (strlen( buff ) + (dwPathLen - 1)) < sizeof( cmd ) ) { STARTUPINFOA StartupInfo; PROCESS_INFORMATION ProcessInformation; BOOL CreateProcessStatus;
hr = StringCbVPrintfA( cmd, sizeof(cmd), buff, achPath ); if ( SUCCEEDED(hr) ) { RtlZeroMemory(&StartupInfo,sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.dwFlags = 0; StartupInfo.wShowWindow = 0; CreateProcessStatus = CreateProcessA( NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInformation );
if ( CreateProcessStatus ) { DBG_REQUIRE( CloseHandle(ProcessInformation.hProcess) ); DBG_REQUIRE( CloseHandle(ProcessInformation.hThread) ); } else { DBGPRINTF(( DBG_CONTEXT, "[RegisterFrontPage] CreateProcess returned %d for %s\n", GetLastError(), cmd )); } } else { DBGPRINTF(( DBG_CONTEXT, "[RegisterFrontPage] StringCbVPrintfA returned 0x%08x for %s\n", hr, cmd )); } } }
} else { DBGINFOW((DBG_CONTEXT, L"[RegisterFrontPage] Failed to open reg or read value\n")); }
if ( hkey ) { RegCloseKey( hkey ); } } }
VOID CSvcExtImpIMDCOMSINK::ProcessCommand( LPWSTR pszPath, DWORD dwMetabaseProperty, DWORD dwStartValue) { WCHAR pszServiceName[METADATA_MAX_NAME_LEN]; DWORD dwValue = 0; DWORD dwRequiredDataLen; HRESULT hresReturn; METADATA_RECORD mdrData;
MD_SET_DATA_RECORD_EXT(&mdrData, dwMetabaseProperty, METADATA_NO_ATTRIBUTES, ALL_METADATA, DWORD_METADATA, sizeof(DWORD), (PBYTE)&dwValue)
hresReturn = m_pcCom->ComMDGetMetaData(METADATA_MASTER_ROOT_HANDLE, pszPath, &mdrData, &dwRequiredDataLen);
if (FAILED(hresReturn)) { DBGINFOW((DBG_CONTEXT, L"[ProcessCommandInternal] GetData Failed, return code = %X\n", hresReturn)); } else { //
// PREFIX
// ComMDGetMetaData should not return success without setting the data
// value pointed to by dwValue. I'm not sure if PREFIX is incapable of
// recognizing the extra level of indirection or if there is some path
// that I missed in reviewing ComMDGetMetaData. I'm going to shut down
// this warning, but I'll open an issue with the PREFIX guys.
//
/* INTRINSA suppress = uninitialized */ if (dwValue == dwStartValue) { if (GetServiceNameFromPath(pszPath, pszServiceName)) { StartIISService(pszServiceName); } } }
}
#define SERVICE_NAME_PREFIX L"/LM/"
BOOL GetServiceNameFromPath( LPWSTR pszPath, LPWSTR pszServiceName) /*++
Routine Description:
Start an IIS service
Arguments: pszPath - path spcifying which IIS service to start pszServiceName - updated with service name
Return Value: TRUE - Success FALSE - Failure
--*/ { LPWSTR pszPathIndex; UINT cS;
DBG_ASSERT(pszPath != NULL); DBG_ASSERT(pszServiceName != NULL);
pszPathIndex = pszPath; if ((_wcsnicmp( pszPathIndex, \ SERVICE_NAME_PREFIX, ((sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) - 1)) == 0) && (pszPath[(sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) - 1] != (WCHAR)'\0')) { pszPathIndex += ((sizeof(SERVICE_NAME_PREFIX) / sizeof(WCHAR)) -1);
//
// copy to temp buffer until path delim
//
for ( cS = 0 ; cS < METADATA_MAX_NAME_LEN-1 && (*pszPathIndex != (WCHAR)'/'); ) { pszServiceName[cS++] = *pszPathIndex++; } pszServiceName[cS] = (WCHAR)'\0';
return TRUE; }
return FALSE; }
VOID StartIISService( LPWSTR pszServiceName) /*++
Routine Description:
Start an IIS service
Arguments: pszServiceName - specify which IIS service to start
Return Value: TRUE - Success FALSE - Failure
--*/ { SC_HANDLE scManagerHandle; SC_HANDLE serviceHandle;
DBG_ASSERT(pszServiceName != NULL);
//
// Start service WinNT-style
//
//
// Open the service control manager
//
scManagerHandle = OpenSCManager( NULL, // local machine
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS ); // all access
if ( scManagerHandle != NULL ) { //
// Open the service
//
serviceHandle = OpenService( scManagerHandle, pszServiceName, SERVICE_START );
if ( serviceHandle != NULL ) { //
// Make sure the service is running
//
if (!StartService( serviceHandle, 0, NULL) && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)) { DBGINFOW(( DBG_CONTEXT, L"[StartIISService] StartService(%s) Failed, Error = %X\n", pszServiceName, GetLastError())); }
CloseServiceHandle( serviceHandle ); }
//
// Close open handle
//
CloseServiceHandle( scManagerHandle);
} }
|