#include "pch.h"
BOOL RegConfigReader::DeleteItem(const char *pszItem)
{
HKEY hkey;
BOOL fRet = FALSE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_szKey, 0, KEY_READ | KEY_SET_VALUE, &hkey) == ERROR_SUCCESS)
{
if (RegDeleteValue (hkey, pszItem) == ERROR_SUCCESS)
{
fRet = TRUE;
}
RegCloseKey(hkey);
}
return fRet;
}
BOOL RegConfigReader::Open()
{
if (m_szKey[0])
{
DWORD dw; if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, m_szKey, 0, "", REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &m_hk, &dw) == ERROR_SUCCESS)
return TRUE;
SRVDBG_Info2("Missing registry key", m_szKey);
}
return FALSE;
}
BOOL RegConfigReader::Close()
{
return (ERROR_SUCCESS == RegCloseKey(m_hk));
}
BOOL RegConfigReader::FastReadInt(const char *pszItem, int *pnVal, BOOL fRequired , int nDefault )
{
ZAssert(pszItem);
ZAssert(pnVal);
DWORD dwSize = sizeof(DWORD);
if (RegQueryValueEx(m_hk, pszItem, NULL, NULL, (BYTE *)pnVal, &dwSize) != ERROR_SUCCESS)
{
if (fRequired)
{
SRVDBG_Info3("Missing registry value", m_szKey, pszItem);
return FALSE;
}
*pnVal = nDefault;
}
return TRUE;
}
BOOL RegConfigReader::FastReadSz(const char *pszItem, char *psz, int cchMax, BOOL fRequired , const char *pszDefault )
{
ZAssert(pszItem);
ZAssert(psz);
ZAssert(fRequired || pszDefault);
ZAssert((NULL == pszDefault) || (lstrlen(pszDefault) < cchMax-1));
DWORD dwSize = cchMax;
if (RegQueryValueEx(m_hk, pszItem, NULL, NULL, (BYTE *)psz, &dwSize) != ERROR_SUCCESS)
{
if (fRequired)
{
SRVDBG_Info3("Missing registry key", m_szKey, pszItem);
return FALSE;
}
lstrcpy(psz, pszDefault);
}
return TRUE;
}
BOOL RegConfigReader::FastWriteInt(const char *pszItem, int nVal)
{
return (RegSetValueEx(m_hk, pszItem, 0, REG_DWORD, (BYTE *)&nVal, sizeof(nVal)) == ERROR_SUCCESS);
}
BOOL RegConfigReader::FastWriteSz (const char *pszItem, const char *psz, int cch)
{
return (RegSetValueEx(m_hk, pszItem, 0, REG_SZ, (BYTE *)psz, cch) == ERROR_SUCCESS);
}
BOOL RegConfigReader::CompIdToKey()
{
switch (m_compId)
{
case kCompId_FedSrv:
lstrcpy(m_szKey, HKLM_FedSrv);
break;
default:
ZAssert(FALSE);
SRVDBG_Info("Bogus component specified to config reader");
m_szKey[0] = 0;
return FALSE;
}
return TRUE;
}
BOOL Config::Init(const ConfigInfo *pConfigItems, int nItems, BOOL fRange, int cRange)
{
ZAssert(pConfigItems);
KillArgs();
m_fRange = fRange;
m_cRange = cRange;
m_nArgs = nItems;
m_pArgs = new ARGS[nItems];
ZAssert(m_pArgs); m_pConfigInfo = new ConfigInfoBuffer[nItems];
ZAssert(m_pConfigInfo); for (int i=0; i < nItems; i++)
{
m_pConfigInfo[i].info.pszKeyName = new char[lstrlen(pConfigItems[i].pszKeyName) + 1];
lstrcpy(m_pConfigInfo[i].info.pszKeyName, pConfigItems[i].pszKeyName);
m_pConfigInfo[i].info.type = pConfigItems[i].type;
m_pConfigInfo[i].info.cb = pConfigItems[i].cb;
m_pConfigInfo[i].info.nRequired = pConfigItems[i].nRequired;
m_pArgs[i].type = pConfigItems[i].type;
m_pArgs[i].cb = pConfigItems[i].cb;
if (m_pArgs[i].type == kConfigType_SZ)
{
m_pArgs[i].pszVal = new char[pConfigItems[i].cb * (fRange ? cRange : 1)];
ZAssert(m_pArgs[i].pszVal); char *pszDef = pConfigItems[i].pszDefault;
if (NULL == pszDef)
pszDef = "";
m_pConfigInfo[i].info.pszDefault = new char[lstrlen(pszDef) + 1];
ZAssert(m_pConfigInfo[i].info.pszDefault); lstrcpy(m_pConfigInfo[i].info.pszDefault, pszDef);
m_pConfigInfo[i].pBuf = (BYTE *)m_pArgs[i].pszVal;
m_pConfigInfo[i].info.cb = pConfigItems[i].cb;
}
else
{
if (fRange)
{
m_pArgs[i].pdwVal = new DWORD[cRange];
ZAssert(m_pArgs[i].pdwVal); m_pConfigInfo[i].pBuf = (BYTE *)m_pArgs[i].pdwVal;
}
else
{
m_pConfigInfo[i].pBuf = (BYTE *)&(m_pArgs[i].dwVal);
}
m_pConfigInfo[i].info.dwDefault = pConfigItems[i].dwDefault;
m_pConfigInfo[i].info.cb = sizeof(DWORD);
}
}
ConfigReader *pMgr = CreateConfigReader(m_compId);
ZAssert(pMgr);
BOOL fRet;
if (fRange)
fRet = pMgr->ReadRgRg(cRange, m_pConfigInfo, nItems);
else
fRet = pMgr->ReadRg(m_pConfigInfo, nItems);
if (!fRet)
{
KillArgs();
}
delete pMgr;
return fRet;
}
void Config::KillArgs()
{
if (m_pArgs)
{
ZAssert(m_pConfigInfo);
for (DWORD i=0; i < m_nArgs; i++)
{
delete [] m_pConfigInfo[i].info.pszKeyName;
if (m_pArgs[i].type == kConfigType_SZ)
{
delete [] m_pArgs[i].pszVal;
delete [] m_pConfigInfo[i].info.pszDefault;
}
else if (m_fRange)
{
delete [] m_pArgs[i].pdwVal;
}
}
delete [] m_pArgs;
m_pArgs = NULL;
}
m_nArgs = 0;
delete [] m_pConfigInfo;
m_pConfigInfo = NULL;
}
BOOL Config::GetDWORDArg(DWORD nArg, DWORD *pdw, int nRange)
{
ZAssert(pdw);
ZAssert(nArg < m_nArgs);
ZAssert(!m_fRange || (nRange < m_cRange));
ZAssert(m_pArgs);
if ((nArg >= m_nArgs) || (m_pArgs[nArg].type != kConfigType_DWORD) || (m_fRange && (nRange >= m_cRange)))
{
SRVDBG_Info("Failed to retrieve DWORD from registry");
return FALSE;
}
if (m_fRange)
*pdw = m_pArgs[nArg].pdwVal[nRange];
else
*pdw = m_pArgs[nArg].dwVal;
return TRUE;
}
BOOL Config::GetStringArg(DWORD nArg, char *pszBuf, int cchBuf, int nRange)
{
ZAssert(pszBuf);
ZAssert(nArg < m_nArgs);
ZAssert(m_pArgs);
ZAssert(!m_fRange || (nRange < m_cRange));
if ((nArg >= m_nArgs) || (m_pArgs[nArg].type != kConfigType_SZ))
{
SRVDBG_Info("Failed to retrieve string from registry");
return FALSE;
}
if (m_fRange)
{
if (nRange >= m_cRange)
{
SRVDBG_Info("Failed to retrieve string range from registry");
return FALSE;
}
if (cchBuf < lstrlen(&m_pArgs[nArg].pszVal[nRange * m_pArgs[nArg].cb])+1)
{
SRVDBG_Info("Failed to retrieve string from registry");
return FALSE;
}
lstrcpy(pszBuf, &m_pArgs[nArg].pszVal[nRange * m_pArgs[nArg].cb]);
}
else
{
if (cchBuf < lstrlen(m_pArgs[nArg].pszVal)+1)
{
SRVDBG_Info("Failed to retrieve string from registry");
return FALSE;
}
lstrcpy(pszBuf, m_pArgs[nArg].pszVal);
}
return TRUE;
}
ConfigInfo *Config::GetConfigInfo(int *pcConfig)
{
ZAssert(m_pConfigInfo);
ZAssert(pcConfig);
*pcConfig = m_nArgs;
if (m_nArgs)
{
ConfigInfo *pInfo = new ConfigInfo[m_nArgs];
ZAssert(pInfo); for (DWORD i=0; i < m_nArgs; i++)
{
pInfo[i] = m_pConfigInfo[i].info;
}
return pInfo;
}
return NULL;
}
void ConfigCache::DeleteConfigList()
{
for (int i=0; i < kCompId_Last; i++)
{
while (m_rgpConfigList[i])
{
CONFIG_LIST *pNext = m_rgpConfigList[i]->pNext;
delete m_rgpConfigList[i]->pConfig;
delete m_rgpConfigList[i];
m_rgpConfigList[i] = pNext;
}
}
}
Config * ConfigCache::FindConfig(ComponentId compId)
{
ZAssert(compId < kCompId_Last);
CONFIG_LIST *pNode = m_rgpConfigList[compId];
while (pNode)
{
ZAssert(pNode->pConfig);
ZAssert(pNode->pConfig->GetComponentId() == compId);
Config *pCfg = pNode->pConfig;
return pCfg;
pNode = pNode->pNext;
}
return NULL;
}
void ConfigCache::AddConfig(Config *pConfig)
{
ZAssert(pConfig);
ZAssert(pConfig->GetComponentId() < kCompId_Last);
ComponentId compId = pConfig->GetComponentId();
CONFIG_LIST *pNode = new CONFIG_LIST;
ZAssert(pNode); m_pcsEditList->Enter();
pNode->dwTimeAdded = GetTickCount();
pNode->pConfig = pConfig;
pNode->pNext = m_rgpConfigList[compId];
m_rgpConfigList[compId] = pNode;
m_pcsEditList->Leave();
}
void ConfigCache::AddConfigToTail(Config *pConfig)
{
ZAssert(pConfig);
ZAssert(pConfig->GetComponentId() < kCompId_Last);
ComponentId compId = pConfig->GetComponentId();
CONFIG_LIST *pNewNode = new CONFIG_LIST;
ZAssert(pNewNode); m_pcsEditList->Enter();
pNewNode->dwTimeAdded = GetTickCount();
pNewNode->pConfig = pConfig;
pNewNode->pNext = NULL;
CONFIG_LIST **ppNode = &m_rgpConfigList[compId];
while (NULL != *ppNode)
ppNode = &((*ppNode)->pNext);
*ppNode = pNewNode;
m_pcsEditList->Leave();
}
Config * ConfigCache::RemoveHead(ComponentId compId)
{
ZAssert(compId < kCompId_Last);
Config *pRet = NULL;
m_pcsEditList->Enter();
if (NULL != m_rgpConfigList[compId])
{
CONFIG_LIST *pOld = m_rgpConfigList[compId];
pRet = pOld->pConfig;
m_rgpConfigList[compId] = pOld->pNext;
delete pOld;
}
m_pcsEditList->Leave();
return pRet;
}
Config * ConfigCache::RemoveHeadIfOld(ComponentId compId, DWORD dwDeltaOld)
{
ZAssert(compId < kCompId_Last);
Config *pRet = NULL;
m_pcsEditList->Enter();
DWORD dwNow = GetTickCount();
if (NULL != m_rgpConfigList[compId])
{
BOOL fOld = FALSE;
if (m_rgpConfigList[compId]->dwTimeAdded < dwNow)
{
if (dwNow - m_rgpConfigList[compId]->dwTimeAdded >= dwDeltaOld)
{
fOld = TRUE;
}
}
else
{
if ((dwNow > dwDeltaOld) || ((dwNow + (MAXDWORD - m_rgpConfigList[compId]->dwTimeAdded)) > dwDeltaOld))
fOld = TRUE;
}
if (fOld)
{
CONFIG_LIST *pOld = m_rgpConfigList[compId];
pRet = pOld->pConfig;
m_rgpConfigList[compId] = pOld->pNext;
delete pOld;
}
}
m_pcsEditList->Leave();
return pRet;
}
Config * ConfigCache::ReplaceConfig(ComponentId compId, Config *pConfig)
{
ZAssert(pConfig);
ZAssert(pConfig->GetComponentId() < kCompId_Last);
ZAssert(pConfig->GetComponentId() == compId);
Config *pRet = NULL;
m_pcsEditList->Enter();
CONFIG_LIST *pNode = m_rgpConfigList[compId];
while (pNode)
{
ZAssert(pNode->pConfig);
ZAssert(pNode->pConfig->GetComponentId() == compId);
break;
pNode = pNode->pNext;
}
if (NULL != pNode)
{
pRet = pNode->pConfig;
pNode->pConfig = pConfig;
}
else
{
AddConfig(pConfig);
}
m_pcsEditList->Leave();
return pRet;
}
ConfigManager::~ConfigManager()
{
if (m_hthrGarbageCollect)
{
ZAssert(m_hevtDie);
SetEvent(m_hevtDie);
if (WAIT_TIMEOUT == WaitForSingleObject(m_hthrGarbageCollect, 20000))
SRVDBG_Error("Failed while waiting for thread");
CloseHandle(m_hthrGarbageCollect);
}
if (m_hevtDie)
CloseHandle(m_hevtDie);
delete m_pcsAdd;
}
BOOL ConfigManager::Init()
{
ZAssert(NULL == m_hevtDie);
ZAssert(NULL == m_hthrGarbageCollect);
if (NULL != m_hevtDie)
{
SRVDBG_Warning("Called ConfigManager::Init() twice.");
return FALSE;
}
if (NULL == m_pcsAdd)
{
m_pcsAdd = new CriticalSection;
ZAssert(m_pcsAdd); }
m_hevtDie = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == m_hevtDie)
{
SRVDBG_Error("Failed to create ConfigManager event");
return FALSE;
}
DWORD dwId;
m_hthrGarbageCollect = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE) GarbageCollectThreadThunk, this, 0, &dwId);
if (NULL == m_hthrGarbageCollect)
{
SRVDBG_Error("Failed to create ConfigManager thread");
return FALSE;
}
return TRUE;
}
BOOL ConfigManager::LoadConfig(ComponentId compId, const ConfigInfo *pInfo, int cInfo)
{
m_pcsAdd->Enter();
Config *pCfg = new Config(compId);
ZAssert(pCfg); BOOL fRet = pCfg->Init(pInfo, cInfo, FALSE, 0); if (fRet)
{
Config *pOld = m_cacheComponent.ReplaceConfig(compId, pCfg);
if (pOld)
m_cacheGarbage.AddConfigToTail(pOld);
}
else
{
delete pCfg;
}
m_pcsAdd->Leave();
return fRet;
}
BOOL ConfigManager::ReloadConfig(ComponentId compId)
{
Config *pCfg = m_cacheComponent.FindConfig(compId);
if (pCfg)
{
int cInfo;
ConfigInfo *pInfo = pCfg->GetConfigInfo(&cInfo);
if (pInfo)
{
BOOL fRet = LoadConfig(compId, pInfo, cInfo);
delete [] pInfo;
return fRet;
}
}
return FALSE;
}
BOOL ConfigManager::GetConfigDWORD(ComponentId compId, DWORD nArg, DWORD *pdw)
{
Config *pCfg = m_cacheComponent.FindConfig(compId);
if (pCfg)
return pCfg->GetDWORDArg(nArg, pdw, 0);
return FALSE;
}
BOOL ConfigManager::GetConfigString(ComponentId compId, DWORD nArg, char *pszBuf, int cchBuf)
{
Config *pCfg = m_cacheComponent.FindConfig(compId);
if (pCfg)
return pCfg->GetStringArg(nArg, pszBuf, cchBuf, 0);
return FALSE;
}
BOOL ConfigManager::IsConfigLoaded(ComponentId compId)
{
return (NULL != m_cacheComponent.FindConfig(compId));
}
void ConfigManager::GarbageCollectThread()
{
ZAssert(this);
while (TRUE)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hevtDie, 3*60000L))
{
for (int i=0; i < kCompId_Last; i++)
{
Config *pCfg = m_cacheGarbage.RemoveHead((ComponentId) i);
while (pCfg)
{
delete pCfg;
pCfg = m_cacheGarbage.RemoveHead((ComponentId) i);
}
}
break;
}
for (int i=0; i < kCompId_Last; i++)
{
Config *pCfg = m_cacheGarbage.RemoveHeadIfOld((ComponentId) i, 10*60000L);
while (pCfg)
{
delete pCfg;
pCfg = m_cacheGarbage.RemoveHeadIfOld((ComponentId) i, 10*60000L);
}
}
}
}
BOOL ConfigReader::ReadRg(const ConfigInfoBuffer *prgItems, int cItems)
{
ZAssert(prgItems);
ZAssert(cItems);
BOOL fRet = Open();
if (fRet)
{
for (int i=0; i < cItems; i++)
{
switch (prgItems[i].info.type)
{
case kConfigType_SZ:
fRet &= FastReadSz(prgItems[i].info.pszKeyName, (char *) prgItems[i].pBuf, prgItems[i].info.cb, prgItems[i].info.nRequired, prgItems[i].info.pszDefault);
break;
case kConfigType_DWORD:
ZAssert(sizeof(int) == prgItems[i].info.cb);
fRet &= FastReadInt(prgItems[i].info.pszKeyName, (int *) prgItems[i].pBuf, prgItems[i].info.nRequired, prgItems[i].info.dwDefault);
break;
default:
ZAssert(FALSE);
SRVDBG_Error2("Bad reg key type specified", prgItems[i].info.pszKeyName);
fRet = FALSE;
break;
}
}
Close();
}
return fRet;
}
BOOL ConfigReader::ReadRgRg(int cRepeat, const ConfigInfoBuffer *prgItems, int cItems)
{
ZAssert(prgItems);
ZAssert(cItems);
ZAssert(cRepeat);
BOOL fRet = Open();
if (fRet)
{
for (int i=0; i < cItems; i++)
{
BYTE *pb = prgItems[i].pBuf;
for (int j=0; j < cRepeat; j++)
{
char szT[1024];
::wsprintf(szT, "%s%03d", prgItems[i].info.pszKeyName, j);
switch (prgItems[i].info.type)
{
case kConfigType_SZ:
fRet &= FastReadSz(szT, (char *) pb, prgItems[i].info.cb, (j <= prgItems[i].info.nRequired), prgItems[i].info.pszDefault);
break;
case kConfigType_DWORD:
ZAssert(sizeof(int) == prgItems[i].info.cb);
fRet &= FastReadInt(szT, (int *) pb, (j <= prgItems[i].info.nRequired), prgItems[i].info.dwDefault);
break;
default:
ZAssert(FALSE);
SRVDBG_Error2("Bad reg key type specified", prgItems[i].info.pszKeyName);
fRet = FALSE;
break;
}
pb += prgItems[i].info.cb;
}
}
Close();
}
return fRet;
}
BOOL ConfigReader::ReadInt(const char *pszItem, int *pnVal, BOOL fRequired, int nDefault)
{
ZAssert(pszItem);
ZAssert(pnVal);
BOOL fRet = Open();
if (fRet)
{
fRet = FastReadInt(pszItem, pnVal, fRequired, nDefault);
Close();
}
else
{
if (!fRequired)
{
fRet = TRUE;
*pnVal = nDefault;
}
}
return fRet;
}
BOOL ConfigReader::ReadSz(const char *pszItem, char *psz, int cchMax, BOOL fRequired, const char *pszDefault)
{
ZAssert(pszItem);
ZAssert(psz);
ZAssert(fRequired || pszDefault);
ZAssert((NULL == pszDefault) || (lstrlen(pszDefault) < cchMax-1));
BOOL fRet = Open();
if (fRet)
{
fRet = FastReadSz(pszItem, psz, cchMax, fRequired, pszDefault);
Close();
}
else
{
if (!fRequired)
{
fRet = TRUE;
lstrcpy(psz, pszDefault);
}
}
return fRet;
}
BOOL ConfigReader::WriteInt(const char *pszItem, int nVal)
{
ZAssert(pszItem);
BOOL fRet = Open();
if (fRet)
{
fRet = FastWriteInt(pszItem, nVal);
Close();
}
return fRet;
}
BOOL ConfigReader::WriteSz(const char *pszItem, const char *psz, int cch)
{
ZAssert(pszItem);
ZAssert(psz);
BOOL fRet = Open();
if (fRet)
{
fRet = FastWriteSz(pszItem, psz, cch);
Close();
}
return fRet;
}
ConfigReader *CreateConfigReader(ComponentId compId)
{
#ifdef CONFIG_OTHER_BASED
return CreateOtherConfigReader(compId);
#else
return CreateRegConfigReader(compId);
#endif
}
RegConfigReader *CreateRegConfigReader(ComponentId compId)
{
return new RegConfigReader(compId);
}