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