Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

803 lines
26 KiB

/**********************************************************************/
/** 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