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.
 
 
 
 
 
 

3067 lines
89 KiB

/*++
Module Name:
RepSet.cpp
--*/
#include "stdafx.h"
#include "DfsCore.h"
#include "RepSet.h"
#include "netutils.h"
#include "ldaputils.h"
#include <dsgetdc.h> // DsGetSiteName
// sort member list based on m_bstrSite
struct FrsMemberCompare : greater<CFrsMember*>
{
bool operator()(const CFrsMember *pMem1, const CFrsMember *pMem2) const
{ return (lstrcmpi(pMem1->m_bstrSite, pMem2->m_bstrSite) > 0); }
};
//
// retrieve Site
//
HRESULT GetSiteName(IN BSTR i_bstrServer, OUT BSTR* o_pbstrSite)
{
HRESULT hr = S_OK;
LPTSTR lpszSiteName = NULL;
DWORD dwErr = DsGetSiteName(i_bstrServer, &lpszSiteName);
if (NO_ERROR == dwErr)
{
*o_pbstrSite = SysAllocString(lpszSiteName);
NetApiBufferFree((LPBYTE)lpszSiteName);
if (!*o_pbstrSite)
hr = E_OUTOFMEMORY;
} else if (ERROR_NO_SITENAME == dwErr)
{
*o_pbstrSite = SysAllocString(_T(""));
if (!*o_pbstrSite)
hr = E_OUTOFMEMORY;
} else
{
CComBSTR bstrText;
FormatMessageString(&bstrText, 0, IDS_UNKNOWN_SITE, dwErr);
*o_pbstrSite = bstrText.Copy();
if (!*o_pbstrSite)
hr = E_OUTOFMEMORY;
// hr = HRESULT_FROM_WIN32(dwErr);
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// constructor
CReplicaSet::CReplicaSet() :
m_pldap(NULL),
m_bNewSchema(FALSE)
{
dfsDebugOut((_T("CReplicaSet::CReplicaSet this=%p\n"), this));
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// destructor
CReplicaSet::~CReplicaSet()
{
_FreeMemberVariables();
dfsDebugOut((_T("CReplicaSet::~CReplicaSet this=%p\n"), this));
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// various properties
STDMETHODIMP CReplicaSet::get_Type(BSTR *pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrType)
{
m_bstrType = FRS_RSTYPE_OTHER;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrType);
}
*pVal = m_bstrType.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::put_Type(BSTR newVal)
{
if (newVal && (BSTR)m_bstrType && !lstrcmpi(newVal, m_bstrType))
return S_OK; // no change
CComBSTR bstrType = ((newVal && *newVal)? newVal : FRS_RSTYPE_DFS);
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrType);
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_TYPE;
pAttrVals[0].vpValue = (void *)(BSTR)bstrType;
pAttrVals[0].bBerValue = false;
HRESULT hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
if (SUCCEEDED(hr))
m_bstrType = bstrType;
return hr;
}
STDMETHODIMP CReplicaSet::get_TopologyPref(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrTopologyPref)
{
m_bstrTopologyPref = FRS_RSTOPOLOGYPREF_CUSTOM;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrTopologyPref);
}
*pVal = m_bstrTopologyPref.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
dfsDebugOut((_T("get_TopologyPref = %s\n"), m_bstrTopologyPref));
return S_OK;
}
STDMETHODIMP CReplicaSet::put_TopologyPref(BSTR newVal)
{
if (newVal && (BSTR)m_bstrTopologyPref && !lstrcmpi(newVal, m_bstrTopologyPref))
return S_OK; // no change
CComBSTR bstrTopologyPref = ((newVal && *newVal)? newVal : FRS_RSTOPOLOGYPREF_CUSTOM);
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrTopologyPref);
HRESULT hr = S_OK;
if (m_bNewSchema)
{
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_TOPOLOGYPREF;
pAttrVals[0].vpValue = (void *)(BSTR)bstrTopologyPref;
pAttrVals[0].bBerValue = false;
hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
if (SUCCEEDED(hr))
m_bstrTopologyPref = bstrTopologyPref;
} else
{
m_bstrTopologyPref = bstrTopologyPref;
}
dfsDebugOut((_T("put_TopologyPref = %s\n"), m_bstrTopologyPref));
return hr;
}
STDMETHODIMP CReplicaSet::get_HubMemberDN(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrHubMemberDN)
{
m_bstrHubMemberDN = _T("");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrHubMemberDN);
}
*pVal = m_bstrHubMemberDN.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
dfsDebugOut((_T("get_HubMemberDN = %s\n"), m_bstrHubMemberDN));
return S_OK;
}
STDMETHODIMP CReplicaSet::put_HubMemberDN(BSTR newVal)
{
if (newVal && (BSTR)m_bstrHubMemberDN && !lstrcmpi(newVal, m_bstrHubMemberDN))
return S_OK; // no change
CComBSTR bstrHubMemberDN = ((newVal && *newVal) ? newVal : _T(""));
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrHubMemberDN);
HRESULT hr = S_OK;
if (m_bNewSchema)
{
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_HUBSERVER;
pAttrVals[0].bBerValue = false;
if (newVal && *newVal)
{
pAttrVals[0].vpValue = (void *)(BSTR)bstrHubMemberDN;
hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
} else
{
pAttrVals[0].vpValue = NULL;
hr = ::DeleteValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
}
if (SUCCEEDED(hr))
m_bstrHubMemberDN = bstrHubMemberDN;
} else
{
m_bstrHubMemberDN = bstrHubMemberDN;
}
dfsDebugOut((_T("put_HubMemberDN = %s\n"), m_bstrHubMemberDN));
return hr;
}
STDMETHODIMP CReplicaSet::get_PrimaryMemberDN(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrPrimaryMemberDN)
{
m_bstrPrimaryMemberDN = _T("");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrPrimaryMemberDN);
}
*pVal = m_bstrPrimaryMemberDN.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::put_PrimaryMemberDN(BSTR newVal)
{
if (newVal && (BSTR)m_bstrPrimaryMemberDN && !lstrcmpi(newVal, m_bstrPrimaryMemberDN))
return S_OK; // no change
CComBSTR bstrPrimaryMemberDN = ((newVal && *newVal)? newVal : _T(""));
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrPrimaryMemberDN);
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_PRIMARYMEMBER;
pAttrVals[0].bBerValue = false;
HRESULT hr = S_OK;
if (newVal && *newVal)
{
pAttrVals[0].vpValue = (void *)(BSTR)bstrPrimaryMemberDN;
hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
} else
{
pAttrVals[0].vpValue = NULL;
hr = ::DeleteValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
}
if (SUCCEEDED(hr))
m_bstrPrimaryMemberDN = bstrPrimaryMemberDN;
return hr;
}
STDMETHODIMP CReplicaSet::get_FileFilter(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrFileFilter)
{
m_bstrFileFilter = _T("");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFileFilter);
}
*pVal = m_bstrFileFilter.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::put_FileFilter(BSTR newVal)
{
if (newVal && (BSTR)m_bstrFileFilter && !lstrcmpi(newVal, m_bstrFileFilter))
return S_OK; // no change
CComBSTR bstrFileFilter = ((newVal && *newVal) ? newVal : _T(""));
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrFileFilter);
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_FILEFILTER;
pAttrVals[0].bBerValue = false;
HRESULT hr = S_OK;
if (newVal && *newVal)
{
pAttrVals[0].vpValue = (void *)(BSTR)bstrFileFilter;
hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
} else
{
pAttrVals[0].vpValue = NULL;
hr = ::DeleteValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
}
if (SUCCEEDED(hr))
m_bstrFileFilter = bstrFileFilter;
return hr;
}
STDMETHODIMP CReplicaSet::get_DirFilter(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrDirFilter)
{
m_bstrDirFilter = _T("");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDirFilter);
}
*pVal = m_bstrDirFilter.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::put_DirFilter(BSTR newVal)
{
if (newVal && (BSTR)m_bstrDirFilter && !lstrcmpi(newVal, m_bstrDirFilter))
return S_OK; // no change
CComBSTR bstrDirFilter = ((newVal && *newVal)? newVal : _T(""));
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDirFilter);
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_FRS_REPSET_DIRFILTER;
pAttrVals[0].bBerValue = false;
HRESULT hr = S_OK;
if (newVal && *newVal)
{
pAttrVals[0].vpValue = (void *)(BSTR)bstrDirFilter;
hr = ::ModifyValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
} else
{
pAttrVals[0].vpValue = NULL;
hr = ::DeleteValues(m_pldap, m_bstrReplicaSetDN, 1, pAttrVals);
}
if (SUCCEEDED(hr))
m_bstrDirFilter = bstrDirFilter;
return hr;
}
STDMETHODIMP CReplicaSet::get_DfsEntryPath(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
if (!m_bstrDfsEntryPath)
{
m_bstrDfsEntryPath = _T("");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDfsEntryPath);
}
*pVal = m_bstrDfsEntryPath.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::get_Domain(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDomain);
*pVal = m_bstrDomain.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::get_ReplicaSetDN(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrReplicaSetDN);
*pVal = m_bstrReplicaSetDN.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
STDMETHODIMP CReplicaSet::get_NumOfMembers(long* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
*pVal = m_frsMemberList.size();
return S_OK;
}
STDMETHODIMP CReplicaSet::get_NumOfConnections(long* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
*pVal = m_frsConnectionList.size();
return S_OK;
}
STDMETHODIMP CReplicaSet::get_TargetedDC(BSTR* pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDC);
*pVal = m_bstrDC.Copy ();
RETURN_OUTOFMEMORY_IF_NULL(*pVal);
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// various methods
STDMETHODIMP CReplicaSet::Create(
BSTR i_bstrDomain,
BSTR i_bstrReplicaSetDN,
BSTR i_bstrType,
BSTR i_bstrTopologyPref,
BSTR i_bstrHubMemberDN,
BSTR i_bstrPrimaryMemberDN,
BSTR i_bstrFileFilter,
BSTR i_bstrDirFilter
)
{
RETURN_INVALIDARG_IF_NULL(i_bstrDomain);
RETURN_INVALIDARG_IF_NULL(i_bstrReplicaSetDN);
RETURN_INVALIDARG_IF_NULL(i_bstrType);
_FreeMemberVariables();
HRESULT hr = S_OK;
do {
m_bstrDomain = i_bstrDomain;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDomain, &hr);
CComBSTR bstrDomainDN;
hr = GetDomainInfo(
i_bstrDomain,
NULL, // return DC's Dns name
NULL, // return Domain's Dns name
&bstrDomainDN, // return DC=nttest,DC=micr
NULL, // return LDAP://<DC>/<Doma
&m_bstrDomainGuid // return Domain's guid
);
BREAK_IF_FAILED(hr);
hr = ConnectToDS(m_bstrDomain, &m_pldap, &m_bstrDC);
BREAK_IF_FAILED(hr);
//
// get schema version
//
hr = GetSchemaVersionEx(m_bstrDomain, FALSE);
BREAK_IF_FAILED(hr);
m_bNewSchema = (S_OK == hr);
dfsDebugOut((_T("NewSchema=%d\n"), m_bNewSchema));
m_bstrReplicaSetDN = i_bstrReplicaSetDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
m_bstrReplicaSetDN += _T(",");
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
m_bstrReplicaSetDN += bstrDomainDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
m_bstrType = i_bstrType;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrType, &hr);
//
// create container objects if not exist
//
hr = CreateNtfrsSettingsObjects(m_pldap, m_bstrReplicaSetDN);
BREAK_IF_FAILED(hr);
//
// create this nTFRSReplicaSet object
//
LDAP_ATTR_VALUE pAttrVals[7];
int i = 0;
pAttrVals[i].bstrAttribute = OBJCLASS_ATTRIBUTENAME;
pAttrVals[i].vpValue = (void *)OBJCLASS_NTFRSREPLICASET;
pAttrVals[i].bBerValue = false;
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_TYPE;
pAttrVals[i].vpValue = (void *)i_bstrType;
pAttrVals[i].bBerValue = false;
if (i_bstrTopologyPref && *i_bstrTopologyPref)
{
m_bstrTopologyPref = i_bstrTopologyPref;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrTopologyPref, &hr);
if (m_bNewSchema)
{
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_TOPOLOGYPREF;
pAttrVals[i].vpValue = (void *)i_bstrTopologyPref;
pAttrVals[i].bBerValue = false;
}
if (!lstrcmpi(FRS_RSTOPOLOGYPREF_HUBSPOKE, m_bstrTopologyPref))
{
if (i_bstrHubMemberDN && *i_bstrHubMemberDN)
{
m_bstrHubMemberDN = i_bstrHubMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrHubMemberDN, &hr);
if (m_bNewSchema)
{
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_HUBSERVER;
pAttrVals[i].vpValue = (void *)i_bstrHubMemberDN;
pAttrVals[i].bBerValue = false;
}
}
}
}
if (i_bstrPrimaryMemberDN && *i_bstrPrimaryMemberDN)
{
m_bstrPrimaryMemberDN = i_bstrPrimaryMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrPrimaryMemberDN, &hr);
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_PRIMARYMEMBER;
pAttrVals[i].vpValue = (void *)i_bstrPrimaryMemberDN;
pAttrVals[i].bBerValue = false;
}
if (i_bstrFileFilter && *i_bstrFileFilter)
{
m_bstrFileFilter = i_bstrFileFilter;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFileFilter, &hr);
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_FILEFILTER;
pAttrVals[i].vpValue = (void *)i_bstrFileFilter;
pAttrVals[i].bBerValue = false;
}
if (i_bstrDirFilter && *i_bstrDirFilter)
{
m_bstrDirFilter = i_bstrDirFilter;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDirFilter, &hr);
i++;
pAttrVals[i].bstrAttribute = ATTR_FRS_REPSET_DIRFILTER;
pAttrVals[i].vpValue = (void *)i_bstrDirFilter;
pAttrVals[i].bBerValue = false;
}
hr = AddValues(
m_pldap,
m_bstrReplicaSetDN,
++i,
pAttrVals
);
BREAK_IF_FAILED(hr);
} while (0);
if (FAILED(hr))
{
_FreeMemberVariables();
//
// try to clean empty container objects
//
(void)DeleteNtfrsReplicaSetObjectAndContainers(m_pldap, m_bstrReplicaSetDN);
}
return hr;
}
STDMETHODIMP CReplicaSet::Initialize(BSTR i_bstrDomain, BSTR i_bstrReplicaSetDN)
{
RETURN_INVALIDARG_IF_NULL(i_bstrDomain);
RETURN_INVALIDARG_IF_NULL(i_bstrReplicaSetDN);
_FreeMemberVariables();
HRESULT hr = S_OK;
do {
m_bstrDomain = i_bstrDomain;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDomain, &hr);
CComBSTR bstrDomainDN;
hr = GetDomainInfo(
i_bstrDomain,
NULL, // return DC's Dns name
NULL, // return Domain's Dns name
&bstrDomainDN, // return DC=nttest,DC=micr
NULL, // return LDAP://<DC>/<Doma
&m_bstrDomainGuid // return Domain's guid
);
BREAK_IF_FAILED(hr);
m_bstrReplicaSetDN = i_bstrReplicaSetDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
hr = ConnectToDS(m_bstrDomain, &m_pldap, &m_bstrDC);
BREAK_IF_FAILED(hr);
//
// get schema version
//
hr = GetSchemaVersionEx(m_bstrDomain, FALSE);
BREAK_IF_FAILED(hr);
m_bNewSchema = (S_OK == hr);
dfsDebugOut((_T("NewSchema=%d\n"), m_bNewSchema));
m_bstrReplicaSetDN += _T(",");
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
m_bstrReplicaSetDN += bstrDomainDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
PLDAP_ATTR_VALUE pValues[7] = {0,0,0,0,0,0,0};
LDAP_ATTR_VALUE pAttributes[6];
int i = 0;
pAttributes[i].bstrAttribute = ATTR_FRS_REPSET_TYPE;
if (m_bNewSchema)
{
pAttributes[++i].bstrAttribute = ATTR_FRS_REPSET_TOPOLOGYPREF;
pAttributes[++i].bstrAttribute = ATTR_FRS_REPSET_HUBSERVER;
}
pAttributes[++i].bstrAttribute = ATTR_FRS_REPSET_PRIMARYMEMBER;
pAttributes[++i].bstrAttribute = ATTR_FRS_REPSET_FILEFILTER;
pAttributes[++i].bstrAttribute = ATTR_FRS_REPSET_DIRFILTER;
hr = GetValues( m_pldap,
m_bstrReplicaSetDN,
OBJCLASS_SF_NTFRSREPLICASET,
LDAP_SCOPE_BASE,
++i,
pAttributes,
pValues);
BREAK_IF_FAILED(hr);
do {
i = 0;
if (pValues[i])
{
m_bstrType = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrType, &hr);
}
if (!m_bNewSchema)
{
m_bstrHubMemberDN.Empty();
m_bstrTopologyPref = FRS_RSTOPOLOGYPREF_CUSTOM;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrTopologyPref, &hr);
} else
{
i++;
if (pValues[i])
{
m_bstrTopologyPref = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrTopologyPref, &hr);
}
i++;
if (!lstrcmpi(FRS_RSTOPOLOGYPREF_HUBSPOKE, m_bstrTopologyPref))
{
if (pValues[i])
{
m_bstrHubMemberDN = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrHubMemberDN, &hr);
} else
{
// something was wrong, reset Cutom topology
m_bstrTopologyPref = FRS_RSTOPOLOGYPREF_CUSTOM;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrTopologyPref, &hr);
}
}
}
i++;
if (pValues[i])
{
m_bstrPrimaryMemberDN = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrPrimaryMemberDN, &hr);
}
i++;
if (pValues[i])
{
m_bstrFileFilter = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFileFilter, &hr);
}
i++;
if (pValues[i])
{
m_bstrDirFilter = (PTSTR)(pValues[i]->vpValue);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDirFilter, &hr);
}
} while (0);
for (i = 0; i < 7; i++)
{
if (pValues[i])
FreeAttrValList(pValues[i]);
}
hr = _PopulateMemberList();
BREAK_IF_FAILED(hr);
hr = _PopulateConnectionList();
BREAK_IF_FAILED(hr);
dfsDebugOut((_T("members=%d, connections=%d\n"), m_frsMemberList.size(), m_frsConnectionList.size()));
} while (0);
if (FAILED(hr))
_FreeMemberVariables();
return hr;
}
HRESULT CReplicaSet::_PopulateMemberList()
{
PCTSTR ppszAttributes[] = {
ATTR_DISTINGUISHEDNAME,
ATTR_FRS_MEMBER_COMPUTERREF,
0
};
LListElem* pElem = NULL;
HRESULT hr = GetValuesEx(
m_pldap,
m_bstrReplicaSetDN,
LDAP_SCOPE_ONELEVEL,
OBJCLASS_SF_NTFRSMEMBER,
ppszAttributes,
&pElem);
RETURN_IF_FAILED(hr);
LListElem* pCurElem = pElem;
while (pCurElem)
{
PTSTR** pppszValues = pCurElem->pppszAttrValues;
if (!pppszValues ||
!pppszValues[0] || !*(pppszValues[0]) ||
!pppszValues[1] || !*(pppszValues[1]))
{
pCurElem = pCurElem->Next;
continue; // corrupted member object
}
CFrsMember *pMember = new CFrsMember;
hr = pMember->InitEx(m_pldap,
m_bstrDC,
*(pppszValues[0]), // distinguishedName
*(pppszValues[1]) // computerRef
);
if (FAILED(hr))
{
delete pMember;
break;
} else if (S_FALSE == hr)
delete pMember;
else
m_frsMemberList.push_back(pMember);
pCurElem = pCurElem->Next;
}
FreeLListElem(pElem);
if (FAILED(hr))
FreeFrsMembers(&m_frsMemberList);
return hr;
}
STDMETHODIMP CReplicaSet::GetMemberList(
/* [retval][out] */ VARIANT __RPC_FAR *pvarMemberDNs)
{
RETURN_INVALIDARG_IF_NULL(pvarMemberDNs);
VariantInit(pvarMemberDNs);
pvarMemberDNs->vt = VT_ARRAY | VT_VARIANT;
pvarMemberDNs->parray = NULL;
HRESULT hr = S_OK;
int cMembers = m_frsMemberList.size();
if (!cMembers)
return hr; // parray is NULL when the member list is empty
SAFEARRAYBOUND bounds = {cMembers, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
int i = 0;
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); (it != m_frsMemberList.end()) && (i < cMembers); it++, i++)
{
varArray[i].vt = VT_BSTR;
varArray[i].bstrVal = ((*it)->m_bstrMemberDN).Copy();
BREAK_OUTOFMEMORY_IF_NULL(varArray[i].bstrVal, &hr);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
pvarMemberDNs->parray = psa;
else
SafeArrayDestroy(psa);
return hr;
}
STDMETHODIMP CReplicaSet::GetMemberListEx(
/* [retval][out] */ VARIANT __RPC_FAR *pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
VariantInit(pVal);
pVal->vt = VT_ARRAY | VT_VARIANT;
pVal->parray = NULL;
HRESULT hr = S_OK;
int cMembers = m_frsMemberList.size();
if (!cMembers)
return hr; // parray is NULL when the member list is empty
SAFEARRAYBOUND bounds = {cMembers, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
int i = 0;
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); (it != m_frsMemberList.end()) && (i < cMembers); it++, i++)
{
VariantInit(&(varArray[i]));
hr = _GetMemberInfo((*it), &(varArray[i]));
BREAK_IF_FAILED(hr);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
pVal->parray = psa;
else
SafeArrayDestroy(psa);
return hr;
}
HRESULT CReplicaSet::_GetMemberInfo(
IN CFrsMember* i_pFrsMember,
OUT VARIANT* o_pvarMember)
{
RETURN_INVALIDARG_IF_NULL(i_pFrsMember);
RETURN_INVALIDARG_IF_NULL(o_pvarMember);
HRESULT hr = S_OK;
SAFEARRAYBOUND bounds = {NUM_OF_FRSMEMBER_ATTRS, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
BSTR bstr[NUM_OF_FRSMEMBER_ATTRS] = {
i_pFrsMember->m_bstrComputerDN,
i_pFrsMember->m_bstrDomain,
i_pFrsMember->m_bstrMemberDN,
i_pFrsMember->m_bstrRootPath,
i_pFrsMember->m_bstrServer,
i_pFrsMember->m_bstrServerGuid,
i_pFrsMember->m_bstrSite,
i_pFrsMember->m_bstrStagingPath,
i_pFrsMember->m_bstrSubscriberDN
};
for (int i = 0; i < NUM_OF_FRSMEMBER_ATTRS; i++)
{
varArray[i].vt = VT_BSTR;
varArray[i].bstrVal = SysAllocString(bstr[i]);
BREAK_OUTOFMEMORY_IF_NULL(varArray[i].bstrVal, &hr);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
{
o_pvarMember->vt = VT_ARRAY | VT_VARIANT;
o_pvarMember->parray = psa;
} else
SafeArrayDestroy(psa);
return hr;
}
STDMETHODIMP CReplicaSet::GetMemberInfo(
/* [in] */ BSTR i_bstrMemberDN,
/* [retval][out] */ VARIANT __RPC_FAR *o_pvarMember)
{
RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); it != m_frsMemberList.end(); it++)
{
if (!lstrcmpi(i_bstrMemberDN, (*it)->m_bstrMemberDN))
break;
}
if (it == m_frsMemberList.end())
return S_FALSE; // no such member
return _GetMemberInfo((*it), o_pvarMember);
}
STDMETHODIMP CReplicaSet::GetBadMemberInfo(
/* [in] */ BSTR i_bstrServerName,
/* [retval][out] */ VARIANT __RPC_FAR *o_pvarMember)
{
RETURN_INVALIDARG_IF_NULL(i_bstrServerName);
int n = lstrlen(i_bstrServerName);
int nLen = 0;
int nMinLen = 0;
CFrsMember* pMember = NULL;
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); it != m_frsMemberList.end(); it++)
{
if (!mylstrncmpi(i_bstrServerName, (*it)->m_bstrServer, n))
{
nLen = lstrlen((*it)->m_bstrServer);
if (!pMember || nLen < nMinLen)
{
nMinLen = nLen;
pMember = *it;
}
}
}
if (!pMember)
return S_FALSE; // no such member
return _GetMemberInfo(pMember, o_pvarMember);
}
STDMETHODIMP CReplicaSet::IsFRSMember(
/* [in] */ BSTR i_bstrDnsHostName,
/* [in] */ BSTR i_bstrRootPath
)
{
if (!i_bstrDnsHostName || !*i_bstrDnsHostName ||
!i_bstrRootPath || !*i_bstrRootPath)
return S_FALSE;
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); it != m_frsMemberList.end(); it++)
{
if (!lstrcmpi(i_bstrDnsHostName, (*it)->m_bstrServer) &&
!lstrcmpi(i_bstrRootPath, (*it)->m_bstrRootPath))
break;
}
if (it == m_frsMemberList.end())
return S_FALSE; // no such member
return S_OK;
}
STDMETHODIMP CReplicaSet::IsHubMember(
/* [in] */ BSTR i_bstrDnsHostName,
/* [in] */ BSTR i_bstrRootPath
)
{
if (!i_bstrDnsHostName || !*i_bstrDnsHostName ||
!i_bstrRootPath || !*i_bstrRootPath)
return S_FALSE;
if (0 != lstrcmpi(FRS_RSTOPOLOGYPREF_HUBSPOKE, m_bstrTopologyPref))
return S_FALSE; // not a hubspoke topology
CFrsMemberList::iterator it;
for (it = m_frsMemberList.begin(); it != m_frsMemberList.end(); it++)
{
if (!lstrcmpi(i_bstrDnsHostName, (*it)->m_bstrServer) &&
!lstrcmpi(i_bstrRootPath, (*it)->m_bstrRootPath))
break;
}
if (it == m_frsMemberList.end())
return S_FALSE; // no such member
if (!lstrcmpi(m_bstrHubMemberDN, (*it)->m_bstrMemberDN))
return S_OK;
return S_FALSE;
}
STDMETHODIMP CReplicaSet::AddMember(
/* [in] */ BSTR i_bstrServer,
/* [in] */ BSTR i_bstrRootPath,
/* [in] */ BSTR i_bstrStagingPath,
/* [in] */ BOOL i_bAddConnectionNow,
/* [retval][out] */ BSTR __RPC_FAR *o_pbstrMemberDN)
{
CComBSTR bstrComputerDomain;
CComBSTR bstrDnsHostName;
CComBSTR bstrComputerGuid;
CComBSTR bstrComputerDN;
HRESULT hr = GetServerInfo(i_bstrServer,
&bstrComputerDomain,
NULL, //o_pbstrNetbiosName
NULL, //o_pbValidDSObject
&bstrDnsHostName,
&bstrComputerGuid,
&bstrComputerDN
);
if (S_OK != hr)
return hr; // don't add this member if it doesn't have an appropriate computer obj in a domain
//
// is i_bstrServer already a frs member
//
BOOL bIsFrsMember = FALSE;
for (CFrsMemberList::iterator i = m_frsMemberList.begin(); i != m_frsMemberList.end(); i++)
{
if (!lstrcmpi(bstrComputerGuid, (*i)->m_bstrServerGuid))
{
bIsFrsMember = TRUE;
break;
}
}
if (bIsFrsMember)
{
if (0 != lstrcmpi(i_bstrRootPath, (*i)->m_bstrRootPath))
return S_FALSE; // cannot have two folders on the same computer join for the same replica set
// member exists, return info of it
if (o_pbstrMemberDN)
{
*o_pbstrMemberDN = (*i)->m_bstrMemberDN.Copy();
RETURN_OUTOFMEMORY_IF_NULL(*o_pbstrMemberDN);
}
return hr;
}
//
// find out if the computer object sits in the same domain as the member object
//
CComBSTR bstrDCofComputerObj;
BOOL bSameDomain = FALSE;
PLDAP pldapComputer = NULL;
if (!lstrcmpi(bstrComputerDomain, m_bstrDomain))
{
bSameDomain = TRUE;
pldapComputer = m_pldap;
} else
{
hr = ConnectToDS(bstrComputerDomain, &pldapComputer, &bstrDCofComputerObj);
RETURN_IF_FAILED(hr);
}
CComBSTR bstrMemberDN;
CComBSTR bstrSubscriberDN;
do {
//
// create a nTFRSMember object in the DS
//
bstrMemberDN = _T("CN=");
BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrMemberDN, &hr);
bstrMemberDN += bstrComputerGuid;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrMemberDN, &hr);
bstrMemberDN += _T(",");
BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrMemberDN, &hr);
bstrMemberDN += m_bstrReplicaSetDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrMemberDN, &hr);
hr = CreateNtfrsMemberObject(m_pldap, bstrMemberDN, bstrComputerDN, bstrDCofComputerObj);
BREAK_IF_FAILED(hr);
//
// create a nTFRSSubscriber object in the DS
//
hr = GetSubscriberDN(m_bstrReplicaSetDN, m_bstrDomainGuid, bstrComputerDN, &bstrSubscriberDN);
BREAK_IF_FAILED(hr);
hr = CreateNtfrsSubscriptionsObjects(pldapComputer, bstrSubscriberDN, bstrComputerDN);
BREAK_IF_FAILED(hr);
hr = CreateNtfrsSubscriberObject(
pldapComputer,
bstrSubscriberDN,
bstrMemberDN,
i_bstrRootPath,
i_bstrStagingPath,
m_bstrDC
);
} while (0);
if (!bSameDomain)
CloseConnectionToDS(pldapComputer);
RETURN_IF_FAILED(hr);
//
// add to m_frsMemberList
//
CFrsMember *pMember = new CFrsMember;
hr = pMember->Init(
bstrDnsHostName,
bstrComputerDomain,
bstrComputerGuid,
i_bstrRootPath,
i_bstrStagingPath,
bstrMemberDN,
bstrComputerDN,
bstrSubscriberDN
);
if (FAILED(hr))
{
delete pMember;
return hr;
}
m_frsMemberList.push_back(pMember);
//
// if TopologyPref is not custom, add connections
//
if (i_bAddConnectionNow)
{
hr = _AdjustConnectionsAdd(bstrMemberDN, pMember->m_bstrSite);
RETURN_IF_FAILED(hr);
}
//
// if o_pbstrMemberDN specified, return o_pbstrMemberDN
//
if (o_pbstrMemberDN)
*o_pbstrMemberDN = bstrMemberDN.Detach();
return hr;
}
HRESULT CReplicaSet::_DeleteMember(CFrsMember* pFrsMember)
{
HRESULT hr = S_OK;
//
// delete nTFRSSubscriber object
//
BOOL bSameDomain = FALSE;
PLDAP pldapComputer = NULL;
if (!lstrcmpi(pFrsMember->m_bstrDomain, m_bstrDomain))
{
bSameDomain = TRUE;
pldapComputer = m_pldap;
} else
{
hr = ConnectToDS(pFrsMember->m_bstrDomain, &pldapComputer, NULL);
RETURN_IF_FAILED(hr);
}
hr = DeleteNtfrsSubscriberObjectAndContainers(
pldapComputer,
pFrsMember->m_bstrSubscriberDN,
pFrsMember->m_bstrComputerDN);
if (!bSameDomain)
CloseConnectionToDS(pldapComputer);
RETURN_IF_FAILED(hr);
//
// adjust connections based on current topologyPref
//
if (m_frsMemberList.size() <= 2)
{
hr = _SetCustomTopologyPref();
} else if (!lstrcmpi(FRS_RSTOPOLOGYPREF_RING, m_bstrTopologyPref))
{
BSTR bstrMemberDN[2];
int i = 0;
CFrsConnectionList::iterator it;
for (it = m_frsConnectionList.begin(); (it != m_frsConnectionList.end()) && (i < 2); it++)
{
if (!lstrcmpi(pFrsMember->m_bstrMemberDN, (*it)->m_bstrFromMemberDN))
bstrMemberDN[i++] = (*it)->m_bstrToMemberDN;
}
if (i != 2)
hr = _SetCustomTopologyPref(); // corrupted, reset to custom
else
{
hr = AddConnection(bstrMemberDN[0], bstrMemberDN[1], TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
hr = AddConnection(bstrMemberDN[1], bstrMemberDN[0], TRUE, FALSE, (long)PRIORITY_LOW, NULL);
}
}
RETURN_IF_FAILED(hr);
//
// delete connections with other members
//
hr = _RemoveConnectionsFromAndTo(pFrsMember);
RETURN_IF_FAILED(hr);
//
// delete nTFRSMember object
//
hr = DeleteDSObject(m_pldap, pFrsMember->m_bstrMemberDN, TRUE);
return hr;
}
STDMETHODIMP CReplicaSet::RemoveMember(
/* [in] */ BSTR i_bstrMemberDN)
{
HRESULT hr = S_OK;
CFrsMemberList::iterator i;
for (i = m_frsMemberList.begin(); i != m_frsMemberList.end(); i++)
{
if (!lstrcmpi(i_bstrMemberDN, (*i)->m_bstrMemberDN))
break;
}
if (i == m_frsMemberList.end())
return hr; // no such member at all, return
//
// if it's the hub, change topologyPref to be custom
//
if (!lstrcmpi(FRS_RSTOPOLOGYPREF_HUBSPOKE, m_bstrTopologyPref) &&
!lstrcmpi(i_bstrMemberDN, m_bstrHubMemberDN))
{
hr = _SetCustomTopologyPref();
RETURN_IF_FAILED(hr);
}
//
// delete nTFRSSubscriber object
// adjust connections
// delete connections with other members
// delete nTFRSMember object
//
hr = _DeleteMember((*i));
//
// remove it from m_frsMemberList
//
delete (*i);
m_frsMemberList.erase(i);
return hr;
}
STDMETHODIMP CReplicaSet::RemoveMemberEx(
/* [in] */ BSTR i_bstrDnsHostName,
/* [in] */ BSTR i_bstrRootPath)
{
HRESULT hr = S_OK;
CFrsMemberList::iterator i;
for (i = m_frsMemberList.begin(); i != m_frsMemberList.end(); i++)
{
if (!lstrcmpi(i_bstrDnsHostName, (*i)->m_bstrServer) &&
!lstrcmpi(i_bstrRootPath, (*i)->m_bstrRootPath))
break;
}
if (i == m_frsMemberList.end())
return hr; // no such member at all, return
//
// if it's the hub, change topologyPref to be custom
//
if (!lstrcmpi(FRS_RSTOPOLOGYPREF_HUBSPOKE, m_bstrTopologyPref) &&
!lstrcmpi((*i)->m_bstrMemberDN, m_bstrHubMemberDN))
{
hr = _SetCustomTopologyPref();
RETURN_IF_FAILED(hr);
}
//
// delete nTFRSSubscriber object
// adjust connections
// delete connections with other members
// delete nTFRSMember object
//
hr = _DeleteMember((*i));
//
// remove it from m_frsMemberList
//
delete (*i);
m_frsMemberList.erase(i);
return hr;
}
STDMETHODIMP CReplicaSet::RemoveAllMembers()
{
HRESULT hr = S_OK;
CFrsMemberList::iterator i = m_frsMemberList.begin();
while (i != m_frsMemberList.end())
{
//
// delete nTFRSSubscriber object
// adjust connections
// delete connections with other members
// delete nTFRSMember object
//
hr = _DeleteMember((*i));
BREAK_IF_FAILED(hr);
//
// remove it from m_frsMemberList
//
delete (*i);
m_frsMemberList.erase(i);
i = m_frsMemberList.begin();
}
return hr;
}
HRESULT CReplicaSet::_PopulateConnectionList()
{
PCTSTR ppszAttributes[] = {
ATTR_DISTINGUISHEDNAME,
ATTR_NTDS_CONNECTION_FROMSERVER,
ATTR_NTDS_CONNECTION_ENABLEDCONNECTION,
ATTR_NTDS_CONNECTION_OPTIONS,
0
};
LListElem* pElem = NULL;
HRESULT hr = GetValuesEx(
m_pldap,
m_bstrReplicaSetDN,
LDAP_SCOPE_SUBTREE,
OBJCLASS_SF_NTDSCONNECTION,
ppszAttributes,
&pElem);
RETURN_IF_FAILED(hr);
LListElem* pCurElem = pElem;
while (pCurElem)
{
PTSTR** pppszValues = pCurElem->pppszAttrValues;
if (!pppszValues ||
!pppszValues[0] || !*(pppszValues[0]) ||
!pppszValues[1] || !*(pppszValues[1]) ||
!pppszValues[2] || !*(pppszValues[2]))
{
pCurElem = pCurElem->Next;
continue; // corrupted connection object
}
PTSTR pszParentDN = _tcsstr(*(pppszValues[0]), _T(",CN="));
if (!pszParentDN)
{
pCurElem = pCurElem->Next;
continue; // corrupted connection object
}
pszParentDN++; // point to the 2nd CN=XXX
BOOL bFromServerFound = FALSE;
BOOL bToServerFound = FALSE;
CFrsMemberList::iterator i;
for (i = m_frsMemberList.begin(); i != m_frsMemberList.end(); i++)
{
if (!bToServerFound && !lstrcmpi(pszParentDN, (*i)->m_bstrMemberDN))
{
bToServerFound = TRUE;
}
if (!bFromServerFound && !lstrcmpi(*(pppszValues[1]), (*i)->m_bstrMemberDN))
{
bFromServerFound = TRUE;
}
}
if (!bFromServerFound || !bToServerFound)
{
pCurElem = pCurElem->Next;
continue; // unknown fromServer or toServer, skip this connection
}
DWORD dwOptions = _tcstoul(*(pppszValues[3]), NULL, 10);
BOOL bEnable = (CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, *(pppszValues[2]), -1, CONNECTION_ENABLED_TRUE, -1));
CFrsConnection* pFrsConnection = new CFrsConnection;
BREAK_OUTOFMEMORY_IF_NULL(pFrsConnection, &hr);
hr = pFrsConnection->Init(
*(pppszValues[0]), // FQDN
*(pppszValues[1]), // fromServer
bEnable, // enableConnection
dwOptions // options
);
if (FAILED(hr))
{
delete pFrsConnection;
break;
}
m_frsConnectionList.push_back(pFrsConnection);
pCurElem = pCurElem->Next;
}
FreeLListElem(pElem);
if (FAILED(hr))
FreeFrsConnections(&m_frsConnectionList);
return hr;
}
STDMETHODIMP CReplicaSet::GetConnectionList(
/* [retval][out] */ VARIANT __RPC_FAR *o_pvarConnectionDNs)
{
RETURN_INVALIDARG_IF_NULL(o_pvarConnectionDNs);
VariantInit(o_pvarConnectionDNs);
o_pvarConnectionDNs->vt = VT_ARRAY | VT_VARIANT;
o_pvarConnectionDNs->parray = NULL;
HRESULT hr = S_OK;
int cConnections = m_frsConnectionList.size();
if (!cConnections)
return hr; // parray is NULL when the connection list is empty
SAFEARRAYBOUND bounds = {cConnections, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
int i = 0;
CFrsConnectionList::iterator it;
for (it = m_frsConnectionList.begin(); (it != m_frsConnectionList.end()) && (i < cConnections); it++, i++)
{
varArray[i].vt = VT_BSTR;
varArray[i].bstrVal = ((*it)->m_bstrConnectionDN).Copy();
BREAK_OUTOFMEMORY_IF_NULL(varArray[i].bstrVal, &hr);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
o_pvarConnectionDNs->parray = psa;
else
SafeArrayDestroy(psa);
return hr;
}
STDMETHODIMP CReplicaSet::GetConnectionListEx(
/* [retval][out] */ VARIANT __RPC_FAR *pVal)
{
RETURN_INVALIDARG_IF_NULL(pVal);
VariantInit(pVal);
pVal->vt = VT_ARRAY | VT_VARIANT;
pVal->parray = NULL;
HRESULT hr = S_OK;
int cConnections = m_frsConnectionList.size();
if (!cConnections)
return hr; // parray is NULL when the connection list is empty
SAFEARRAYBOUND bounds = {cConnections, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
int i = 0;
CFrsConnectionList::iterator it;
for (it = m_frsConnectionList.begin(); (it != m_frsConnectionList.end()) && (i < cConnections); it++, i++)
{
VariantInit(&(varArray[i]));
hr = _GetConnectionInfo((*it), &(varArray[i]));
BREAK_IF_FAILED(hr);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
pVal->parray = psa;
else
SafeArrayDestroy(psa);
return hr;
}
HRESULT CReplicaSet::_GetConnectionInfo(
IN CFrsConnection* i_pFrsConnection,
OUT VARIANT* o_pvarConnection)
{
RETURN_INVALIDARG_IF_NULL(i_pFrsConnection);
RETURN_INVALIDARG_IF_NULL(o_pvarConnection);
HRESULT hr = S_OK;
SAFEARRAYBOUND bounds = {NUM_OF_FRSCONNECTION_ATTRS, 0};
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, &bounds);
RETURN_OUTOFMEMORY_IF_NULL(psa);
VARIANT* varArray;
SafeArrayAccessData(psa, (void**)&varArray);
BSTR bstr[NUM_OF_FRSCONNECTION_ATTRS - 2] = {
i_pFrsConnection->m_bstrConnectionDN,
i_pFrsConnection->m_bstrFromMemberDN,
i_pFrsConnection->m_bstrToMemberDN
};
for (int i = 0; i < NUM_OF_FRSCONNECTION_ATTRS - 2; i++)
{
varArray[i].vt = VT_BSTR;
varArray[i].bstrVal = SysAllocString(bstr[i]);
BREAK_OUTOFMEMORY_IF_NULL(varArray[i].bstrVal, &hr);
}
if (SUCCEEDED(hr))
{
varArray[i].vt = VT_I4;
varArray[i].lVal = (long)(i_pFrsConnection->m_bEnable);
varArray[++i].vt = VT_I4;
varArray[i].lVal = (long)(i_pFrsConnection->m_dwOptions);
}
SafeArrayUnaccessData(psa);
if (SUCCEEDED(hr))
{
o_pvarConnection->vt = VT_ARRAY | VT_VARIANT;
o_pvarConnection->parray = psa;
} else
SafeArrayDestroy(psa);
return S_OK;
}
STDMETHODIMP CReplicaSet::GetConnectionInfo(
/* [in] */ BSTR i_bstrConnectionDN,
/* [retval][out] */ VARIANT __RPC_FAR *o_pvarConnection)
{
RETURN_INVALIDARG_IF_NULL(i_bstrConnectionDN);
CFrsConnectionList::iterator it;
for (it = m_frsConnectionList.begin(); it != m_frsConnectionList.end(); it++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*it)->m_bstrConnectionDN))
break;
}
if (it == m_frsConnectionList.end())
return S_FALSE;
return _GetConnectionInfo((*it), o_pvarConnection);
}
STDMETHODIMP CReplicaSet::AddConnection(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN,
/* [in] */ BOOL i_bEnable,
/* [in] */ BOOL i_bSyncImmediately,
/* [in] */ long i_nPriority,
/* [retval][out] */ BSTR __RPC_FAR *o_pbstrConnectionDN)
{
if (!lstrcmpi(i_bstrFromMemberDN, i_bstrToMemberDN))
return S_OK;
HRESULT hr = S_OK;
//
// is it an existing connection?
//
BOOL bIsFrsConnection = FALSE;
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
{
bIsFrsConnection = TRUE;
break;
}
}
if (bIsFrsConnection)
{
// connection exists, return info of it
if (o_pbstrConnectionDN)
{
*o_pbstrConnectionDN = (*i)->m_bstrConnectionDN.Copy();
RETURN_OUTOFMEMORY_IF_NULL(*o_pbstrConnectionDN);
}
return hr;
}
//
// locate the fromMember and the toMember in the m_frsMemberList
//
CFrsMemberList::iterator from;
for (from = m_frsMemberList.begin(); from != m_frsMemberList.end(); from++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*from)->m_bstrMemberDN))
break;
}
if (from == m_frsMemberList.end())
{
// fromServer is not a frsMember yet
return E_INVALIDARG;
}
CFrsMemberList::iterator to;
for (to = m_frsMemberList.begin(); to != m_frsMemberList.end(); to++)
{
if (!lstrcmpi(i_bstrToMemberDN, (*to)->m_bstrMemberDN))
break;
}
if (to == m_frsMemberList.end())
{
// toServer is not a frsMember yet
return E_INVALIDARG;
}
//
// create the nTDSConnection object
//
CComBSTR bstrConnectionDN = _T("CN=");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrConnectionDN);
bstrConnectionDN += (*from)->m_bstrServerGuid;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrConnectionDN);
bstrConnectionDN += _T(",");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrConnectionDN);
bstrConnectionDN += (*to)->m_bstrMemberDN;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrConnectionDN);
DWORD dwOptions = (i_bSyncImmediately ? 0x80000000 : 0x0);
switch (i_nPriority)
{
case 1:
case 2:
dwOptions |= (PRIORITY_HIGH << 28);
break;
case 3:
case 4:
dwOptions |= (PRIORITY_MEDIUM << 28);
break;
default:
dwOptions |= (PRIORITY_LOW << 28);
break;
}
hr = CreateNtdsConnectionObject(
m_pldap,
bstrConnectionDN,
i_bstrFromMemberDN,
i_bEnable,
dwOptions
);
RETURN_IF_FAILED(hr);
//
// add to m_frsConnectionList
//
CFrsConnection* pFrsConnection = new CFrsConnection;
RETURN_OUTOFMEMORY_IF_NULL(pFrsConnection);
hr = pFrsConnection->Init(
bstrConnectionDN, // FQDN
i_bstrFromMemberDN, // fromServer
i_bEnable, // enableConnection
dwOptions);
if (FAILED(hr))
{
delete pFrsConnection;
return hr;
}
m_frsConnectionList.push_back(pFrsConnection);
//
// if o_pbstrConnectionDN specified, return o_pbstrConnectionDN
//
if (o_pbstrConnectionDN)
*o_pbstrConnectionDN = bstrConnectionDN.Detach();
return hr;
}
STDMETHODIMP CReplicaSet::RemoveConnection(
/* [in] */ BSTR i_bstrConnectionDN)
{
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*i)->m_bstrConnectionDN))
break;
}
if (i == m_frsConnectionList.end())
return hr; // no such connection, return
//
// delete the nTDSConnection object
//
hr = DeleteDSObject(m_pldap, (*i)->m_bstrConnectionDN, TRUE);
RETURN_IF_FAILED(hr);
//
// remove it from m_frsConnectionList
//
delete (*i);
m_frsConnectionList.erase(i);
return hr;
}
STDMETHODIMP CReplicaSet::RemoveConnectionEx(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN)
{
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
break;
}
if (i == m_frsConnectionList.end())
return hr; // no such connection, return
//
// delete the nTDSConnection object
//
hr = DeleteDSObject(m_pldap, (*i)->m_bstrConnectionDN, TRUE);
RETURN_IF_FAILED(hr);
//
// remove it from m_frsConnectionList
//
delete (*i);
m_frsConnectionList.erase(i);
return hr;
}
STDMETHODIMP CReplicaSet::RemoveAllConnections()
{
HRESULT hr = S_OK;
CFrsConnectionList::iterator i = m_frsConnectionList.begin();
while (i != m_frsConnectionList.end())
{
//
// delete the nTDSConnection object
//
hr = DeleteDSObject(m_pldap, (*i)->m_bstrConnectionDN, TRUE);
BREAK_IF_FAILED(hr);
//
// remove it from m_frsConnectionList
//
delete (*i);
m_frsConnectionList.erase(i);
i = m_frsConnectionList.begin();
}
return hr;
}
HRESULT CReplicaSet::_RemoveConnectionsFromAndTo(CFrsMember* pFrsMember)
{
RETURN_INVALIDARG_IF_NULL(pFrsMember);
HRESULT hr = S_OK;
CFrsConnectionList::iterator i = m_frsConnectionList.begin();
while (i != m_frsConnectionList.end())
{
CFrsConnectionList::iterator itConn = i++;
if (!lstrcmpi(pFrsMember->m_bstrMemberDN, (*itConn)->m_bstrFromMemberDN) ||
!lstrcmpi(pFrsMember->m_bstrMemberDN, (*itConn)->m_bstrToMemberDN))
{
//
// delete the nTDSConnection object
//
hr = DeleteDSObject(m_pldap, (*itConn)->m_bstrConnectionDN, TRUE);
RETURN_IF_FAILED(hr);
//
// remove it from m_frsConnectionList
//
delete (*itConn);
m_frsConnectionList.erase(itConn);
}
}
return hr;
}
STDMETHODIMP CReplicaSet::EnableConnection(
/* [in] */ BSTR i_bstrConnectionDN,
/* [in] */ BOOL i_bEnable)
{
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*i)->m_bstrConnectionDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
//
// update attribute enabledConnection of this nTDSConnection object
//
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_NTDS_CONNECTION_ENABLEDCONNECTION;
pAttrVals[0].vpValue = (void *)(i_bEnable ? CONNECTION_ENABLED_TRUE : CONNECTION_ENABLED_FALSE);
pAttrVals[0].bBerValue = false;
hr = ::ModifyValues(m_pldap, (*i)->m_bstrConnectionDN, 1, pAttrVals);
//
// update i in the m_frsConnectionList
//
if (SUCCEEDED(hr))
(*i)->m_bEnable = i_bEnable;
return hr;
}
STDMETHODIMP CReplicaSet::EnableConnectionEx(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN,
/* [in] */ BOOL i_bEnable)
{
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
//
// update attribute enabledConnection of this nTDSConnection object
//
LDAP_ATTR_VALUE pAttrVals[1];
pAttrVals[0].bstrAttribute = ATTR_NTDS_CONNECTION_ENABLEDCONNECTION;
pAttrVals[0].vpValue = (void *)(i_bEnable ? CONNECTION_ENABLED_TRUE : CONNECTION_ENABLED_FALSE);
pAttrVals[0].bBerValue = false;
hr = ::ModifyValues(m_pldap, (*i)->m_bstrConnectionDN, 1, pAttrVals);
//
// update i in the m_frsConnectionList
//
if (SUCCEEDED(hr))
(*i)->m_bEnable = i_bEnable;
return hr;
}
HRESULT CReplicaSet::_GetConnectionSchedule(
/* [in] */ BSTR i_bstrConnectionDN,
/* [retval][out] */ VARIANT* o_pVar)
{
//
// get attribute schedule of this nTDSConnection object
//
PLDAP_ATTR_VALUE pValues[2] = {0,0};
LDAP_ATTR_VALUE pAttributes[1];
pAttributes[0].bstrAttribute = ATTR_NTDS_CONNECTION_SCHEDULE;
pAttributes[0].bBerValue = true;
HRESULT hr = GetValues( m_pldap,
i_bstrConnectionDN,
OBJCLASS_SF_NTDSCONNECTION,
LDAP_SCOPE_BASE,
1,
pAttributes,
pValues);
if (SUCCEEDED(hr) && pValues[0])
{
hr = ScheduleToVariant((SCHEDULE *)(pValues[0]->vpValue), o_pVar);
FreeAttrValList(pValues[0]);
} else if (!(pValues[0]) || HRESULT_FROM_WIN32(ERROR_DS_NO_RESULTS_RETURNED) == hr)
{
SCHEDULE *pSchedule = NULL;
hr = GetDefaultSchedule(&pSchedule);
if (SUCCEEDED(hr))
{
hr = ScheduleToVariant(pSchedule, o_pVar);
free(pSchedule);
}
}
return hr;
}
STDMETHODIMP CReplicaSet::GetConnectionSchedule(
/* [in] */ BSTR i_bstrConnectionDN,
/* [retval][out] */ VARIANT* o_pVar)
{
RETURN_INVALIDARG_IF_NULL(i_bstrConnectionDN);
RETURN_INVALIDARG_IF_NULL(o_pVar);
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*i)->m_bstrConnectionDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
return _GetConnectionSchedule(i_bstrConnectionDN, o_pVar);
}
STDMETHODIMP CReplicaSet::GetConnectionScheduleEx(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN,
/* [retval][out] */ VARIANT* o_pVar)
{
RETURN_INVALIDARG_IF_NULL(i_bstrFromMemberDN);
RETURN_INVALIDARG_IF_NULL(i_bstrToMemberDN);
RETURN_INVALIDARG_IF_NULL(o_pVar);
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
return _GetConnectionSchedule((*i)->m_bstrConnectionDN, o_pVar);
}
STDMETHODIMP CReplicaSet::SetConnectionSchedule(
/* [in] */ BSTR i_bstrConnectionDN,
/* [in] */ VARIANT* i_pVar)
{
RETURN_INVALIDARG_IF_NULL(i_bstrConnectionDN);
RETURN_INVALIDARG_IF_NULL(i_pVar);
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*i)->m_bstrConnectionDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
SCHEDULE *pSchedule = NULL;
hr = VariantToSchedule(i_pVar, &pSchedule);
RETURN_IF_FAILED(hr);
hr = ::SetConnectionSchedule(m_pldap, (*i)->m_bstrConnectionDN, pSchedule);
free(pSchedule);
return hr;
}
STDMETHODIMP CReplicaSet::SetConnectionScheduleEx(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN,
/* [in] */ VARIANT* i_pVar)
{
RETURN_INVALIDARG_IF_NULL(i_bstrFromMemberDN);
RETURN_INVALIDARG_IF_NULL(i_bstrToMemberDN);
RETURN_INVALIDARG_IF_NULL(i_pVar);
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
SCHEDULE *pSchedule = NULL;
hr = VariantToSchedule(i_pVar, &pSchedule);
RETURN_IF_FAILED(hr);
hr = ::SetConnectionSchedule(m_pldap, (*i)->m_bstrConnectionDN, pSchedule);
free(pSchedule);
return hr;
}
STDMETHODIMP CReplicaSet::SetScheduleOnAllConnections(
/* [in] */ VARIANT* i_pVar)
{
RETURN_INVALIDARG_IF_NULL(i_pVar);
HRESULT hr = S_OK;
SCHEDULE *pSchedule = NULL;
hr = VariantToSchedule(i_pVar, &pSchedule);
RETURN_IF_FAILED(hr);
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
hr = ::SetConnectionSchedule(m_pldap, (*i)->m_bstrConnectionDN, pSchedule);
BREAK_IF_FAILED(hr);
}
free(pSchedule);
return hr;
}
STDMETHODIMP CReplicaSet::SetConnectionOptions(
/* [in] */ BSTR i_bstrConnectionDN,
/* [in] */ BOOL i_bSyncImmediately,
/* [in] */ long i_nPriority)
{
RETURN_INVALIDARG_IF_NULL(i_bstrConnectionDN);
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrConnectionDN, (*i)->m_bstrConnectionDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
DWORD dwOptions = (i_bSyncImmediately ? 0x80000000 : 0x0);
switch (i_nPriority)
{
case 1:
case 2:
dwOptions |= (PRIORITY_HIGH << 28);
break;
case 3:
case 4:
dwOptions |= (PRIORITY_MEDIUM << 28);
break;
default:
dwOptions |= (PRIORITY_LOW << 28);
break;
}
hr = ::SetConnectionOptions(m_pldap, (*i)->m_bstrConnectionDN, dwOptions);
if (SUCCEEDED(hr))
{
//
// update m_dwOptions in the m_frsConnectionList
//
if (SUCCEEDED(hr))
(*i)->m_dwOptions = dwOptions;
}
return hr;
}
STDMETHODIMP CReplicaSet::SetConnectionOptionsEx(
/* [in] */ BSTR i_bstrFromMemberDN,
/* [in] */ BSTR i_bstrToMemberDN,
/* [in] */ BOOL i_bSyncImmediately,
/* [in] */ long i_nPriority)
{
RETURN_INVALIDARG_IF_NULL(i_bstrFromMemberDN);
RETURN_INVALIDARG_IF_NULL(i_bstrToMemberDN);
HRESULT hr = S_OK;
//
// locate connection in the m_frsConnectionList
//
CFrsConnectionList::iterator i;
for (i = m_frsConnectionList.begin(); i != m_frsConnectionList.end(); i++)
{
if (!lstrcmpi(i_bstrFromMemberDN, (*i)->m_bstrFromMemberDN) &&
!lstrcmpi(i_bstrToMemberDN, (*i)->m_bstrToMemberDN))
break;
}
if (i == m_frsConnectionList.end())
return E_INVALIDARG; // no such conneciton, return error
DWORD dwOptions = (i_bSyncImmediately ? 0x80000000 : 0x0);
switch (i_nPriority)
{
case 1:
case 2:
dwOptions |= (PRIORITY_HIGH << 28);
break;
case 3:
case 4:
dwOptions |= (PRIORITY_MEDIUM << 28);
break;
default:
dwOptions |= (PRIORITY_LOW << 28);
break;
}
hr = ::SetConnectionOptions(m_pldap, (*i)->m_bstrConnectionDN, dwOptions);
if (SUCCEEDED(hr))
{
//
// update m_dwOptions in the m_frsConnectionList
//
if (SUCCEEDED(hr))
(*i)->m_dwOptions = dwOptions;
}
return hr;
}
STDMETHODIMP CReplicaSet::CreateConnections()
{
HRESULT hr = S_OK;
//
// create connections from scratch
//
if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_CUSTOM))
return hr;
CFrsMemberList::iterator n1;
CFrsMemberList::iterator n2;
if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_RING))
{
//
// sort member list on Site, such that members on the same site will be neighbors
//
m_frsMemberList.sort(FrsMemberCompare());
CFrsMemberList::iterator head;
head = n1 = m_frsMemberList.begin();
while (n1 != m_frsMemberList.end())
{
n2 = n1++;
if (n1 == m_frsMemberList.end())
{
if (m_frsMemberList.size() == 2)
break;
n1 = head;
}
hr = AddConnection((*n1)->m_bstrMemberDN, (*n2)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
hr = AddConnection((*n2)->m_bstrMemberDN, (*n1)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
if (n1 == head)
break;
}
} else if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
{
for (n1 = m_frsMemberList.begin(); n1 != m_frsMemberList.end(); n1++)
{
if (!lstrcmpi((*n1)->m_bstrMemberDN, m_bstrHubMemberDN))
continue;
hr = AddConnection((*n1)->m_bstrMemberDN, m_bstrHubMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
hr = AddConnection(m_bstrHubMemberDN, (*n1)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
}
} else if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_FULLMESH))
{
for (n1 = m_frsMemberList.begin(); n1 != m_frsMemberList.end(); n1++)
{
for (n2 = m_frsMemberList.begin(); n2 != m_frsMemberList.end(); n2++)
{
if (!lstrcmpi((*n1)->m_bstrMemberDN, (*n2)->m_bstrMemberDN))
continue;
hr = AddConnection((*n1)->m_bstrMemberDN, (*n2)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
}
BREAK_IF_FAILED(hr);
}
}
return hr;
}
STDMETHODIMP CReplicaSet::Delete()
{
dfsDebugOut((_T("Delete ReplicaSet: %s\n"), m_bstrReplicaSetDN));
HRESULT hr = S_OK;
//
// delete all connections
//
hr = RemoveAllConnections();
RETURN_IF_FAILED(hr);
//
// delete all members
//
// Note: the nTFRSReplicaSet object will be deleted if empty
//
hr = RemoveAllMembers();
RETURN_IF_FAILED(hr);
//
// delete nTFRSReplicaSettings container objects if empty
//
(void) DeleteNtfrsReplicaSetObjectAndContainers(m_pldap, m_bstrReplicaSetDN);
//
// Reset this instance
//
_FreeMemberVariables();
return hr;
}
HRESULT CReplicaSet::_SetCustomTopologyPref()
{
HRESULT hr = put_TopologyPref(FRS_RSTOPOLOGYPREF_CUSTOM);
if (SUCCEEDED(hr))
hr = put_HubMemberDN(_T(""));
return hr;
}
HRESULT CReplicaSet::_AdjustConnectionsAdd(BSTR i_bstrNewMemberDN, BSTR i_bstrSite)
{
RETURN_INVALIDARG_IF_NULL(i_bstrNewMemberDN);
HRESULT hr = S_OK;
//
// adjust connections after pFrsMember is added
//
if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_CUSTOM) || m_frsMemberList.empty())
return hr;
if (m_frsMemberList.size() == 2)
{
CFrsMemberList::iterator head = m_frsMemberList.begin();
hr = AddConnection((*head)->m_bstrMemberDN, i_bstrNewMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
if (SUCCEEDED(hr))
hr = AddConnection(i_bstrNewMemberDN, (*head)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
return hr;
}
CFrsMemberList::iterator n1;
CFrsMemberList::iterator n2;
if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_RING))
{
CComBSTR bstrMemberDN1;
CComBSTR bstrMemberDN2;
CFrsConnectionList::iterator conn;
if (i_bstrSite && *i_bstrSite)
{
for (n1 = m_frsMemberList.begin(); n1 != m_frsMemberList.end(); n1++)
{
if (!lstrcmpi((*n1)->m_bstrSite, i_bstrSite) && // has the same site as the new member
lstrcmpi((*n1)->m_bstrMemberDN, i_bstrNewMemberDN)) // different from the new member
{
//
// see if there is an existing connection from/to this member n1
//
for (conn = m_frsConnectionList.begin(); conn != m_frsConnectionList.end(); conn++)
{
if (!lstrcmpi((*n1)->m_bstrMemberDN, (*conn)->m_bstrFromMemberDN))
{
bstrMemberDN1 = (*n1)->m_bstrMemberDN;
bstrMemberDN2 = (*conn)->m_bstrToMemberDN;
break;
} else if (!lstrcmpi((*n1)->m_bstrMemberDN, (*conn)->m_bstrToMemberDN))
{
bstrMemberDN1 = (*n1)->m_bstrMemberDN;
bstrMemberDN2 = (*conn)->m_bstrFromMemberDN;
break;
}
}
if ((BSTR)bstrMemberDN1 && (BSTR)bstrMemberDN2)
break; // we've located the insertion point
}
}
}
if (!bstrMemberDN1 || !bstrMemberDN2)
{
//
// locate an existing connection, if any
//
if (m_frsConnectionList.empty())
{
n1 = m_frsMemberList.begin();
n2 = n1++;
bstrMemberDN1 = (*n1)->m_bstrMemberDN;
bstrMemberDN2 = (*n2)->m_bstrMemberDN;
} else
{
conn = m_frsConnectionList.begin();
bstrMemberDN1 = (*conn)->m_bstrFromMemberDN;
bstrMemberDN2 = (*conn)->m_bstrToMemberDN;
}
}
hr = AddConnection(bstrMemberDN1, i_bstrNewMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
hr = AddConnection(i_bstrNewMemberDN, bstrMemberDN1, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
hr = AddConnection(bstrMemberDN2, i_bstrNewMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
hr = AddConnection(i_bstrNewMemberDN, bstrMemberDN2, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
if (m_frsMemberList.size() > 3)
{
hr = RemoveConnectionEx(bstrMemberDN2, bstrMemberDN1);
RETURN_IF_FAILED(hr);
hr = RemoveConnectionEx(bstrMemberDN1, bstrMemberDN2);
RETURN_IF_FAILED(hr);
}
} else if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
{
hr = AddConnection(i_bstrNewMemberDN, m_bstrHubMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
hr = AddConnection(m_bstrHubMemberDN, i_bstrNewMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
RETURN_IF_FAILED(hr);
} else if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_FULLMESH))
{
for (n1 = m_frsMemberList.begin(); n1 != m_frsMemberList.end(); n1++)
{
hr = AddConnection((*n1)->m_bstrMemberDN, i_bstrNewMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
hr = AddConnection(i_bstrNewMemberDN, (*n1)->m_bstrMemberDN, TRUE, FALSE, (long)PRIORITY_LOW, NULL);
BREAK_IF_FAILED(hr);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// _FreeMemberVariables
void FreeDfsAlternates(CDfsAlternateList* pList)
{
if (pList && !pList->empty())
{
for (CDfsAlternateList::iterator i = pList->begin(); i != pList->end(); i++)
delete (*i);
pList->clear();
}
}
void FreeFrsMembers(CFrsMemberList* pList)
{
if (pList && !pList->empty())
{
for (CFrsMemberList::iterator i = pList->begin(); i != pList->end(); i++)
delete (*i);
pList->clear();
}
}
void FreeFrsConnections(CFrsConnectionList* pList)
{
if (pList && !pList->empty())
{
for (CFrsConnectionList::iterator i = pList->begin(); i != pList->end(); i++)
delete (*i);
pList->clear();
}
}
void CReplicaSet::_FreeMemberVariables()
{
m_bstrType.Empty();
m_bstrTopologyPref.Empty();
m_bstrHubMemberDN.Empty();
m_bstrPrimaryMemberDN.Empty();
m_bstrFileFilter.Empty();
m_bstrDirFilter.Empty();
m_bstrDfsEntryPath.Empty();
m_bstrReplicaSetDN.Empty();
FreeDfsAlternates(&m_dfsAlternateList);
FreeFrsMembers(&m_frsMemberList);
FreeFrsConnections(&m_frsConnectionList);
m_bstrDomain.Empty();
m_bstrDomainGuid.Empty();
m_bstrDC.Empty();
m_bNewSchema = FALSE;
if (m_pldap)
{
CloseConnectionToDS(m_pldap);
m_pldap = NULL;
}
}
///////////////////////////////////////////////////////////////////
//
// CFrsMember
//
HRESULT CFrsMember::InitEx(
PLDAP i_pldap, // points to the i_bstrMemberDN's DS
BSTR i_bstrDC, // domain controller pointed by i_pldap
BSTR i_bstrMemberDN, // FQDN of nTFRSMember object
BSTR i_bstrComputerDN // =NULL, FQDN of computer object
)
{
_ReSet();
RETURN_INVALIDARG_IF_NULL(i_pldap);
RETURN_INVALIDARG_IF_NULL(i_bstrDC);
RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
HRESULT hr = S_OK;
do {
m_bstrMemberDN = i_bstrMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrMemberDN, &hr);
if (i_bstrComputerDN && *i_bstrComputerDN)
{
m_bstrComputerDN = i_bstrComputerDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrComputerDN, &hr);
}
hr = _GetMemberInfo(i_pldap, i_bstrDC, m_bstrMemberDN, m_bstrComputerDN);
} while (0);
if (S_OK != hr)
_ReSet();
return hr;
}
HRESULT CFrsMember::Init(
IN BSTR i_bstrDnsHostName,
IN BSTR i_bstrComputerDomain,
IN BSTR i_bstrComputerGuid,
IN BSTR i_bstrRootPath,
IN BSTR i_bstrStagingPath,
IN BSTR i_bstrMemberDN,
IN BSTR i_bstrComputerDN,
IN BSTR i_bstrSubscriberDN
)
{
_ReSet();
RETURN_INVALIDARG_IF_NULL(i_bstrDnsHostName);
RETURN_INVALIDARG_IF_NULL(i_bstrComputerDomain);
RETURN_INVALIDARG_IF_NULL(i_bstrComputerGuid);
RETURN_INVALIDARG_IF_NULL(i_bstrRootPath);
RETURN_INVALIDARG_IF_NULL(i_bstrStagingPath);
RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
RETURN_INVALIDARG_IF_NULL(i_bstrComputerDN);
RETURN_INVALIDARG_IF_NULL(i_bstrSubscriberDN);
HRESULT hr = S_OK;
do {
hr = GetSiteName(i_bstrDnsHostName, &m_bstrSite);
BREAK_IF_FAILED(hr);
m_bstrServer = i_bstrDnsHostName;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrServer, &hr);
m_bstrDomain = i_bstrComputerDomain;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDomain, &hr);
m_bstrServerGuid = i_bstrComputerGuid;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrServerGuid, &hr);
m_bstrRootPath = i_bstrRootPath;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrRootPath, &hr);
m_bstrStagingPath = i_bstrStagingPath;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrStagingPath, &hr);
m_bstrMemberDN = i_bstrMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrMemberDN, &hr);
m_bstrComputerDN = i_bstrComputerDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrComputerDN, &hr);
m_bstrSubscriberDN = i_bstrSubscriberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrSubscriberDN, &hr);
} while (0);
if (FAILED(hr))
_ReSet();
return hr;
}
CFrsMember* CFrsMember::Copy()
{
CFrsMember* pNew = new CFrsMember;
if (pNew)
{
HRESULT hr = S_OK;
do {
pNew->m_bstrServer = m_bstrServer;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrServer, &hr);
pNew->m_bstrSite = m_bstrSite;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrSite, &hr);
pNew->m_bstrDomain = m_bstrDomain;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrDomain, &hr);
pNew->m_bstrServerGuid = m_bstrServerGuid;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrServerGuid, &hr);
pNew->m_bstrRootPath = m_bstrRootPath;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrRootPath, &hr);
pNew->m_bstrStagingPath = m_bstrStagingPath;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrStagingPath, &hr);
pNew->m_bstrMemberDN = m_bstrMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrMemberDN, &hr);
pNew->m_bstrComputerDN = m_bstrComputerDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrComputerDN, &hr);
pNew->m_bstrSubscriberDN = m_bstrSubscriberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrSubscriberDN, &hr);
} while (0);
if (FAILED(hr))
{
delete pNew;
pNew = NULL;
}
}
return pNew;
}
void CFrsMember::_ReSet()
{
m_bstrServer.Empty();
m_bstrSite.Empty();
m_bstrDomain.Empty();
m_bstrServerGuid.Empty();
m_bstrRootPath.Empty();
m_bstrStagingPath.Empty();
m_bstrMemberDN.Empty();
m_bstrComputerDN.Empty();
m_bstrSubscriberDN.Empty();
}
//
// Given: MemberDN
// Read: ComputerDN, Domain, Site, ServerName
//
// Return:
// S_FALSE if no such object found
//
HRESULT CFrsMember::_GetMemberInfo
(
PLDAP i_pldap, // points to the i_bstrMemberDN's DS
BSTR i_bstrDC, // domain controller pointed by i_pldap
BSTR i_bstrMemberDN, // FQDN of nTFRSMember object
BSTR i_bstrComputerDN // = NULL FQDN of computer object
)
{
m_bstrDomain.Empty();
RETURN_INVALIDARG_IF_NULL(i_pldap);
RETURN_INVALIDARG_IF_NULL(i_bstrDC);
RETURN_INVALIDARG_IF_NULL(*i_bstrDC);
RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
RETURN_INVALIDARG_IF_NULL(*i_bstrMemberDN);
HRESULT hr = S_OK;
do {
if (!i_bstrComputerDN || !*i_bstrComputerDN)
{
m_bstrComputerDN.Empty();
//
// Read:
// m_bstrComputerDN
//
PLDAP_ATTR_VALUE pValues[2] = {0,0};
LDAP_ATTR_VALUE pAttributes[1];
pAttributes[0].bstrAttribute = ATTR_FRS_MEMBER_COMPUTERREF;
hr = GetValues( i_pldap,
m_bstrMemberDN,
OBJCLASS_SF_NTFRSMEMBER,
LDAP_SCOPE_BASE,
1,
pAttributes,
pValues);
BREAK_IF_FAILED(hr);
hr = E_FAIL;
if (pValues[0])
{
m_bstrComputerDN = (PTSTR)(pValues[0]->vpValue);
hr = (!m_bstrComputerDN) ? E_OUTOFMEMORY : S_OK;
FreeAttrValList(pValues[0]);
}
BREAK_IF_FAILED(hr);
}
//
// retrieve the domain for both ComputerDN and i_bstrMemberDN
// If they are the same, reuse the handle to the LDAP port;
// otherwise, open a new handle.
//
// Read:
// m_bstrDomainDN
//
BOOL bSameDomain = FALSE;
HANDLE hDS = NULL;
DWORD dwErr = DsBind(i_bstrDC, NULL, &hDS);
if (NO_ERROR != dwErr)
{
hr = HRESULT_FROM_WIN32(dwErr);
break;
}
const PTSTR pszFQDNs[2] = {(BSTR)m_bstrComputerDN, i_bstrMemberDN};
DS_NAME_RESULT* pDsNameResult = NULL;
dwErr = DsCrackNames(
hDS,
DS_NAME_NO_FLAGS,
DS_FQDN_1779_NAME,
DS_CANONICAL_NAME,
2,
pszFQDNs,
&pDsNameResult
);
if (NO_ERROR == dwErr)
{
do {
PDS_NAME_RESULT_ITEM pItem = pDsNameResult->rItems;
if (DS_NAME_NO_ERROR != pItem->status)
{
dwErr = pItem->status;
} else
{
// retrieve info of m_bstrComputerDN
m_bstrDomain = pItem->pDomain;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrDomain, &hr);
// retrieve info of i_bstrMemberDN
pItem++;
if (DS_NAME_NO_ERROR != pItem->status)
{
dwErr = pItem->status;
} else
{
bSameDomain = !mylstrncmpi(m_bstrDomain, pItem->pDomain, lstrlen(m_bstrDomain));
}
}
} while (0);
DsFreeNameResult(pDsNameResult);
}
DsUnBind(&hDS);
if (NO_ERROR != dwErr)
{
hr = HRESULT_FROM_WIN32(dwErr);
break;
}
//
// Create a new ldap handle if not in the same domain
//
PLDAP pldapComputer = NULL;
if (bSameDomain)
pldapComputer = i_pldap;
else
{
hr = ConnectToDS(m_bstrDomain, &pldapComputer);
BREAK_IF_FAILED(hr);
}
//
// Read:
// m_bstrSubscriberDN, m_bstrRootPath, m_bstrStagingPath
//
hr = _GetSubscriberInfo(pldapComputer, m_bstrComputerDN, i_bstrMemberDN);
//
// Read:
// m_bstrServer, m_bstrServerGuid, m_bstrSite
//
if (S_OK == hr)
hr = _GetComputerInfo(pldapComputer, m_bstrComputerDN);
//
// Close the newly created ldap handle
//
if (!bSameDomain)
CloseConnectionToDS(pldapComputer);
} while (0);
if (S_OK != hr)
{
if (!i_bstrComputerDN || !*i_bstrComputerDN)
m_bstrComputerDN.Empty();
m_bstrDomain.Empty();
}
return hr;
}
//
// Given: ComputerDN, MemberDN
// Read:
// m_bstrSubscriberDN, m_bstrRootPath, m_bstrStagingPath
//
// Return:
// S_FALSE if no such object found
//
HRESULT CFrsMember::_GetSubscriberInfo
(
PLDAP i_pldap, // points to the i_bstrComputerDN's DS
BSTR i_bstrComputerDN, // FQDN of the computer object
BSTR i_bstrMemberDN // FQDN of the corresponding nTFRSMember object
)
{
m_bstrSubscriberDN.Empty();
m_bstrRootPath.Empty();
m_bstrStagingPath.Empty();
RETURN_INVALIDARG_IF_NULL(i_pldap);
RETURN_INVALIDARG_IF_NULL(i_bstrComputerDN);
RETURN_INVALIDARG_IF_NULL(*i_bstrComputerDN);
RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
RETURN_INVALIDARG_IF_NULL(*i_bstrMemberDN);
//
// locate the nTFRSSubscriber object whose attribute "frsMemberReference"
// matches i_bstrMemberDN
//
CComBSTR bstrSearchFilter = _T("(&(objectCategory=nTFRSSubscriber)(frsMemberReference=");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrSearchFilter);
bstrSearchFilter += i_bstrMemberDN;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrSearchFilter);
bstrSearchFilter += _T("))");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrSearchFilter);
PCTSTR ppszAttributes[] = {
ATTR_DISTINGUISHEDNAME,
ATTR_FRS_SUBSCRIBER_ROOTPATH,
ATTR_FRS_SUBSCRIBER_STAGINGPATH,
0
};
LListElem* pElem = NULL;
HRESULT hr = GetValuesEx(
i_pldap,
i_bstrComputerDN,
LDAP_SCOPE_SUBTREE,
bstrSearchFilter,
ppszAttributes,
&pElem);
RETURN_IF_FAILED(hr);
if (!pElem) // no matching nTFRSSubscriber object
return S_FALSE;
LListElem* pCurElem = pElem;
while (pCurElem)
{
PTSTR** pppszValues = pCurElem->pppszAttrValues;
if (!pppszValues ||
!pppszValues[0] || !*(pppszValues[0]) ||
!pppszValues[1] || !*(pppszValues[1]) ||
!pppszValues[2] || !*(pppszValues[2]))
{
pCurElem = pCurElem->Next;
continue; // corrupted subscriber object
}
m_bstrSubscriberDN = *(pppszValues[0]);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrSubscriberDN, &hr);
m_bstrRootPath = *(pppszValues[1]);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrRootPath, &hr);
m_bstrStagingPath = *(pppszValues[2]);
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrStagingPath, &hr);
pCurElem = pCurElem->Next;
}
FreeLListElem(pElem);
if (FAILED(hr))
{
m_bstrSubscriberDN.Empty();
m_bstrRootPath.Empty();
m_bstrStagingPath.Empty();
}
return hr;
}
//
// Given: ComputerDN
// Read: m_bstrServer, m_bstrServerGuid, m_bstrSite
//
HRESULT CFrsMember::_GetComputerInfo
(
PLDAP i_pldap, // points to the i_bstrComputerDN's DS
BSTR i_bstrComputerDN // FQDN of the computer object
)
{
m_bstrServer.Empty();
m_bstrServerGuid.Empty();
m_bstrSite.Empty();
RETURN_INVALIDARG_IF_NULL(i_pldap);
RETURN_INVALIDARG_IF_NULL(i_bstrComputerDN);
RETURN_INVALIDARG_IF_NULL(*i_bstrComputerDN);
HRESULT hr = S_OK;
do {
//
// read dNSHostName and objectGUID on the ComputerDN
//
PLDAP_ATTR_VALUE pValues[3] = {0,0,0};
LDAP_ATTR_VALUE pAttributes[2];
pAttributes[0].bstrAttribute = ATTR_DNSHOSTNAME;
pAttributes[1].bstrAttribute = ATTR_OBJECTGUID;
pAttributes[1].bBerValue = true;
hr = GetValues( i_pldap,
i_bstrComputerDN,
OBJCLASS_SF_COMPUTER,
LDAP_SCOPE_BASE,
2,
pAttributes,
pValues);
BREAK_IF_FAILED(hr);
hr = E_FAIL;
if (pValues[0])
{
m_bstrServer = (PTSTR)(pValues[0]->vpValue);
hr = (!m_bstrServer) ? E_OUTOFMEMORY : S_OK;
FreeAttrValList(pValues[0]);
}
if (pValues[1])
{
if (SUCCEEDED(hr))
{
if (pValues[1]->bBerValue)
{
hr = UuidToStructuredString((UUID*)(pValues[1]->vpValue), &m_bstrServerGuid);
} else
{
m_bstrServerGuid = (PTSTR)(pValues[1]->vpValue);
hr = (!m_bstrServerGuid) ? E_OUTOFMEMORY : S_OK;
}
}
FreeAttrValList(pValues[1]);
}
BREAK_IF_FAILED(hr);
//
// retrieve Site
//
hr = GetSiteName(m_bstrServer, &m_bstrSite);
BREAK_IF_FAILED(hr);
} while (0);
if (FAILED(hr))
{
m_bstrServer.Empty();
m_bstrServerGuid.Empty();
m_bstrSite.Empty();
}
return hr;
}
//////////////////////////////////////////////////////////
//
// CFrsConnection
//
HRESULT CFrsConnection::Init(
BSTR i_bstrConnectionDN,
BSTR i_bstrFromMemberDN,
BOOL i_bEnable,
DWORD i_dwOptions)
{
_ReSet();
RETURN_INVALIDARG_IF_NULL(i_bstrConnectionDN);
RETURN_INVALIDARG_IF_NULL(i_bstrFromMemberDN);
HRESULT hr = S_OK;
do {
m_bstrConnectionDN = i_bstrConnectionDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrConnectionDN, &hr);
m_bstrFromMemberDN = i_bstrFromMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromMemberDN, &hr);
TCHAR* p = _tcschr(m_bstrConnectionDN, _T(','));
if (!p)
{
hr = E_INVALIDARG;
break;
}
m_bstrToMemberDN = p + 1;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToMemberDN, &hr);
m_bEnable = i_bEnable;
m_dwOptions = i_dwOptions;
} while (0);
if (FAILED(hr))
_ReSet();
return hr;
}
CFrsConnection* CFrsConnection::Copy()
{
CFrsConnection* pNew = new CFrsConnection;
if (pNew)
{
HRESULT hr = S_OK;
do {
pNew->m_bstrConnectionDN = m_bstrConnectionDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrConnectionDN, &hr);
pNew->m_bstrFromMemberDN = m_bstrFromMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrFromMemberDN, &hr);
pNew->m_bstrToMemberDN = m_bstrToMemberDN;
BREAK_OUTOFMEMORY_IF_NULL((BSTR)pNew->m_bstrToMemberDN, &hr);
pNew->m_bEnable = m_bEnable;
pNew->m_dwOptions = m_dwOptions;
} while (0);
if (FAILED(hr))
{
delete pNew;
pNew = NULL;
}
}
return pNew;
}
void CFrsConnection::_ReSet()
{
m_bstrConnectionDN.Empty();
m_bstrFromMemberDN.Empty();
m_bstrToMemberDN.Empty();
m_bEnable = TRUE;
m_dwOptions = 0;
}