You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
541 lines
15 KiB
541 lines
15 KiB
/*++
|
|
|
|
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);
|
|
|
|
}
|
|
}
|