Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1040 lines
27 KiB

/*++
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 <dsgetdc.h>
/////////////////////////////////////////////////////////////////////////////////////////////////
// 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<CReplicaEnum> *pReplicaEnum = new CComObject<CReplicaEnum>();
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;
}