windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/ulw3/w3server.cxx
2020-09-26 16:20:57 +08:00

1467 lines
31 KiB
C++

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
w3server.cxx
Abstract:
W3_SERVER object holds global state for ULW3.DLL
Author:
Taylor Weiss (TaylorW) 26-Jan-1999
Revision History:
--*/
#include "precomp.hxx"
#include "rawconnection.hxx"
#include "cgi_handler.h"
/*++
class MB_LISTENER
Implements a metabase change listener for W3_SERVER.
--*/
class MB_LISTENER
: public MB_BASE_NOTIFICATION_SINK
{
public:
MB_LISTENER( W3_SERVER * pParent )
: m_pParent( pParent )
{
}
STDMETHOD( SynchronizedSinkNotify )(
DWORD dwMDNumElements,
MD_CHANGE_OBJECT pcoChangeList[]
)
{
return m_pParent->MetabaseChangeNotification( dwMDNumElements, pcoChangeList );
}
private:
W3_SERVER * m_pParent;
};
W3_SERVER::W3_SERVER( BOOL fCompatibilityMode )
: m_Signature (W3_SERVER_SIGNATURE),
m_pMetaBase (NULL),
m_InitStatus (INIT_NONE),
m_fInBackwardCompatibilityMode(fCompatibilityMode),
m_fUseDigestSSP (FALSE),
m_EventLog (L"W3SVC"),
m_pCounterDataBuffer (NULL),
m_dwCounterDataBuffer (0),
m_cSites (0),
m_pTokenCache (NULL),
m_pUlCache (NULL),
m_pUrlInfoCache (NULL),
m_pFileCache (NULL),
m_pMetaCache (NULL)
{
}
W3_SERVER::~W3_SERVER()
{
if (m_pCounterDataBuffer != NULL)
{
LocalFree(m_pCounterDataBuffer);
m_pCounterDataBuffer = NULL;
}
m_Signature = W3_SERVER_FREE_SIGNATURE;
}
// static
DWORD W3_SITE_LIST::ExtractKey(const W3_SITE *site)
{
return site->QueryId();
}
// static
VOID W3_SITE_LIST::AddRefRecord(W3_SITE *site, int nIncr)
{
if (nIncr > 0)
{
site->AddRef();
}
else if (nIncr < 0)
{
site->Release();
}
else
{
DBG_ASSERT( !"Invalid reference");
}
}
HRESULT FakeCollectCounters(PBYTE *ppCounterData,
DWORD *pdwCounterData)
{
return g_pW3Server->CollectCounters(ppCounterData,
pdwCounterData);
}
HRESULT
W3_SERVER::Initialize(
INT argc,
LPWSTR argv[]
)
/*++
Routine Description:
Initialize ULW3.DLL but do not begin listening for requests
Arguments:
argc - Command line argument count
argv[] - Command line arguments (from WAS)
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
ULATQ_CONFIG ulatqConfig;
INT iRet;
WSADATA wsaData;
DBGPRINTF((
DBG_CONTEXT,
"Initializing the W3 Server Started CTC = %d \n",
GetTickCount()
));
//
// Keep track of how much we have initialized so that we can cleanup
// only that which is necessary
//
//
// Initialize Computer name, trivial so doesn't need its own state
//
DWORD cbSize = sizeof m_pszComputerName;
if (!GetComputerNameA(m_pszComputerName, &cbSize))
{
strcpy(m_pszComputerName, "<Server>");
}
m_cchComputerName = strlen(m_pszComputerName);
m_InitStatus = INIT_NONE;
//
// Initialize IISUTIL
//
if ( !InitializeIISUtil() )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
DBGPRINTF(( DBG_CONTEXT,
"Error initializing IISUTIL. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_IISUTIL;
DBGPRINTF((
DBG_CONTEXT,
"W3 Server initializing WinSock. CTC = %d \n",
GetTickCount()
));
//
// Initialize WinSock
//
if ( WSAStartup( MAKEWORD( 1, 1 ), &wsaData ) != 0 )
{
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
DBGPRINTF(( DBG_CONTEXT,
"Error initializing WinSock. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_WINSOCK;
DBGPRINTF((
DBG_CONTEXT,
"W3 Server WinSock initialized. CTC = %d \n",
GetTickCount()
));
//
// Initialize the metabase access (ABO)
//
hr = CoCreateInstance( CLSID_MSAdminBase,
NULL,
CLSCTX_SERVER,
IID_IMSAdminBase,
(LPVOID *)&(m_pMetaBase)
);
if( FAILED(hr) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error creating ABO object. hr = %x\n",
hr ));
goto exit;
}
hr = ReadUseDigestSSP();
if( FAILED(hr) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error reading UseDigestSSP property. hr = %x\n",
hr ));
goto exit;
}
m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
m_InitStatus = INIT_METABASE;
DBGPRINTF((
DBG_CONTEXT,
"W3 Server Metabase initialized. CTC = %d \n",
GetTickCount()
));
//
// Initialize metabase change notification mechanism
//
m_pMetabaseListener = new MB_LISTENER( this );
if ( m_pMetabaseListener == NULL )
{
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto exit;
}
m_InitStatus = INIT_MB_LISTENER;
//
// Initialize global filter list
//
hr = GlobalFilterInitialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error doing global filter initialization. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_FILTERS;
//
// Initialize W3_SITE
//
hr = W3_SITE::W3SiteInitialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error doing global W3_SITE initialization. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_W3_SITE;
//
// Initialize site list
//
m_pSiteList = new W3_SITE_LIST();
if ( m_pSiteList == NULL )
{
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto exit;
}
m_InitStatus = INIT_SITE_LIST;
//
// Initialize ULATQ
//
ulatqConfig.pfnNewRequest = W3_MAIN_CONTEXT::OnNewRequest;
ulatqConfig.pfnIoCompletion = W3_MAIN_CONTEXT::OnIoCompletion;
ulatqConfig.pfnDisconnect = OnUlDisconnect;
ulatqConfig.pfnOnShutdown = W3_SERVER::OnShutdown;
ulatqConfig.pfnCollectCounters = FakeCollectCounters;
hr = UlAtqInitialize( argc,
argv,
&ulatqConfig );
if( FAILED(hr) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing ULATQ. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_ULATQ;
DBGPRINTF((
DBG_CONTEXT,
"W3 Server UlAtq initialized (ipm has signalled). CTC = %d \n",
GetTickCount()
));
//
// Initialize caches
//
hr = InitializeCaches();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing caches. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_CACHES;
//
// Initialize connection table
//
hr = W3_CONNECTION::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing connection table. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_W3_CONNECTION;
//
// Initialize W3_CONTEXTs
//
hr = W3_CONTEXT::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing W3_CONTEXT globals. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_W3_CONTEXT;
//
// Initialize W3_REQUEST
//
hr = W3_REQUEST::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing W3_REQUEST globals. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_W3_REQUEST;
//
// Initialize W3_RESPONSE
//
hr = W3_RESPONSE::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing W3_RESPONSE globals. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_W3_RESPONSE;
//
// Initialize server variables
//
hr = SERVER_VARIABLE_HASH::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing server variable hash table. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_SERVER_VARIABLES;
//
// Initialize Mime-mappings
//
hr = InitializeMimeMap(INET_INFO_PARAMETERS_KEY);
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing mime map table. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_MIME_MAP;
//
// Initialize logging
//
if (FAILED(hr = LOGGING::Initialize()))
{
goto exit;
}
m_InitStatus = INIT_LOGGING;
//
// If we are in backward compatibility mode, then initialize stream
// filter here
//
if (m_fInBackwardCompatibilityMode)
{
hr = RAW_CONNECTION::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initialize ISAPI raw data filter support. hr = %x\n",
hr ));
goto exit;
}
}
m_InitStatus = INIT_RAW_CONNECTION;
//
// Client certificate object wrapper
//
hr = CERTIFICATE_CONTEXT::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing certificate contexts. hr = %x\n",
hr ));
goto exit;
}
m_InitStatus = INIT_CERTIFICATE_CONTEXT;
//
// Initialize Http Compression
// Ignore failure but remember if we Initialized.
//
hr = HTTP_COMPRESSION::Initialize();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error initializing Http Compression. hr = %x\n",
hr ));
hr = S_OK;
}
else
{
m_InitStatus = INIT_HTTP_COMPRESSION;
}
exit:
return hr;
}
VOID
W3_SERVER::Terminate(
HRESULT hrReason
)
/*++
Routine Description:
Terminate ULW3 globals. This should be done after we have stopped
listening for new requests (duh)
Arguments:
None
Return Value:
TRUE if successful, else FALSE
--*/
{
DBGPRINTF(( DBG_CONTEXT,
"Terminating W3_SERVER object\n" ));
//
// Wait for all threads doing W3CORE stuff to drain
//
W3_MAIN_CONTEXT::WaitForThreadDrain();
switch( m_InitStatus )
{
case INIT_HTTP_COMPRESSION:
HTTP_COMPRESSION::Terminate();
case INIT_CERTIFICATE_CONTEXT:
CERTIFICATE_CONTEXT::Terminate();
case INIT_RAW_CONNECTION:
if (m_fInBackwardCompatibilityMode)
{
RAW_CONNECTION::Terminate();
}
case INIT_LOGGING:
LOGGING::Terminate();
case INIT_MIME_MAP:
CleanupMimeMap();
case INIT_SERVER_VARIABLES:
SERVER_VARIABLE_HASH::Terminate();
case INIT_W3_RESPONSE:
W3_RESPONSE::Terminate();
case INIT_W3_REQUEST:
W3_REQUEST::Terminate();
case INIT_W3_CONTEXT:
W3_CONTEXT::Terminate();
case INIT_W3_CONNECTION:
W3_CONNECTION::Terminate();
case INIT_CACHES:
TerminateCaches();
case INIT_ULATQ:
UlAtqTerminate( hrReason );
case INIT_SITE_LIST:
delete m_pSiteList;
m_pSiteList = NULL;
case INIT_W3_SITE:
W3_SITE::W3SiteTerminate();
case INIT_FILTERS:
GlobalFilterTerminate();
case INIT_MB_LISTENER:
if ( m_pMetabaseListener != NULL )
{
m_pMetabaseListener->Release();
m_pMetabaseListener = NULL;
}
case INIT_METABASE:
if ( m_pMetaBase )
{
m_pMetaBase->Release();
}
case INIT_WINSOCK:
WSACleanup();
case INIT_IISUTIL:
TerminateIISUtil();
}
m_InitStatus = INIT_NONE;
}
HRESULT
W3_SERVER::LoadString(
DWORD dwStringID,
CHAR * pszString,
DWORD * pcbString
)
/*++
Routine Description:
Load a resource string from W3CORE.DLL
Arguments:
dwStringID - String ID
pszString - Filled with string
pcbString - On input the size of the buffer pszString, on successful
output, the length of the string copied to pszString
Return Value:
HRESULT
--*/
{
DWORD cbCopied;
if ( pszString == NULL ||
pcbString == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
cbCopied = LoadStringA( GetModuleHandleA( "W3CORE.DLL" ),
dwStringID,
pszString,
*pcbString );
if ( cbCopied == 0 )
{
return HRESULT_FROM_WIN32( GetLastError() );
}
*pcbString = cbCopied;
return NO_ERROR;
}
HRESULT
W3_SERVER::StartListen(
VOID
)
/*++
Routine Description:
Begin listening for requests. This function will return once we have
stopped listening for requests (due to WAS stopping us for some reason)
Listen for metabase changes.
Arguments:
None
Return Value:
HRESULT
--*/
{
HRESULT hr = NOERROR;
DBG_ASSERT( m_pMetabaseListener );
//
// Starting getting metabase changes
//
hr = m_pMetabaseListener->StartListening( m_pMetaBase );
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error trying to listen for metabase changes. hr = %x\n",
hr ));
return hr;
}
//
// Listen for the stream filter
//
if (m_fInBackwardCompatibilityMode)
{
hr = RAW_CONNECTION::StartListening();
if ( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error listening on filter channel. hr = %x\n",
hr ));
m_pMetabaseListener->StopListening( m_pMetaBase );
return hr;
}
}
//
// Start listening for requests
//
hr = UlAtqStartListen();
if( FAILED( hr ) )
{
DBGPRINTF(( DBG_CONTEXT,
"Error listening for HTTP requests. hr = %x\n",
hr ));
if (m_fInBackwardCompatibilityMode)
{
RAW_CONNECTION::StopListening();
}
m_pMetabaseListener->StopListening( m_pMetaBase );
return hr;
}
//
// StartListen() will return when we are to shutdown.
//
m_pMetabaseListener->StopListening( m_pMetaBase );
return NO_ERROR;
}
W3_SITE *
W3_SERVER::FindSite(
DWORD dwInstance
)
{
W3_SITE *site = NULL;
LK_RETCODE lkrc = m_pSiteList->FindKey(dwInstance, &site);
if (site != NULL)
{
DBG_ASSERT(lkrc == LK_SUCCESS);
}
return site;
}
BOOL W3_SERVER::AddSite(W3_SITE *site,
bool fOverWrite)
{
if (m_pSiteList->InsertRecord(site, fOverWrite) == LK_SUCCESS)
{
if (!fOverWrite)
{
InterlockedIncrement((LPLONG)&m_cSites);
}
return TRUE;
}
return FALSE;
}
BOOL W3_SERVER::RemoveSite(W3_SITE *pInstance)
{
if (m_pSiteList->DeleteRecord(pInstance) == LK_SUCCESS)
{
InterlockedDecrement((LPLONG)&m_cSites);
return TRUE;
}
return FALSE;
}
void W3_SERVER::DestroyAllSites()
{
m_pSiteList->Clear();
}
HRESULT
W3_SERVER::MetabaseChangeNotification(
DWORD dwMDNumElements,
MD_CHANGE_OBJECT pcoChangeList[]
)
/*++
Routine Description:
This is the entry point for metabase changes.
It just loops through pcoChangeList and passes
the change to the handler method.
Arguments:
dwMDNumElements - Number of change objects
pcoChangeList - Array of change objects
Return Value:
--*/
{
DBGPRINTF(( DBG_CONTEXT,
"MetabaseChangeNotification called.\n"
));
//
// Verify that the change is for /LM/W3SVC/ or lower
// and dispatch the change.
//
HRESULT hr = NOERROR;
for( DWORD i = 0; i < dwMDNumElements; ++i )
{
if( _wcsnicmp( pcoChangeList[i].pszMDPath,
W3_SERVER_MB_PATH,
W3_SERVER_MB_PATH_CCH ) == 0 )
{
hr = HandleMetabaseChange( pcoChangeList[i] );
}
}
//
// Update system change number for use by file cache (etags)
//
m_pMetaBase->GetSystemChangeNumber( &m_dwSystemChangeNumber );
return hr;
}
VOID
W3_SERVER::TerminateCaches(
VOID
)
/*++
Routine Description:
Cleanup all the caches
Arguments:
None
Return Value:
None
--*/
{
//
// First flush all caches (only references which should remain on cached
// objects should be thru the hash tables themselves). Once we have
// flushed all the caches, all the cached objects should go away.
//
// If they don't that's a bug and ACache assert will fire
//
W3CacheFlushAllCaches();
//
// Now just unregister and cleanup the caches
//
if ( m_pMetaCache != NULL )
{
W3CacheUnregisterCache( m_pMetaCache );
m_pMetaCache->Terminate();
delete m_pMetaCache;
m_pMetaCache = NULL;
}
if ( m_pFileCache != NULL )
{
W3CacheUnregisterCache( m_pFileCache );
m_pFileCache->Terminate();
delete m_pFileCache;
m_pFileCache = NULL;
}
if ( m_pTokenCache != NULL )
{
W3CacheUnregisterCache( m_pTokenCache );
m_pTokenCache->Terminate();
delete m_pTokenCache;
m_pTokenCache = NULL;
}
if ( m_pUrlInfoCache != NULL )
{
W3CacheUnregisterCache( m_pUrlInfoCache );
m_pUrlInfoCache->Terminate();
delete m_pUrlInfoCache;
m_pUrlInfoCache = NULL;
}
if ( m_pUlCache != NULL )
{
W3CacheUnregisterCache( m_pUlCache );
m_pUlCache->Terminate();
delete m_pUlCache;
m_pUlCache = NULL;
}
W3CacheTerminate();
}
HRESULT
W3_SERVER::InitializeCaches(
VOID
)
/*++
Routine Description:
Initialize caches
Arguments:
None
Return Value:
HRESULT
--*/
{
HRESULT hr = NO_ERROR;
BOOL fCacheInit = FALSE;
//
// Url cache
//
m_pUrlInfoCache = new W3_URL_INFO_CACHE;
if ( m_pUrlInfoCache != NULL )
{
hr = m_pUrlInfoCache->Initialize();
if ( FAILED( hr ) )
{
delete m_pUrlInfoCache;
m_pUrlInfoCache = NULL;
}
}
if ( m_pUrlInfoCache == NULL )
{
goto Failure;
}
//
// Token cache
//
m_pTokenCache = new TOKEN_CACHE;
if ( m_pTokenCache != NULL )
{
hr = m_pTokenCache->Initialize();
if ( FAILED( hr ) )
{
delete m_pTokenCache;
m_pTokenCache = NULL;
}
}
if ( m_pTokenCache == NULL )
{
goto Failure;
}
//
// File cache
//
m_pFileCache = new W3_FILE_INFO_CACHE;
if ( m_pFileCache != NULL )
{
hr = m_pFileCache->Initialize();
if ( FAILED( hr ) )
{
delete m_pFileCache;
m_pFileCache = NULL;
}
}
if ( m_pFileCache == NULL )
{
goto Failure;
}
//
// Metacache
//
m_pMetaCache = new W3_METADATA_CACHE;
if ( m_pMetaCache != NULL )
{
hr = m_pMetaCache->Initialize();
if ( FAILED( hr ) )
{
delete m_pMetaCache;
m_pMetaCache = NULL;
}
}
if ( m_pMetaCache == NULL )
{
goto Failure;
}
//
// UL response cache
//
m_pUlCache = new UL_RESPONSE_CACHE;
if ( m_pUlCache != NULL )
{
hr = m_pUlCache->Initialize();
if ( FAILED( hr ) )
{
delete m_pUlCache;
m_pUlCache = NULL;
}
}
if ( m_pUlCache == NULL )
{
goto Failure;
}
//
// Now initialize the manager and register the caches
//
DBG_ASSERT( m_pMetaBase != NULL );
hr = W3CacheInitialize( m_pMetaBase );
if ( FAILED( hr ) )
{
goto Failure;
}
fCacheInit = TRUE;
hr = W3CacheRegisterCache( m_pMetaCache );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = W3CacheRegisterCache( m_pFileCache );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = W3CacheRegisterCache( m_pTokenCache );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = W3CacheRegisterCache( m_pUrlInfoCache );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = W3CacheRegisterCache( m_pUlCache );
if ( FAILED( hr ) )
{
goto Failure;
}
return NO_ERROR;
Failure:
if ( fCacheInit )
{
W3CacheTerminate();
}
if ( m_pMetaCache != NULL )
{
delete m_pMetaCache;
m_pMetaCache = NULL;
}
if ( m_pFileCache != NULL )
{
delete m_pFileCache;
m_pFileCache = NULL;
}
if ( m_pTokenCache != NULL )
{
delete m_pTokenCache;
m_pTokenCache = NULL;
}
if ( m_pUrlInfoCache != NULL )
{
delete m_pUrlInfoCache;
m_pUrlInfoCache = NULL;
}
if ( m_pUlCache != NULL )
{
delete m_pUlCache;
m_pUlCache = NULL;
}
return hr;
}
HRESULT
W3_SERVER::HandleMetabaseChange(
const MD_CHANGE_OBJECT & ChangeObject
)
/*++
Routine Description:
Handle change notifications from the metabase.
The change object will contain a change to
/LM/W3SVC/ or lower in the metabase tree.
Changes to /LM/W3SVC/ may alter W3_SERVER and
are passed to all sites in the site list.
Changes to /LM/W3SVC/{site id}/ or lower will
affect only one site so are just passed on.
Arguments:
ChangeObject
Return Value:
CODEWORK - Partial implementation 1/26/00 - TaylorW
--*/
{
DBGPRINTF(( DBG_CONTEXT,
"W3_SERVER Notfied - Path(%S) Type(%d) NumIds(%08x)\n",
ChangeObject.pszMDPath,
ChangeObject.dwMDChangeType,
ChangeObject.dwMDNumDataIDs
));
HRESULT hr = NOERROR;
BOOL IsPathW3 = FALSE;
BOOL IsPathSite = FALSE;
//
// Find the instance id if present
//
DWORD SiteId;
LPWSTR SiteIdString = ChangeObject.pszMDPath + W3_SERVER_MB_PATH_CCH;
LPWSTR StringEnd;
if( SiteIdString[0] == L'\0' )
{
IsPathW3 = TRUE;
}
else
{
SiteId = wcstoul( SiteIdString, &StringEnd, 10 );
if( SiteId != 0 )
{
IsPathSite = TRUE;
}
}
W3_SITE * Site = NULL;
LK_RETCODE lkrc;
if( IsPathSite )
{
//
// We just need to notify a specific site
//
DBG_ASSERT( SiteId );
Site = FindSite(SiteId);
if (Site != NULL)
{
hr = Site->HandleMetabaseChange( ChangeObject );
Site->Release();
}
}
else if( IsPathW3 )
{
//
// We need to notify every site
//
m_pSiteList->WriteLock();
W3_SITE_LIST TempSiteList;
for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
iter != m_pSiteList->end();
++iter)
{
Site = iter.Record();
Site->HandleMetabaseChange( ChangeObject, &TempSiteList );
}
m_pSiteList->Clear();
m_cSites = 0;
for (W3_SITE_LIST::iterator iter = TempSiteList.begin();
iter != TempSiteList.end();
++iter)
{
Site = iter.Record();
AddSite(Site);
}
m_pSiteList->WriteUnlock();
//
// Handle changes to this object's data
//
// At this point all we care about is data changes
//
if( (ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_DELETE_DATA) ||
(ChangeObject.dwMDChangeType & MD_CHANGE_TYPE_SET_DATA) )
{
//
// CODEWORK: Handle changes to W3_SERVER metadata
// Probably this is just the inprocess isapi list
//
}
}
// BUGBUG - Ignore Errors
return S_OK;
}
//static
VOID
W3_SERVER::OnShutdown(
BOOL fDoImmediate
)
/*++
Routine Description:
Called right after IPM indication of shutdown (but before drain)
Arguments:
None
Return Value:
None
--*/
{
if (g_pW3Server->m_fInBackwardCompatibilityMode)
{
RAW_CONNECTION::StopListening();
}
if (fDoImmediate)
{
W3_CGI_HANDLER::KillAllCgis();
}
}
HRESULT W3_SERVER::CollectCounters(PBYTE *ppCounterData,
DWORD *pdwCounterData)
{
//
// Initialize to null
//
*ppCounterData = NULL;
*pdwCounterData = 0;
//
// Make sure we have enough memory
//
DWORD dwCounterBufferNeeded = sizeof(IISWPSiteCounters) * m_cSites +
sizeof(IISWPGlobalCounters) + sizeof(ULONGLONG);
if (m_pCounterDataBuffer == NULL)
{
m_pCounterDataBuffer = (PBYTE)LocalAlloc(LMEM_FIXED, dwCounterBufferNeeded);
if (m_pCounterDataBuffer == NULL)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
m_dwCounterDataBuffer = dwCounterBufferNeeded;
}
else if (m_dwCounterDataBuffer < dwCounterBufferNeeded)
{
m_pCounterDataBuffer = (PBYTE)LocalReAlloc(m_pCounterDataBuffer,
dwCounterBufferNeeded,
LMEM_MOVEABLE);
if (m_pCounterDataBuffer == NULL)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
m_dwCounterDataBuffer = dwCounterBufferNeeded;
}
m_pSiteList->ReadLock();
//
// Get the Site counters
//
DWORD i = 0;
for (W3_SITE_LIST::iterator iter = m_pSiteList->begin();
iter != m_pSiteList->end();
++iter, ++i)
{
//
// In case some more new sites got added in between, skip them for now
//
if ((i+1)*sizeof(IISWPSiteCounters) + sizeof(IISWPGlobalCounters) >=
m_dwCounterDataBuffer)
{
break;
}
W3_SITE *pSite = iter.Record();
pSite->GetStatistics((IISWPSiteCounters *)
(m_pCounterDataBuffer +
i*sizeof(IISWPSiteCounters) + sizeof(DWORD)));
}
m_pSiteList->ReadUnlock();
//
// Set the number of sites
//
*(DWORD *)m_pCounterDataBuffer = i;
//
// Get the Global counters
//
IISWPGlobalCounters *pCacheCtrs = (IISWPGlobalCounters *)
(m_pCounterDataBuffer + i*sizeof(IISWPSiteCounters) + sizeof(DWORD));
//
// This contains some ULONGLONG values so align it, this is how WAS
// expects it
//
pCacheCtrs = (IISWPGlobalCounters *)(((DWORD_PTR)pCacheCtrs + 7) & ~7);
GetCacheStatistics(pCacheCtrs);
*ppCounterData = m_pCounterDataBuffer;
*pdwCounterData = DIFF((LPBYTE)pCacheCtrs - m_pCounterDataBuffer) + sizeof(IISWPGlobalCounters);
return S_OK;
}
VOID
W3_SERVER::GetCacheStatistics(
IISWPGlobalCounters * pCacheCtrs
)
/*++
Routine Description:
Get cache statistics for perfmon purposes
Arguments:
pCacheCtrs - Receives the statistics for cache
Notes:
CacheBytesTotal and CacheBytesInUse are not kept on a per-server basis
so they are only returned when retrieving summary statistics.
Returns:
None
--*/
{
//
// Get file cache statistics
//
if ( m_pFileCache != NULL )
{
pCacheCtrs->CurrentFilesCached = m_pFileCache->PerfQueryCurrentEntryCount();
pCacheCtrs->TotalFilesCached = m_pFileCache->PerfQueryTotalEntriesCached();
pCacheCtrs->FileCacheHits = m_pFileCache->PerfQueryHits();
pCacheCtrs->FileCacheMisses = m_pFileCache->PerfQueryMisses();
pCacheCtrs->FileCacheFlushes = m_pFileCache->PerfQueryFlushCalls();
pCacheCtrs->ActiveFlushedFiles = m_pFileCache->PerfQueryActiveFlushedEntries();
pCacheCtrs->TotalFlushedFiles = m_pFileCache->PerfQueryFlushes();
pCacheCtrs->CurrentFileCacheMemoryUsage = m_pFileCache->PerfQueryCurrentMemCacheSize();
pCacheCtrs->MaxFileCacheMemoryUsage = m_pFileCache->PerfQueryMaxMemCacheSize();
}
//
// Get URI cache statistics
//
if ( m_pUrlInfoCache != NULL )
{
pCacheCtrs->CurrentUrisCached = m_pUrlInfoCache->PerfQueryCurrentEntryCount();
pCacheCtrs->TotalUrisCached = m_pUrlInfoCache->PerfQueryTotalEntriesCached();
pCacheCtrs->UriCacheHits = m_pUrlInfoCache->PerfQueryHits();
pCacheCtrs->UriCacheMisses = m_pUrlInfoCache->PerfQueryMisses();
pCacheCtrs->UriCacheFlushes = m_pUrlInfoCache->PerfQueryFlushCalls();
pCacheCtrs->TotalFlushedUris = m_pUrlInfoCache->PerfQueryFlushes();
}
//
// BLOB cache counters (actually since there is no blob cache we will
// sub in the metacache counters which are more interesting since
// metacache misses are really painful
//
if ( m_pMetaCache != NULL )
{
pCacheCtrs->CurrentBlobsCached = m_pMetaCache->PerfQueryCurrentEntryCount();
pCacheCtrs->TotalBlobsCached = m_pMetaCache->PerfQueryTotalEntriesCached();
pCacheCtrs->BlobCacheHits = m_pMetaCache->PerfQueryHits();
pCacheCtrs->BlobCacheMisses = m_pMetaCache->PerfQueryMisses();
pCacheCtrs->BlobCacheFlushes = m_pMetaCache->PerfQueryFlushCalls();
pCacheCtrs->TotalFlushedBlobs = m_pMetaCache->PerfQueryFlushes();
}
}
HRESULT
W3_SERVER::ReadUseDigestSSP(
VOID
)
/*++
Routine description:
Read the UseDigestSSP property from the metabase
Arguments:
none
Return Value:
HRESULT
--*/
{
MB mb( QueryMDObject() );
if ( !mb.Open( QueryMDPath() ) )
{
return HRESULT_FROM_WIN32(GetLastError());
}
if ( !mb.GetDword( L"",
MD_USE_DIGEST_SSP,
IIS_MD_UT_SERVER,
( DWORD * )&m_fUseDigestSSP,
0 ) )
{
m_fUseDigestSSP = TRUE;
}
return S_OK;
}