/*++ Module Name: DfsJP.cpp Abstract: This COM Class provides method to get information of Dfs Junction Points and to enumerate replica of a junction point. --*/ #include "stdafx.h" #include "DfsCore.h" #include "DfsJP.h" #include "DfsRep.h" #include "JPEnum.h" #include "RepEnum.h" #include "netutils.h" #include "ldaputils.h" #include ///////////////////////////////////////////////////////////////////////////////////////////////// // CDfsJuntionPoint ///////////////////////////////////////////////////////////////////////////////////////////////// CDfsJunctionPoint :: CDfsJunctionPoint () { dfsDebugOut((_T("CDfsJunctionPoint::CDfsJunctionPoint this=%p\n"), this)); } ///////////////////////////////////////////////////////////////////////////////////////////////// CDfsJunctionPoint :: ~CDfsJunctionPoint () { _FreeMemberVariables(); dfsDebugOut((_T("CDfsJunctionPoint::~CDfsJunctionPoint this=%p\n"), this)); } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_State ( long* pVal ) { return E_NOTIMPL; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_EntryPath ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; *pVal = m_bstrEntryPath.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_JunctionName ( BOOL i_bDfsNameIncluded, BSTR* pVal ) { if (!pVal) return E_INVALIDARG; if (i_bDfsNameIncluded) *pVal = m_bstrJunctionNameEx.Copy (); else *pVal = m_bstrJunctionName.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_Comment ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; DFS_INFO_100* pInfoBuffer = NULL; NET_API_STATUS nRet = NetDfsGetInfo( m_bstrEntryPath, NULL, NULL, 100, (LPBYTE*)&pInfoBuffer ); dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 100 for comment, nRet=%d\n"), m_bstrEntryPath, nRet)); if (NERR_Success == nRet) { *pVal = SysAllocString(pInfoBuffer->Comment); NetApiBufferFree(pInfoBuffer); if (!*pVal) return E_OUTOFMEMORY; } return HRESULT_FROM_WIN32(nRet); } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: put_Comment ( BSTR newVal ) { DFS_INFO_100 InfoBuffer = {(newVal ? newVal : _T(""))}; NET_API_STATUS nRet = NetDfsSetInfo ( m_bstrEntryPath, NULL, NULL, 100, (LPBYTE) &InfoBuffer ); dfsDebugOut((_T("NetDfsSetInfo entry=%s, level 100 for comment, nRet=%d\n"), m_bstrEntryPath, nRet)); return HRESULT_FROM_WIN32(nRet); } ///////////////////////////////////////////////////////////////////////////// // get_Timeout STDMETHODIMP CDfsJunctionPoint :: get_Timeout ( long* pVal ) { if (!pVal || !m_bstrEntryPath) return E_INVALIDARG; DFS_INFO_4* pInfoBuffer = NULL; NET_API_STATUS nRet = NetDfsGetInfo( m_bstrEntryPath, NULL, NULL, 4, (LPBYTE*)&pInfoBuffer ); dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 4 for Timeout, nRet=%d\n"), m_bstrEntryPath, nRet)); if (NERR_Success == nRet) { *pVal = pInfoBuffer->Timeout; NetApiBufferFree(pInfoBuffer); } return HRESULT_FROM_WIN32(nRet); } ///////////////////////////////////////////////////////////////////////////// // put_Timeout STDMETHODIMP CDfsJunctionPoint :: put_Timeout ( long newVal ) { if (!m_bstrEntryPath) return E_INVALIDARG; DFS_INFO_102 DfsInfoLevel102 = {newVal}; NET_API_STATUS nRet = NetDfsSetInfo ( m_bstrEntryPath, NULL, NULL, 102, (LPBYTE) &DfsInfoLevel102 ); dfsDebugOut((_T("NetDfsSetInfo entry=%s, level 102 for Timeout, nRet=%d\n"), m_bstrEntryPath, nRet)); return HRESULT_FROM_WIN32(nRet); } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetDN ( BSTR* pVal ) { if (!pVal) return E_INVALIDARG; if (!m_bstrEntryPath) return E_INVALIDARG; HRESULT hr = S_OK; if (!m_bstrReplicaSetDN) { hr = _GetReplicaSetDN(m_bstrEntryPath); RETURN_IF_FAILED(hr); } *pVal = m_bstrReplicaSetDN.Copy (); if (!*pVal) return E_OUTOFMEMORY; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetExist ( BOOL* pVal ) { if (!pVal) return E_INVALIDARG; if (!m_bstrEntryPath) return E_INVALIDARG; *pVal = m_bReplicaSetExist; return S_OK; } STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetExistEx ( BSTR* o_pbstrDC, BOOL* pVal ) { if (!pVal || !o_pbstrDC) return E_INVALIDARG; if (!m_bstrEntryPath) return E_INVALIDARG; HRESULT hr = S_OK; if (!m_bstrReplicaSetDN) { hr = _GetReplicaSetDN(m_bstrEntryPath); RETURN_IF_FAILED(hr); } DFS_TYPE dwDfsType = DFS_TYPE_UNASSIGNED; CComBSTR bstrDomainName; CComBSTR bstrDomainDN; hr = _GetDfsType(&dwDfsType, &bstrDomainName, &bstrDomainDN); RETURN_IF_FAILED(hr); m_bReplicaSetExist = FALSE; if (dwDfsType == DFS_TYPE_FTDFS) { CComBSTR bstrDN = m_bstrReplicaSetDN; if ((BSTR)bstrDN) bstrDN += _T(","); if ((BSTR)bstrDN) bstrDN += bstrDomainDN; RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDN); PLDAP pldap = NULL; CComBSTR bstrDC; hr = ConnectToDS(bstrDomainName, &pldap, &bstrDC); if (SUCCEEDED(hr)) { m_bReplicaSetExist = (S_OK == IsValidObject(pldap, bstrDN)); CloseConnectionToDS(pldap); *o_pbstrDC = bstrDC.Copy(); if (!*o_pbstrDC) hr = E_OUTOFMEMORY; } } *pVal = m_bReplicaSetExist; return hr; } HRESULT CDfsJunctionPoint :: _GetDfsType( OUT DFS_TYPE* o_pdwDfsType, OUT BSTR* o_pbstrDomainName, OUT BSTR* o_pbstrDomainDN ) { if (!o_pdwDfsType) return E_INVALIDARG; if (!m_spiDfsRoot) return E_INVALIDARG; HRESULT hr = S_OK; m_spiDfsRoot->get_DfsType((long *)o_pdwDfsType); if (*o_pdwDfsType == DFS_TYPE_FTDFS) { if (o_pbstrDomainName) hr = m_spiDfsRoot->get_DomainName(o_pbstrDomainName); if (SUCCEEDED(hr) && o_pbstrDomainDN) hr = m_spiDfsRoot->get_DomainDN(o_pbstrDomainDN); } return hr; } STDMETHODIMP CDfsJunctionPoint :: put_ReplicaSetExist ( BOOL newVal ) { if (!m_bstrEntryPath) return E_INVALIDARG; m_bReplicaSetExist = newVal; return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CDfsJunctionPoint::_Init( PDFS_INFO_3 pDfsInfo, BOOL bReplicaSetExist, BSTR bstrReplicaSetDN ) { _FreeMemberVariables(); if (bReplicaSetExist && (!bstrReplicaSetDN || !*bstrReplicaSetDN)) return E_INVALIDARG; HRESULT hr = S_OK; do { m_bstrEntryPath = pDfsInfo->EntryPath; BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrEntryPath, &hr); hr = GetUNCPathComponent(m_bstrEntryPath, &m_bstrJunctionName, 4, 0); BREAK_IF_FAILED(hr); hr = GetUNCPathComponent(m_bstrEntryPath, &m_bstrJunctionNameEx, 3, 0); BREAK_IF_FAILED(hr); PDFS_STORAGE_INFO pStorage = pDfsInfo->Storage; for (DWORD i = 0; i < pDfsInfo->NumberOfStorages && pStorage; i++, pStorage++) { hr = _AddToReplicaList(pStorage->ServerName, pStorage->ShareName, pStorage->State); BREAK_IF_FAILED(hr); } m_bReplicaSetExist = bReplicaSetExist; if (m_bReplicaSetExist) { m_bstrReplicaSetDN = bstrReplicaSetDN; BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr); } } while (0); if (FAILED(hr)) _FreeMemberVariables(); return hr; } STDMETHODIMP CDfsJunctionPoint :: Initialize ( IUnknown *i_piDfsRoot, BSTR i_szEntryPath, BOOL i_bReplicaSetExist, BSTR i_bstrReplicaSetDN ) { /*++ Routine Description: This initializes the junction point. Before this method is called the data stored by DfsJunctionPoint is NULL. If initialization fails the properties will be NULL. Arguments: i_szEntryPath - The the Entry Path to the Junction Point. --*/ RETURN_INVALIDARG_IF_NULL(i_piDfsRoot); RETURN_INVALIDARG_IF_NULL(i_szEntryPath); if ((IDfsRoot *)m_spiDfsRoot) m_spiDfsRoot.Release(); i_piDfsRoot->QueryInterface(IID_IDfsRoot, (void **)&m_spiDfsRoot); PDFS_INFO_3 pDfsInfo = NULL; NET_API_STATUS nRet = NetDfsGetInfo( i_szEntryPath, NULL, NULL, 3, (LPBYTE*) &pDfsInfo ); dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 3 for Link Initialization, nRet=%d\n"), i_szEntryPath, nRet)); if (NERR_Success != nRet) { if (NERR_DfsNoSuchVolume == nRet) return S_FALSE; // no such link else return HRESULT_FROM_WIN32(nRet); } HRESULT hr = _Init(pDfsInfo, i_bReplicaSetExist, i_bstrReplicaSetDN); NetApiBufferFree(pDfsInfo); return hr; } // Note: not all fields of pDfsInfo is filled in, e.g., comment/timeout are not filled in HRESULT VariantToDfsInfoLevel3(VARIANT *pVar, OUT PDFS_INFO_3 *ppDfsInfo) { *ppDfsInfo = NULL; if (V_VT(pVar) != (VT_ARRAY | VT_VARIANT)) return E_INVALIDARG; SAFEARRAY *psa_2 = V_ARRAY(pVar); long lLowerBound = 0; long lUpperBound = 0; long lCount = 0; if (!psa_2) return E_INVALIDARG; SafeArrayGetLBound(psa_2, 1, &lLowerBound ); SafeArrayGetUBound(psa_2, 1, &lUpperBound ); lCount = lUpperBound - lLowerBound + 1; if (lCount != ARRAY_COUNT_FOR_DFS_INFO_3) return E_INVALIDARG; HRESULT hr = S_OK; VARIANT HUGEP *pArray_2; SafeArrayAccessData(psa_2, (void HUGEP **) &pArray_2); do { if (V_VT(&(pArray_2[0])) != VT_BSTR || V_VT(&(pArray_2[1])) != (VT_ARRAY | VT_VARIANT)) { hr = E_INVALIDARG; break; } SAFEARRAY *psa_1 = V_ARRAY(&(pArray_2[1])); if (!psa_1) { lCount = 0; // empty root/link container } else { SafeArrayGetLBound(psa_1, 1, &lLowerBound ); SafeArrayGetUBound(psa_1, 1, &lUpperBound ); lCount = lUpperBound - lLowerBound + 1; } *ppDfsInfo = (PDFS_INFO_3)calloc( sizeof(DFS_INFO_3) + lCount * sizeof(DFS_STORAGE_INFO), 1); BREAK_OUTOFMEMORY_IF_NULL(*ppDfsInfo, &hr); LPDFS_STORAGE_INFO pStorage = (LPDFS_STORAGE_INFO)((BYTE*)*ppDfsInfo + sizeof(DFS_INFO_3)); (*ppDfsInfo)->EntryPath = pArray_2[0].bstrVal; (*ppDfsInfo)->NumberOfStorages = lCount; (*ppDfsInfo)->Storage = pStorage; VARIANT HUGEP *pArray_1; SafeArrayAccessData(psa_1, (void HUGEP **)&pArray_1); for (long i = 0; i < lCount; i++, pStorage++) { if (V_VT(&(pArray_1[i])) != (VT_ARRAY | VT_VARIANT)) { hr = E_INVALIDARG; break; } SAFEARRAY *psa_0 = V_ARRAY(&(pArray_1[i])); SafeArrayGetLBound(psa_0, 1, &lLowerBound ); SafeArrayGetUBound(psa_0, 1, &lUpperBound ); if (ARRAY_COUNT_FOR_DFS_STORAGE_INFO != (lUpperBound - lLowerBound + 1)) { hr = E_INVALIDARG; break; } VARIANT HUGEP *pArray_0; SafeArrayAccessData(psa_0, (void HUGEP **)&pArray_0); if (V_VT(&(pArray_0[0])) != VT_BSTR || V_VT(&(pArray_0[1])) != VT_BSTR || V_VT(&(pArray_0[2])) != VT_I4) { hr = E_INVALIDARG; } else { pStorage->ServerName = pArray_0[0].bstrVal; pStorage->ShareName = pArray_0[1].bstrVal; pStorage->State = pArray_0[2].lVal; } SafeArrayUnaccessData(psa_0); } SafeArrayUnaccessData(psa_1); } while (0); SafeArrayUnaccessData(psa_2); if (FAILED(hr) && *ppDfsInfo) free((void *)*ppDfsInfo); return hr; } STDMETHODIMP CDfsJunctionPoint :: InitializeEx ( IUnknown *piDfsRoot, VARIANT *pVar, BOOL bReplicaSetExist, BSTR bstrReplicaSetDN ) { RETURN_INVALIDARG_IF_NULL(piDfsRoot); RETURN_INVALIDARG_IF_NULL(pVar); if ((IDfsRoot *)m_spiDfsRoot) m_spiDfsRoot.Release(); piDfsRoot->QueryInterface(IID_IDfsRoot, (void **)&m_spiDfsRoot); PDFS_INFO_3 pDfsInfo = NULL; HRESULT hr = VariantToDfsInfoLevel3(pVar, &pDfsInfo); if (SUCCEEDED(hr)) { hr = _Init(pDfsInfo, bReplicaSetExist, bstrReplicaSetDN); free((void *)pDfsInfo); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get_CountOfDfsReplicas ( long* pVal ) { if (!pVal) return(E_INVALIDARG); *pVal = m_Replicas.size(); return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////// void CDfsJunctionPoint :: _FreeMemberVariables ( ) { m_bstrEntryPath.Empty(); m_bstrJunctionName.Empty(); m_bstrJunctionNameEx.Empty(); m_bstrReplicaSetDN.Empty(); m_bReplicaSetExist = FALSE; FreeReplicas(&m_Replicas); } ///////////////////////////////////////////////////////////////////////////////////////////////// HRESULT CDfsJunctionPoint :: _GetReplicaSetDN ( BSTR i_szEntryPath ) { // as an example, given an entry path \\dom\public\dir1\dir2 // set m_bstrReplicaSetDN to be: // "CN=public|dir1|dir2,CN=public,CN=DFS Volumes, // CN=File Replication Service,CN=System" CComBSTR bstrDfsName; // e.g., "public" HRESULT hr = GetUNCPathComponent(i_szEntryPath, &bstrDfsName, 3, 4); RETURN_IF_FAILED(hr); CComBSTR bstrDfsRootDN = _T("CN="); RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN); bstrDfsRootDN += bstrDfsName; RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN); bstrDfsRootDN += CN_DFSVOLUMES_PREFIX; RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN); hr = ExtendDNIfLongJunctionName(m_bstrJunctionNameEx, bstrDfsRootDN, &m_bstrReplicaSetDN); return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CDfsJunctionPoint :: get__NewEnum ( LPUNKNOWN* pVal ) { /*++ Routine Description: This property gets a new replica enumerator pointer. Arguments: pVal - Pointer in which the pointer to IEnumVARIANT pointer will be returned. --*/ if (!pVal) return E_INVALIDARG; *pVal = NULL; // Create a new ReplicaEnum object which implements IEnumVARIANT // and return the pointer to IEnumVARIANT. CComObject *pReplicaEnum = new CComObject(); if (!pReplicaEnum) return E_OUTOFMEMORY; // Initialize the enumerator with the list of replicas and the entrypath. HRESULT hr = pReplicaEnum->Initialize(&m_Replicas, m_bstrEntryPath); // Get the enumerator pointer. if (SUCCEEDED(hr)) hr = pReplicaEnum->QueryInterface(IID_IEnumVARIANT, (void **)pVal); if (FAILED(hr)) { delete pReplicaEnum; return hr; } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// // AddReplica HRESULT CDfsJunctionPoint::_AddToReplicaList(BSTR bstrServerName, BSTR bstrShareName, long lDfsStorageState) { REPLICAINFO* pDfsReplica = new REPLICAINFO; RETURN_OUTOFMEMORY_IF_NULL(pDfsReplica); HRESULT hr = pDfsReplica->Init(bstrServerName, bstrShareName, lDfsStorageState); if (FAILED(hr)) { delete pDfsReplica; return hr; } m_Replicas.push_back(pDfsReplica); return S_OK; } void CDfsJunctionPoint::_DeleteFromReplicaList(BSTR bstrServerName, BSTR bstrShareName) { for (REPLICAINFOLIST::iterator i = m_Replicas.begin(); i != m_Replicas.end(); i++) { if (0 == lstrcmpi(bstrServerName, (*i)->m_bstrServerName) && 0 == lstrcmpi(bstrShareName, (*i)->m_bstrShareName)) { delete (*i); m_Replicas.erase(i); break; } } } HRESULT CDfsJunctionPoint::_GetDfsStorageState ( BSTR i_szServerName, BSTR i_szShareName, long* o_pVal ) { if (!i_szServerName || !i_szShareName || !o_pVal) return E_INVALIDARG; *o_pVal = DFS_STORAGE_STATE_OFFLINE; PDFS_INFO_3 pDfsInfo = NULL; NET_API_STATUS nstatRetVal = NetDfsGetInfo ( m_bstrEntryPath, i_szServerName, i_szShareName, 3, (LPBYTE*)&pDfsInfo ); dfsDebugOut((_T("NetDfsGetInfo entry=%s, server=%s, share=%s, level 3 for State, nRet=%d\n"), m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal)); if (nstatRetVal != NERR_Success) { if (nstatRetVal == NERR_DfsNoSuchVolume) return S_FALSE; else return HRESULT_FROM_WIN32 (nstatRetVal); } BOOL bFound = FALSE; LPDFS_STORAGE_INFO pStorageInfo = pDfsInfo->Storage; for (UINT i=0; i < pDfsInfo->NumberOfStorages; i++, pStorageInfo++) { if ( !lstrcmpi(pStorageInfo->ServerName, i_szServerName) && !lstrcmpi(pStorageInfo->ShareName, i_szShareName) ) { bFound = TRUE; *o_pVal = pStorageInfo->State; break; } } NetApiBufferFree(pDfsInfo); return (bFound ? S_OK : S_FALSE); } STDMETHODIMP CDfsJunctionPoint :: AddReplica ( BSTR i_szServerName, BSTR i_szShareName, VARIANT* o_pvarReplicaObject ) { /*++ Routine Description: This method adds a Replica to an existing Junction Point. Arguments: i_szServerName - The name of the server which hosts the share that the junction point should point to. i_szShareName - The name of the share that the junction point should point to. o_pvarReplicaObject - The Newly Created Replica's Object is returned here. --*/ if (!i_szServerName || !i_szShareName || !o_pvarReplicaObject) return E_INVALIDARG; HRESULT hr = S_OK; long lDfsStorageState = DFS_STORAGE_STATE_OFFLINE; NET_API_STATUS nstatRetVal = NetDfsAdd ( m_bstrEntryPath, i_szServerName, i_szShareName, NULL, DFS_RESTORE_VOLUME ); dfsDebugOut((_T("NetDfsAdd entry=%s, server=%s, share=%s, DFS_RESTORE_VOLUME, nRet=%d\n"), m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal)); if (NERR_Success != nstatRetVal) { return HRESULT_FROM_WIN32 (nstatRetVal); } else { hr = _GetDfsStorageState(i_szServerName, i_szShareName, &lDfsStorageState); if (S_OK != hr) { // something is wrong, we failed to find the target we just added return E_FAIL; } } // Gets the IReplica interface pointer. IDfsReplica* pIReplicaPtr = NULL; hr = CoCreateInstance(CLSID_DfsReplica, NULL, CLSCTX_INPROC_SERVER, IID_IDfsReplica, (void **)&pIReplicaPtr); RETURN_IF_FAILED(hr); // Initialize the replica object. hr = pIReplicaPtr->Initialize( m_bstrEntryPath, i_szServerName, i_szShareName, lDfsStorageState ); if (SUCCEEDED(hr)) hr = _AddToReplicaList(i_szServerName, i_szShareName, lDfsStorageState); if (SUCCEEDED(hr)) { o_pvarReplicaObject->vt = VT_DISPATCH; o_pvarReplicaObject->pdispVal = (IDispatch*)pIReplicaPtr; } else { pIReplicaPtr->Release(); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////// // RemoveReplica STDMETHODIMP CDfsJunctionPoint :: RemoveReplica ( BSTR i_szServerName, BSTR i_szShareName ) { /*++ Routine Description: This method removes a replica for the Junction point. Arguments: i_szServerName - The name of the server hosting the share that the replica is representing. i_szShareName - The name of the share that the replica is representing --*/ if (!i_szServerName || !i_szShareName) return E_INVALIDARG; NET_API_STATUS nstatRetVal = NetDfsRemove( m_bstrEntryPath, i_szServerName, i_szShareName ); dfsDebugOut((_T("NetDfsRemove entrypath=%s, server=%s, share=%s, nRet=%d\n"), m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal)); if (ERROR_NOT_FOUND == nstatRetVal) nstatRetVal = NERR_Success; if (NERR_Success == nstatRetVal) _DeleteFromReplicaList(i_szServerName, i_szShareName); return HRESULT_FROM_WIN32 (nstatRetVal); } STDMETHODIMP CDfsJunctionPoint::RemoveAllReplicas() { /*++ Routine Description: This method deletes the Junction point. --*/ if (m_Replicas.empty()) return S_OK; // // DFS DCR: allow link deletion happen at once // NET_API_STATUS nstatRetVal = NetDfsRemove( m_bstrEntryPath, NULL, NULL ); dfsDebugOut((_T("NetDfsRemove at once entrypath=%s, nRet=%d\n"), m_bstrEntryPath, nstatRetVal)); if (ERROR_NOT_FOUND == nstatRetVal) nstatRetVal = NERR_Success; if (NERR_Success == nstatRetVal) FreeReplicas(&m_Replicas); return HRESULT_FROM_WIN32 (nstatRetVal); } ///////////////////////////////////////////////////////////////////////////////////////////////// // DeleteRootReplica STDMETHODIMP CDfsJunctionPoint::DeleteRootReplica ( BSTR i_bstrDomainName, BSTR i_bstrDfsName, BSTR i_bstrServerName, BSTR i_bstrShareName, BOOL i_bForce ) { RETURN_INVALIDARG_IF_TRUE(!i_bstrServerName || !*i_bstrServerName); RETURN_INVALIDARG_IF_TRUE(!i_bstrShareName || !*i_bstrShareName); NET_API_STATUS nStatus = NERR_Success; if (!i_bstrDfsName || !*i_bstrDfsName) // standalone Dfs { nStatus = NetDfsRemoveStdRoot( i_bstrServerName, i_bstrShareName, 0 // No Flags. ); dfsDebugOut((_T("NetDfsRemoveStdRoot server=%s, share=%s, nRet=%d\n"), i_bstrServerName, i_bstrShareName, nStatus)); } else { if (!i_bForce) { nStatus = NetDfsRemoveFtRoot( i_bstrServerName, i_bstrShareName, i_bstrDfsName, 0 // No Flags. ); dfsDebugOut((_T("NetDfsRemoveFtRoot server=%s, share=%s, DfsName=%s, nRet=%d\n"), i_bstrServerName, i_bstrShareName, i_bstrDfsName, nStatus)); } else { nStatus = NetDfsRemoveFtRootForced( i_bstrDomainName, i_bstrServerName, i_bstrShareName, i_bstrDfsName, 0 // No Flags. ); dfsDebugOut((_T("NetDfsRemoveFtRootForced domain=%s, server=%s, share=%s, DfsName=%s, nRet=%d\n"), i_bstrDomainName, i_bstrServerName, i_bstrShareName, i_bstrDfsName, nStatus)); } } if (NERR_Success == nStatus) _DeleteFromReplicaList(i_bstrServerName, i_bstrShareName); return HRESULT_FROM_WIN32(nStatus); } ///////////////////////////////////////////////////////////////////////////////////////////////// // GetOneRootReplica // always return the first entry in the m_Replicas list. STDMETHODIMP CDfsJunctionPoint::GetOneRootReplica ( OUT BSTR* o_pbstrServerName, OUT BSTR* o_pbstrShareName ) { RETURN_INVALIDARG_IF_NULL(o_pbstrServerName); RETURN_INVALIDARG_IF_NULL(o_pbstrShareName); *o_pbstrServerName = NULL; *o_pbstrShareName = NULL; if (m_Replicas.empty()) return E_INVALIDARG; REPLICAINFOLIST::iterator i = m_Replicas.begin(); *o_pbstrServerName = SysAllocString((*i)->m_bstrServerName); RETURN_OUTOFMEMORY_IF_NULL(*o_pbstrServerName); *o_pbstrShareName = SysAllocString((*i)->m_bstrShareName); if (!*o_pbstrShareName) { SysFreeString(*o_pbstrServerName); *o_pbstrServerName = NULL; return E_OUTOFMEMORY; } return S_OK; }