/*++ Module Name: DfsRoot.cpp --*/ #include "stdafx.h" #include "DfsCore.h" #include "DfsRoot.h" #include "JPEnum.h" #include #include // DsRoleGetPrimaryDomainInformation #include "netutils.h" #include "ldaputils.h" ///////////////////////////////////////////////////////////////////////////////////////////////// // CDfsRoot constructor CDfsRoot::CDfsRoot() : m_pDfsJP(NULL), m_dwDfsType(DFS_TYPE_UNASSIGNED), m_lCountOfDfsJunctionPointsFiltered(0), m_lLinkFilterType(FILTERDFSLINKS_TYPE_NO_FILTER) { dfsDebugOut((_T("CDfsRoot::CDfsRoot this=%p\n"), this)); } ///////////////////////////////////////////////////////////////////////////////////////////////// // CDfsRoot destructor CDfsRoot::~CDfsRoot() { _FreeMemberVariables(); dfsDebugOut((_T("CDfsRoot::~CDfsRoot this=%p\n"), this)); } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_DomainName STDMETHODIMP CDfsRoot :: get_DomainName ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_bstrDomainName.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_DomainGuid STDMETHODIMP CDfsRoot :: get_DomainGuid ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_bstrDomainGuid.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_DomainDN STDMETHODIMP CDfsRoot :: get_DomainDN ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_bstrDomainDN.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_DfsType STDMETHODIMP CDfsRoot :: get_DfsType ( long* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_dwDfsType; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_State STDMETHODIMP CDfsRoot :: get_State ( long* pVal ) { return m_pDfsJP->get_State(pVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_DfsName STDMETHODIMP CDfsRoot :: get_DfsName ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG ; *pVal = m_bstrDfsName.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_ReplicaSetDN STDMETHODIMP CDfsRoot :: get_ReplicaSetDN ( BSTR* pVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_ReplicaSetDN(pVal); } STDMETHODIMP CDfsRoot :: get_ReplicaSetExist ( BOOL* pVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_ReplicaSetExist(pVal); } STDMETHODIMP CDfsRoot :: get_ReplicaSetExistEx ( BSTR* o_pbstrDC, BOOL* pVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_ReplicaSetExistEx(o_pbstrDC, pVal); } STDMETHODIMP CDfsRoot :: put_ReplicaSetExist ( BOOL newVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->put_ReplicaSetExist(newVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_CountOfDfsJunctionPoints STDMETHODIMP CDfsRoot :: get_CountOfDfsJunctionPoints ( long* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_JunctionPoints.size(); return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_CountOfDfsJunctionPointsFiltered STDMETHODIMP CDfsRoot :: get_CountOfDfsJunctionPointsFiltered ( long* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_lCountOfDfsJunctionPointsFiltered; return S_OK; } HRESULT DfsInfo3ToVariant(PDFS_INFO_3 pDfsInfo, OUT VARIANT *pVal) { RETURN_INVALIDARG_IF_NULL(pDfsInfo); RETURN_INVALIDARG_IF_NULL(pVal); HRESULT hr = S_OK; int cStorages = pDfsInfo->NumberOfStorages; // create an array of array of variants to hold all storage data SAFEARRAY* psa_1 = NULL; if (cStorages > 0 ) { SAFEARRAYBOUND bounds_1 = {cStorages, 0}; psa_1 = SafeArrayCreate(VT_VARIANT, 1, &bounds_1); RETURN_OUTOFMEMORY_IF_NULL(psa_1); VARIANT* varArray_1 = NULL; SafeArrayAccessData(psa_1, (void**)&varArray_1); for (int i = 0; i < cStorages; i++) { // create an array of variants to hold each Storage data (3 elements) SAFEARRAYBOUND bounds_0 = {ARRAY_COUNT_FOR_DFS_STORAGE_INFO, 0}; SAFEARRAY* psa_0 = SafeArrayCreate(VT_VARIANT, 1, &bounds_0); BREAK_OUTOFMEMORY_IF_NULL(psa_0, &hr); VARIANT* varArray_0 = NULL; SafeArrayAccessData(psa_0, (void**)&varArray_0); do { varArray_0[0].vt = VT_BSTR; varArray_0[0].bstrVal = SysAllocString(pDfsInfo->Storage[i].ServerName); BREAK_OUTOFMEMORY_IF_NULL(varArray_0[0].bstrVal, &hr); varArray_0[1].vt = VT_BSTR; varArray_0[1].bstrVal = SysAllocString(pDfsInfo->Storage[i].ShareName); BREAK_OUTOFMEMORY_IF_NULL(varArray_0[1].bstrVal, &hr); varArray_0[2].vt = VT_I4; varArray_0[2].lVal = pDfsInfo->Storage[i].State; } while (0); SafeArrayUnaccessData(psa_0); if (FAILED(hr)) { SafeArrayDestroy(psa_0); break; } // add this array to be an element varArray_1[i].vt = VT_ARRAY | VT_VARIANT; varArray_1[i].parray = psa_0; } SafeArrayUnaccessData(psa_1); } if (SUCCEEDED(hr)) { // now create an array of variants to hold DfsInfoLevel SAFEARRAYBOUND bounds_2 = {ARRAY_COUNT_FOR_DFS_INFO_3, 0}; SAFEARRAY* psa_2 = SafeArrayCreate(VT_VARIANT, 1, &bounds_2); if (!psa_2) { hr = E_OUTOFMEMORY; } else { VARIANT* varArray_2 = NULL; SafeArrayAccessData(psa_2, (void**)&varArray_2); do { varArray_2[0].vt = VT_BSTR; varArray_2[0].bstrVal = SysAllocString(pDfsInfo->EntryPath); BREAK_OUTOFMEMORY_IF_NULL(varArray_2[0].bstrVal, &hr); varArray_2[1].vt = VT_ARRAY | VT_VARIANT; varArray_2[1].parray = psa_1; } while (0); SafeArrayUnaccessData(psa_2); if (FAILED(hr)) SafeArrayDestroy(psa_2); } if (SUCCEEDED(hr)) { VariantInit(pVal); pVal->vt = VT_ARRAY | VT_VARIANT; pVal->parray = psa_2; } } if (FAILED(hr)) SafeArrayDestroy(psa_1); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // Initialize HRESULT CDfsRoot::_Init( PDFS_INFO_3 pDfsInfo, StringMap* pMap) { RETURN_INVALIDARG_IF_NULL(pDfsInfo); RETURN_INVALIDARG_IF_NULL(pMap); HRESULT hr = S_OK; do { hr = GetUNCPathComponent(pDfsInfo->EntryPath, &m_bstrDfsName, 3, 4); BREAK_IF_FAILED(hr); // decide whether it's a domain-based or standalone CComBSTR bstrScope; hr = GetUNCPathComponent(pDfsInfo->EntryPath, &bstrScope, 2, 3); BREAK_IF_FAILED(hr); if ((pDfsInfo->State & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_STANDALONE) { m_dwDfsType = DFS_TYPE_STANDALONE; } else if ((pDfsInfo->State & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_AD_BLOB) { m_dwDfsType = DFS_TYPE_FTDFS; } else { // flavor flag is not set, we're dealing with old version of metadata blob // see if bstrScope is a domain name #ifdef DEBUG SYSTEMTIME time0 = {0}; GetSystemTime(&time0); #endif // DEBUG PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; DWORD nRet = DsGetDcName( NULL, bstrScope, NULL, NULL, DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME, &pDCInfo ); #ifdef DEBUG SYSTEMTIME time1 = {0}; GetSystemTime(&time1); PrintTimeDelta(_T("CDfsRoot::_Init-DsGetDcName"), &time0, &time1); #endif // DEBUG if (ERROR_SUCCESS == nRet) { NetApiBufferFree(pDCInfo); m_dwDfsType = DFS_TYPE_FTDFS; } else { // check to see if it's a valid server name PWKSTA_INFO_100 wki100 = NULL; nRet = NetWkstaGetInfo(bstrScope, 100, (LPBYTE *)&wki100 ); if (ERROR_SUCCESS == nRet) { m_dwDfsType = DFS_TYPE_STANDALONE; NetApiBufferFree((LPVOID)wki100); } else { hr = HRESULT_FROM_WIN32(nRet); } } } if (SUCCEEDED(hr) && m_dwDfsType == DFS_TYPE_FTDFS) { hr = GetDomainInfo( bstrScope, NULL, // DC &m_bstrDomainName, &m_bstrDomainDN, NULL, // LDAPDomainPath &m_bstrDomainGuid); } BREAK_IF_FAILED(hr); if (m_dwDfsType == DFS_TYPE_FTDFS) { (void) _GetAllReplicaSets(pMap); } CComVariant varData; hr = DfsInfo3ToVariant(pDfsInfo, &varData); BREAK_IF_FAILED(hr); hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER, IID_IDfsJunctionPoint, (void **)&m_pDfsJP); BREAK_IF_FAILED(hr); if (m_dwDfsType == DFS_TYPE_FTDFS) { CComBSTR bstrDfsLinkName; hr = GetUNCPathComponent(pDfsInfo->EntryPath, &bstrDfsLinkName, 3, 0); BREAK_IF_FAILED(hr); StringMap::iterator it = pMap->find(bstrDfsLinkName); if (it != pMap->end()) hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, TRUE, (*it).second); else hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, FALSE, NULL); } else { hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, FALSE, NULL); } } while (0); return hr; } int __cdecl CompareJPs(const void *arg1, const void *arg2 ) { return lstrcmpi( (*(PDFS_INFO_3 *)arg1)->EntryPath, (*(PDFS_INFO_3 *)arg2)->EntryPath ); } STDMETHODIMP CDfsRoot :: Initialize ( BSTR i_szDfsName ) { /*++ Routine Description: This method intializes the newly created object and previously initialised DfsRoot object. Arguments: i_szDfsName - The Dfs name which can be any of the following type: 1. \\domain.dns.name\FtDfs, 2. \\domain\FtDfs, 3. \\server\share, 4. \\server, 5. server. Notes: Initialize performs the following: 1. Gets the name of the domain for the server hosting / participating in the Dfs Root. 2. Gets all child junction points and root level replicas for this Dfs. 3. Gets the type (standalone or fault tolerant) of the DFS. 4. Gets the display name of the DFS, \\domain.dns.name\FtDfs or \\server\share and Dfs Name which is FtDfs or server.. Return: S_FALSE if i_szDfsName doesn't host any dfs root --*/ RETURN_INVALIDARG_IF_NULL(i_szDfsName); _FreeMemberVariables(); LPBYTE pBuffer = NULL; DWORD dwEntriesRead = 0; DWORD dwResumeHandle = 0; NET_API_STATUS nRet = NetDfsEnum( i_szDfsName, 3, // level 3 0xffffffff, &pBuffer, &dwEntriesRead, &dwResumeHandle); dfsDebugOut((_T("NetDfsEnum DfsName=%s, level 3 for Root Initialization, nRet=%d\n"), i_szDfsName, nRet)); if (NERR_Success != nRet) { return (ERROR_NO_MORE_ITEMS == nRet || ERROR_NOT_FOUND == nRet) ? S_FALSE : HRESULT_FROM_WIN32(nRet); } else if (0 == dwEntriesRead) { if (pBuffer) NetApiBufferFree(pBuffer); return S_FALSE; } HRESULT hr = S_OK; do { DWORD i = 0; PDFS_INFO_3 pDfsInfo = (PDFS_INFO_3)pBuffer; // // root may not be the 1st entry, find the root entry, switch it to the top // for (i = 0; i < dwEntriesRead; i++) { if (pDfsInfo[i].State & DFS_VOLUME_FLAVORS) break; // the i-th entry is the root entry } if (i != 0 && i != dwEntriesRead) { DFS_INFO_3 tmpInfo = {0}; memcpy(&tmpInfo, pDfsInfo, sizeof(DFS_INFO_3)); memcpy(pDfsInfo, pDfsInfo + i, sizeof(DFS_INFO_3)); memcpy(pDfsInfo + i, &tmpInfo, sizeof(DFS_INFO_3)); } // i=0 is the Root info StringMap mapReplicaSets; hr = _Init(pDfsInfo, &mapReplicaSets); BREAK_IF_FAILED(hr); if (dwEntriesRead > 1) { pDfsInfo++; PDFS_INFO_3 *pArray = (PDFS_INFO_3 *)calloc(dwEntriesRead - 1, sizeof(PDFS_INFO_3)); BREAK_OUTOFMEMORY_IF_NULL(pArray, &hr); PDFS_INFO_3 *pArrayElem = NULL; for (i = 1, pArrayElem = pArray; i < dwEntriesRead; i++, pDfsInfo++, pArrayElem++) *pArrayElem = pDfsInfo; qsort((void *)pArray, dwEntriesRead - 1, sizeof(PDFS_INFO_3), CompareJPs); StringMap::iterator it; for (i = 1, pArrayElem = pArray; i < dwEntriesRead; i++, pArrayElem++) { if (m_dwDfsType == DFS_TYPE_FTDFS) { CComBSTR bstrDfsLinkName; hr = GetUNCPathComponent((*pArrayElem)->EntryPath, &bstrDfsLinkName, 3, 0); BREAK_IF_FAILED(hr); it = mapReplicaSets.find(bstrDfsLinkName); if (it != mapReplicaSets.end()) hr = _AddToJPList(*pArrayElem, TRUE, (*it).second); else hr = _AddToJPList(*pArrayElem, FALSE, NULL); } else { hr = _AddToJPList(*pArrayElem, FALSE, NULL); } BREAK_IF_FAILED(hr); } free((void *)pArray); } } while (0); NetApiBufferFree(pBuffer); if (FAILED(hr)) _FreeMemberVariables(); return hr; } void _FreeStringMap(IN StringMap* pMap) { if (pMap && !pMap->empty()) { for (StringMap::iterator i = pMap->begin(); i != pMap->end(); i++) { if ((*i).first) free( (void *)((*i).first) ); if ((*i).second) free( (void *)((*i).second) ); } pMap->clear(); } } HRESULT CDfsRoot :: _GetAllReplicaSets( OUT StringMap* pMap ) { _FreeStringMap(pMap); RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDomainName); RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDomainDN); HRESULT hr = S_OK; PLDAP pldap = NULL; do { hr = ConnectToDS(m_bstrDomainName, &pldap); BREAK_IF_FAILED(hr); CComBSTR bstrContainerDN = _T("CN="); BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr); bstrContainerDN += m_bstrDfsName; BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr); bstrContainerDN += CN_DFSVOLUMES_PREFIX_COMMA; BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr); bstrContainerDN += m_bstrDomainDN; BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr); // // get all the replica sets under the container // PCTSTR ppszAttributes[] = {ATTR_DISTINGUISHEDNAME, 0}; LListElem* pElem = NULL; hr = GetValuesEx( pldap, bstrContainerDN, LDAP_SCOPE_SUBTREE, _T("(&(objectCategory=nTFRSReplicaSet)(frsReplicaSetType=3))"), ppszAttributes, &pElem); BREAK_IF_FAILED(hr); LListElem* pCurElem = pElem; while (pCurElem) { PTSTR** pppszValues = pCurElem->pppszAttrValues; if (!pppszValues || !pppszValues[0] || !*(pppszValues[0])) { hr = E_FAIL; break; } PTSTR pszDN = *(pppszValues[0]); PTSTR p = _tcsstr(pszDN, _T(",DC=")); if (!p) { hr = E_INVALIDARG; break; } *p = _T('\0'); PTSTR pszReplicaSetDN = _tcsdup(pszDN); *p = _T(','); BREAK_OUTOFMEMORY_IF_NULL(pszReplicaSetDN, &hr); CComBSTR bstrDfsLinkName; hr = GetDfsLinkNameFromDN(pszReplicaSetDN, &bstrDfsLinkName); PTSTR pszDfsLinkName = NULL; if (SUCCEEDED(hr)) { pszDfsLinkName = _tcsdup(bstrDfsLinkName); if (!pszDfsLinkName) hr = E_OUTOFMEMORY; } if (FAILED(hr)) { free(pszReplicaSetDN); break; } pMap->insert(StringMap::value_type(pszDfsLinkName, pszReplicaSetDN)); pCurElem = pCurElem->Next; } FreeLListElem(pElem); BREAK_IF_FAILED(hr); } while (0); if (pldap) CloseConnectionToDS(pldap); if (FAILED(hr)) _FreeStringMap(pMap); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // CreateJunctionPoint STDMETHODIMP CDfsRoot :: CreateJunctionPoint ( BSTR i_szJPName, BSTR i_szServerName, BSTR i_szShareName, BSTR i_szComment, long i_lTimeout, VARIANT* o_pIDfsJunctionPoint ) { if (!i_szJPName || !i_szServerName || !i_szShareName || !o_pIDfsJunctionPoint) return E_INVALIDARG; RETURN_INVALIDARG_IF_NULL(m_pDfsJP); CComBSTR bstrEntryPath; // Start with the root entry path. HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath); RETURN_IF_FAILED(hr); bstrEntryPath += _T("\\"); RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath); bstrEntryPath += i_szJPName; RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath); NET_API_STATUS nstatRetVal = NetDfsAdd( bstrEntryPath, i_szServerName, i_szShareName, i_szComment, DFS_ADD_VOLUME | DFS_RESTORE_VOLUME ); dfsDebugOut((_T("NetDfsAdd entry=%s, server=%s, share=%s, comment=%s, DFS_ADD_VOLUME | DFS_RESTORE_VOLUME, nRet=%d\n"), bstrEntryPath, i_szServerName, i_szShareName, i_szComment, nstatRetVal)); if (nstatRetVal != NERR_Success) return HRESULT_FROM_WIN32 (nstatRetVal); // Get the interface pointer IDfsJunctionPoint* pIJunctionPointPtr = NULL; hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER, IID_IDfsJunctionPoint, (void **)&pIJunctionPointPtr); RETURN_IF_FAILED(hr); hr = pIJunctionPointPtr->Initialize((IUnknown *)this, bstrEntryPath, FALSE, NULL); if (SUCCEEDED(hr)) { hr = pIJunctionPointPtr->put_Timeout(i_lTimeout); if (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) == hr) { // we're most probably managing NT4 here, which doesn't support Timeout hr = S_OK; } } if (SUCCEEDED(hr)) hr = _AddToJPListEx(pIJunctionPointPtr, TRUE); if (SUCCEEDED(hr)) { o_pIDfsJunctionPoint->vt = VT_DISPATCH; o_pIDfsJunctionPoint->pdispVal = pIJunctionPointPtr; } else { pIJunctionPointPtr->Release(); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // DeleteJunctionPoint STDMETHODIMP CDfsRoot::DeleteJunctionPoint ( BSTR i_szJPName ) { if (!i_szJPName) return E_INVALIDARG; RETURN_INVALIDARG_IF_NULL(m_pDfsJP); CComBSTR bstrEntryPath; // Start with the root entry path. HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath); RETURN_IF_FAILED(hr); bstrEntryPath += _T("\\"); RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath); bstrEntryPath += i_szJPName; RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath); // Get the interface pointer JUNCTIONNAMELIST::iterator i; for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++) { if (!lstrcmpi((*i)->m_bstrJPName, i_szJPName)) break; } if (i != m_JunctionPoints.end()) { hr = ((*i)->m_piDfsJunctionPoint)->RemoveAllReplicas(); if (SUCCEEDED(hr)) { delete (*i); m_JunctionPoints.erase(i); } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // DeleteDfsHost STDMETHODIMP CDfsRoot::DeleteDfsHost ( BSTR i_bstrServerName, BSTR i_bstrShareName, BOOL i_bForce ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); switch (m_dwDfsType) { case DFS_TYPE_STANDALONE: return m_pDfsJP->DeleteRootReplica(NULL, NULL, i_bstrServerName, i_bstrShareName, i_bForce); case DFS_TYPE_FTDFS: return m_pDfsJP->DeleteRootReplica(m_bstrDomainName, m_bstrDfsName, i_bstrServerName, i_bstrShareName, i_bForce); default: return E_INVALIDARG; } } ///////////////////////////////////////////////////////////////////////////////////////////////// // GetOneDfsHost STDMETHODIMP CDfsRoot::GetOneDfsHost ( OUT BSTR* o_pbstrServerName, OUT BSTR* o_pbstrShareName ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->GetOneRootReplica(o_pbstrServerName, o_pbstrShareName); } ///////////////////////////////////////////////////////////////////////////////////////////////// // _FreeMemberVariables void CDfsRoot :: _FreeMemberVariables ( ) { m_bstrDfsName.Empty(); m_bstrDomainName.Empty(); m_bstrDomainGuid.Empty(); m_bstrDomainDN.Empty(); m_lLinkFilterType = FILTERDFSLINKS_TYPE_NO_FILTER; m_bstrEnumFilter.Empty(); FreeJunctionNames(&m_JunctionPoints); if (m_pDfsJP) { m_pDfsJP->Release(); m_pDfsJP = NULL; } } ///////////////////////////////////////////////////////////////////////////////////////////////// // get__NewEnum STDMETHODIMP CDfsRoot :: get__NewEnum ( LPUNKNOWN* pVal ) { /*++ Routine Description: Returns a new enumerator interface (IEnumVARIANT) to enumerate Junction points. This depends upon the EnumFilter value. Arguments: pVal - Pointer to a Variant in which the enumerator will be returned. --*/ if (!pVal) return E_INVALIDARG; *pVal = NULL; //Create a Junction point enumerator and initialize it with //the internal list. CComObject *pJunctionPointEnum = new CComObject(); if (!pJunctionPointEnum) return E_OUTOFMEMORY; HRESULT hr = pJunctionPointEnum->Initialize(&m_JunctionPoints, m_lLinkFilterType, m_bstrEnumFilter, (ULONG*)&m_lCountOfDfsJunctionPointsFiltered); if (SUCCEEDED(hr)) hr = pJunctionPointEnum->QueryInterface(IID_IEnumVARIANT, (void **)pVal); if (FAILED(hr)) delete pJunctionPointEnum; return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_RootReplicaEnum STDMETHODIMP CDfsRoot :: get_RootReplicaEnum ( LPUNKNOWN* pVal ) { /*++ Routine Description: Call the inner junction point to return a new enumerator interface (IEnumVARIANT) to enumerate root replicas. Arguments: pVal - Pointer to a Variant in which the enumerator will be returned. --*/ RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get__NewEnum(pVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // GetRootJP STDMETHODIMP CDfsRoot :: GetRootJP ( VARIANT* o_pIDfsJunctionPoint ) { RETURN_INVALIDARG_IF_NULL(o_pIDfsJunctionPoint); RETURN_INVALIDARG_IF_NULL(m_pDfsJP); m_pDfsJP->AddRef(); o_pIDfsJunctionPoint->vt = VT_DISPATCH; o_pIDfsJunctionPoint->pdispVal = m_pDfsJP; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_RootEntryPath STDMETHODIMP CDfsRoot :: get_RootEntryPath ( BSTR* pVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_EntryPath(pVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // Comment STDMETHODIMP CDfsRoot :: get_Comment(BSTR *pVal) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_Comment(pVal); } STDMETHODIMP CDfsRoot :: put_Comment(BSTR newVal) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->put_Comment(newVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // Timeout STDMETHODIMP CDfsRoot::get_Timeout(long *pVal) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_Timeout(pVal); } STDMETHODIMP CDfsRoot::put_Timeout(long newVal) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->put_Timeout(newVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // DeleteAllJunctionPoints HRESULT CDfsRoot :: DeleteAllJunctionPoints() { /*++ Routine Description: Deletes all Junction junction points. --*/ HRESULT hr = S_OK; for (JUNCTIONNAMELIST::iterator i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++) { hr = DeleteJunctionPoint((*i)->m_bstrJPName); BREAK_IF_FAILED(hr); } return hr; } // // gets/puts the type of Enumerator Filter. // STDMETHODIMP CDfsRoot::get_EnumFilterType ( long* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_lLinkFilterType; return S_OK; } STDMETHODIMP CDfsRoot::put_EnumFilterType ( long newVal ) { m_lLinkFilterType = (FILTERDFSLINKS_TYPE)newVal; return S_OK; } // // gets/puts the Enumerator Filter // STDMETHODIMP CDfsRoot::get_EnumFilter ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = NULL; if ((BSTR)m_bstrEnumFilter) { *pVal = m_bstrEnumFilter.Copy (); if (!*pVal) return E_OUTOFMEMORY; } return S_OK; } STDMETHODIMP CDfsRoot::put_EnumFilter ( BSTR newVal ) { // we require newVal points to a non-empty string if (!newVal || !*newVal) return E_INVALIDARG; m_bstrEnumFilter = newVal; if (!m_bstrEnumFilter) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// // get_CountOfDfsRootReplicas STDMETHODIMP CDfsRoot :: get_CountOfDfsRootReplicas ( long* pVal ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); return m_pDfsJP->get_CountOfDfsReplicas(pVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // IsJPExisted STDMETHODIMP CDfsRoot :: IsJPExisted ( BSTR i_bstrJPName ) { RETURN_INVALIDARG_IF_NULL(i_bstrJPName); for (JUNCTIONNAMELIST::iterator i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++) { if (!lstrcmpi((*i)->m_bstrJPName, i_bstrJPName)) return S_OK; } return S_FALSE; } ///////////////////////////////////////////////////////////////////////////////////////////////// // RefreshRootReplicas: used to pick up new Dfs hosts STDMETHODIMP CDfsRoot :: RefreshRootReplicas ( ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); CComBSTR bstrEntryPath; HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath); RETURN_IF_FAILED(hr); BOOL bReplicaSetExist = FALSE; hr = m_pDfsJP->get_ReplicaSetExist(&bReplicaSetExist); RETURN_IF_FAILED(hr); CComBSTR bstrReplicaSetDN; hr = m_pDfsJP->get_ReplicaSetDN(&bstrReplicaSetDN); RETURN_IF_FAILED(hr); hr = m_pDfsJP->Initialize((IUnknown *)this, bstrEntryPath, bReplicaSetExist, bstrReplicaSetDN); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // DeleteAllReplicaSets: delete all replica sets related to this Dfs root STDMETHODIMP CDfsRoot :: DeleteAllReplicaSets ( ) { RETURN_INVALIDARG_IF_NULL(m_pDfsJP); if (m_dwDfsType != DFS_TYPE_FTDFS) return S_OK; // // delete replica sets associated with this Dfs root // HRESULT hr = S_OK; BOOL bReplicaSetExist = FALSE; JUNCTIONNAMELIST::iterator i; for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++) { bReplicaSetExist = FALSE; (void)(*i)->m_piDfsJunctionPoint->get_ReplicaSetExist(&bReplicaSetExist); if (bReplicaSetExist) { CComBSTR bstrReplicaSetDN; hr = (*i)->m_piDfsJunctionPoint->get_ReplicaSetDN(&bstrReplicaSetDN); BREAK_IF_FAILED(hr); CComPtr piReplicaSet; hr = CoCreateInstance(CLSID_ReplicaSet, NULL, CLSCTX_INPROC_SERVER, IID_IReplicaSet, (void**)&piReplicaSet); BREAK_IF_FAILED(hr); hr = piReplicaSet->Initialize(m_bstrDomainName, bstrReplicaSetDN); if (SUCCEEDED(hr)) piReplicaSet->Delete(); } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // FreeJunctionNames void FreeJunctionNames (JUNCTIONNAMELIST* pJPList) { if (NULL == pJPList) return; if (!pJPList->empty()) { for (JUNCTIONNAMELIST::iterator i = pJPList->begin(); i != pJPList->end(); i++) { delete (*i); } pJPList->clear(); } _ASSERT(pJPList->empty()); } ///////////////////////////////////////////////////////////////////////////////////////////////// void FreeReplicas(REPLICAINFOLIST* pRepList) { if (NULL == pRepList) return; if (!pRepList->empty()) { for (REPLICAINFOLIST::iterator i = pRepList->begin(); i != pRepList->end(); i++) { delete (*i); } pRepList->clear(); } _ASSERT(pRepList->empty()); } HRESULT CDfsRoot::_AddToJPList( PDFS_INFO_3 pDfsInfo, BOOL bReplicaSetExist, BSTR bstrReplicaSetDN) { HRESULT hr = S_OK; CComPtr piDfsJunctionPoint; hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER, IID_IDfsJunctionPoint, (void **)&piDfsJunctionPoint); RETURN_IF_FAILED(hr); CComVariant varData; hr = DfsInfo3ToVariant(pDfsInfo, &varData); RETURN_IF_FAILED(hr); hr = piDfsJunctionPoint->InitializeEx((IUnknown *)this, &varData, bReplicaSetExist, bstrReplicaSetDN); RETURN_IF_FAILED(hr); return _AddToJPListEx(piDfsJunctionPoint); } HRESULT CDfsRoot::_AddToJPListEx( IDfsJunctionPoint * piDfsJunctionPoint, BOOL bSort) { JUNCTIONNAME* pDfsJP = new JUNCTIONNAME; RETURN_OUTOFMEMORY_IF_NULL(pDfsJP); HRESULT hr = pDfsJP->Init(piDfsJunctionPoint); if (FAILED(hr)) { delete pDfsJP; return hr; } if (bSort) { JUNCTIONNAMELIST::iterator i; for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++) { if (lstrcmpi(pDfsJP->m_bstrJPName, (*i)->m_bstrJPName) < 0) break; } m_JunctionPoints.insert(i, pDfsJP); } else { m_JunctionPoints.push_back(pDfsJP); } return hr; }