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.
 
 
 
 
 
 

2180 lines
68 KiB

/*===================================================================
Microsoft Denali
Microsoft Confidential.
Copyright 1996 Microsoft Corporation. All Rights Reserved.
Component: Globals
File: glob.cpp
Owner: LeiJin
Implementation of Glob class functions
===================================================================*/
#include "denpre.h"
#pragma hdrstop
#include "iiscnfgp.h"
#include "debugger.h"
#include "appcnfg.h"
#include "memchk.h"
#include <iismsg.h>
HRESULT ReadConfigFromMD(CIsapiReqInfo *pIReq, CAppConfig *pAppConfig, BOOL fLoadGlob);
HRESULT MDUnRegisterProperties();
HRESULT MDRegisterProperties(void);
#define DEFAULTSTRSIZE 1024
#define dwUnlimited 0xFFFFFFFF
const DWORD dwMDDefaultTimeOut = 30000;
enum eConfigType { eDLLConfig = 0, eAppConfig };
CAspRegistryParams g_AspRegistryParams;
extern LONG g_fProceedWithShutdownAppln;
LONG g_fProceedWithShutdownGlob = 1;
/*========================================================================================
The following array definition is for D1 to D2 migration only. It contains the necessary
information reads from D1 ASP settings in registry.
=========================================================================================*/
typedef struct _D1propinfo
{
CHAR *szName; // Name of the property in the registry
DWORD dwType; // Type (e.g. REG_DWORD, REG_SZ, etc)
DWORD cbData; // How long is the value
VOID *pData;
BOOL fSuccess; // Load from registry successful or not.
} D1PROPINFO;
#define NUM_D1PROP_NeedMigrated 18
// This index should be match the index in D1PropInfo.
enum D1PropIndex {
D1Prop_NotExist = -1,
D1Prop_BufferingOn = 0,
D1Prop_LogErrorRequests,
D1Prop_ScriptErrorsSentToBrowser,
D1Prop_ScriptErrorMessage,
D1Prop_ScriptFileCacheSize,
D1Prop_ScriptEngineCacheMax,
D1Prop_ScriptTimeout,
D1Prop_SessionTimeout,
// D1Prop_MemFreeFactor,
// D1Prop_MinUsedBlocks,
D1Prop_AllowSessionState,
D1Prop_DefaultScriptLanguage,
// D1Prop_StartConnectionPool,
D1Prop_AllowOutOfProcCmpnts,
D1Prop_EnableParentPaths,
// IIS5.0 (from IIS4.0)
D1Prop_EnableAspHtmlFallback,
D1Prop_EnableChunkedEncoding,
D1Prop_EnableTypelibCache,
D1Prop_ErrorsToNtLog,
D1Prop_ProcessorThreadMax,
D1Prop_RequestQueueMax
};
// This flag is used only in setup time.
BOOL g_fD1ConfigExist = FALSE;
// The index is defined in D1PropIndex.
D1PROPINFO D1PropInfo[] =
{
{ "BufferingOn", REG_DWORD, 0, 0, FALSE},
{ "LogErrorRequests", REG_DWORD, 0, 0, FALSE},
{ "ScriptErrorsSentToBrowser", REG_DWORD, 0, 0, FALSE},
{ "ScriptErrorMessage", REG_SZ, 0, 0, FALSE},
{ "ScriptFileCacheSize", REG_DWORD, 0, 0, FALSE},
{ "ScriptEngineCacheMax", REG_DWORD, 0, 0, FALSE},
{ "ScriptTimeout", REG_DWORD, 0, 0, FALSE},
{ "SessionTimeout", REG_DWORD, 0, 0, FALSE},
{ "AllowSessionState", REG_DWORD, 0, 0, FALSE},
{ "DefaultScriptLanguage", REG_SZ, 0, 0, FALSE},
{ "AllowOutOfProcCmpnts", REG_DWORD, 0, 0, FALSE},
{ "EnableParentPaths", REG_DWORD, 0, 0, FALSE},
// IIS5.0 (from IIS4.0)
{ "EnableAspHtmlFallback", REG_DWORD, 0, 0, FALSE},
{ "EnableChunkedEncoding", REG_DWORD, 0, 0, FALSE},
{ "EnableTypelibCache", REG_DWORD, 0, 0, FALSE},
{ "ErrorsToNTLog", REG_DWORD, 0, 0, FALSE},
{ "ProcessorThreadMax", REG_DWORD, 0, 0, FALSE},
{ "RequestQueueMax", REG_DWORD, 0, 0, FALSE}
};
/*
* The following array contains all the info we need to create and load
* all of the registry entries for denali. See the above PROPINFO structure for details on each of the fields.
*
* NOTE: There is an odd thing about initializers and unions. You must initialize a union with the value of
* the type of the first element in the union. In the anonymous union in the PROPINFO structure, we have defined
* the first type to be DWORD. Thus, for non-DWORD registry entries, the default value must be cast to a DWORD
* before being initialized, or initialized using a more explicit mechanism.
*/
/*
* Info about our properties used by Metabase
*/
typedef struct _MDpropinfo
{
INT id; // Identifier used in Glob if UserType is IIS_MD_UT_WAM,
// Identifier used in AppConfig if UserType is ASP_MD_UT_APP.
INT iD1PropIndex; // Index in D1PropInfo. if equals to -1, that it does not exist in D1.
BOOL fAdminConfig; // Admin Configurable
DWORD dwMDIdentifier; // Metabase identifier
DWORD dwUserType; // IIS_MD_UT_WAM(data per Dll) or ASP_MD_UT_APP(data per App)
DWORD dwType;
DWORD cbData;
union // Default Value
{
DWORD dwDefault; // Default value for DWORDs
INT idDefault; // Default value for strings -- the id of the string in the resource
BYTE *pbDefault; // Pointer to arbitrary default value
};
DWORD dwValueMin; // For DWORD registry entries, min value allowed
DWORD dwValueMax; // For DWORD registry entries, max value allowed
} MDPROPINFO;
//Some default settings for ASP Metabase
#define ASP_MD_DAttributes METADATA_INHERIT
const MDPROPINFO rgMDPropInfo[] =
{
#define THREADGATING_DFLT 0L
#define BUFFERING_DFLT 1L
// ID D1PropIndex AdminConfig? Metabase ID UserType Data Type cbData Def, Min, Max
// Glob Settings
// -------------
{ IGlob_LogErrorRequests, D1Prop_LogErrorRequests, TRUE, MD_ASP_LOGERRORREQUESTS, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IGlob_ScriptFileCacheSize, D1Prop_ScriptFileCacheSize, TRUE, MD_ASP_SCRIPTFILECACHESIZE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 500L, 0L, dwUnlimited},
{ IGlob_ScriptEngineCacheMax, D1Prop_ScriptEngineCacheMax, TRUE, MD_ASP_SCRIPTENGINECACHEMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 250L, 0L, dwUnlimited},
{ IGlob_ExceptionCatchEnable, D1Prop_NotExist, TRUE, MD_ASP_EXCEPTIONCATCHENABLE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IGlob_TrackThreadingModel, D1Prop_NotExist, TRUE, MD_ASP_TRACKTHREADINGMODEL, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IGlob_AllowOutOfProcCmpnts, D1Prop_AllowOutOfProcCmpnts, FALSE, MD_ASP_ALLOWOUTOFPROCCMPNTS, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
// IIS5.0
{ IGlob_EnableAspHtmlFallback, D1Prop_EnableAspHtmlFallback, TRUE, MD_ASP_ENABLEASPHTMLFALLBACK, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IGlob_EnableChunkedEncoding, D1Prop_EnableChunkedEncoding, TRUE, MD_ASP_ENABLECHUNKEDENCODING, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IGlob_EnableTypelibCache, D1Prop_EnableTypelibCache, TRUE, MD_ASP_ENABLETYPELIBCACHE, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IGlob_ErrorsToNtLog, D1Prop_ErrorsToNtLog, TRUE, MD_ASP_ERRORSTONTLOG, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IGlob_ProcessorThreadMax, D1Prop_ProcessorThreadMax, TRUE, MD_ASP_PROCESSORTHREADMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 25L, 0L, dwUnlimited},
{ IGlob_RequestQueueMax, D1Prop_RequestQueueMax, TRUE, MD_ASP_REQEUSTQUEUEMAX, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 3000L, 0L, dwUnlimited},
// IIS6.0 & IIS5.1 - Persisted Template Cache
{ IGlob_PersistTemplateMaxFiles, D1Prop_NotExist, TRUE, MD_ASP_MAXDISKTEMPLATECACHEFILES, IIS_MD_UT_WAM, DWORD_METADATA, sizeof(DWORD), 2000L, 0L, dwUnlimited},
{ IGlob_PersistTemplateDir, D1Prop_NotExist, TRUE, MD_ASP_DISKTEMPLATECACHEDIRECTORY, IIS_MD_UT_WAM, EXPANDSZ_METADATA, dwUnlimited, IDS_DEFAULTPERSISTDIR, 0L, dwUnlimited},
// Application settings
// --------------------
{ IApp_AllowSessionState, D1Prop_AllowSessionState, TRUE, MD_ASP_ALLOWSESSIONSTATE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IApp_BufferingOn, D1Prop_BufferingOn, TRUE, MD_ASP_BUFFERINGON, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), BUFFERING_DFLT, 0L, 1L},
{ IApp_ScriptLanguage, D1Prop_DefaultScriptLanguage, TRUE, MD_ASP_SCRIPTLANGUAGE, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, IDS_SCRIPTLANGUAGE, 0L, dwUnlimited},
{ IApp_EnableParentPaths, D1Prop_EnableParentPaths, TRUE, MD_ASP_ENABLEPARENTPATHS, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IApp_ScriptErrorMessage, D1Prop_ScriptErrorMessage, TRUE, MD_ASP_SCRIPTERRORMESSAGE, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, IDS_DEFAULTMSG_ERROR, 0L, dwUnlimited},
{ IApp_SessionTimeout, D1Prop_SessionTimeout, TRUE, MD_ASP_SESSIONTIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 20L, 1L, dwUnlimited},
{ IApp_QueueTimeout, D1Prop_NotExist, TRUE, MD_ASP_QUEUETIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), dwUnlimited, 1L, dwUnlimited},
{ IApp_CodePage, D1Prop_NotExist, TRUE, MD_ASP_CODEPAGE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), CP_ACP, 0L, dwUnlimited},
{ IApp_ScriptTimeout, D1Prop_ScriptTimeout, TRUE, MD_ASP_SCRIPTTIMEOUT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 90L, 1L, dwUnlimited},
{ IApp_ScriptErrorsSenttoBrowser, D1Prop_ScriptErrorsSentToBrowser, TRUE, MD_ASP_SCRIPTERRORSSENTTOBROWSER, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IApp_AllowDebugging, D1Prop_NotExist, TRUE, MD_ASP_ENABLESERVERDEBUG, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IApp_AllowClientDebug, D1Prop_NotExist, TRUE, MD_ASP_ENABLECLIENTDEBUG, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
// IIS5.0
{ IApp_EnableApplicationRestart, D1Prop_NotExist, TRUE, MD_ASP_ENABLEAPPLICATIONRESTART, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IApp_QueueConnectionTestTime, D1Prop_NotExist, TRUE, MD_ASP_QUEUECONNECTIONTESTTIME, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 3L, 1L, dwUnlimited},
{ IApp_SessionMax, D1Prop_NotExist, TRUE, MD_ASP_SESSIONMAX, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), dwUnlimited, 1L, dwUnlimited},
// IIS5.1 & IIS6.0
{ IApp_ExecuteInMTA, D1Prop_NotExist, TRUE, MD_ASP_EXECUTEINMTA, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1},
{ IApp_LCID, D1Prop_NotExist, TRUE, MD_ASP_LCID, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), LOCALE_SYSTEM_DEFAULT, 0L, dwUnlimited},
// IIS6.0 Only - ServicesWithoutComponents
{ IApp_ServiceFlags, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_FLAGS, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 7L},
{ IApp_PartitionGUID, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_PARTITION_ID, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, 0xffffffff, 0L, dwUnlimited},
{ IApp_SxsName, D1Prop_NotExist, TRUE, MD_ASP_SERVICE_SXS_NAME, ASP_MD_UT_APP, STRING_METADATA, dwUnlimited, 0xffffffff, 0L, dwUnlimited},
// IIS6.0 Only - Misc
{ IApp_KeepSessionIDSecure, D1Prop_NotExist, TRUE, MD_ASP_KEEPSESSIONIDSECURE, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 0L, 0L, 1L},
{ IApp_CalcLineNumber, D1Prop_NotExist, TRUE, MD_ASP_CALCLINENUMBER, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IApp_RunOnEndAsAnon, D1Prop_NotExist, TRUE, MD_ASP_RUN_ONEND_ANON, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), 1L, 0L, 1L},
{ IApp_BufferLimit, D1Prop_NotExist, TRUE, MD_ASP_BUFFER_LIMIT, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), DEFAULT_BUFFER_LIMIT, 0L, dwUnlimited},
{ IApp_RequestEntityLimit, D1Prop_NotExist, TRUE, MD_ASP_MAX_REQUEST_ENTITY_ALLOWED, ASP_MD_UT_APP, DWORD_METADATA, sizeof(DWORD), DEFAULT_REQUEST_ENTITY_LIMIT, 0L, dwUnlimited}
};
const DWORD rgdwMDObsoleteIdentifiers[] =
{MD_ASP_MEMFREEFACTOR,
MD_ASP_MINUSEDBLOCKS
};
const UINT cPropsMax = sizeof(rgMDPropInfo) / sizeof(MDPROPINFO);
/*===================================================================
ReadAndRemoveOldD1PropsFromRegistry
Reads whatever old D1 properties are in the registry and
stores the values into D1PropInfo[] global array.
Removes the old properties found from the registry.
Returns:
HRESULT - S_OK on success
Side effects:
Fills in values in Glob
===================================================================*/
BOOL ReadAndRemoveOldD1PropsFromRegistry()
{
HKEY hkey = NULL;
DWORD iValue;
BYTE cTrys = 0;
DWORD dwType;
BYTE bData[DEFAULTSTRSIZE]; // Size???
BYTE *lpRegString = NULL; // need to use dynamic allocation when we have ERROR_MORE_DATA
DWORD cbData;
HRESULT hr = S_OK;
// Open the key for W3SVC\ASP\Parameters
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC\\ASP\\Parameters", 0, KEY_READ|KEY_WRITE, &hkey) != ERROR_SUCCESS)
return(FALSE);
// Load each of the values
for (iValue = 0; iValue < NUM_D1PROP_NeedMigrated; iValue++)
{
LONG err;
D1PROPINFO *pPropInfo;
pPropInfo = &D1PropInfo[iValue];
cbData = sizeof(bData);
err = RegQueryValueExA(hkey, pPropInfo->szName, 0, &dwType, bData, &cbData);
if (err == ERROR_MORE_DATA)
{
lpRegString = (BYTE *)GlobalAlloc(GPTR, cbData);
if (lpRegString != NULL)
{
err = RegQueryValueExA(hkey, pPropInfo->szName, 0, &dwType, lpRegString, &cbData);
}
else
{
pPropInfo->fSuccess = FALSE;
continue;
}
}
// if get an error, or not the type we expect, then use the default
if (err != ERROR_SUCCESS || dwType != pPropInfo->dwType)
{
pPropInfo->fSuccess = FALSE;
//
// Free up lpRegString
//
if (lpRegString)
{
GlobalFree(lpRegString);
lpRegString = NULL;
}
continue;
}
// Success : Got the data, copy it into Glob
// But first, if this is a DWORD type, make sure it is within allowed Max/Min range
switch (pPropInfo->dwType)
{
case REG_DWORD:
Assert(cbData == sizeof(DWORD));
if (cbData == sizeof(DWORD))
{
pPropInfo->cbData = cbData;
//
// bData is atleast 4 bytes (DEFAULTSTRSIZE > 4 bytes) so bData is always valid even if Prefix tags it as using a
// possibly uninited value as lpRegString may be used in its place. Ignore PREFIX warning.
//
pPropInfo->pData = (VOID *)UIntToPtr((*(DWORD *)bData));
pPropInfo->fSuccess = TRUE;
}
//
// So if its a DWORD then we are not going to need the lpRegString. Release it.
//
if (lpRegString)
{
GlobalFree(lpRegString) ;
lpRegString = NULL;
}
break;
case REG_SZ:
if (lpRegString == NULL)
{ // The string fit into default allocation
lpRegString = (BYTE *)GlobalAlloc(GPTR, cbData * sizeof(WCHAR));
if (lpRegString == NULL)
return FALSE;
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)bData, -1, (LPWSTR)lpRegString, cbData);
}
pPropInfo->cbData = cbData * sizeof(WCHAR);
pPropInfo->pData = (VOID *)lpRegString;
pPropInfo->fSuccess = TRUE;
lpRegString = NULL;
break;
}
// remove the value from the registry
RegDeleteValueA(hkey, pPropInfo->szName);
}
// remove some old properties that 'get lost' in the upgrade
RegDeleteValueA(hkey, "CheckForNestedVroots");
RegDeleteValueA(hkey, "EventLogDirection");
RegDeleteValueA(hkey, "ScriptFileCacheTTL");
RegDeleteValueA(hkey, "StartConnectionPool");
RegDeleteValueA(hkey, "NumInitialThreads");
RegDeleteValueA(hkey, "ThreadCreationThreshold");
RegDeleteValueA(hkey, "MinUsedBlocks");
RegDeleteValueA(hkey, "MemFreeFactor");
RegDeleteValueA(hkey, "MemClsFreeFactor");
RegDeleteValueA(hkey, "ThreadDeleteDelay");
RegDeleteValueA(hkey, "ViperRequestQueueMax");
RegCloseKey(hkey);
// remove the W3SVC\ASP\Paramaters key
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC\\ASP", 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS)
{
RegDeleteKeyA(hkey, "Parameters");
RegCloseKey(hkey);
}
// remove the W3SVC\ASP key
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\W3SVC", 0, KEY_READ|KEY_WRITE, &hkey) == ERROR_SUCCESS)
{
RegDeleteKeyA(hkey, "ASP");
RegCloseKey(hkey);
}
return TRUE;
}
/*==================================================================
MDRegisterProperties
Register info about our properties in the metabase. This funtion is
called during regsvr32, self-registration time.
Returns:
HRESULT - S_OK on success
Side effects:
Registers denali properties in the metabase
===================================================================*/
HRESULT MDRegisterProperties(void)
{
HRESULT hr = S_OK;
DWORD iValue;
IMSAdminBase *pMetabase = NULL;
METADATA_HANDLE hMetabase = NULL;
METADATA_RECORD recMetaData;
BYTE szDefaultString[2*DEFAULTSTRSIZE];
HRESULT hrT = S_OK;
BOOL fNeedMigrated;
fNeedMigrated = ReadAndRemoveOldD1PropsFromRegistry();
hr = CoInitialize(NULL);
if (FAILED(hr))
{
return hr;
}
hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void **)&pMetabase);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
// Open key to the Web service, and get a handle of \LM\w3svc
hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)(L"\\LM\\W3SVC"),
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
dwMDDefaultTimeOut, &hMetabase);
if (FAILED(hr))
{
goto LExit;
}
//
// Remove obsolete metabase settings
// See rgdwMDObsoleteIdentifiers structure for detail list of properties
//
for (iValue = 0; iValue < sizeof(rgdwMDObsoleteIdentifiers)/sizeof(DWORD);
iValue++)
{
hr = pMetabase->DeleteData( hMetabase,
NULL,
rgdwMDObsoleteIdentifiers[iValue],
0);
if (FAILED(hr))
{
if (hr == MD_ERROR_DATA_NOT_FOUND)
{
hr = S_OK;
}
else
{
Assert(FALSE);
}
}
}
//
// Set metabase properties
//
recMetaData.dwMDDataTag = 0; // this parameter is not used when setting data
for (iValue = 0; iValue < cPropsMax; iValue++)
{
INT cch;
BYTE aByte[4]; // Temporary buffer
DWORD dwLen;
D1PROPINFO *pD1PropInfo;
recMetaData.dwMDIdentifier = rgMDPropInfo[iValue].dwMDIdentifier;
recMetaData.dwMDAttributes = METADATA_INHERIT;
recMetaData.dwMDUserType = rgMDPropInfo[iValue].dwUserType;
recMetaData.dwMDDataType = rgMDPropInfo[iValue].dwType;
dwLen = 0;
recMetaData.dwMDDataLen = 0;
recMetaData.pbMDData = (unsigned char *)aByte;
HRESULT hrGetData = pMetabase->GetData(hMetabase, NULL, &recMetaData, &dwLen);
if (hrGetData == MD_ERROR_DATA_NOT_FOUND)
{
switch (rgMDPropInfo[iValue].dwType)
{
case DWORD_METADATA:
if (fNeedMigrated && rgMDPropInfo[iValue].iD1PropIndex != D1Prop_NotExist )
{
pD1PropInfo = &D1PropInfo[rgMDPropInfo[iValue].iD1PropIndex];
if (pD1PropInfo->fSuccess == TRUE)
{
recMetaData.dwMDDataLen = pD1PropInfo->cbData;
recMetaData.pbMDData = (unsigned char *)&(pD1PropInfo->pData);
break;
}
}
// Did not migrated.
recMetaData.dwMDDataLen = rgMDPropInfo[iValue].cbData;
recMetaData.pbMDData = (unsigned char *)&(rgMDPropInfo[iValue].dwDefault);
break;
case EXPANDSZ_METADATA:
case STRING_METADATA:
if (fNeedMigrated && rgMDPropInfo[iValue].iD1PropIndex != D1Prop_NotExist )
{
pD1PropInfo = &D1PropInfo[rgMDPropInfo[iValue].iD1PropIndex];
if (pD1PropInfo->fSuccess == TRUE)
{
recMetaData.dwMDDataLen = pD1PropInfo->cbData;
recMetaData.pbMDData = (unsigned char *)(pD1PropInfo->pData);
break;
}
}
//
// if its a string and its index is defined as 0xffffffff then just dont load the string and continue.
//
if (rgMDPropInfo[iValue].idDefault == 0xffffffff)
continue;
// Did not migrated
cch = CwchLoadStringOfId(rgMDPropInfo[iValue].idDefault, (LPWSTR)szDefaultString, DEFAULTSTRSIZE);
if (cch == 0)
{
DBGPRINTF((DBG_CONTEXT, "LoadString failed, id = %d\n", rgMDPropInfo[iValue].idDefault));
recMetaData.dwMDDataLen = cch;
recMetaData.pbMDData = NULL;
}
else
{
recMetaData.dwMDDataLen = (cch + 1)*sizeof(WCHAR);
recMetaData.pbMDData = szDefaultString;
}
break;
default:
// So far, DWORD and STRING are the only 2 types.
// Never reach this code path.
Assert(FALSE);
continue;
}
// not found - then set
hr = pMetabase->SetData(hMetabase, NULL, &recMetaData);
}
else
{
// don't change if the data is already in the metabase
hr = S_OK;
}
if (FAILED(hr))
{
DBGPRINTF((DBG_CONTEXT, "Metabase SetData failed, identifier = %08x.\n", rgMDPropInfo[iValue].dwMDIdentifier));
}
}
hrT = pMetabase->CloseKey(hMetabase);
if (fNeedMigrated)
{
if (D1PropInfo[D1Prop_DefaultScriptLanguage].pData != NULL)
{
GlobalFree(D1PropInfo[D1Prop_DefaultScriptLanguage].pData);
}
if (D1PropInfo[D1Prop_ScriptErrorMessage].pData != NULL)
{
GlobalFree(D1PropInfo[D1Prop_ScriptErrorMessage].pData);
}
}
LExit:
if (pMetabase)
pMetabase->Release();
CoUninitialize();
return hr;
}
/*===================================================================
SetConfigToDefaults
Before loading values from the Metabase, set up default values
in case anything goes wrong.
Parameters:
CAppConfig Application Config Object / per application
fLoadGlob if fLoadGlob is TRUE, load glob data, otherwise, load data into AppConfig object.
Returns:
HRESULT - S_OK on success
Side effects:
===================================================================*/
HRESULT SetConfigToDefaults(CAppConfig *pAppConfig, BOOL fLoadGlob)
{
HRESULT hr = S_OK;
DWORD dwMDUserType = 0;
BYTE *szRegString = NULL;
UINT iEntry = 0;
if (fLoadGlob)
{
dwMDUserType = IIS_MD_UT_WAM;
}
else
{
dwMDUserType = ASP_MD_UT_APP;
}
for(iEntry = 0; iEntry < cPropsMax; iEntry++)
{
if (rgMDPropInfo[iEntry].dwUserType != dwMDUserType)
continue;
// After metabase has been read once, data with fAdminConfig = FALSE cant be changed on the fly.
// so we dont bother to reset it
if (fLoadGlob)
{
if (TRUE == Glob(fMDRead) && FALSE == rgMDPropInfo[iEntry].fAdminConfig)
{
continue;
}
}
else
{
if (TRUE == pAppConfig->fInited() && FALSE == rgMDPropInfo[iEntry].fAdminConfig)
{
continue;
}
}
switch (rgMDPropInfo[iEntry].dwType)
{
case DWORD_METADATA:
if (fLoadGlob)
gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)&rgMDPropInfo[iEntry].dwDefault);
else
hr = pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)&rgMDPropInfo[iEntry].dwDefault);
break;
case STRING_METADATA:
case EXPANDSZ_METADATA:
if (rgMDPropInfo[iEntry].idDefault == 0xffffffff)
continue;
szRegString = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
if (szRegString == NULL) {
hr = E_OUTOFMEMORY;
break;
}
CchLoadStringOfId(rgMDPropInfo[iEntry].idDefault, (LPSTR)szRegString, DEFAULTSTRSIZE);
if (rgMDPropInfo[iEntry].dwType == EXPANDSZ_METADATA) {
BYTE *pszExpanded = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
if (pszExpanded == NULL) {
hr = E_OUTOFMEMORY;
break;
}
INT result = ExpandEnvironmentStringsA((LPCSTR)szRegString,
(LPSTR)pszExpanded,
DEFAULTSTRSIZE);
if ((result <= DEFAULTSTRSIZE) && (result > 0)) {
GlobalFree(szRegString);
szRegString = pszExpanded;
}
}
if (fLoadGlob)
gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
else
hr = pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
break;
default:
Assert(FALSE);
break;
}
}
return hr;
}
/*===================================================================
ReadConfigFromMD
Read our properties from the registry. If our props are missing, the
registry is messed up, try to re-register. If our props are there, but
one or more values is missing, use the defaults.
Parameters:
CAppConfig Application Config Object / per application
fLoadGlob if fLoadGlob is TRUE, load glob data, otherwise, load data into AppConfig object.
Returns:
HRESULT - S_OK on success
Side effects:
===================================================================*/
HRESULT ReadConfigFromMD
(
CIsapiReqInfo *pIReq,
CAppConfig *pAppConfig,
BOOL fLoadGlob
)
{
HRESULT hr = S_OK;
HRESULT hrT = S_OK;
DWORD dwNumDataEntries = 0;
DWORD cbRequired = 0;
DWORD dwMDUserType = 0;
DWORD cbBuffer;
BYTE bBuffer[2000];
BYTE *pBuffer = NULL;
BYTE *szRegString = NULL;
BOOL fAllocBuffer = FALSE;
CHAR szMDOORange[DEFAULTSTRSIZE];
TCHAR szMDGlobPath[] = _T("\\LM\\W3SVC");
TCHAR *szMDPath = NULL;
UINT iEntry = 0;
METADATA_GETALL_RECORD *pMDGetAllRec;
if (fLoadGlob)
{
// BUGs 88902, 105745:
// If we are InProc, then use the "root" path for global values
// If OutOfProc, then use the app path for global values
if (pIReq->FInPool())
szMDPath = szMDGlobPath;
else
szMDPath = pIReq->QueryPszApplnMDPath();
dwMDUserType = IIS_MD_UT_WAM;
}
else
{
dwMDUserType = ASP_MD_UT_APP;
szMDPath = pAppConfig->SzMDPath();
}
Assert(szMDPath != NULL);
//
// At this point szMDPath should never be NULL if it is then we bail out.
//
if (!szMDPath)
{
DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: szMDPath is NULL\n"));
return E_FAIL;
}
// PreLoad config data with default, in case anything failed.
hr = SetConfigToDefaults(pAppConfig, fLoadGlob);
if (FAILED(hr))
{
Assert(FALSE);
DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: Setting defaults failed with %x\n",hr));
return hr;
}
// Set flags.
//
BOOL fConfigLoaded[cPropsMax];
for (iEntry = 0; iEntry < cPropsMax; iEntry++) {
fConfigLoaded[iEntry] = FALSE;
}
pBuffer = bBuffer;
hr = pIReq->GetAspMDAllData(szMDPath,
dwMDUserType,
sizeof(bBuffer),
(unsigned char *)pBuffer,
&cbRequired,
&dwNumDataEntries
);
if (hr == RETURNCODETOHRESULT(ERROR_INSUFFICIENT_BUFFER)) {
pBuffer = (BYTE *)GlobalAlloc(GPTR, cbRequired);
if (pBuffer == NULL)
return E_OUTOFMEMORY;
fAllocBuffer = TRUE;
cbBuffer = cbRequired;
hr = pIReq->GetAspMDAllData(szMDPath,
dwMDUserType,
cbRequired,
(unsigned char *)pBuffer,
&cbRequired,
&dwNumDataEntries);
}
if (FAILED(hr)) {
DBGPRINTF((DBG_CONTEXT,"ReadConfigFromMD: GetAspMDAllData failed with %x\n",hr));
return hr;
}
else {
INT cProps = 0;
pMDGetAllRec = (METADATA_GETALL_RECORD *)pBuffer;
for (UINT iValue = 0; iValue < dwNumDataEntries; iValue ++)
{
DWORD dwData;
DWORD iTemp;
DWORD cbStr;
CHAR szMDOORangeFormat[DEFAULTSTRSIZE];
// Init iEntry to be -1, -1 is invalid for rgMDPropInfo[] Array Index.
iEntry = -1;
for (iTemp = 0; iTemp < cPropsMax; iTemp++) {
if (rgMDPropInfo[iTemp].dwMDIdentifier == pMDGetAllRec->dwMDIdentifier) {
iEntry = iTemp;
break;
}
}
// Not found
if (iEntry == -1) {
pMDGetAllRec++;
continue;
}
// Do found the entry in rgMDPropInfo, but datatype does not match.
// Should never happen.
if (rgMDPropInfo[iEntry].dwUserType != dwMDUserType) { // GetAllData should filter out the unwanted UserType.
Assert(FALSE);
pMDGetAllRec++;
continue;
}
cProps++;
// After metabase has been read once, data with fAdminConfig = FALSE cant be changed on the fly.
// so we dont bother to reread it
if (fLoadGlob) {
if (TRUE == Glob(fMDRead) && FALSE == rgMDPropInfo[iEntry].fAdminConfig) {
pMDGetAllRec++;
continue;
}
}
else {
if (TRUE == pAppConfig->fInited() && FALSE == rgMDPropInfo[iEntry].fAdminConfig) {
pMDGetAllRec++;
continue;
}
}
switch(pMDGetAllRec->dwMDDataType) {
case DWORD_METADATA:
Assert(pMDGetAllRec->dwMDDataLen == sizeof(DWORD));
dwData = *(UNALIGNED64 DWORD *)(pBuffer + pMDGetAllRec->dwMDDataOffset);
if (dwData > rgMDPropInfo[iEntry].dwValueMax) {
szMDOORange[0] = '\0';
CchLoadStringOfId(IDS_MDOORANGE_FORMAT, szMDOORangeFormat, DEFAULTSTRSIZE);
sprintf(szMDOORange, szMDOORangeFormat,
rgMDPropInfo[iEntry].dwMDIdentifier,
rgMDPropInfo[iEntry].dwValueMax);
MSG_Warning((LPCSTR)szMDOORange);
dwData = rgMDPropInfo[iEntry].dwValueMax;
}
if (dwData < rgMDPropInfo[iEntry].dwValueMin) {
szMDOORange[0] = '\0';
CchLoadStringOfId(IDS_MDOORANGE_FORMAT, szMDOORangeFormat, DEFAULTSTRSIZE);
sprintf(szMDOORange, szMDOORangeFormat,
rgMDPropInfo[iEntry].dwMDIdentifier,
rgMDPropInfo[iEntry].dwValueMin);
MSG_Warning((LPCSTR)szMDOORange);
dwData = rgMDPropInfo[iEntry].dwValueMin;
}
if (fLoadGlob)
gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)&dwData);
else
pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)&dwData);
fConfigLoaded[iEntry] = TRUE;
break;
case STRING_METADATA:
case EXPANDSZ_METADATA:
// bug fix 102010 DBCS fixes (& 99806)
//cbStr = (pMDGetAllRec->dwMDDataLen) / sizeof(WCHAR);
cbStr = pMDGetAllRec->dwMDDataLen;
szRegString = (BYTE *)GlobalAlloc(GPTR, cbStr);
if (szRegString == NULL) {
hr = E_OUTOFMEMORY;
break;
}
WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(pBuffer + pMDGetAllRec->dwMDDataOffset), -1,
(LPSTR)szRegString, cbStr, NULL, NULL);
if (pMDGetAllRec->dwMDDataType == EXPANDSZ_METADATA) {
BYTE *pszExpanded = (BYTE *)GlobalAlloc(GPTR, DEFAULTSTRSIZE);
if (pszExpanded == NULL) {
hr = E_OUTOFMEMORY;
break;
}
INT result = ExpandEnvironmentStringsA((LPCSTR)szRegString,
(LPSTR)pszExpanded,
DEFAULTSTRSIZE);
if ((result <= DEFAULTSTRSIZE) && (result > 0)) {
GlobalFree(szRegString);
szRegString = pszExpanded;
}
}
if (fLoadGlob)
gGlob.SetGlobValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
else
pAppConfig->SetValue(rgMDPropInfo[iEntry].id, (BYTE *)(&szRegString));
fConfigLoaded[iEntry] = TRUE;
szRegString = NULL;
break;
default:
Assert(FALSE);
break;
}
pMDGetAllRec++;
}
}
if (SUCCEEDED(hr) && !gGlob.m_fMDRead && fLoadGlob)
gGlob.m_fMDRead = TRUE;
if (fAllocBuffer == TRUE) {
GlobalFree(pBuffer);
}
return hr;
}
/*==================================================================
CMDGlobConfigSink::CMDGlobConfigSink
Constructor
===================================================================*/
CMDGlobConfigSink::CMDGlobConfigSink()
{
m_cRef = 1;
InterlockedCompareExchange(&g_fProceedWithShutdownGlob,0,1);
}
/*==================================================================
CMDGlobConfigSink::~CMDGlobConfigSink
Destructor
===================================================================*/
CMDGlobConfigSink::~CMDGlobConfigSink()
{
InterlockedCompareExchange(&g_fProceedWithShutdownGlob,1,0);
}
/*==================================================================
CMDGlobConfigSink::QueryInterface
Returns:
HRESULT - S_OK on success
Side effects:
===================================================================*/
STDMETHODIMP CMDGlobConfigSink::QueryInterface(REFIID iid, void **ppv)
{
*ppv = NULL;
if (iid == IID_IUnknown || iid == IID_IMSAdminBaseSink)
*ppv = (IMSAdminBaseSink *)this;
else
return ResultFromScode(E_NOINTERFACE);
((IUnknown *)*ppv)->AddRef();
return S_OK;
}
/*==================================================================
CMDGlobConfigSink::AddRef
Returns:
ULONG - The new ref counter of object
Side effects:
===================================================================*/
STDMETHODIMP_(ULONG) CMDGlobConfigSink::AddRef(void)
{
LONG cRefs = InterlockedIncrement((long *)&m_cRef);
return cRefs;
}
/*==================================================================
CMDGlobConfigSink::Release
Returns:
ULONG - The new ref counter of object
Side effects: Delete object if ref counter is zero.
===================================================================*/
STDMETHODIMP_(ULONG) CMDGlobConfigSink::Release(void)
{
LONG cRefs = InterlockedDecrement((long *)&m_cRef);
if (cRefs == 0)
{
delete this;
}
return cRefs;
}
/*==================================================================
CMDGlobConfigSink::SinkNotify
Returns:
HRESULT - S_OK on success
Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
===================================================================*/
STDMETHODIMP CMDGlobConfigSink::SinkNotify(
DWORD dwMDNumElements,
MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
{
if (IsShutDownInProgress())
return S_OK;
UINT iEventNum = 0;
DWORD iDataIDNum = 0;
WCHAR wszMDPath[] = L"/LM/W3SVC/";
UINT cSize = 0;
cSize = wcslen(wszMDPath);
for (iEventNum = 0; iEventNum < dwMDNumElements; iEventNum++)
{
if (0 == wcsnicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath, cSize + 1))
{
for (iDataIDNum = 0; iDataIDNum < pcoChangeList[iEventNum].dwMDNumDataIDs; iDataIDNum++)
{
if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] >= ASP_MD_SERVER_BASE
&& pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] <= MD_ASP_ID_LAST)
{
gGlob.NotifyNeedUpdate();
return S_OK;
}
}
}
}
return S_OK;
}
/*===================================================================
MDUnRegisterProperties
Remove info about our properties in the Metabase.
Returns:
HRESULT - S_OK on success
Side effects:
Removes denali properties in the Metabase
// to settings per dll.
===================================================================*/
HRESULT MDUnRegisterProperties(void)
{
HRESULT hr = S_OK;
DWORD iValue;
IMSAdminBase *pMetabase = NULL;
METADATA_HANDLE hMetabase = NULL;
BYTE szDefaultString[DEFAULTSTRSIZE];
BOOL fMDSaveData = TRUE;
HRESULT hrT = S_OK;
hr = CoInitialize(NULL);
if (FAILED(hr))
{
return hr;
}
hr = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_SERVER, IID_IMSAdminBase, (void **)&pMetabase);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
// Open key to the Web service, and get a handle of \LM\w3svc
hr = pMetabase->OpenKey(METADATA_MASTER_ROOT_HANDLE, (LPWSTR)L"\\LM\\W3SVC",
METADATA_PERMISSION_WRITE, dwMDDefaultTimeOut, &hMetabase);
if (FAILED(hr))
{
goto LExit;
}
for (iValue = 0; iValue < cPropsMax; iValue++)
{
hr = pMetabase->DeleteData( hMetabase,
NULL,
rgMDPropInfo[iValue].dwMDIdentifier,
0);
if (FAILED(hr))
{
if (hr == MD_ERROR_DATA_NOT_FOUND)
{
hr = S_OK;
}
else
{
Assert(FALSE);
}
}
}
hrT = pMetabase->CloseKey(hMetabase);
// Add data to W3SVC
LExit:
if (pMetabase)
pMetabase->Release();
CoUninitialize();
return hr;
}
HRESULT GetMetabaseIF(IMSAdminBase **hMetabase)
{
IClassFactory *pcsfFactory = NULL;
HRESULT hr;
hr = CoGetClassObject(
CLSID_MSAdminBase,
CLSCTX_SERVER,
NULL,
IID_IClassFactory,
(void **)&pcsfFactory);
if (FAILED(hr)) {
DBGPRINTF((DBG_CONTEXT,"MDInit: CoGetClassObject failed with %x\n",hr));
return hr;
}
hr = pcsfFactory->CreateInstance(
NULL,
IID_IMSAdminBase,
(void **) hMetabase);
pcsfFactory->Release();
if (FAILED(hr)) {
DBGPRINTF((DBG_CONTEXT,"MDInit: CreateInstance failed with %x\n",hr));
goto LExit;
}
Assert(*hMetabase != NULL);
if (FAILED(hr))
{
(*hMetabase)->Release();
(*hMetabase) = NULL;
goto LExit;
}
LExit:
return(hr);
}
/*===================================================================
Cglob::CGlob
Constructor. Fill glob with some default values.
in:
returns:
Side effects:
===================================================================*/
CGlob::CGlob()
:
m_pITypeLibDenali(NULL),
m_pITypeLibTxn(NULL),
m_dwNumberOfProcessors(1),
m_fInited(FALSE),
m_fMDRead(FALSE),
m_fNeedUpdate(TRUE),
m_dwScriptEngineCacheMax(120),
m_dwScriptFileCacheSize(dwUnlimited),
m_fLogErrorRequests(TRUE),
m_fExceptionCatchEnable(TRUE),
m_fAllowOutOfProcCmpnts(FALSE),
m_fAllowDebugging(FALSE),
m_fTrackThreadingModel(FALSE),
m_dwMDSinkCookie(0),
m_pMetabaseSink(NULL),
m_pMetabase(NULL),
m_fEnableAspHtmlFallBack(FALSE),
m_fEnableTypelibCache(TRUE),
m_fEnableChunkedEncoding(TRUE), // UNDONE: temp.
m_fDupIISLogToNTLog(FALSE),
m_dwRequestQueueMax(500), // default limit on # of requests
m_dwProcessorThreadMax(10),
m_dwPersistTemplateMaxFiles(1000),
m_pszPersistTemplateDir(NULL)
{
SYSTEM_INFO si;
// Find out how many processors are on this machine
GetSystemInfo(&si);
m_dwNumberOfProcessors = si.dwNumberOfProcessors;
if (m_dwNumberOfProcessors <= 0)
{
m_dwNumberOfProcessors = 1; // Just in case!
}
}
/*===================================================================
Cglob::SetGlobValue
Set global values.
in:
int index the index in the propinfo[]
BYTE* pData lp to the Data being copied/assigned in the glob.
returns:
BOOL TRUE/FALSE
Side effects:
Free old string memory and allocate new memory for string.
===================================================================*/
HRESULT CGlob::SetGlobValue(unsigned int iValue, BYTE *pData)
{
Assert((iValue < IGlob_MAX) && (pData != NULL));
switch(iValue) {
case IGlob_LogErrorRequests:
InterlockedExchange((LPLONG)&m_fLogErrorRequests, *(LONG *)pData);
break;
case IGlob_ScriptFileCacheSize:
InterlockedExchange((LPLONG)&m_dwScriptFileCacheSize, *(LONG *)pData);
break;
case IGlob_ScriptEngineCacheMax:
InterlockedExchange((LPLONG)&m_dwScriptEngineCacheMax, *(LONG *)pData);
break;
case IGlob_ExceptionCatchEnable:
InterlockedExchange((LPLONG)&m_fExceptionCatchEnable, *(LONG *)pData);
break;
case IGlob_TrackThreadingModel:
InterlockedExchange((LPLONG)&m_fTrackThreadingModel, *(LONG *)pData);
break;
case IGlob_AllowOutOfProcCmpnts:
InterlockedExchange((LPLONG)&m_fAllowOutOfProcCmpnts, *(LONG *)pData);
break;
case IGlob_EnableAspHtmlFallback:
InterlockedExchange((LPLONG)&m_fEnableAspHtmlFallBack, *(LONG *)pData);
break;
case IGlob_EnableChunkedEncoding:
InterlockedExchange((LPLONG)&m_fEnableChunkedEncoding, *(LONG *)pData);
break;
case IGlob_EnableTypelibCache:
InterlockedExchange((LPLONG)&m_fEnableTypelibCache, *(LONG *)pData);
break;
case IGlob_ErrorsToNtLog:
InterlockedExchange((LPLONG)&m_fDupIISLogToNTLog, *(LONG *)pData);
break;
case IGlob_ProcessorThreadMax:
InterlockedExchange((LPLONG)&m_dwProcessorThreadMax, *(LONG *)pData);
break;
case IGlob_RequestQueueMax:
InterlockedExchange((LPLONG)&m_dwRequestQueueMax, *(LONG *)pData);
break;
case IGlob_PersistTemplateMaxFiles:
InterlockedExchange((LPLONG)&m_dwPersistTemplateMaxFiles, *(LONG *)pData);
break;
case IGlob_PersistTemplateDir:
GlobStringUseLock();
if (m_pszPersistTemplateDir != NULL) {
GlobalFree(m_pszPersistTemplateDir);
}
m_pszPersistTemplateDir = *(LPSTR *)pData;
GlobStringUseUnLock();
break;
default:
break;
}
return S_OK;
}
/*===================================================================
HRESULT CGlob::GlobInit
Get all interesting global values (mostly from registry)
Returns:
HRESULT - S_OK on success
Side effects:
fills in glob. May be slow
===================================================================*/
HRESULT CGlob::GlobInit(void)
{
HRESULT hr = S_OK;
m_fInited = FALSE;
ErrInitCriticalSection(&m_cs, hr);
if (FAILED(hr))
return(hr);
hr = MDInit();
if (FAILED(hr))
return hr;
//Finish loading, any registry change from this moment requires Admin Configurable(TRUE) to take
//affect. Other registry changes need to have IIS be stopped and restarted.
m_fInited = TRUE;
m_fNeedUpdate = FALSE;
// get the registry based ASP parameters
g_AspRegistryParams.Init();
return(hr);
}
/*===================================================================
GlobUnInit
Free all GlobalString Values.
Returns:
HRESULT - S_OK on success
Side effects:
memory freed.
===================================================================*/
HRESULT CGlob::GlobUnInit(void)
{
HRESULT hr = S_OK;
MDUnInit();
//
// Wait for COM to release the Global Sink
//
while (!g_fProceedWithShutdownGlob)
Sleep(100);
DeleteCriticalSection(&m_cs);
return(hr);
}
/*==================================================================
CGlob::MDInit
1. Create Metabase interface.
2. Load Glob configuration Settings from Metabase
2. Register SinkNotify() callback function through Metabase connectionpoint interface.
Returns:
HRESULT - S_OK on success
Side effects: Register SinkNotify().
===================================================================*/
HRESULT CGlob::MDInit(void)
{
HRESULT hr = S_OK;
IConnectionPointContainer *pConnPointContainer = NULL;
IConnectionPoint *pConnPoint = NULL;
if (FAILED(hr = GetMetabaseIF(&m_pMetabase))) {
goto LExit;
}
m_pMetabaseSink = new CMDGlobConfigSink();
if (!m_pMetabaseSink)
return E_OUTOFMEMORY;
m_dwMDSinkCookie = 0;
// Init the Glob structure with defaults. The metabase will actually be read later
hr = SetConfigToDefaults(NULL, TRUE);
if (SUCCEEDED(hr)) {
// Advise Metabase about SinkNotify().
hr = m_pMetabase->QueryInterface(IID_IConnectionPointContainer, (void **)&pConnPointContainer);
if (pConnPointContainer != NULL)
{
//Find the requested Connection Point. This AddRef's the return pointer.
hr = pConnPointContainer->FindConnectionPoint(IID_IMSAdminBaseSink, &pConnPoint);
pConnPointContainer->Release();
if (pConnPoint != NULL)
{
hr = pConnPoint->Advise((IUnknown *)m_pMetabaseSink, &m_dwMDSinkCookie);
pConnPoint->Release();
}
}
} else {
DBGPRINTF((DBG_CONTEXT,"MDInit: SetConfigToDefaults failed with %x\n",hr));
}
if (FAILED(hr)) //Advise failed
{
DBGPRINTF((DBG_CONTEXT,"MDInit: Advise failed with %x\n",hr));
m_pMetabase->Release();
m_pMetabase = NULL;
}
LExit:
return hr;
}
/*==================================================================
CGlob::MDUnInit
1. UnRegister SinkNofity() from Metabase connectionpoint interface.
2. delete m_pMetabaseSink.
3. release interface pointer of m_pMetabase.
Returns:
HRESULT - S_OK on success
Side effects: release interface pointer of m_pMetabase
===================================================================*/
HRESULT CGlob::MDUnInit(void)
{
HRESULT hr = S_OK;
IConnectionPointContainer *pConnPointContainer = NULL;
IConnectionPoint *pConnPoint = NULL;
IClassFactory *pcsfFactory = NULL;
if (m_pMetabase != NULL)
{
//Advise Metabase about SinkNotify().
hr = m_pMetabase->QueryInterface(IID_IConnectionPointContainer, (void **)&pConnPointContainer);
if (pConnPointContainer != NULL)
{
//Find the requested Connection Point. This AddRef's the return pointer.
hr = pConnPointContainer->FindConnectionPoint(IID_IMSAdminBaseSink, &pConnPoint);
pConnPointContainer->Release();
if (pConnPoint != NULL)
{
hr = pConnPoint->Unadvise(m_dwMDSinkCookie);
if (FAILED(hr))
{
DBGPRINTF((DBG_CONTEXT, "UnAdvise Glob Config Change Notify failed.\n"));
}
pConnPoint->Release();
m_dwMDSinkCookie = 0;
}
}
m_pMetabase->Release();
m_pMetabase = NULL;
}
if (m_pMetabaseSink)
{
m_pMetabaseSink->Release();
m_pMetabaseSink = NULL;
}
return hr;
}
/*==================================================================
CMDAppConfigSink::CMDAppConfigSink
Constructor
===================================================================*/
CMDAppConfigSink::CMDAppConfigSink (CApplnMgr *pApplnMgr)
{
m_cRef = 1;
m_pApplnMgr = pApplnMgr;
InterlockedCompareExchange(&g_fProceedWithShutdownAppln,0,1);
}
/*==================================================================
CMDAppConfigSink::~CMDAppConfigSink
Destructor
===================================================================*/
CMDAppConfigSink::~CMDAppConfigSink ()
{
InterlockedCompareExchange(&g_fProceedWithShutdownAppln,1,0);
}
/*==================================================================
CMDAppConfigSink::QueryInterface
Returns:
HRESULT - S_OK on success
Side effects:
===================================================================*/
STDMETHODIMP CMDAppConfigSink::QueryInterface(REFIID iid, void **ppv)
{
*ppv = 0;
if (iid == IID_IUnknown || iid == IID_IMSAdminBaseSink)
*ppv = (IMSAdminBaseSink *)this;
else
return ResultFromScode(E_NOINTERFACE);
((IUnknown *)*ppv)->AddRef();
return S_OK;
}
/*==================================================================
CMDAppConfigSink::AddRef
Returns:
ULONG - The new ref counter of object
Side effects:
===================================================================*/
STDMETHODIMP_(ULONG) CMDAppConfigSink::AddRef(void)
{
LONG cRefs = InterlockedIncrement((long *)&m_cRef);
return cRefs;
}
/*==================================================================
CMDGlobConfigSink::Release
Returns:
ULONG - The new ref counter of object
Side effects: Delete object if ref counter is zero.
===================================================================*/
STDMETHODIMP_(ULONG) CMDAppConfigSink::Release(void)
{
LONG cRefs = InterlockedDecrement((long *)&m_cRef);
if (cRefs == 0)
{
delete this;
}
return cRefs;
}
/*==================================================================
CMDAppConfigSink::SinkNotify
Returns:
HRESULT - S_OK on success
Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
===================================================================*/
STDMETHODIMP CMDAppConfigSink::SinkNotify(
DWORD dwMDNumElements,
MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
{
if (IsShutDownInProgress())
return S_OK;
return m_pApplnMgr->NotifyAllMBListeners(dwMDNumElements,pcoChangeList);
}
/*===================================================================
CAppConfig::CAppConfig
Returns:
Nothing
Side Effects:
None.
===================================================================*/
CAppConfig::CAppConfig()
:
m_dwScriptTimeout(45),
m_dwSessionTimeout(10),
m_dwQueueTimeout(0xffffffff),
m_fScriptErrorsSentToBrowser(TRUE),
m_fBufferingOn(TRUE),
m_fEnableParentPaths(TRUE),
m_fAllowSessionState(TRUE),
m_fAllowOutOfProcCmpnts(FALSE),
m_fAllowDebugging(FALSE),
m_fAllowClientDebug(FALSE),
m_fExecuteInMTA(FALSE),
m_fEnableApplicationRestart(TRUE),
m_dwQueueConnectionTestTime(3),
m_dwSessionMax(0xffffffff),
m_fInited(FALSE),
m_fRestartEnabledUpdated(FALSE),
m_uCodePage(CP_ACP),
m_fIsValidProglangCLSID(FALSE),
m_fIsValidPartitionGUID(FALSE),
m_fSxsEnabled(FALSE),
m_fTrackerEnabled(FALSE),
m_fUsePartition(FALSE),
m_fRunOnEndAsAnon(TRUE),
m_hAnonToken(INVALID_HANDLE_VALUE),
m_dwBufferLimit(DEFAULT_BUFFER_LIMIT),
m_dwRequestEntityLimit(DEFAULT_REQUEST_ENTITY_LIMIT),
m_cRefs(1)
{
m_uCodePage = GetACP();
for (UINT cMsg = 0; cMsg < APP_CONFIG_MESSAGEMAX; cMsg++)
m_szString[cMsg] = 0;
}
/*===================================================================
CAppConfig::Init
Init the CAppConfig. Only called once.
in:
CAppln pAppln The backpointer to Application.
Side effects:
Allocate CMDAppConfigSink. Register metabase sink. etc.
===================================================================*/
HRESULT CAppConfig::Init
(
CIsapiReqInfo *pIReq,
CAppln *pAppln
)
{
HRESULT hr=S_OK;
//
// Initialize the Lock
//
ErrInitCriticalSection( &m_csLock, hr );
if (FAILED(hr))
return hr;
m_fCSInited = TRUE;
m_pAppln = pAppln;
//
// Read info into Glob structure
//
hr = ReadConfigFromMD(pIReq, this, FALSE);
if (SUCCEEDED(hr)) {
hr = g_ScriptManager.ProgLangIdOfLangName((LPCSTR)m_szString[IAppMsg_SCRIPTLANGUAGE],
&m_DefaultScriptEngineProgID);
// BUG 295239:
// If it failed, we still should create an application because the error message
// "New Application Failed" is too confusing for the user. This is not a fatal error
// because it is still (theoretically) possible to run scripts (those with explicit language
// attributes) Therefore, we reset the hr to S_OK.
m_fIsValidProglangCLSID = SUCCEEDED(hr);
hr = S_OK;
}
if (SUCCEEDED(hr) && m_szString[IAppMsg_PARTITIONGUID]) {
BSTR pbstrPartitionGUID = NULL;
hr = SysAllocStringFromSz(m_szString[IAppMsg_PARTITIONGUID], 0, &pbstrPartitionGUID, CP_ACP);
if (FAILED(hr)) {
Assert(0);
hr = S_OK;
}
else {
hr = CLSIDFromString(pbstrPartitionGUID, &m_PartitionGUID);
m_fIsValidPartitionGUID = SUCCEEDED(hr);
hr = S_OK;
}
if (pbstrPartitionGUID)
SysFreeString(pbstrPartitionGUID);
}
if (SUCCEEDED(hr) && fRunOnEndAsAnon()) {
if (pIReq->ServerSupportFunction(HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN,
pAppln->GetApplnPath(SOURCEPATHTYPE_VIRTUAL),
(DWORD *)&m_hAnonToken,
NULL) == FALSE) {
// if the SSF fails, just revert the handle to the INVALID_VALUE. We could fail
// here, but we don't really know if this will even be needed as there may not be
// a global.asa or if there is a global.asa, there might not be OnEnd functions.
m_hAnonToken = INVALID_HANDLE_VALUE;
}
}
m_fInited = TRUE;
m_fNeedUpdate = FALSE;
return hr;
}
/*===================================================================
CAppConfig::UnInit
UnInit the CAppConfig. Only called once.
in:
None.
Side effects:
DeAllocate CMDAppConfigSink. disconnect metabase sink. etc.
===================================================================*/
HRESULT CAppConfig::UnInit(void)
{
for (int iStr = 0; iStr < APP_CONFIG_MESSAGEMAX; iStr++)
{
if (m_szString[iStr] != NULL)
{
GlobalFree(m_szString[iStr]);
m_szString[iStr] = NULL;
}
}
if (m_hAnonToken != INVALID_HANDLE_VALUE)
CloseHandle(m_hAnonToken);
return S_OK;
}
ULONG STDMETHODCALLTYPE CAppConfig::AddRef(void)
{
ULONG cRef = InterlockedIncrement ((LPLONG)&m_cRefs);
return cRef;
}
ULONG STDMETHODCALLTYPE CAppConfig::Release(void)
{
ULONG cRef = InterlockedDecrement ((LPLONG)&m_cRefs);
if (m_cRefs == 0)
delete this;
return cRef;
}
/*==================================================================
CAppConfig::SinkNotify
Returns:
HRESULT - S_OK on success
Side effects: Set fNeedUpdate to TRUE, and glob data will gets update next time a request coming in.
===================================================================*/
STDMETHODIMP CAppConfig::SinkNotify(
DWORD dwMDNumElements,
MD_CHANGE_OBJECT_W __RPC_FAR pcoChangeList[])
{
if (IsShutDownInProgress())
return S_OK;
UINT iEventNum = 0;
DWORD iDataIDNum = 0;
WCHAR *wszMDPath = NULL;
BOOL fWszMDPathAllocd = FALSE;
UINT cSize = 0;
HRESULT hr = S_OK;
BOOL fRestartAppln = FALSE;
// Lock while we are in here to prevent the appconfig object from being
// cleaned up underneath of us
Lock();
#if UNICODE
wszMDPath = SzMDPath();
cSize = wcslen(wszMDPath);
// Tag on a trailing '/'because the directories in pszMDPath will have one
if (wszMDPath[cSize - 1] != L'/') {
wszMDPath = new WCHAR[cSize+2];
if (wszMDPath == NULL) {
hr = E_OUTOFMEMORY;
goto LExit;
}
fWszMDPathAllocd = TRUE;
wcscpy(wszMDPath, SzMDPath());
wszMDPath[cSize] = L'/';
wszMDPath[cSize + 1] = 0;
}
#else
CHAR * szMDPathT = SzMDPath();
Assert(szMDPathT != NULL);
DWORD cbStr = strlen(szMDPathT);
wszMDPath = new WCHAR[cbStr + 2]; // Allow for adding trailing '/' and '\0'
if (wszMDPath == NULL) {
hr = E_OUTOFMEMORY;
goto LExit;
}
fWszMDPathAllocd = TRUE;
cSize = MultiByteToWideChar(CP_ACP, 0, szMDPathT, cbStr, wszMDPath, cbStr + 2);
if (cSize == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto LExit;
}
wszMDPath[cSize] = 0;
wszMDPath[cSize + 1] = 0;
// Tag on a trailing '/'because the directories in pszMDPath will have one
if (wszMDPath[cSize - 1] != L'/') {
wszMDPath[cSize] = L'/';
}
#endif
for (iEventNum = 0; iEventNum < dwMDNumElements; iEventNum++)
{
DWORD dwMDChangeType = pcoChangeList[iEventNum].dwMDChangeType;
if ((dwMDChangeType == MD_CHANGE_TYPE_DELETE_OBJECT) || (dwMDChangeType == MD_CHANGE_TYPE_RENAME_OBJECT))
{
if (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0)
{
fRestartAppln = TRUE;
}
}
if (0 == wcsnicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath, min(cSize, wcslen((LPWSTR)pcoChangeList[iEventNum].pszMDPath))))
{
for (iDataIDNum = 0; iDataIDNum < pcoChangeList[iEventNum].dwMDNumDataIDs; iDataIDNum++)
{
if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] == MD_VR_PATH)
{
if (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0)
{
fRestartAppln = TRUE;
}
}
if (pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] >= ASP_MD_SERVER_BASE
&& pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] <= MD_ASP_ID_LAST)
{
if (fNeedUpdate() == FALSE)
NotifyNeedUpdate();
if ((pcoChangeList[iEventNum].pdwMDDataIDs[iDataIDNum] == MD_ASP_ENABLEAPPLICATIONRESTART)
&& (wcsicmp(wszMDPath, (LPWSTR)pcoChangeList[iEventNum].pszMDPath) == 0))
{
NotifyRestartEnabledUpdated();
goto LExit;
}
}
}
}
}
LExit:
UnLock();
if (fWszMDPathAllocd)
delete [] wszMDPath;
//
// The Restart() call an potentially delete the parent (no applications locked)
// If we restart just as we exit the thread then there is no race condition.
// The two cases where the race could still occur are covered with the locks on the ApplnMgr. The places are
// (1) NotifyRestartEnabledUpdate which can be used to restart only from AssignApplnToBrowserRequest which is protected by a g_ApplnMgr.Lock() critsec and
// (2) Another SinkNotify (which will be on another RPC thread and so protected by the same g_ApplnMgr.Lock() critsec
//
if (fRestartAppln)
m_pAppln->Restart(TRUE);
return hr;
}
/*===================================================================
CAppConfig::szMDPath
in:
None
returns:
LPTSTR: ptr to szmetabsekey
Side effects:
Get MetabaseKey
===================================================================*/
LPTSTR CAppConfig::SzMDPath()
{
return m_pAppln->GetMetabaseKey();
}
/*===================================================================
CAppConfig::SetValue
in:
int index the index in the propinfo[]
BYTE* pData lp to the Data being copied/assigned in the glob.
returns:
BOOL TRUE/FALSE
Side effects:
Free old string memory and allocate new memory for string.
===================================================================*/
HRESULT CAppConfig::SetValue(unsigned int iValue, BYTE *pData)
{
HRESULT hr = S_OK;
Assert((iValue < IApp_MAX) && (pData != NULL));
switch(iValue) {
case IApp_CodePage: {
LONG lCodePage = *(LONG *)pData;
if (lCodePage == 0)
lCodePage = GetACP();
InterlockedExchange((LPLONG)&m_uCodePage, lCodePage);
break;
}
case IApp_BufferingOn:
InterlockedExchange((LPLONG)&m_fBufferingOn, *(LONG *)pData);
break;
case IApp_ScriptErrorsSenttoBrowser:
InterlockedExchange((LPLONG)&m_fScriptErrorsSentToBrowser, *(LONG *)pData);
break;
case IApp_ScriptErrorMessage:
GlobStringUseLock();
if (m_szString[IAppMsg_SCRIPTERROR] != NULL) {
GlobalFree(m_szString[IAppMsg_SCRIPTERROR]);
}
m_szString[IAppMsg_SCRIPTERROR] = *(LPSTR *)pData;
GlobStringUseUnLock();
break;
case IApp_ScriptTimeout:
InterlockedExchange((LPLONG)&m_dwScriptTimeout, *(LONG *)pData);
break;
case IApp_SessionTimeout:
InterlockedExchange((LPLONG)&m_dwSessionTimeout, *(LONG *)pData);
break;
case IApp_QueueTimeout:
InterlockedExchange((LPLONG)&m_dwQueueTimeout, *(LONG *)pData);
break;
case IApp_EnableParentPaths:
InterlockedExchange((LPLONG)&m_fEnableParentPaths, !*(LONG *)pData);
break;
case IApp_AllowSessionState:
InterlockedExchange((LPLONG)&m_fAllowSessionState, *(LONG *)pData);
break;
case IApp_ScriptLanguage:
GlobStringUseLock();
if (m_szString[IAppMsg_SCRIPTLANGUAGE] != NULL) {
GlobalFree(m_szString[IAppMsg_SCRIPTLANGUAGE] );
}
m_szString[IAppMsg_SCRIPTLANGUAGE] = *(LPSTR *)pData;
if (m_szString[IAppMsg_SCRIPTLANGUAGE] != NULL) {
if('\0' == m_szString[IAppMsg_SCRIPTLANGUAGE][0]) {
WCHAR wszString[128];
CwchLoadStringOfId(IDS_SCRIPTLANGUAGE, wszString, 128);
MSG_Warning(MSG_APPL_WARNING_DEFAULT_SCRIPTLANGUAGE, m_pAppln->GetMetabaseKey(), wszString);
GlobalFree(m_szString[IAppMsg_SCRIPTLANGUAGE] );
m_szString[IAppMsg_SCRIPTLANGUAGE] = (LPSTR)GlobalAlloc(GPTR, 128);
CchLoadStringOfId(IDS_SCRIPTLANGUAGE, (LPSTR)m_szString[IAppMsg_SCRIPTLANGUAGE], 128);
}
}
hr = g_ScriptManager.ProgLangIdOfLangName((LPCSTR)m_szString[IAppMsg_SCRIPTLANGUAGE],
&m_DefaultScriptEngineProgID);
GlobStringUseUnLock();
break;
case IApp_AllowClientDebug:
InterlockedExchange((LPLONG)&m_fAllowClientDebug, *(LONG *)pData);
break;
case IApp_AllowDebugging:
InterlockedExchange((LPLONG)&m_fAllowDebugging, *(LONG *)pData);
break;
case IApp_EnableApplicationRestart:
InterlockedExchange((LPLONG)&m_fEnableApplicationRestart, *(LONG *)pData);
break;
case IApp_QueueConnectionTestTime:
InterlockedExchange((LPLONG)&m_dwQueueConnectionTestTime, *(LONG *)pData);
break;
case IApp_SessionMax:
InterlockedExchange((LPLONG)&m_dwSessionMax, *(LONG *)pData);
break;
case IApp_ExecuteInMTA:
InterlockedExchange((LPLONG)&m_fExecuteInMTA, *(LONG *)pData);
break;
case IApp_LCID:
InterlockedExchange((LPLONG)&m_uLCID, *(LONG *)pData);
break;
case IApp_KeepSessionIDSecure:
InterlockedExchange((LPLONG)&m_fKeepSessionIDSecure, *(LONG *)pData);
break;
case IApp_CalcLineNumber:
InterlockedExchange((LPLONG)&m_fCalcLineNumber, *(LONG *)pData);
break;
case IApp_ServiceFlags:
InterlockedExchange((LPLONG)&m_fTrackerEnabled, !!((*(LONG *)pData) & IFlag_SF_TrackerEnabled));
InterlockedExchange((LPLONG)&m_fSxsEnabled, !!((*(LONG *)pData) & IFlag_SF_SxsEnabled));
InterlockedExchange((LPLONG)&m_fUsePartition, !!((*(LONG *)pData) & IFlag_SF_UsePartition));
break;
case IApp_PartitionGUID:
GlobStringUseLock();
if (m_szString[IAppMsg_PARTITIONGUID] != NULL) {
GlobalFree(m_szString[IAppMsg_PARTITIONGUID] );
}
m_szString[IAppMsg_PARTITIONGUID] = *(LPSTR *)pData;
if (m_szString[IAppMsg_PARTITIONGUID] != NULL) {
if('\0' == m_szString[IAppMsg_PARTITIONGUID][0]) {
GlobalFree(m_szString[IAppMsg_PARTITIONGUID] );
m_szString[IAppMsg_PARTITIONGUID] = NULL;
}
}
GlobStringUseUnLock();
break;
case IApp_SxsName:
GlobStringUseLock();
if (m_szString[IAppMsg_SXSNAME] != NULL) {
GlobalFree(m_szString[IAppMsg_SXSNAME] );
}
m_szString[IAppMsg_SXSNAME] = *(LPSTR *)pData;
if (m_szString[IAppMsg_SXSNAME] != NULL) {
if('\0' == m_szString[IAppMsg_SXSNAME][0]) {
GlobalFree(m_szString[IAppMsg_SXSNAME] );
m_szString[IAppMsg_SXSNAME] = NULL;
}
}
GlobStringUseUnLock();
break;
case IApp_RunOnEndAsAnon:
InterlockedExchange((LPLONG)&m_fRunOnEndAsAnon, *(LONG *)pData);
break;
case IApp_BufferLimit:
InterlockedExchange((LPLONG)&m_dwBufferLimit, *(LONG *)pData);
break;
case IApp_RequestEntityLimit:
InterlockedExchange((LPLONG)&m_dwRequestEntityLimit, *(LONG *)pData);
break;
default:
break;
}
return hr;
}
/*===================================================================
CAppConfig::Update
Update settings in CAppConfig.
in:
returns:
HRESULT
Side effects:
Update CAppConfig settings.
===================================================================*/
HRESULT CAppConfig::Update(CIsapiReqInfo *pIReq)
{
Glob(Lock);
if (m_fNeedUpdate == TRUE)
{
InterlockedExchange((LPLONG)&m_fNeedUpdate, 0);
m_fRestartEnabledUpdated = FALSE;
}
else
{
Glob(UnLock);
return S_OK;
}
Glob(UnLock);
return ReadConfigFromMD(pIReq, this, FALSE);
}
/*===================================================================
CAspRegistryParams::Init
Read the registry based ASP Parameters
in:
returns:
void
===================================================================*/
void CAspRegistryParams::Init()
{
HKEY hkey = NULL;
DWORD dwType;
DWORD cbData;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\ASP\\Parameters", 0, KEY_READ, &hkey) != ERROR_SUCCESS)
return;
// get DisableF5Attack
cbData = sizeof(DWORD);
m_fF5AttackValuePresent = RegQueryValueExA(hkey, "F5AttackDetectionEnabled", 0, &dwType, (LPBYTE)&m_dwF5AttackValue, &cbData) == NO_ERROR;
// get HangDetRequestThreshold
cbData = sizeof(DWORD);
m_fHangDetRequestThresholdPresent = RegQueryValueExA(hkey, "HangDetRequestThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetRequestThreshold, &cbData) == NO_ERROR;
// get HangDetThreadHungThreshold
cbData = sizeof(DWORD);
m_fHangDetThreadHungThresholdPresent = RegQueryValueExA(hkey, "HangDetThreadHungThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetThreadHungThreshold, &cbData) == NO_ERROR;
// get HangDetConsecIllStatesThreshold
cbData = sizeof(DWORD);
m_fHangDetConsecIllStatesThresholdPresent = RegQueryValueExA(hkey, "HangDetConsecIllStatesThreshold", 0, &dwType, (LPBYTE)&m_dwHangDetConsecIllStatesThreshold, &cbData) == NO_ERROR;
// get HangDetEnabled
cbData = sizeof(DWORD);
m_fHangDetEnabledPresent = RegQueryValueExA(hkey, "HangDetEnabled", 0, &dwType, (LPBYTE)&m_dwHangDetEnabled, &cbData) == NO_ERROR;
// get EnableChangeNotificationForUNC
cbData = sizeof(DWORD);
m_fChangeNotificationForUNCPresent = RegQueryValueExA(hkey, "EnableChangeNotificationForUNC", 0, &dwType, (LPBYTE)& m_dwChangeNotificationForUNC, &cbData) == NO_ERROR;
// get FileMonitoringEnabled
cbData = sizeof(DWORD);
m_fFileMonitoringEnabledPresent = RegQueryValueExA(hkey, "FileMonitoringEnabled", 0, &dwType, (LPBYTE)&m_dwFileMonitoringEnabled, &cbData) == NO_ERROR;
// get FileMonitoringTimeout
cbData = sizeof(DWORD);
m_fFileMonitoringTimeoutSecondsPresent = RegQueryValueExA(hkey, "FileMonitoringTimeoutSeconds", 0, &dwType, (LPBYTE)&m_dwFileMonitoringTimeoutSeconds, &cbData) == NO_ERROR;
// get MaxCSR
cbData = sizeof(DWORD);
m_fMaxCSRPresent = RegQueryValueExA(hkey, "MaxCSR", 0, &dwType, (LPBYTE)&m_dwMaxCSR, &cbData) == NO_ERROR;
// get MaxCPU
cbData = sizeof(DWORD);
m_fMaxCPUPresent = RegQueryValueExA(hkey, "MaxCPU", 0, &dwType, (LPBYTE)&m_dwMaxCPU, &cbData) == NO_ERROR;
// get DisableOOMRecycle
cbData = sizeof(DWORD);
m_fDisableOOMRecyclePresent = RegQueryValueExA(hkey, "DisableOOMRecycle", 0, &dwType, (LPBYTE)&m_dwDisableOOMRecycle, &cbData) == NO_ERROR;
// get DisableLazyContentPropagation
cbData = sizeof(DWORD);
m_fDisableLazyContentPropagationPresent = RegQueryValueExA(hkey, "DisableLazyContentPropagation", 0, &dwType, (LPBYTE)&m_dwDisableLazyContentPropagation, &cbData) == NO_ERROR;
// get ThreadMax
cbData = sizeof(DWORD);
m_fTotalThreadMaxPresent = RegQueryValueExA(hkey, "ThreadMax", 0, &dwType, (LPBYTE)&m_dwTotalThreadMax, &cbData) == NO_ERROR;
// get DisableComPlusCpuMetric
cbData = sizeof(DWORD);
m_fDisableComPlusCpuMetricPresent = RegQueryValueExA(hkey, "DisableComPlusCpuMetric", 0, &dwType, (LPBYTE)&m_dwDisableComPlusCpuMetric, &cbData) == NO_ERROR;
RegCloseKey(hkey);
}