|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
iisadmin.cxx
Abstract:
Contains the admin functions of the IIS_SERVICE class
Author:
Johnson Apacible (JohnsonA) 24-June-1996
--*/
#include "tcpdllp.hxx"
#include <rpc.h>
#include <tsunami.hxx>
#include <iistypes.hxx>
#include "inetreg.h"
#include "tcpcons.h"
#include "apiutil.h"
BOOL PopulateSiteArray( LPINET_INFO_SITE_LIST * ppSites, PVOID pvUnused, IN IIS_SERVER_INSTANCE * pInst );
PIIS_SERVICE IIS_SERVICE::FindFromServiceInfoList( IN DWORD dwServiceId ) /*++
Description:
Finds a given Services Info object from the global list.
Arguments:
dwServiceId - Service id of service to look for.
Returns: pointer to service object, if found. NULL, otherwise.
--*/ { PLIST_ENTRY listEntry; PIIS_SERVICE pInetSvc;
//
// Loop through the list of running internet servers and call the callback
// for each server that has one of the service id bits set
//
AcquireGlobalLock( ); for ( listEntry = sm_ServiceInfoListHead.Flink; listEntry != &sm_ServiceInfoListHead; listEntry = listEntry->Flink ) {
pInetSvc = CONTAINING_RECORD( listEntry, IIS_SERVICE, m_ServiceListEntry );
if ( dwServiceId == pInetSvc->QueryServiceId() && (pInetSvc->QueryCurrentServiceState() == SERVICE_RUNNING || pInetSvc->QueryCurrentServiceState() == SERVICE_PAUSED ) ) {
//
// reference and return
//
if ( !pInetSvc->CheckAndReference( ) ) { IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "Failed to reference service %d\n", dwServiceId)); } pInetSvc = NULL; }
ReleaseGlobalLock( ); return pInetSvc; } }
ReleaseGlobalLock( );
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "FindFromServiceList cannot find service %d\n", dwServiceId)); }
return NULL;
} // IIS_SERVICE::FindFromServiceInfoList
BOOL IIS_SERVICE::SetServiceAdminInfo( IN DWORD dwLevel, IN DWORD dwServiceId, IN DWORD dwInstance, IN BOOL fCommonConfig, IN INETA_CONFIG_INFO * pConfigInfo ) /*++
Description:
Sets the service configuration.
Arguments:
dwLevel - Info level dwServiceId - ID of service to set dwInstance - ID of instance to set fCommonConfig - Determines if we should set the common or the service configuration pConfigInfo - Configuration structure
Returns: TRUE on sucess and FALSE if there is a failure
--*/ { BOOL fRet = TRUE; PIIS_SERVICE pInetSvc;
DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "SetServiceAdmin called for svc %d inst %d\n", dwServiceId, dwInstance)); }
pInetSvc = FindFromServiceInfoList( dwServiceId ); if ( pInetSvc == NULL ) { SetLastError( ERROR_SERVICE_NOT_ACTIVE); fRet = FALSE; goto exit; }
//
// Set the parameters and update
//
fRet = pInetSvc->SetInstanceConfiguration( dwInstance, dwLevel, fCommonConfig, pConfigInfo );
//
// This was referenced in Find
//
pInetSvc->Dereference( ); exit: return fRet; } // IIS_SERVICE::SetServiceAdminInfo
BOOL IIS_SERVICE::GetServiceAdminInfo( IN DWORD dwLevel, IN DWORD dwServiceId, IN DWORD dwInstance, IN BOOL fCommonConfig, OUT PDWORD nRead, OUT LPINETA_CONFIG_INFO * ppConfigInfo ) /*++
Description:
Gets the service configuration.
Arguments:
dwLevel - Info level of this operation dwServiceId - ID of service to get dwInstance - ID of instance to get fCommonConfig - Determines if we should get the common or the service configuration pBuffer - on return, will contains a pointer to the configuration block
Returns: TRUE on sucess and FALSE if there is a failure
--*/ { BOOL fRet = FALSE; PIIS_SERVICE pInetSvc;
DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "GetServiceAdmin called for svc %d inst %x\n", dwServiceId, dwInstance)); }
pInetSvc = FindFromServiceInfoList( dwServiceId ); if ( pInetSvc == NULL ) { SetLastError( ERROR_SERVICE_NOT_ACTIVE); goto exit; }
//
// Get the params
//
fRet = pInetSvc->GetInstanceConfiguration( dwInstance, dwLevel, fCommonConfig, nRead, ppConfigInfo );
//
// This was referenced in Find
//
pInetSvc->Dereference( );
exit: return fRet; } // IIS_SERVICE::GetServiceAdminInfo
BOOL IIS_SERVICE::GetServiceSiteInfo( IN DWORD dwServiceId, OUT LPINET_INFO_SITE_LIST * ppSites ) /*++
Description:
Gets the list of service instances.
Arguments:
dwServiceId - ID of service to get ppSites - on return, will contain a pointer to the array of sites
Returns: TRUE on sucess and FALSE if there is a failure
--*/ { BOOL fRet = FALSE; PIIS_SERVICE pInetSvc; DWORD cInstances = 0; LPINET_INFO_SITE_LIST pSites; DBG_ASSERT( IIS_SERVICE::sm_fInitialized);
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "GetServiceSiteInfo called for svc %d\n", dwServiceId)); }
pInetSvc = FindFromServiceInfoList( dwServiceId ); if ( pInetSvc == NULL ) { SetLastError( ERROR_SERVICE_NOT_ACTIVE); return FALSE; }
//
// Get the params
//
pInetSvc->AcquireServiceLock(TRUE);
cInstances = pInetSvc->QueryInstanceCount();
//allocate enough memory to hold the Site Info Arrary
pSites = (LPINET_INFO_SITE_LIST) midl_user_allocate (sizeof(INET_INFO_SITE_LIST) + sizeof(INET_INFO_SITE_ENTRY)*cInstances);
if (!pSites) { pInetSvc->ReleaseServiceLock(TRUE);
//This was referenced in Find
pInetSvc->Dereference( ); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } *ppSites = pSites; pSites->cEntries = 0; fRet = pInetSvc->EnumServiceInstances( (PVOID) ppSites, NULL, (PFN_INSTANCE_ENUM) PopulateSiteArray ); if (!fRet) { for (DWORD i=0; i<pSites->cEntries; i++) { midl_user_free(pSites->aSiteEntry[i].pszComment); } midl_user_free(pSites);
*ppSites = NULL; } pInetSvc->ReleaseServiceLock(TRUE);
//This was referenced in Find
pInetSvc->Dereference( ); return fRet; } // IIS_SERVICE::GetServiceSiteInfo
BOOL PopulateSiteArray( LPINET_INFO_SITE_LIST * ppSites, PVOID pvUnused, IN IIS_SERVER_INSTANCE * pInst ) /*++
Description:
Fills the ppSites array with the instance id and site comment.
Arguments: pvUnused - not used pInst - pointer to service instance ppSites - on return, will contain a pointer to the array of sites
Returns: TRUE on sucess and FALSE if there is a failure
--*/ { DWORD cbComment = 0; LPINET_INFO_SITE_LIST pSites = *ppSites;
//Set the instance ID
pSites->aSiteEntry[pSites->cEntries].dwInstance = pInst->QueryInstanceId();
//allocate memory for the site name
cbComment = (strlen(pInst->QuerySiteName())+1) * sizeof(WCHAR); pSites->aSiteEntry[pSites->cEntries].pszComment = (LPWSTR)midl_user_allocate(cbComment);
if (!(pSites->aSiteEntry[pSites->cEntries].pszComment)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; }
//
// Need unicode conversion here
//
if (!MultiByteToWideChar( CP_ACP, // code page
MB_PRECOMPOSED, // character-type options
pInst->QuerySiteName(), // address of string to map
-1, // number of bytes in string
pSites->aSiteEntry[pSites->cEntries].pszComment, // address of wide-character buffer
cbComment / sizeof(WCHAR) // size of buffer
)) { pSites->aSiteEntry[pSites->cEntries].pszComment[0] = L'\0'; }
pSites->cEntries++;
return TRUE;
} //PopulateSiteArray
DWORD IIS_SERVICE::GetNewInstanceId( VOID ) /*++
Description:
Returns a new instance ID.
Arguments:
None.
Returns:
A non zero dword containing the instance ID. 0 if there was an error.
--*/ { DWORD dwId; CHAR regParamKey[MAX_PATH+1]; MB mb( (IMDCOM*) QueryMDObject() );
AcquireServiceLock( );
for (; ; ) {
dwId = ++m_maxInstanceId;
if ( m_maxInstanceId > INET_INSTANCE_MAX ) { m_maxInstanceId = INET_INSTANCE_MIN; }
//
// Make sure the metapath does not exist
//
GetMDInstancePath( dwId, regParamKey ); if ( !mb.Open( regParamKey ) ) {
DBG_ASSERT(GetLastError() == ERROR_FILE_NOT_FOUND); if ( GetLastError() != ERROR_FILE_NOT_FOUND ) { DBGPRINTF((DBG_CONTEXT, "Error %d trying to open %s.\n", GetLastError(), regParamKey ));
dwId = 0; } break; }
}
ReleaseServiceLock( );
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "GetNewInstanceId returns %d\n", dwId)); }
return dwId;
} // IIS_SERVICE::GetNewInstanceId
BOOL IIS_SERVICE::SetInstanceConfiguration( IN DWORD dwInstance, IN DWORD dwLevel, IN BOOL fCommonConfig, IN LPINETA_CONFIG_INFO pConfig ) /*++
Description:
Set the configuration for the instance.
Arguments:
dwInstance - Instance number to find - IGNORED FOR SET!! dwLevel - level of information to set pCommonConfig - Whether info is common or service specific pConfig - pointer to the configuration block
Returns:
A dword containing the instance ID. --*/ { BOOL fRet = FALSE; PLIST_ENTRY listEntry; PIIS_SERVER_INSTANCE pInstance;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "SetInstanceConfiguration called for instance %d\n", dwInstance)); }
//
// Try to find this instance
//
AcquireServiceLock( TRUE );
//
// Find the instance in the instance list
//
if ( dwInstance == INET_INSTANCE_ROOT ) { DBG_ASSERT( !"Explicit default instance no longer supported inherited from metabase)\n" ); pInstance = NULL; } else { pInstance = FindIISInstance( QueryDownLevelInstance() ); }
if ( pInstance != NULL ) { goto found; }
SetLastError(ERROR_FILE_NOT_FOUND); DBG_ASSERT(!fRet); goto exit;
found:
if ( fCommonConfig ) {
fRet = pInstance->SetCommonConfig( pConfig, TRUE);
} else {
fRet = pInstance->SetServiceConfig( (CHAR *) pConfig); }
exit: ReleaseServiceLock( TRUE ); return fRet;
} // IIS_SERVICE::SetInstanceConfiguration
BOOL IIS_SERVICE::GetInstanceConfiguration( IN DWORD dwInstance, IN DWORD dwLevel, IN BOOL fCommonConfig, OUT PDWORD nRead, OUT LPINETA_CONFIG_INFO * pBuffer ) /*++
Description:
Get the configuration for the instance.
Arguments:
dwInstance - Instance number to find - IGNORED!! dwLevel - level of information to get pCommonConfig - Whether info is common or service specific nRead - pointer to a DWORD where the number of entries to be returned is set. pBuffer - pointer to the configuration block
Returns:
A dword containing the instance ID. --*/ {
PLIST_ENTRY listEntry; PIIS_SERVER_INSTANCE pInstance; DWORD nInstances = 1; DWORD nSize; PCHAR pConfig;
//
// Set and Get only work against the default instance
//
dwInstance = QueryDownLevelInstance();
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "GetInstanceConfiguration [%x][%d] called for instance %x L%d\n", this, fCommonConfig, dwInstance, dwLevel)); }
//
// We support only 1
//
*nRead = 0; *pBuffer = NULL;
if ( fCommonConfig ) {
DBG_ASSERT( dwLevel == 1 );
nSize = sizeof( INETA_CONFIG_INFO );
} else {
DWORD err;
nSize = GetServiceConfigInfoSize(dwLevel); if ( nSize == 0 ) { SetLastError(ERROR_INVALID_LEVEL); return(FALSE); } }
//
// Try to find this instance
//
AcquireServiceLock( );
if ( dwInstance == INET_INSTANCE_ALL ) { nInstances = QueryInstanceCount( ); if ( nInstances == 0 ) { goto exit; } IF_DEBUG(INSTANCE) { DBGPRINTF((DBG_CONTEXT,"%d instances found\n",nInstances)); } }
*pBuffer = (LPINETA_CONFIG_INFO) MIDL_user_allocate(nInstances * nSize); if ( *pBuffer == NULL ) { goto error_exit; }
ZeroMemory( *pBuffer, nInstances * nSize );
//
// Loop through the list of running internet servers and call the callback
// for each server that has one of the service id bits set
//
pConfig = (CHAR *) *pBuffer;
if ( dwInstance != INET_INSTANCE_ROOT ) {
for ( listEntry = m_InstanceListHead.Flink; listEntry != &m_InstanceListHead; listEntry = listEntry->Flink ) {
pInstance = CONTAINING_RECORD( listEntry, IIS_SERVER_INSTANCE, m_InstanceListEntry );
if ( (dwInstance == pInstance->QueryInstanceId()) || (dwInstance == INET_INSTANCE_ALL) || (dwInstance == INET_INSTANCE_FIRST) ) {
if ( fCommonConfig ) { if ( !pInstance->GetCommonConfig(pConfig,dwLevel) ) { goto error_exit; } } else { if ( !pInstance->GetServiceConfig(pConfig,dwLevel) ) { goto error_exit; } }
//
// if not get all, return.
//
(*nRead)++; pConfig += nSize;
if ( dwInstance != INET_INSTANCE_ALL ) { break; } } } } else {
DBG_ASSERT( !"Default instance no longer supported!\n" ); }
exit:
if ( *nRead == 0 ) { if ( dwInstance != INET_INSTANCE_ALL ) { SetLastError(ERROR_FILE_NOT_FOUND); goto error_exit; } }
ReleaseServiceLock( );
DBG_ASSERT(nInstances == *nRead); return TRUE;
error_exit:
ReleaseServiceLock( );
IF_DEBUG(ERROR) { DBGPRINTF((DBG_CONTEXT,"Error %x in GetInstanceConfiguration\n", GetLastError())); }
if ( *pBuffer != NULL ) { MIDL_user_free(*pBuffer); *pBuffer = NULL; } *nRead = 0; return(FALSE);
} // IIS_SERVICE::GetInstanceConfiguration
PIIS_SERVER_INSTANCE IIS_SERVICE::FindIISInstance( IN DWORD dwInstance ) /*++
Description:
Find the instance *** Service lock assumed held ***
Arguments:
dwInstance - Instance number to find
Returns:
Pointer to the instance. NULL if not found. --*/ { BOOL fRet = TRUE; PLIST_ENTRY listEntry; PIIS_SERVER_INSTANCE pInstance;
//
// Find the instance in the instance list
//
for ( listEntry = m_InstanceListHead.Flink; listEntry != &m_InstanceListHead; listEntry = listEntry->Flink ) {
pInstance = CONTAINING_RECORD( listEntry, IIS_SERVER_INSTANCE, m_InstanceListEntry );
if ( (dwInstance == pInstance->QueryInstanceId()) || (dwInstance == INET_INSTANCE_FIRST) ) {
return pInstance; } }
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "FindIISInstance: Cannot find instance %d\n", dwInstance)); }
SetLastError(ERROR_FILE_NOT_FOUND); return(NULL);
} // IIS_SERVICE::FindIISInstance
BOOL IIS_SERVICE::DeleteInstanceInfo( IN DWORD dwInstance ) { PIIS_SERVER_INSTANCE pInstance; DWORD err = NO_ERROR;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "DeleteInstanceInfo called for %d\n", dwInstance)); }
//
// Find the instance and close it
//
AcquireServiceLock( TRUE );
//
// Find the instance in the instance list
//
pInstance = FindIISInstance( dwInstance );
if( pInstance == NULL ) {
err = ERROR_FILE_NOT_FOUND;
} else {
//
// Remove it from the list
//
RemoveEntryList( &pInstance->m_InstanceListEntry ); m_nInstance--;
//
// Shut it down
//
pInstance->CloseInstance();
//
// Dereference it
//
pInstance->Dereference( );
}
ReleaseServiceLock( TRUE );
if( err == NO_ERROR ) {
return TRUE;
}
SetLastError( err ); return FALSE;
} // IIS_SERVICE::DeleteInstanceInfo
BOOL IIS_SERVICE::EnumerateInstanceUsers( IN DWORD dwInstance, OUT PDWORD nRead, OUT PCHAR* pBuffer ) {
PIIS_SERVER_INSTANCE pInstance; BOOL fRet;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "EnumerateInstanceUsers called for service %x (Instance %d)\n", this, dwInstance )); }
//
// Find the instance
//
AcquireServiceLock( );
//
// Find the instance in the instance list
//
pInstance = FindIISInstance( dwInstance ); if ( pInstance != NULL ) { goto found; }
ReleaseServiceLock( ); SetLastError(ERROR_FILE_NOT_FOUND); return(FALSE);
found:
fRet = pInstance->EnumerateUsers( pBuffer, nRead ); ReleaseServiceLock( );
return(fRet);
} // IIS_SERVICE::EnumerateInstanceUsers
BOOL IIS_SERVICE::DisconnectInstanceUser( IN DWORD dwInstance, IN DWORD dwIdUser ) {
PIIS_SERVER_INSTANCE pInstance; BOOL fRet;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "DisconnectInstanceUsers called for service %x (Instance %d)\n", this, dwInstance )); }
//
// Find the instance
//
AcquireServiceLock( );
//
// Find the instance in the instance list
//
pInstance = FindIISInstance( dwInstance ); if ( pInstance != NULL ) { goto found; }
ReleaseServiceLock( ); SetLastError(ERROR_FILE_NOT_FOUND); return(FALSE);
found:
fRet = pInstance->DisconnectUser( dwIdUser ); ReleaseServiceLock( );
return(fRet);
} // IIS_SERVICE::DisconnectInstanceUsers
BOOL IIS_SERVICE::GetInstanceStatistics( IN DWORD dwInstance, IN DWORD dwLevel, OUT PCHAR* pBuffer ) {
PIIS_SERVER_INSTANCE pInstance; BOOL fRet;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "GetInstanceStats called for service %x (Instance %d)\n", this, dwInstance )); }
//
// Find the instance and close it
//
AcquireServiceLock( TRUE);
if (dwInstance == 0 ) { fRet = GetGlobalStatistics(dwLevel,pBuffer); } else if ( dwInstance == INET_INSTANCE_GLOBAL) { //
// We need to aggregate statistics across all instances
//
PLIST_ENTRY listEntry; PCHAR pStats; BOOL fFirst = TRUE;
fRet = FALSE; *pBuffer = NULL; //
// Loop through all the instances and add their counters
//
for ( listEntry = m_InstanceListHead.Flink; listEntry != &m_InstanceListHead; listEntry = listEntry->Flink) { pInstance = CONTAINING_RECORD( listEntry, IIS_SERVER_INSTANCE, m_InstanceListEntry );
pInstance->LockThisForRead(); fRet = pInstance->GetStatistics(dwLevel, &pStats); pInstance->UnlockThis(); if (fRet) { if (fFirst) { //
// This is the first successful retrieval.
//
*pBuffer = pStats; fFirst = FALSE; } else { AggregateStatistics(*pBuffer, pStats); MIDL_user_free(pStats); } } } } else {
//
// Find the instance in the instance list
//
pInstance = FindIISInstance( dwInstance ); if ( pInstance != NULL ) { fRet = pInstance->GetStatistics(dwLevel,pBuffer); } else { SetLastError(ERROR_FILE_NOT_FOUND); fRet = FALSE; } }
ReleaseServiceLock( TRUE);
return(fRet);
} // IIS_SERVICE::GetInstanceStatistics
BOOL IIS_SERVICE::GetGlobalStatistics( IN DWORD dwLevel, OUT PCHAR *pBuffer ) { return FALSE; } // IIS_SERVICE::GetGlobalStatistics
BOOL IIS_SERVICE::ClearInstanceStatistics( IN DWORD dwInstance ) {
PIIS_SERVER_INSTANCE pInstance; BOOL fRet;
IF_DEBUG( INSTANCE ) { DBGPRINTF((DBG_CONTEXT, "ClearInstanceStats called for service %x (instance %d)\n", this, dwInstance )); }
//
// Find the instance and close it
//
AcquireServiceLock( );
//
// Find the instance in the instance list
//
pInstance = FindIISInstance( dwInstance ); if ( pInstance != NULL ) { goto found; }
ReleaseServiceLock( ); SetLastError(ERROR_FILE_NOT_FOUND); return(FALSE);
found:
fRet = pInstance->ClearStatistics( ); ReleaseServiceLock( );
return(fRet);
} // IIS_SERVICE::ClearInstanceStatistics
|