|
|
/*++
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; }
|