Leaked source code of windows server 2003
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

/*++
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);
}
}