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.
 
 
 
 
 
 

769 lines
25 KiB

//-----------------------------------------------------------------------------
//
//
// File: DomCfg.cpp
//
// Description: Implementation of CDomainConfigTable and CInternalDomainInfo
//
// Author: mikeswa
//
// Copyright (C) 1998 Microsoft Corporation
//
//-----------------------------------------------------------------------------
#include "aqprecmp.h"
#include <domhash.h>
#include "domcfg.h"
#include "aqutil.h"
//Encourage compiler to include symbols for enums
eDomainInfoFlags g_eDomainInfo = DOMAIN_INFO_USE_SSL;
eIntDomainInfoFlags g_eIntDomainInfo = INT_DOMAIN_INFO_INVALID;
//---[ RemoveConfigEntryIteratorFn ]--------------------------------------------
//
//
// Description:
// Deletes and releases all internal domain info objects in table
// Parameters:
// IN pvContext - pointer to context (ignored)
// IN pvData - data entry to look at
// IN fWildcardData - TRUE if data is a wildcard entry (ignored)
// OUT pfContinue - TRUE if iterator should continue to the next entry
// OUT pfRemoveEntry - TRUE if entry should be deleted
// Returns:
// -
// History:
// 6/17/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
VOID RemoveConfigEntryIteratorFn(PVOID pvContext, PVOID pvData, BOOL fWildcard,
BOOL *pfContinue, BOOL *pfDelete)
{
CInternalDomainInfo *pIntDomainInfo = (CInternalDomainInfo *) pvData;
*pfDelete = TRUE;
*pfContinue = TRUE;
_ASSERT(INT_DOMAIN_INFO_SIG == pIntDomainInfo->m_dwSignature);
pIntDomainInfo->m_dwIntDomainInfoFlags |= INT_DOMAIN_INFO_INVALID;
pIntDomainInfo->Release();
}
//---[ RemoveOutdatedConfigEntryIteratorFn ]------------------------------------
//
//
// Description:
// Deletes and releases all outdated internal domain info objects in table.
// An internal domain entry is considered outdated if its version number
// does not match the global version number.
// Parameters:
// IN pvContext - pointer to context (current version number)
// IN pvData - data entry to look at
// IN fWildcardData - TRUE if data is a wildcard entry (ignored)
// OUT pfContinue - TRUE if iterator should continue to the next entry
// OUT pfRemoveEntry - TRUE if entry should be deleted
// Returns:
// -
// History:
// 9/29/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
VOID RemoveOutdatedConfigEntryIteratorFn(PVOID pvContext, PVOID pvData,
BOOL fWildcard, BOOL *pfContinue, BOOL *pfDelete)
{
CInternalDomainInfo *pIntDomainInfo = (CInternalDomainInfo *) pvData;
_ASSERT(INT_DOMAIN_INFO_SIG == pIntDomainInfo->m_dwSignature);
_ASSERT(pvContext);
*pfContinue = TRUE;
if (pIntDomainInfo->m_dwVersion != *((DWORD *)pvContext))
{
//make sure it is not the root entry
if ((1*sizeof(CHAR) == pIntDomainInfo->m_DomainInfo.cbDomainNameLength) &&
('*' == pIntDomainInfo->m_DomainInfo.szDomainName[0]) &&
('\0' == pIntDomainInfo->m_DomainInfo.szDomainName[1]))
{
//
//NOTE - It is not expected for this to happen. We expect
//SMTP to always provide a default entry. If SMTP changes such
//that does not, then dynamic updates would fail, because we never
//mark the default entry that we create as invalid. Once a link
//picks up this entry, it will never let it go.
//
_ASSERT(0 && "SMTP did not supply a * entry");
//It is the root entry... update verision number
//NOTE: The Root entry is a special case... it is required to be
//present at all times, and is not always inserted into the
//metabase. Because of this, it's version number may be incorrect,
//so we need to make sure that we don't remove it.
*pfDelete = FALSE;
pIntDomainInfo->m_dwVersion = *((DWORD *)pvContext);
}
else
{
//The entry is old
*pfDelete = TRUE;
pIntDomainInfo->m_dwIntDomainInfoFlags |= INT_DOMAIN_INFO_INVALID;
pIntDomainInfo->Release();
}
}
else
{
*pfDelete = FALSE;
}
}
//---[ HrCopyStringProperty ]--------------------------------------------------
//
//
// Description:
// Private helper function that is used to allocate and copy string
// properties in the DomainInfo struct
// Parameters:
// OUT (ref) szDest Dest string to allocate and copy to
// IN szSource Source string to copy
// IN cbLength Length of string (without ending '\0'
// Returns:
// S_OK on success
//
//-----------------------------------------------------------------------------
HRESULT inline HrCopyStringProperty(LPSTR &szDest, const LPSTR szSource,
DWORD cbLength)
{
HRESULT hr = S_OK;
_ASSERT(szSource); //must have a buffer to copy
_ASSERT(!szDest);
szDest = (LPSTR) pvMalloc(cbLength + sizeof(CHAR));
if (!szDest)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
//copy data
memcpy(szDest, szSource, cbLength); //copy string
szDest[cbLength] = '\0';
Exit:
return hr;
}
//---[ COPY_DOMAIN_INFO_STRING_PROP ]------------------------------------------
//
//
// Description:
// Macro used to call private helper function HrCopyStringProperty
// Parameters:
// pOldDomainInfo DomainInfo Struct to copy
// pNewDomainInfo New DomainInfo stuct to copy to
// cbProp Name of size property
// szProp Name of string proptery
// Returns:
//
//
//-----------------------------------------------------------------------------
#define COPY_DOMAIN_INFO_STRING_PROP(pOldDomainInfo, pNewDomainInfo, cbProp, szProp) \
{ \
_ASSERT(!(pNewDomainInfo)->cbProp); \
_ASSERT(!(pNewDomainInfo)->szProp); \
(pNewDomainInfo)->cbProp = (pOldDomainInfo)->cbProp; \
if ((pOldDomainInfo)->cbProp) \
hr = HrCopyStringProperty((pNewDomainInfo)->szProp, \
(pOldDomainInfo)->szProp, (pOldDomainInfo)->cbProp); \
}
//---[ CInternalDomainInfo::CInternalDomainInfo ]------------------------------
//
//
// Description:
// Object constructor. Initializes DomainInfo struct
// Parameters:
// DWORD dwVersion Current DomainConfigTable version
// Returns:
// -
// History:
// 9/29/98 - MikeSwa - added version
//
//-----------------------------------------------------------------------------
CInternalDomainInfo::CInternalDomainInfo(DWORD dwVersion)
{
ZeroMemory(&m_DomainInfo.dwDomainInfoFlags, sizeof(DomainInfo) - sizeof(DWORD));
m_dwIntDomainInfoFlags = INT_DOMAIN_INFO_OK;
m_dwSignature = INT_DOMAIN_INFO_SIG;
m_dwVersion = dwVersion;
//make sure our assumptions about the struct of DomainInfo are valid
_ASSERT(1 == ((DWORD *) &m_DomainInfo.dwDomainInfoFlags) - ((DWORD *) &m_DomainInfo));
m_DomainInfo.cbVersion = sizeof(DomainInfo);
}
//---[ CInternalDomainInfo::~CInternalDomainInfo ]-----------------------------
//
//
// Description:
// Class destructor... deallocates any memory associated with the
// DomainInfo struct
// Parameters:
// -
// Returns:
// -
//
//-----------------------------------------------------------------------------
CInternalDomainInfo::~CInternalDomainInfo()
{
_ASSERT(m_DomainInfo.cbVersion == sizeof(DomainInfo));
if (m_DomainInfo.szDomainName)
FreePv(m_DomainInfo.szDomainName);
if (m_DomainInfo.szETRNDomainName)
FreePv(m_DomainInfo.szETRNDomainName);
if (m_DomainInfo.szSmartHostDomainName)
FreePv(m_DomainInfo.szSmartHostDomainName);
if (m_DomainInfo.szDropDirectory)
FreePv(m_DomainInfo.szDropDirectory);
if (m_DomainInfo.szAuthType)
FreePv(m_DomainInfo.szAuthType);
if (m_DomainInfo.szUserName)
FreePv(m_DomainInfo.szUserName);
if (m_DomainInfo.szPassword)
FreePv(m_DomainInfo.szPassword);
if (m_DomainInfo.pvBlob)
FreePv(m_DomainInfo.pvBlob);
}
//---[ CInternalDomainInfo::HrInit ]-------------------------------------------
//
//
// Description:
// Clones a DomainInfo struct and allocates needed memory
// Parameters:
// IN pDomainInfo DomainInfo struct to copy
// Returns:
// S_OK on success
// E_OUTOFMEMORY if allocations fail
//-----------------------------------------------------------------------------
HRESULT CInternalDomainInfo::HrInit(DomainInfo *pDomainInfo)
{
HRESULT hr = S_OK;
m_DomainInfo.dwDomainInfoFlags = pDomainInfo->dwDomainInfoFlags;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbDomainNameLength, szDomainName);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbETRNDomainNameLength, szETRNDomainName);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbSmartHostDomainNameLength, szSmartHostDomainName);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbDropDirectoryLength, szDropDirectory);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbAuthTypeLength, szAuthType);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbUserNameLength, szUserName);
if (FAILED(hr))
goto Exit;
COPY_DOMAIN_INFO_STRING_PROP(pDomainInfo, &m_DomainInfo,
cbPasswordLength, szPassword);
if (FAILED(hr))
goto Exit;
m_DomainInfo.cEtrnDelayTime = pDomainInfo->cEtrnDelayTime;
//Copy the blob
if (pDomainInfo->cbBlob)
{
_ASSERT(pDomainInfo->pvBlob);
m_DomainInfo.pvBlob = (DWORD *) pvMalloc(pDomainInfo->cbBlob);
if (!m_DomainInfo.pvBlob)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
//copy data
memcpy(m_DomainInfo.pvBlob, pDomainInfo->pvBlob, pDomainInfo->cbBlob);
m_DomainInfo.cbBlob = pDomainInfo->cbBlob;
}
Exit:
return hr;
}
//---[ CDomainConfigTable::CDomainConfigTable ]--------------------------------
//
//
// Description:
// Constuctor for CDomainConfig Table
// Parameters:
// -
// Returns:
// -
//
//-----------------------------------------------------------------------------
CDomainConfigTable::CDomainConfigTable() :
m_slPrivateData("CDomainConfigTable")
{
m_dwFlags = 0;
m_dwSignature = DOMAIN_CONFIG_SIG;
m_dwCurrentConfigVersion = 0;
m_pLastStarDomainInfo = NULL;
m_pDefaultDomainConfig = NULL;
}
//---[ CDomainConfigTable::~CDomainConfigTable ]-------------------------------
//
//
// Description:
// Destructor for CDomainConfig Table
// Parameters:
// -
// Returns:
// -
//
//-----------------------------------------------------------------------------
CDomainConfigTable::~CDomainConfigTable()
{
TraceFunctEnterEx((LPARAM) this, "CDomainConfigTable::~CDomainConfigTable");
HRESULT hr = S_OK;
//Delete all entries from the table
if (DOMCFG_DOMAIN_NAME_TABLE_INIT & m_dwFlags)
{
//iterate over all domains and delete entries in hash table
m_dnt.HrIterateOverSubDomains(NULL, RemoveConfigEntryIteratorFn, NULL);
if (m_pDefaultDomainConfig != NULL) {
m_pDefaultDomainConfig->Release();
m_pDefaultDomainConfig = NULL;
}
m_dwFlags ^= DOMCFG_DOMAIN_NAME_TABLE_INIT;
}
TraceFunctLeave();
}
//---[ CDomainConfigTable::HrInit ]--------------------------------------------
//
//
// Description:
// Initializes DOMAIN_NAME_TABLE hash table
// Parameters:
// -
// Returns:
// S_OK on success
//
//-----------------------------------------------------------------------------
HRESULT CDomainConfigTable::HrInit()
{
TraceFunctEnterEx((LPARAM) this, "CDomainConfigTable::HrInit");
HRESULT hr = S_OK;
CInternalDomainInfo *pIntDomainInfoDefault = NULL;
DOMAIN_STRING strDomain;
hr = m_dnt.HrInit();
if (FAILED(hr))
goto Exit;
m_dwFlags |= DOMCFG_DOMAIN_NAME_TABLE_INIT;
//Part 1
//
//Allocate an InternalDomainInfo for m_pDefaultDomainConfig. This
//will be used for links/connections for which a routing sink has returned
//no connector
m_pDefaultDomainConfig = new CInternalDomainInfo(m_dwCurrentConfigVersion);
if (!m_pDefaultDomainConfig)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
m_pDefaultDomainConfig->m_DomainInfo.cbDomainNameLength = 1;
m_pDefaultDomainConfig->m_DomainInfo.szDomainName =
(LPSTR) pvMalloc(2*sizeof(CHAR));
if (!m_pDefaultDomainConfig->m_DomainInfo.szDomainName)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
memcpy(m_pDefaultDomainConfig->m_DomainInfo.szDomainName, "*", 2);
//Part 2
//
//Create default "*" entry in the DCT so that arbitrary domains will have
//something to match against. Note that this entry is separate from the
//m_pDefaultDomainConfig entry that is *not* part of the DCT, and is used
//for links/connections that are *not* supposed to match anything in the DCT
pIntDomainInfoDefault = new CInternalDomainInfo(m_dwCurrentConfigVersion);
if (!pIntDomainInfoDefault)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pIntDomainInfoDefault->m_DomainInfo.cbDomainNameLength = 1;
pIntDomainInfoDefault->m_DomainInfo.szDomainName = (LPSTR) pvMalloc(2*sizeof(CHAR));
if (!pIntDomainInfoDefault->m_DomainInfo.szDomainName)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
memcpy(pIntDomainInfoDefault->m_DomainInfo.szDomainName, "*", 2);
strDomain.Length = (USHORT) pIntDomainInfoDefault->m_DomainInfo.cbDomainNameLength;
strDomain.MaximumLength = strDomain.Length;
strDomain.Buffer = pIntDomainInfoDefault->m_DomainInfo.szDomainName;
hr = m_dnt.HrInsertDomainName(&strDomain, (PVOID) pIntDomainInfoDefault);
if (FAILED(hr))
goto Exit;
Exit:
TraceFunctLeave();
return hr;
}
//---[ CDomainConfigTable::HrSetInternalDomainInfo ]---------------------------
//
//
// Description:
// Inserts InternalDomainInfo into hash table based on szDomain
// Parameters:
// IN pIntDomainInfo Internal DomainInfo to insert
// Returns:
// S_OK on success
//
//-----------------------------------------------------------------------------
HRESULT CDomainConfigTable::HrSetInternalDomainInfo(
IN CInternalDomainInfo *pIntDomainInfo)
{
TraceFunctEnterEx((LPARAM) this, "CDomainConfigTable::SetInternalDomainInfo");
HRESULT hr = S_OK;
DOMAIN_STRING strDomain;
CInternalDomainInfo *pIntDomainInfoCurrent = NULL;
_ASSERT(pIntDomainInfo);
_ASSERT(pIntDomainInfo->m_DomainInfo.szDomainName);
_ASSERT(pIntDomainInfo->m_DomainInfo.cbDomainNameLength);
_ASSERT(pIntDomainInfo->m_dwVersion == m_dwCurrentConfigVersion);
strDomain.Length = (USHORT) pIntDomainInfo->m_DomainInfo.cbDomainNameLength;
strDomain.MaximumLength = (USHORT) pIntDomainInfo->m_DomainInfo.cbDomainNameLength;
strDomain.Buffer = pIntDomainInfo->m_DomainInfo.szDomainName;
pIntDomainInfo->AddRef();
//Get Lock on table
m_slPrivateData.ExclusiveLock();
//HACK ALERT
//
//SMTP calls this routine with info from one of two places:
//1. For each domain configured in the /smtpsvc/1/domains container in the
// metabase. In PT, these entries are populated from address spaces on
// connectors.
//2. For outbound-security configured at the /smtpsvc/1 (ie, at the VS)
// level, it creates a "dummy" entry for the "*" domain.
//
//Unfortunately, this creates a problem if you have a connector with the
// * address space, because the insertion in item 2 will overwrite the
// insertion for * in item 1.
//To handle this case, we keep the "last" * entry received in the
// m_pLastStarDomainInfo. If we receive a second entry, then we know the
// m_pLastStarDomainInfo is a domain entry from item 1. Otherwise, it
// is the default config info.
//
//
//If this is the "*" domain, then store it in m_pLastStarDomainInfo, until
//we decide whether this is really the star domain info from item 1 or
//the info from item 2
//
if (pIntDomainInfo->m_DomainInfo.cbDomainNameLength == 1 &&
pIntDomainInfo->m_DomainInfo.szDomainName[0] == '*') {
if (m_pLastStarDomainInfo == NULL) {
m_pLastStarDomainInfo = pIntDomainInfo;
hr = S_OK;
goto Exit;
} else {
// This is the second * domain entry we have seen. Insert the
// previous entry into the DMT, and keep this one as the last star
// entry seen.
pIntDomainInfoCurrent = pIntDomainInfo;
pIntDomainInfo = m_pLastStarDomainInfo;
m_pLastStarDomainInfo = pIntDomainInfoCurrent;
pIntDomainInfoCurrent = NULL;
dwInterlockedSetBits(&m_dwFlags, DOMCFG_MULTIPLE_STAR_DOMAINS);
}
}
hr = m_dnt.HrInsertDomainName(&strDomain, (PVOID) pIntDomainInfo);
if (FAILED(hr))
{
if (DOMHASH_E_DOMAIN_EXISTS == hr)
{
//someone already inserted for this domain
hr = m_dnt.HrRemoveDomainName(&strDomain,
(PVOID *) &pIntDomainInfoCurrent);
_ASSERT(DOMHASH_E_NO_SUCH_DOMAIN != hr); //someone violated write-lock
if (FAILED(hr))
goto Exit;
_ASSERT(pIntDomainInfoCurrent);
//Mark old info as invalid & release
pIntDomainInfoCurrent->m_dwIntDomainInfoFlags |= INT_DOMAIN_INFO_INVALID;
_ASSERT(pIntDomainInfoCurrent->m_dwVersion <= pIntDomainInfo->m_dwVersion);
pIntDomainInfoCurrent->Release();
pIntDomainInfoCurrent = NULL;
hr = m_dnt.HrInsertDomainName(&strDomain, (PVOID) pIntDomainInfo);
_ASSERT(DOMHASH_E_DOMAIN_EXISTS != hr); //someone violated write-lock
if (FAILED(hr))
goto Exit;
}
else
{
goto Exit;
}
}
Exit:
m_slPrivateData.ExclusiveUnlock();
TraceFunctLeave();
return hr;
}
//---[ CDomainConfigTable::HrGetInternalDomainInfo ]---------------------------
//
//
// Description:
// Gets internal Domaininfo stuct from hash table. Will use wildcard
// matching
// Parameters:
// IN cbDomainnameLength Length of string to search for
// IN szDomainName Domain Name to search for
// OUT ppIntDomainInfo Domain info returned (must be released)
// Returns:
// S_OK if match is found
// AQUEUE_E_INVALID_DOMAIN if no match is found
//
//-----------------------------------------------------------------------------
HRESULT CDomainConfigTable::HrGetInternalDomainInfo(
IN DWORD cbDomainNameLength,
IN LPSTR szDomainName,
OUT CInternalDomainInfo **ppIntDomainInfo)
{
TraceFunctEnterEx((LPARAM) this, "CDomainConfigTable::GetInternalDomainInfo");
HRESULT hr = S_OK;
DOMAIN_STRING strDomain;
_ASSERT(cbDomainNameLength);
_ASSERT(szDomainName);
_ASSERT(ppIntDomainInfo);
strDomain.Length = (USHORT) cbDomainNameLength;
strDomain.MaximumLength = (USHORT) cbDomainNameLength;
strDomain.Buffer = szDomainName;
m_slPrivateData.ShareLock();
//Use wildcard lookup
hr = m_dnt.HrFindDomainName(&strDomain, (PVOID *) ppIntDomainInfo, FALSE);
if (FAILED(hr))
{
//It should at least match the default domain
_ASSERT(DOMHASH_E_NO_SUCH_DOMAIN != hr);
goto Exit;
}
_ASSERT(*ppIntDomainInfo);
(*ppIntDomainInfo)->AddRef();
Exit:
m_slPrivateData.ShareUnlock();
TraceFunctLeave();
return hr;
}
//---[ CDomainConfigTable::HrGetDefaultDomainInfo ]---------------------------
//
//
// Description:
// Gets internal Default Domaininfo stuct.
// Parameters:
// OUT ppIntDomainInfo Domain info returned (must be released)
// Returns:
// S_OK if successful
// AQUEUE_E_INVALID_DOMAIN if error
//
//-----------------------------------------------------------------------------
HRESULT CDomainConfigTable::HrGetDefaultDomainInfo(
OUT CInternalDomainInfo **ppIntDomainInfo)
{
TraceFunctEnterEx((LPARAM) this, "CDomainConfigTable::GetDefaultDomainInfo");
HRESULT hr = S_OK;
*ppIntDomainInfo = NULL;
m_slPrivateData.ShareLock();
if (m_pDefaultDomainConfig != NULL) {
*ppIntDomainInfo = m_pDefaultDomainConfig;
} else {
hr = AQUEUE_E_INVALID_DOMAIN;
goto Exit;
}
_ASSERT(*ppIntDomainInfo);
(*ppIntDomainInfo)->AddRef();
Exit:
m_slPrivateData.ShareUnlock();
TraceFunctLeave();
return hr;
}
//---[ CDomainConfigTable::StartConfigUpdate ]---------------------------------
//
//
// Description:
// Signals that the metabase has been updated, and we will now begin to
// get updated information. Increments an internal version number that
// will be used to removed old, outdated entries once all of the config
// info has been updated.
// Parameters:
// -
// Returns:
// -
// History:
// 9/29/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
void CDomainConfigTable::StartConfigUpdate()
{
InterlockedIncrement((PLONG) &m_dwCurrentConfigVersion);
_ASSERT(!(m_dwFlags & DOMCFG_FINISH_UPDATE_PENDING));
_ASSERT(m_pLastStarDomainInfo == NULL);
dwInterlockedSetBits(&m_dwFlags, DOMCFG_FINISH_UPDATE_PENDING);
dwInterlockedUnsetBits(&m_dwFlags, DOMCFG_MULTIPLE_STAR_DOMAINS);
}
//---[ CDomainConfigTable::FinishConfigUpdate ]--------------------------------
//
//
// Description:
// Used to signal when all updated configuration information has been
// passed in. Will then walk all of our cached configuration information
// and remove outdated entries
// Parameters:
// -
// Returns:
// -
// History:
// 9/29/98 - MikeSwa Created
//
//-----------------------------------------------------------------------------
void CDomainConfigTable::FinishConfigUpdate()
{
HRESULT hr = S_OK;
DWORD dwCurrentVersion = m_dwCurrentConfigVersion;
CInternalDomainInfo *pIntDomainInfo = NULL;
//There should be a matching start
_ASSERT(m_dwFlags & DOMCFG_FINISH_UPDATE_PENDING);
//
// Get the last "*" domain in case we need to explicitly update the table
// with it.
//
m_slPrivateData.ShareLock();
pIntDomainInfo = m_pLastStarDomainInfo;
if (pIntDomainInfo)
pIntDomainInfo->AddRef();
m_slPrivateData.ShareUnlock();
//
// If only 1 "*" domain has been configured, then we have not inserted
// it in the DNT, and the actual data there is out of date. We
// need to insert it into the table.
//
if (pIntDomainInfo && !(DOMCFG_MULTIPLE_STAR_DOMAINS & m_dwFlags))
{
HrSetInternalDomainInfo(pIntDomainInfo);
}
//
// Release the internal domain info if we got it.
//
if (pIntDomainInfo)
pIntDomainInfo->Release();
dwInterlockedUnsetBits(&m_dwFlags, DOMCFG_FINISH_UPDATE_PENDING);
//Lock table, remove outdated entries, and update the default domain config
m_slPrivateData.ExclusiveLock();
if (m_pLastStarDomainInfo) {
m_pDefaultDomainConfig->m_dwIntDomainInfoFlags |=
INT_DOMAIN_INFO_INVALID;
m_pDefaultDomainConfig->Release();
m_pDefaultDomainConfig = m_pLastStarDomainInfo;
m_pLastStarDomainInfo = NULL;
}
hr = m_dnt.HrIterateOverSubDomains(NULL,
RemoveOutdatedConfigEntryIteratorFn, &dwCurrentVersion);
m_slPrivateData.ExclusiveUnlock();
if (FAILED(hr))
_ASSERT(DOMHASH_E_NO_SUCH_DOMAIN == hr);
}