|
|
//
// MODULE: CommonREGCONNECT.CPP
//
// PURPOSE: read - write to the registry; common code for Online TS and Local TS, which differ
// on many functions of this class
//
// COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
//
// AUTHOR: Oleg Kalosha, Joe Mabel
//
// ORIGINAL DATE: 8-24-98 in Online TS. This file abstracted 1-19-98
//
// NOTES:
//
// Version Date By Comments
//--------------------------------------------------------------------
// V3.0 08-04-98 OK
// V3.0 09-10-98 JM backslashing; access log file info
// V3.1 01-19-98 JM branch out version exclusively for Local TS
#pragma warning(disable:4786)
#include "stdafx.h"
#include "apgtsregconnect.h"
#include "event.h"
#include "apgtsevt.h"
#include "apgtscls.h"
#include "apgts.h"
#include "apiwraps.h"
CMutexOwner CAPGTSRegConnector::s_mx(_T("APGTSRegConnector"));
////////////////////////////////////////////////////////////////////////////////////
// CAPGTSRegConnector
////////////////////////////////////////////////////////////////////////////////////
CAPGTSRegConnector::~CAPGTSRegConnector() { }
// When this lock is held, it locks against not just other threads locking this object,
// but against other threads locking any objects of class CAPGTSRegConnector.
void CAPGTSRegConnector::Lock() { WAIT_INFINITE( s_mx.Handle() ); }
void CAPGTSRegConnector::Unlock() { ::ReleaseMutex(s_mx.Handle()); }
bool CAPGTSRegConnector::IsRead() { bool ret = false; Lock(); ret = m_RegistryInfo.m_bIsRead; Unlock(); return ret; }
// the root key (typically "SOFTWARE\Microsoft" in Local TS or "SOFTWARE\\ISAPITroubleShoot" in Online TS) exists
bool CAPGTSRegConnector::Exists() { bool ret = false; CRegUtil reg; Lock(); if (reg.Open(HKEY_LOCAL_MACHINE, RegSoftwareLoc(), KEY_QUERY_VALUE)) if (reg.Open(RegThisProgram(), KEY_QUERY_VALUE)) ret = true; reg.Close(); Unlock(); return ret; }
/*static*/ CString & CAPGTSRegConnector::StringFromConnector(ERegConnector e, CString & str) { switch (e) { case eResourcePath: str = FULLRESOURCE_STR; break; case eVrootPath: str = VROOTPATH_STR; break; case eMaxThreads: str = MAX_THREADS_STR; break; case eThreadsPP: str = THREADS_PER_PROCESSOR_STR; break; case eMaxWQItems: str = MAX_WORK_QUEUE_ITEMS_STR; break; case eCookieLife: str = COOKIE_LIFE_IN_MINS_STR; break; case eReloadDelay: str = RELOAD_DELAY_STR; break; case eDetailedEventLogging: str = DETAILED_EVENT_LOGGING_STR; break; case eLogFilePath: str = LOG_FILE_DIR_STR; break; case eTopicFileExtension: str = LOG_FILE_DIR_STR; break; case eSniffAutomatic: str = SNIFF_AUTOMATIC_STR; break; case eSniffManual: str = SNIFF_MANUAL_STR; break; default: str = _T(""); break; } return str; }
/*static*/ CAPGTSRegConnector::ERegConnector CAPGTSRegConnector::ConnectorFromString( const CString & str) { ERegConnector e = eIndefinite;
if (str == FULLRESOURCE_STR) e = eResourcePath; else if (str == VROOTPATH_STR) e = eVrootPath; else if (str == MAX_THREADS_STR) e = eMaxThreads; else if (str == THREADS_PER_PROCESSOR_STR) e = eThreadsPP; else if (str == MAX_WORK_QUEUE_ITEMS_STR) e = eMaxWQItems; else if (str == COOKIE_LIFE_IN_MINS_STR) e = eCookieLife; else if (str == RELOAD_DELAY_STR) e = eReloadDelay; else if (str == DETAILED_EVENT_LOGGING_STR) e = eDetailedEventLogging; else if (str == LOG_FILE_DIR_STR) e = eLogFilePath; else if (str == SNIFF_AUTOMATIC_STR) e = eSniffAutomatic; else if (str == SNIFF_MANUAL_STR) e = eSniffManual;
return e; }
/*static*/ bool CAPGTSRegConnector::IsNumeric(ERegConnector e) { switch (e) { case eMaxThreads: return true; case eThreadsPP: return true; case eMaxWQItems: return true; case eCookieLife: return true; case eReloadDelay: return true; case eDetailedEventLogging: return true; case eSniffAutomatic: return true; case eSniffManual: return true; default: return false; } }
/*static*/ bool CAPGTSRegConnector::IsString(ERegConnector e) { switch (e) { case eResourcePath: return true; case eVrootPath: return true; case eLogFilePath: return true; case eTopicFileExtension: return true; default: return false; } } ////////////////////////////////////////////////////////
// The following 2 functions set values in the registry. Note that they do NOT
// maintain member values. That must be done at a higher level.
// Like CRegUtil::SetNumericValue(), and CRegUtil::SetStringValue(),
// these assume we already have right key open.
// These also assume we have the relevant lock.
void CAPGTSRegConnector::SetNumericValue(CRegUtil ®, ERegConnector e, DWORD dwValue) { CString str; if( IsNumeric(e) && reg.SetNumericValue(StringFromConnector(e, str), dwValue)) return;
// either inappropriate input or otherwise couldn't set value
throw CAPGTSRegConnectorException(__FILE__, __LINE__, reg, e); } //
// See comments on CAPGTSRegConnector::SetNumericValue
void CAPGTSRegConnector::SetStringValue(CRegUtil ®, ERegConnector e, CString strValue) { CString str; if( IsString(e) && reg.SetStringValue(StringFromConnector(e, str), strValue)) return;
// either inappropriate input or otherwise couldn't set value
throw CAPGTSRegConnectorException(__FILE__, __LINE__, reg, e); } ///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// The following 3 functions set values in the registry. Note that they do NOT
// maintain member values. Typically, these are to be used in a CAPGTSRegConnector
// that exists briefly for the sole purpose of setting registry values.
//
// If there is a CRegistryMonitor in existence -- whether it is this object itself
// or a distinct object -- it will become aware of this change by monitoring
// the registry and will behave accordingly.
//
// SetOneNumericValue() is a higher-level way to set a numeric value.
// Does not assume anything about open keys or held locks.
// Does assume value is in the usual area where APGTS stores its registry data.
bool CAPGTSRegConnector::SetOneNumericValue(ERegConnector e, DWORD dwValue) { bool bRet=true; Lock(); try { CRegUtil reg; bool was_created = false; if (reg.Create(HKEY_LOCAL_MACHINE, RegSoftwareLoc(), &was_created, KEY_QUERY_VALUE | KEY_WRITE)) { if (reg.Create(RegThisProgram(), &was_created, KEY_READ | KEY_WRITE)) { SetNumericValue(reg, e, dwValue); } } } catch(CAPGTSRegConnectorException& exception) { exception.Log(); exception.Close(); bRet=false; } Unlock(); return bRet; } //
// See comments on CAPGTSRegConnector::SetOneNumericValue
// SetOneStringValue() is a higher-level way to set a string value.
// Does not assume anything about open keys or held locks.
// Does assume value is in the usual area where APGTS stores its registry data.
bool CAPGTSRegConnector::SetOneStringValue(ERegConnector e, const CString & strValue) { bool bRet=true; Lock(); try { CRegUtil reg; bool was_created = false; if (reg.Create(HKEY_LOCAL_MACHINE, RegSoftwareLoc(), &was_created, KEY_QUERY_VALUE | KEY_WRITE)) { if (reg.Create(RegThisProgram(), &was_created, KEY_READ | KEY_WRITE)) { SetStringValue(reg, e, strValue); } } } catch(CAPGTSRegConnectorException& exception) { exception.Log(); exception.Close(); bRet=false; } Unlock(); return bRet; } //
// See comments on CAPGTSRegConnector::SetOneNumericValue. This is the public function
// Function returns true if strName represents a value we maintain.
// bChanged returns true if the value is changed. If the function returns false, bChanged
// always returns false.
bool CAPGTSRegConnector::SetOneValue(const CString & strName, const CString & strValue, bool &bChanged) { ERegConnector e = ConnectorFromString(strName); if (IsNumeric(e)) { bChanged = SetOneNumericValue(e, _ttoi(strValue)); return true; } else if (IsString(e)) { bChanged = SetOneStringValue(e, strValue); return true; } else { CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), _T(""), _T(""), EV_GTS_ERROR_INVALIDREGCONNECTOR ); bChanged = false; return false; } }
//////////////////////////////////////////////////////
// Having read a string strNew from the registry & done any massaging it gets,
// assign this string value to the appropriate variable strPersist.
// Returns true and logs dwEvent if strPersist is changed (new value differs from old).
/*static*/ bool CAPGTSRegConnector::AssignString(CString & strPersist, const CString & strNew, DWORD dwEvent) { if (!(strNew == strPersist)) { CString str = strPersist; str += _T(" | "); str += strNew; CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent(SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), str, _T(""), dwEvent);
strPersist = strNew; return true; } return false; }
// Having read a numeric dwNew from the registry
// assign this value to the appropriate variable dwPersist.
// Also used a second time if we need to force the value to an acceptable number.
// Returns true and logs dwEvent if dwPersist is changed (new value differs from old).
// If dwEventDecrease is non-zero, it provides a distinct message to log if the value
// is decreased rather than increased.
/*static*/ bool CAPGTSRegConnector::AssignNumeric(DWORD & dwPersist, DWORD dwNew, DWORD dwEvent, DWORD dwEventDecrease /* =0 */) { if (dwNew != dwPersist) { CString strOld; strOld.Format(_T("%d"), dwPersist ); CString strNew; strNew.Format(_T("%d"), dwNew); CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent(SrcLoc.GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), strOld, strNew, (dwEventDecrease != 0 && dwNew < dwPersist) ? dwEventDecrease : dwEvent); dwPersist = dwNew; return true; } return false; }
/*static*/ bool CAPGTSRegConnector::ForceRangeOfNumeric( DWORD & dw, DWORD dwDefault, DWORD dwEvent, DWORD dwMin, /*=1*/ DWORD dwMax /*=ABS_MAX_REG_PARAM_VAL*/ ) { // do limited validation;
if (dw > dwMax || dw < dwMin) { AssignNumeric(dw, dwDefault, dwEvent); return true; } return false; }
// pump data into m_RegistryInfo - PLUS sets absent data in registry to default.
// OUTPUT maskChanged or-ed ERegConnector-based mask of elements that have been
// changed since last read
// OUTPUT maskCreated or-ed ERegConnector-based mask of elements that were created
// in registry (because they previously didn't exist in registry)
bool CAPGTSRegConnector::Read(int & maskChanged, int & maskCreated) { bool ret = true;
Lock(); try { ReadUpdateRegistry(maskChanged, maskCreated); m_RegistryInfo.m_bIsRead = true; } catch(CAPGTSRegConnectorException& exception) { exception.Log(); exception.Close(); ret = false; } Unlock();
return ret; }
void CAPGTSRegConnector::Clear() { Lock();
// Check if our registry tree exists.
if (!Exists()) { // Rebuilds our registry tree if it has been damaged or deleted.
CRegUtil reg; bool was_created = false;
if (reg.Create(HKEY_LOCAL_MACHINE, RegSoftwareLoc(), &was_created, KEY_QUERY_VALUE | KEY_WRITE)) reg.Create(RegThisProgram(), &was_created, KEY_READ | KEY_WRITE); reg.Close(); }
m_RegistryInfo.SetToDefault(); Unlock(); }
bool CAPGTSRegConnector::GetNumericInfo(ERegConnector en, DWORD& out) { bool ret = true; Lock(); if (en == eMaxThreads) out = m_RegistryInfo.dwMaxThreads; else if (en == eThreadsPP) out = m_RegistryInfo.dwThreadsPP; else if (en == eMaxWQItems) out = m_RegistryInfo.dwMaxWQItems; else if (en == eCookieLife) out = m_RegistryInfo.dwCookieLife; else if (en == eReloadDelay) out = m_RegistryInfo.dwReloadDelay; else if (en == eDetailedEventLogging) out = m_RegistryInfo.dwDetailedEventLogging; else if (en == eSniffAutomatic) out = m_RegistryInfo.dwSniffAutomatic; else if (en == eSniffManual) out = m_RegistryInfo.dwSniffManual; else ret = false; Unlock(); return ret; }
bool CAPGTSRegConnector::GetStringInfo(ERegConnector en, CString& out) { bool ret = true; Lock(); if (en == eResourcePath) out = m_RegistryInfo.strResourcePath; else if (en == eVrootPath) out = m_RegistryInfo.strVrootPath; else if (en == eLogFilePath) out = m_RegistryInfo.strLogFilePath; else if (en == eTopicFileExtension) out = m_RegistryInfo.strTopicFileExtension; else ret = false; Unlock(); return ret; }
// AddBackslash appends a backslash ('\') to CStrings that do not already end in '\'.
/* static */void CAPGTSRegConnector::AddBackslash(CString & str) { int len = str.GetLength(); if (len && str.Right(1).Find('\\') >= 0) { // do nothing, already has backslash
} else // add backslash
str += "\\"; return; }
// BackslashIt replaces all frontslashes ('/') in str with backslashes ('\')
// and (optionally) forces termination with a backslash
/* static */void CAPGTSRegConnector::BackslashIt(CString & str, bool bForce) { int loc; while ((loc = str.Find('/')) != -1) { str = str.Left(loc) + "\\" + str.Mid(loc+1); } if (bForce) AddBackslash(str); }
// APGTS key access
CString CAPGTSRegConnector::ThisProgramFullKey() { CString str; str.Format(_T("%s\\%s"), RegSoftwareLoc(), RegThisProgram()); return str; }
////////////////////////////////////////////////////////////////////////////////////
// CAPGTSRegConnectorException
////////////////////////////////////////////////////////////////////////////////////
void CAPGTSRegConnectorException::Log() { CString str; switch (eVariable) { case CAPGTSRegConnector::eResourcePath: case CAPGTSRegConnector::eVrootPath: case CAPGTSRegConnector::eMaxThreads: case CAPGTSRegConnector::eThreadsPP: case CAPGTSRegConnector::eMaxWQItems: case CAPGTSRegConnector::eCookieLife: case CAPGTSRegConnector::eReloadDelay: case CAPGTSRegConnector::eDetailedEventLogging: case CAPGTSRegConnector::eLogFilePath: case CAPGTSRegConnector::eSniffAutomatic: case CAPGTSRegConnector::eSniffManual: CAPGTSRegConnector::StringFromConnector(eVariable, str); break;
case CAPGTSRegConnector::eProblemWithKey: str = _T("Can't open reg key"); break; case CAPGTSRegConnector::eProblemWithLogKey: str = _T("Can't open IIS reg key"); break;
case CAPGTSRegConnector::eIndefinite: // falls through to default.
default: str = _T("<Problem not specified>"); break; }
CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ ); CEvent::ReportWFEvent(GetSrcFileLineStr(), SrcLoc.GetSrcFileLineStr(), str, _T(""), TSERR_REG_READ_WRITE_PROBLEM); }
|