|
|
/*++
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>
//extern HANDLE hevtDone;
#define REG_FP_LOAD_VALUE "NewFPWebCmdLine"
#define REG_FP_UNLOAD_VALUE "DelFPWebCmdLine"
#ifdef _NO_TRACING_
DECLARE_DEBUG_PRINTS_OBJECT(); #endif
CSvcExtImpIMDCOMSINK::CSvcExtImpIMDCOMSINK(IMDCOM * pcCom): m_dwRefCount(1), m_pcCom(pcCom) { }
CSvcExtImpIMDCOMSINK::~CSvcExtImpIMDCOMSINK() { }
HRESULT CSvcExtImpIMDCOMSINK::QueryInterface(REFIID riid, void **ppObject) { 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( /* [in] */ METADATA_HANDLE hMDHandle, /* [in] */ DWORD dwMDNumElements, /* [size_is][in] */ MD_CHANGE_OBJECT __RPC_FAR pcoChangeList[ ]) { DWORD i, 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: { ProcessServerCommand(pcoChangeList[i].pszMDPath); 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( /* [in] */ 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 ) { HKEY hkey = NULL; CHAR buff[255]; CHAR cmd[512]; CHAR achPath[512]; LPSTR pszOp; DWORD cbBuff = sizeof( buff ); DWORD dwType; DWORD dwValue; 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 = 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; DWORD ErrorCode;
sprintf( cmd, buff, achPath );
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 {
DBGINFOW((DBG_CONTEXT, L"[RegisterFrontPage] Failed to open reg or read value\n")); }
if ( hkey ) { RegCloseKey( hkey ); } } }
VOID CSvcExtImpIMDCOMSINK::ProcessServerCommand( LPWSTR pszPath ) { HKEY hkey = NULL; WCHAR pszServiceName[METADATA_MAX_NAME_LEN]; DWORD dwType; DWORD dwValue; DWORD dwRequiredDataLen; HRESULT hresReturn; METADATA_RECORD mdrData;
MD_SET_DATA_RECORD_EXT(&mdrData, MD_SERVER_COMMAND, 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"[ProcessServerCommand] 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 == MD_SERVER_COMMAND_START) { 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; DWORD errorCode; DWORD iPoll; SERVICE_STATUS ss;
DBG_ASSERT(pszServiceName != NULL);
if ( IISGetPlatformType() == PtWindows95 )
{ //
// Start service Win95-style
//
if ( !IsInetinfoRunning() ) { if ( _wcsicmp( pszServiceName, L"W3SVC" ) == 0 ) { // We only can start W3SVC on Win95
if ( !W95StartW3SVC() ) { DBGINFOW((DBG_CONTEXT, L"[StartIISService] W95StartW3SVC Failed\n")); } } } }
else
{ //
// 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);
}
}
return; }
|