|
|
/**********************************************************************/ /** Microsoft Passport **/ /** Copyright(c) Microsoft Corporation, 1999 - 2001 **/ /**********************************************************************/
/*
nexusconfig.cpp
FILE HISTORY:
*/
// NexusConfig.cpp: implementation of the CNexusConfig class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NexusConfig.h"
#include "PassportGuard.hpp"
#include "helperfuncs.h"
PassportLock CNexusConfig::m_ReadLock;
#define ALT_ATTRIBUTE_SUFFIX L"Default"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// turn a char into it's hex value
#define XTOI(x) (isalpha(x) ? (toupper(x)-'A'+10) : (x - '0'))
//===========================================================================
//
// CNexusConfig
//
CNexusConfig::CNexusConfig() : m_defaultProfileSchema(NULL), m_defaultTicketSchema(NULL), m_valid(FALSE), m_szReason(NULL), m_refs(0) { }
//===========================================================================
//
// ~CNexusConfig
//
CNexusConfig::~CNexusConfig() { // profile schemata
if (!m_profileSchemata.empty()) { BSTR2PS::iterator ita = m_profileSchemata.begin(); for (; ita != m_profileSchemata.end(); ita++) { FREE_BSTR(ita->first); ita->second->Release(); } m_profileSchemata.clear(); }
// ticket schemata
if (!m_ticketSchemata.empty()) { BSTR2TS::iterator ita = m_ticketSchemata.begin(); for (; ita != m_ticketSchemata.end(); ita++) { FREE_BSTR(ita->first); ita->second->Release(); } m_ticketSchemata.clear(); }
//
if (!m_domainAttributes.empty()) { BSTR2DA::iterator itc = m_domainAttributes.begin(); for (; itc != m_domainAttributes.end(); itc++) { FREE_BSTR(itc->first); if (!itc->second->empty()) { // Now we're deleting ATTRVALs
ATTRMAP::iterator itd = itc->second->begin(); for (; itd != itc->second->end(); itd++) { ATTRVAL* pAttrVal = itd->second;
if(pAttrVal->bDoLCIDReplace) { FREE_BSTR(pAttrVal->bstrAttrVal); } else { LCID2ATTR::iterator ite = pAttrVal->pLCIDAttrMap->begin(); for (;ite != pAttrVal->pLCIDAttrMap->end(); ite++) { FREE_BSTR(ite->second); }
delete pAttrVal->pLCIDAttrMap; } FREE_BSTR(itd->first); delete itd->second; } } delete itc->second; } m_domainAttributes.clear(); } if (m_szReason) FREE_BSTR(m_szReason); }
//===========================================================================
//
// getFailureString
//
BSTR CNexusConfig::getFailureString() { if (m_valid) return NULL; return m_szReason; }
//===========================================================================
//
// setReason
//
void CNexusConfig::setReason(LPTSTR reason) { if (m_szReason) FREE_BSTR(m_szReason); m_szReason = ALLOC_BSTR(reason); }
//===========================================================================
//
// AddRef
//
CNexusConfig* CNexusConfig::AddRef() { InterlockedIncrement(&m_refs); return this; }
//===========================================================================
//
// Release
//
void CNexusConfig::Release() { long refs = InterlockedDecrement(&m_refs); if (refs == 0) delete this; }
//===========================================================================
//
// Read
//
BOOL CNexusConfig::Read(IXMLDocument* s) { //BUGBUG Put this here because having two threads in Read at the same
// time is almost guaranteed to cause STL maps to hurl (heap
// corruption, pointer nastiness, etc. Long term solution
// is to move these to LKRHash tables as well.
PassportGuard<PassportLock> readGuard(m_ReadLock);
MSXML::IXMLDocumentPtr pDoc; MSXML::IXMLElementCollectionPtr pElts, pSchemas, pDomains, pAtts; MSXML::IXMLElementPtr pElt, pDom, pAtt; VARIANT iTopLevel, iSubNodes, iAtts; _bstr_t name(L"Name"), suffix(L"DomainSuffix"), lcidatt(L"lcid"), version(L"Version"); LONG cTLN, cSN, cAtts;
BSTR attribute = NULL, value = NULL; _bstr_t lcid;
HRESULT hr = S_OK;
try { pDoc = s;
pElts = pDoc->root->children; m_bstrVersion = pDoc->root->getAttribute(version);
VariantInit(&iTopLevel); iTopLevel.vt = VT_I4; cTLN = pElts->length;
for (iTopLevel.lVal=0; iTopLevel.lVal < cTLN; iTopLevel.lVal++) { pElt = pElts->item(&iTopLevel); CComBSTR tagName; hr = pElt->get_tagName(&tagName);
if(hr != S_OK) continue; if (!_wcsicmp(tagName,FOLDER_TICKET_SCHEMATA)) { VariantInit(&iSubNodes); iSubNodes.vt = VT_I4; pSchemas = pElt->children; cSN = pSchemas->length; for (iSubNodes.lVal=0;iSubNodes.lVal < cSN;iSubNodes.lVal++) { pElt = pSchemas->item(&iSubNodes); // Read a schema
// BUGBUG probably more efficient ways to handle this variant->BSTR issue
BSTR schemaName = NULL; _bstr_t tmp = pElt->getAttribute(name); if (tmp.length() > 0) schemaName = ALLOC_BSTR(tmp);
CTicketSchema *pSchema = new CTicketSchema(); pSchema->AddRef(); if (schemaName && pSchema) { BSTR2TS::value_type pMapVal(schemaName,pSchema); pSchema->ReadSchema(pElt); if (!_wcsicmp(schemaName,L"CORE")) m_defaultTicketSchema = pSchema; m_ticketSchemata.insert(pMapVal); } else { if (schemaName) FREE_BSTR(schemaName); if (pSchema) pSchema->Release(); } }
} else if (!_wcsicmp(tagName,FOLDER_PROFILE_SCHEMATA)) { VariantInit(&iSubNodes); iSubNodes.vt = VT_I4; pSchemas = pElt->children; cSN = pSchemas->length; for (iSubNodes.lVal=0;iSubNodes.lVal < cSN;iSubNodes.lVal++) { pElt = pSchemas->item(&iSubNodes); // Read a schema
// BUGBUG probably more efficient ways to handle this variant->BSTR issue
BSTR schemaName = NULL; _bstr_t tmp = pElt->getAttribute(name); if (tmp.length() > 0) schemaName = ALLOC_BSTR(tmp);
CProfileSchema *pSchema = new CProfileSchema(); pSchema->AddRef(); if (schemaName && pSchema) { BSTR2PS::value_type pMapVal(schemaName,pSchema); pSchema->Read(pElt); if (!_wcsicmp(schemaName,L"CORE")) m_defaultProfileSchema = pSchema; m_profileSchemata.insert(pMapVal); } else { if (schemaName) FREE_BSTR(schemaName); if (pSchema) pSchema->Release(); } } } else if (!_wcsicmp(tagName,FOLDER_PASSPORT_NETWORK)) { // individual domain attributes
pElt = pElts->item(&iTopLevel); VariantInit(&iSubNodes); iSubNodes.vt = VT_I4; pDomains = pElt->children; cSN = pDomains->length; VariantInit(&iAtts); iAtts.vt = VT_I4;
for (iSubNodes.lVal=0;iSubNodes.lVal < cSN;iSubNodes.lVal++) { pDom = pDomains->item(&iSubNodes); BSTR dname = NULL; _bstr_t rawdn = pDom->getAttribute(suffix);
dname = ALLOC_BSTR(rawdn);
if (!dname) continue;
pAtts = pDom->children; cAtts = pAtts->length;
// Add new hash table for this domain
ATTRMAP *newsite = new ATTRMAP; if (!newsite) continue;
BSTR2DA::value_type pNewSite(dname, newsite); m_domainAttributes.insert(pNewSite);
for (iAtts.lVal = 0; iAtts.lVal < cAtts; iAtts.lVal++) { pAtt = pAtts->item(&iAtts); lcid = pAtt->getAttribute(lcidatt); bool bIsReplaceLcid = (_wcsicmp(lcid, L"lang_replace") == 0); pAtt->get_tagName(&attribute); pAtt->get_text(&value);
TAKEOVER_BSTR(attribute); TAKEOVER_BSTR(value); if (attribute && value) { // Find or add the lcid->value map for this attr
ATTRMAP::const_iterator lcit = newsite->find(attribute); ATTRVAL* attrval; if (lcit == newsite->end()) { attrval = new ATTRVAL; if(attrval != NULL) { attrval->bDoLCIDReplace = bIsReplaceLcid; if(!bIsReplaceLcid) { attrval->pLCIDAttrMap = new LCID2ATTR; } else { attrval->bstrAttrVal = value; value = NULL; }
ATTRMAP::value_type pAtt(attribute,attrval); newsite->insert(pAtt); attribute = NULL; } else { FREE_BSTR(attribute); attribute = NULL; FREE_BSTR(value); value = NULL; } } else { FREE_BSTR(attribute); attribute = NULL; attrval = lcit->second; }
short iLcid = 0; if(!bIsReplaceLcid) { if (lcid.length() == 4) { LPWSTR szlcid = lcid; if (iswxdigit(szlcid[0]) && iswxdigit(szlcid[1]) && iswxdigit(szlcid[2]) && iswxdigit(szlcid[3])) { iLcid = (XTOI(szlcid[0]) << 12) + (XTOI(szlcid[1]) << 8) + (XTOI(szlcid[2]) << 4) + (XTOI(szlcid[3]) << 0); } else { if (g_pAlert) g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_LCID_ERROR, lcid); } } else if (lcid.length() == 2) { LPWSTR szlcid = lcid; if (iswxdigit(szlcid[0]) && iswxdigit(szlcid[1])) { iLcid = (XTOI(szlcid[0]) << 12) + (XTOI(szlcid[1]) << 8); } else { if (g_pAlert) g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_LCID_ERROR, lcid); } } else if (lcid.length() > 0) { if (g_pAlert) g_pAlert->report(PassportAlertInterface::ERROR_TYPE, PM_LCID_ERROR, lcid); }
LCID2ATTR::value_type lcAtt(iLcid,value); if (attrval && attrval->pLCIDAttrMap) { attrval->pLCIDAttrMap->insert(lcAtt); } else { FREE_BSTR(value); value = NULL; } } else { if (value) { FREE_BSTR(value); value = NULL; } } } else { if (attribute) { FREE_BSTR(attribute); attribute = NULL; } if (value) { FREE_BSTR(value); value = NULL; } } } } } } } catch (...) { // _bstr_t r = e.Description();
if (attribute) { FREE_BSTR(attribute); attribute = NULL; } if (value) { FREE_BSTR(value); value = NULL; } return FALSE; } m_valid = TRUE; return TRUE;
}
//===========================================================================
//
// DomainExists
//
bool CNexusConfig::DomainExists(LPCWSTR domain) { BSTR2DA::const_iterator it = m_domainAttributes.find(_bstr_t(domain)); return (it == m_domainAttributes.end() ? false : true); }
//===========================================================================
//
// getDomainAttribute
//
void CNexusConfig::getDomainAttribute( LPCWSTR domain, // in
LPCWSTR attr, // in
DWORD valuebuflen, // in (chars, not bytes!)
LPWSTR valuebuf, // out
USHORT lcid, // in
BOOL bNoAlt, // in if to try alternate attribute
BOOL bExactLcid // if do exact lcid match
) { BSTR2DA::const_iterator it; ATTRMAP::const_iterator daiter; ATTRVAL* pAttrVal;
if(valuebuf == NULL) goto Cleanup;
*valuebuf = L'\0';
it = m_domainAttributes.find(_bstr_t(domain)); if (it == m_domainAttributes.end()) { // Not found
goto Cleanup; }
daiter = (*it).second->find(_bstr_t(attr)); if (daiter == it->second->end()) { // Not found
goto Cleanup; }
pAttrVal = daiter->second; if(pAttrVal->bDoLCIDReplace) { LPWSTR szSrc = pAttrVal->bstrAttrVal; LPWSTR szDst = valuebuf; DWORD dwLenRemaining = valuebuflen;
while(*szSrc != L'\0' && dwLenRemaining != 0) { if(*szSrc == L'%') { szSrc++;
switch((WCHAR)CharUpperW((LPWSTR)(*szSrc))) { case L'L': { WCHAR szLCID[32];
_ultow(lcid, szLCID, 10);
int nLength = lstrlenW(szLCID);
for(int nIndex = 0; nIndex < nLength && dwLenRemaining != 0; nIndex++) { *(szDst++) = szLCID[nIndex]; --dwLenRemaining; }
szSrc++; } break;
case L'C': { WCHAR szCharCode[3];
//
// TODO Insert code here to lookup char code
// based on lcid.
//
lstrcpyW(szCharCode, L"EN");
*(szDst++) = szCharCode[0]; --dwLenRemaining;
if(dwLenRemaining != 0) { *(szDst++) = szCharCode[1]; --dwLenRemaining; }
szSrc++; } break;
default:
*(szDst++) = L'%'; --dwLenRemaining;
if(dwLenRemaining != 0) { *(szDst++) = *(szSrc++); --dwLenRemaining; }
break; } } else { *(szDst++) = *(szSrc++); dwLenRemaining--; } }
if(dwLenRemaining != 0) *szDst = L'\0'; else valuebuf[valuebuflen - 1] = L'\0'; } else { LCID2ATTR* pLcidMap = pAttrVal->pLCIDAttrMap; LCID2ATTR::const_iterator lciter = pLcidMap->find(lcid); if (lciter == pLcidMap->end()) { // try default lcid
ATTRMAP::const_iterator defaultLcidIt; defaultLcidIt = (*it).second->find(_bstr_t(L"DEFAULTLCID")); if (defaultLcidIt != it->second->end()) { ATTRVAL* pDefaultAttrVal; pDefaultAttrVal = (*defaultLcidIt).second; LCID2ATTR::const_iterator pDefaultLcidMapIt = pDefaultAttrVal->pLCIDAttrMap->find(0);
if ((*pDefaultLcidMapIt).second && *((*pDefaultLcidMapIt).second)) { LONG defaultLcid = 0; defaultLcid = FromHex((*pDefaultLcidMapIt).second);
if (lcid == defaultLcid) { lciter = pLcidMap->find(0); } } } // BOOL bNoAlt, // in if to try alternate attribute
// BOOL bExactLcid // if do exact lcid match
if (lciter == pLcidMap->end() && !bNoAlt) { // try to find the alternative attribute by appending the suffix
WCHAR wszAltAttr[MAX_PATH + 1]; if( wnsprintf(wszAltAttr, MAX_PATH, L"%s%s", attr, ALT_ATTRIBUTE_SUFFIX ) > 0) { getDomainAttribute(domain, wszAltAttr, valuebuflen, valuebuf, lcid, TRUE, TRUE); if ( *valuebuf != 0 ) // found
goto Cleanup; } } // Not found
if (lciter == pLcidMap->end() && lcid != 0 && !bExactLcid) { lciter = pLcidMap->find(PRIMARYLANGID(lcid)); // primary language
if (lciter == pLcidMap->end()) { lciter = pLcidMap->find(0); if (lciter == pLcidMap->end()) goto Cleanup; } } } if(lciter != pLcidMap->end()) lstrcpynW(valuebuf, (*lciter).second, valuebuflen); }
Cleanup:
return; }
//===========================================================================
//
// getProfileSchema
//
CProfileSchema* CNexusConfig::getProfileSchema(BSTR schemaName) { if (schemaName == NULL) return m_defaultProfileSchema;
BSTR2PS::const_iterator it = m_profileSchemata.find(schemaName); if (it == m_profileSchemata.end()) return NULL; else return (*it).second; }
//===========================================================================
//
// getTicketSchema
//
CTicketSchema* CNexusConfig::getTicketSchema(BSTR schemaName) { if (schemaName == NULL) return m_defaultTicketSchema;
BSTR2TS::const_iterator it = m_ticketSchemata.find(schemaName); if (it == m_ticketSchemata.end()) return NULL; else return (*it).second; }
//===========================================================================
//
// getDomains
//
LPCWSTR* CNexusConfig::getDomains(int *numDomains) { int i;
if (!numDomains) return NULL;
*numDomains = m_domainAttributes.size();
if (*numDomains == 0) return NULL;
LPCWSTR* retVal = new LPCWSTR[*numDomains];
if (!retVal) return NULL;
BSTR2DA::const_iterator itc = m_domainAttributes.begin(); for (i = 0; itc != m_domainAttributes.end(); itc++, i++) { retVal[i] = itc->first; } return retVal; }
//===========================================================================
//
// GetXMLInfo
//
BSTR CNexusConfig::GetXMLInfo() { return m_bstrVersion; }
//===========================================================================
//
// Dump
//
void CNexusConfig::Dump(BSTR* pbstrDump) { if(pbstrDump == NULL) return;
*pbstrDump = NULL;
CComBSTR bstrDump;
// because CComBSTR will throw an exception if a memory allocation fails
// we need to wrap this code with a try/catch.
try { BSTR2DA::const_iterator domainIterator; for(domainIterator = m_domainAttributes.begin(); domainIterator != m_domainAttributes.end(); domainIterator++) { ATTRMAP* pAttrMap = domainIterator->second;
bstrDump += L"Domain: "; bstrDump += domainIterator->first; bstrDump += L"<BR><BR>";
ATTRMAP::const_iterator attrIterator;
for(attrIterator = pAttrMap->begin(); attrIterator != pAttrMap->end(); attrIterator++) { bstrDump += L"Attribute: "; bstrDump += attrIterator->first; bstrDump += L"<BR><BR>";
ATTRVAL* pAttrVal = attrIterator->second; if(pAttrVal->bDoLCIDReplace) { bstrDump += L"LCID = lang_replace Value = "; bstrDump += pAttrVal->bstrAttrVal; bstrDump += L"<BR>"; } else { LCID2ATTR* pLCIDMap = pAttrVal->pLCIDAttrMap;
LCID2ATTR::const_iterator lcidIterator;
for(lcidIterator = pLCIDMap->begin(); lcidIterator != pLCIDMap->end(); lcidIterator++) { WCHAR szBuf[32];
bstrDump += L"LCID = "; bstrDump += _itow(lcidIterator->first, szBuf, 10); bstrDump += L" Value = "; bstrDump += lcidIterator->second; bstrDump += L"<BR>"; }
bstrDump += L"<BR>"; } }
bstrDump += L"<BR>"; }
*pbstrDump = bstrDump.Detach(); } catch(...) { *pbstrDump = NULL; } }
// EOF
|