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

  1. /*++
  2. Module Name:
  3. DfsJP.cpp
  4. Abstract:
  5. This COM Class provides method to get information of Dfs
  6. Junction Points and to enumerate replica of a junction point.
  7. --*/
  8. #include "stdafx.h"
  9. #include "DfsCore.h"
  10. #include "DfsJP.h"
  11. #include "DfsRep.h"
  12. #include "JPEnum.h"
  13. #include "RepEnum.h"
  14. #include "netutils.h"
  15. #include "ldaputils.h"
  16. #include <dsgetdc.h>
  17. /////////////////////////////////////////////////////////////////////////////////////////////////
  18. // CDfsJuntionPoint
  19. /////////////////////////////////////////////////////////////////////////////////////////////////
  20. CDfsJunctionPoint :: CDfsJunctionPoint ()
  21. {
  22. dfsDebugOut((_T("CDfsJunctionPoint::CDfsJunctionPoint this=%p\n"), this));
  23. }
  24. /////////////////////////////////////////////////////////////////////////////////////////////////
  25. CDfsJunctionPoint :: ~CDfsJunctionPoint ()
  26. {
  27. _FreeMemberVariables();
  28. dfsDebugOut((_T("CDfsJunctionPoint::~CDfsJunctionPoint this=%p\n"), this));
  29. }
  30. /////////////////////////////////////////////////////////////////////////////////////////////////
  31. STDMETHODIMP CDfsJunctionPoint :: get_State
  32. (
  33. long* pVal
  34. )
  35. {
  36. return E_NOTIMPL;
  37. }
  38. /////////////////////////////////////////////////////////////////////////////////////////////////
  39. STDMETHODIMP CDfsJunctionPoint :: get_EntryPath
  40. (
  41. BSTR* pVal
  42. )
  43. {
  44. if (!pVal)
  45. return E_INVALIDARG;
  46. *pVal = m_bstrEntryPath.Copy ();
  47. if (!*pVal)
  48. return E_OUTOFMEMORY;
  49. return S_OK;
  50. }
  51. /////////////////////////////////////////////////////////////////////////////////////////////////
  52. STDMETHODIMP CDfsJunctionPoint :: get_JunctionName
  53. (
  54. BOOL i_bDfsNameIncluded,
  55. BSTR* pVal
  56. )
  57. {
  58. if (!pVal)
  59. return E_INVALIDARG;
  60. if (i_bDfsNameIncluded)
  61. *pVal = m_bstrJunctionNameEx.Copy ();
  62. else
  63. *pVal = m_bstrJunctionName.Copy ();
  64. if (!*pVal)
  65. return E_OUTOFMEMORY;
  66. return S_OK;
  67. }
  68. /////////////////////////////////////////////////////////////////////////////////////////////////
  69. STDMETHODIMP CDfsJunctionPoint :: get_Comment
  70. (
  71. BSTR* pVal
  72. )
  73. {
  74. if (!pVal)
  75. return E_INVALIDARG;
  76. DFS_INFO_100* pInfoBuffer = NULL;
  77. NET_API_STATUS nRet = NetDfsGetInfo(
  78. m_bstrEntryPath,
  79. NULL,
  80. NULL,
  81. 100,
  82. (LPBYTE*)&pInfoBuffer
  83. );
  84. dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 100 for comment, nRet=%d\n"),
  85. m_bstrEntryPath, nRet));
  86. if (NERR_Success == nRet)
  87. {
  88. *pVal = SysAllocString(pInfoBuffer->Comment);
  89. NetApiBufferFree(pInfoBuffer);
  90. if (!*pVal)
  91. return E_OUTOFMEMORY;
  92. }
  93. return HRESULT_FROM_WIN32(nRet);
  94. }
  95. /////////////////////////////////////////////////////////////////////////////////////////////////
  96. STDMETHODIMP CDfsJunctionPoint :: put_Comment
  97. (
  98. BSTR newVal
  99. )
  100. {
  101. DFS_INFO_100 InfoBuffer = {(newVal ? newVal : _T(""))};
  102. NET_API_STATUS nRet = NetDfsSetInfo (
  103. m_bstrEntryPath,
  104. NULL,
  105. NULL,
  106. 100,
  107. (LPBYTE) &InfoBuffer
  108. );
  109. dfsDebugOut((_T("NetDfsSetInfo entry=%s, level 100 for comment, nRet=%d\n"),
  110. m_bstrEntryPath, nRet));
  111. return HRESULT_FROM_WIN32(nRet);
  112. }
  113. /////////////////////////////////////////////////////////////////////////////
  114. // get_Timeout
  115. STDMETHODIMP CDfsJunctionPoint :: get_Timeout
  116. (
  117. long* pVal
  118. )
  119. {
  120. if (!pVal || !m_bstrEntryPath)
  121. return E_INVALIDARG;
  122. DFS_INFO_4* pInfoBuffer = NULL;
  123. NET_API_STATUS nRet = NetDfsGetInfo(
  124. m_bstrEntryPath,
  125. NULL,
  126. NULL,
  127. 4,
  128. (LPBYTE*)&pInfoBuffer
  129. );
  130. dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 4 for Timeout, nRet=%d\n"),
  131. m_bstrEntryPath, nRet));
  132. if (NERR_Success == nRet)
  133. {
  134. *pVal = pInfoBuffer->Timeout;
  135. NetApiBufferFree(pInfoBuffer);
  136. }
  137. return HRESULT_FROM_WIN32(nRet);
  138. }
  139. /////////////////////////////////////////////////////////////////////////////
  140. // put_Timeout
  141. STDMETHODIMP CDfsJunctionPoint :: put_Timeout
  142. (
  143. long newVal
  144. )
  145. {
  146. if (!m_bstrEntryPath)
  147. return E_INVALIDARG;
  148. DFS_INFO_102 DfsInfoLevel102 = {newVal};
  149. NET_API_STATUS nRet = NetDfsSetInfo (
  150. m_bstrEntryPath,
  151. NULL,
  152. NULL,
  153. 102,
  154. (LPBYTE) &DfsInfoLevel102
  155. );
  156. dfsDebugOut((_T("NetDfsSetInfo entry=%s, level 102 for Timeout, nRet=%d\n"),
  157. m_bstrEntryPath, nRet));
  158. return HRESULT_FROM_WIN32(nRet);
  159. }
  160. /////////////////////////////////////////////////////////////////////////////////////////////////
  161. STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetDN
  162. (
  163. BSTR* pVal
  164. )
  165. {
  166. if (!pVal)
  167. return E_INVALIDARG;
  168. if (!m_bstrEntryPath)
  169. return E_INVALIDARG;
  170. HRESULT hr = S_OK;
  171. if (!m_bstrReplicaSetDN)
  172. {
  173. hr = _GetReplicaSetDN(m_bstrEntryPath);
  174. RETURN_IF_FAILED(hr);
  175. }
  176. *pVal = m_bstrReplicaSetDN.Copy ();
  177. if (!*pVal)
  178. return E_OUTOFMEMORY;
  179. return S_OK;
  180. }
  181. /////////////////////////////////////////////////////////////////////////////////////////////////
  182. STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetExist
  183. (
  184. BOOL* pVal
  185. )
  186. {
  187. if (!pVal)
  188. return E_INVALIDARG;
  189. if (!m_bstrEntryPath)
  190. return E_INVALIDARG;
  191. *pVal = m_bReplicaSetExist;
  192. return S_OK;
  193. }
  194. STDMETHODIMP CDfsJunctionPoint :: get_ReplicaSetExistEx
  195. (
  196. BSTR* o_pbstrDC,
  197. BOOL* pVal
  198. )
  199. {
  200. if (!pVal || !o_pbstrDC)
  201. return E_INVALIDARG;
  202. if (!m_bstrEntryPath)
  203. return E_INVALIDARG;
  204. HRESULT hr = S_OK;
  205. if (!m_bstrReplicaSetDN)
  206. {
  207. hr = _GetReplicaSetDN(m_bstrEntryPath);
  208. RETURN_IF_FAILED(hr);
  209. }
  210. DFS_TYPE dwDfsType = DFS_TYPE_UNASSIGNED;
  211. CComBSTR bstrDomainName;
  212. CComBSTR bstrDomainDN;
  213. hr = _GetDfsType(&dwDfsType, &bstrDomainName, &bstrDomainDN);
  214. RETURN_IF_FAILED(hr);
  215. m_bReplicaSetExist = FALSE;
  216. if (dwDfsType == DFS_TYPE_FTDFS)
  217. {
  218. CComBSTR bstrDN = m_bstrReplicaSetDN;
  219. if ((BSTR)bstrDN) bstrDN += _T(",");
  220. if ((BSTR)bstrDN) bstrDN += bstrDomainDN;
  221. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDN);
  222. PLDAP pldap = NULL;
  223. CComBSTR bstrDC;
  224. hr = ConnectToDS(bstrDomainName, &pldap, &bstrDC);
  225. if (SUCCEEDED(hr))
  226. {
  227. m_bReplicaSetExist = (S_OK == IsValidObject(pldap, bstrDN));
  228. CloseConnectionToDS(pldap);
  229. *o_pbstrDC = bstrDC.Copy();
  230. if (!*o_pbstrDC)
  231. hr = E_OUTOFMEMORY;
  232. }
  233. }
  234. *pVal = m_bReplicaSetExist;
  235. return hr;
  236. }
  237. HRESULT CDfsJunctionPoint :: _GetDfsType(
  238. OUT DFS_TYPE* o_pdwDfsType,
  239. OUT BSTR* o_pbstrDomainName,
  240. OUT BSTR* o_pbstrDomainDN
  241. )
  242. {
  243. if (!o_pdwDfsType)
  244. return E_INVALIDARG;
  245. if (!m_spiDfsRoot)
  246. return E_INVALIDARG;
  247. HRESULT hr = S_OK;
  248. m_spiDfsRoot->get_DfsType((long *)o_pdwDfsType);
  249. if (*o_pdwDfsType == DFS_TYPE_FTDFS)
  250. {
  251. if (o_pbstrDomainName)
  252. hr = m_spiDfsRoot->get_DomainName(o_pbstrDomainName);
  253. if (SUCCEEDED(hr) && o_pbstrDomainDN)
  254. hr = m_spiDfsRoot->get_DomainDN(o_pbstrDomainDN);
  255. }
  256. return hr;
  257. }
  258. STDMETHODIMP CDfsJunctionPoint :: put_ReplicaSetExist
  259. (
  260. BOOL newVal
  261. )
  262. {
  263. if (!m_bstrEntryPath)
  264. return E_INVALIDARG;
  265. m_bReplicaSetExist = newVal;
  266. return S_OK;
  267. }
  268. /////////////////////////////////////////////////////////////////////////////////////////////////
  269. HRESULT CDfsJunctionPoint::_Init(
  270. PDFS_INFO_3 pDfsInfo,
  271. BOOL bReplicaSetExist,
  272. BSTR bstrReplicaSetDN
  273. )
  274. {
  275. _FreeMemberVariables();
  276. if (bReplicaSetExist && (!bstrReplicaSetDN || !*bstrReplicaSetDN))
  277. return E_INVALIDARG;
  278. HRESULT hr = S_OK;
  279. do {
  280. m_bstrEntryPath = pDfsInfo->EntryPath;
  281. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrEntryPath, &hr);
  282. hr = GetUNCPathComponent(m_bstrEntryPath, &m_bstrJunctionName, 4, 0);
  283. BREAK_IF_FAILED(hr);
  284. hr = GetUNCPathComponent(m_bstrEntryPath, &m_bstrJunctionNameEx, 3, 0);
  285. BREAK_IF_FAILED(hr);
  286. PDFS_STORAGE_INFO pStorage = pDfsInfo->Storage;
  287. for (DWORD i = 0; i < pDfsInfo->NumberOfStorages && pStorage; i++, pStorage++)
  288. {
  289. hr = _AddToReplicaList(pStorage->ServerName, pStorage->ShareName, pStorage->State);
  290. BREAK_IF_FAILED(hr);
  291. }
  292. m_bReplicaSetExist = bReplicaSetExist;
  293. if (m_bReplicaSetExist)
  294. {
  295. m_bstrReplicaSetDN = bstrReplicaSetDN;
  296. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrReplicaSetDN, &hr);
  297. }
  298. } while (0);
  299. if (FAILED(hr))
  300. _FreeMemberVariables();
  301. return hr;
  302. }
  303. STDMETHODIMP CDfsJunctionPoint :: Initialize
  304. (
  305. IUnknown *i_piDfsRoot,
  306. BSTR i_szEntryPath,
  307. BOOL i_bReplicaSetExist,
  308. BSTR i_bstrReplicaSetDN
  309. )
  310. {
  311. /*++
  312. Routine Description:
  313. This initializes the junction point. Before this method is called the
  314. data stored by DfsJunctionPoint is NULL. If initialization fails the
  315. properties will be NULL.
  316. Arguments:
  317. i_szEntryPath - The the Entry Path to the Junction Point.
  318. --*/
  319. RETURN_INVALIDARG_IF_NULL(i_piDfsRoot);
  320. RETURN_INVALIDARG_IF_NULL(i_szEntryPath);
  321. if ((IDfsRoot *)m_spiDfsRoot)
  322. m_spiDfsRoot.Release();
  323. i_piDfsRoot->QueryInterface(IID_IDfsRoot, (void **)&m_spiDfsRoot);
  324. PDFS_INFO_3 pDfsInfo = NULL;
  325. NET_API_STATUS nRet = NetDfsGetInfo(
  326. i_szEntryPath,
  327. NULL,
  328. NULL,
  329. 3,
  330. (LPBYTE*) &pDfsInfo
  331. );
  332. dfsDebugOut((_T("NetDfsGetInfo entry=%s, level 3 for Link Initialization, nRet=%d\n"),
  333. i_szEntryPath, nRet));
  334. if (NERR_Success != nRet)
  335. {
  336. if (NERR_DfsNoSuchVolume == nRet)
  337. return S_FALSE; // no such link
  338. else
  339. return HRESULT_FROM_WIN32(nRet);
  340. }
  341. HRESULT hr = _Init(pDfsInfo, i_bReplicaSetExist, i_bstrReplicaSetDN);
  342. NetApiBufferFree(pDfsInfo);
  343. return hr;
  344. }
  345. // Note: not all fields of pDfsInfo is filled in, e.g., comment/timeout are not filled in
  346. HRESULT VariantToDfsInfoLevel3(VARIANT *pVar, OUT PDFS_INFO_3 *ppDfsInfo)
  347. {
  348. *ppDfsInfo = NULL;
  349. if (V_VT(pVar) != (VT_ARRAY | VT_VARIANT))
  350. return E_INVALIDARG;
  351. SAFEARRAY *psa_2 = V_ARRAY(pVar);
  352. long lLowerBound = 0;
  353. long lUpperBound = 0;
  354. long lCount = 0;
  355. if (!psa_2)
  356. return E_INVALIDARG;
  357. SafeArrayGetLBound(psa_2, 1, &lLowerBound );
  358. SafeArrayGetUBound(psa_2, 1, &lUpperBound );
  359. lCount = lUpperBound - lLowerBound + 1;
  360. if (lCount != ARRAY_COUNT_FOR_DFS_INFO_3)
  361. return E_INVALIDARG;
  362. HRESULT hr = S_OK;
  363. VARIANT HUGEP *pArray_2;
  364. SafeArrayAccessData(psa_2, (void HUGEP **) &pArray_2);
  365. do {
  366. if (V_VT(&(pArray_2[0])) != VT_BSTR ||
  367. V_VT(&(pArray_2[1])) != (VT_ARRAY | VT_VARIANT))
  368. {
  369. hr = E_INVALIDARG;
  370. break;
  371. }
  372. SAFEARRAY *psa_1 = V_ARRAY(&(pArray_2[1]));
  373. if (!psa_1)
  374. {
  375. lCount = 0; // empty root/link container
  376. } else
  377. {
  378. SafeArrayGetLBound(psa_1, 1, &lLowerBound );
  379. SafeArrayGetUBound(psa_1, 1, &lUpperBound );
  380. lCount = lUpperBound - lLowerBound + 1;
  381. }
  382. *ppDfsInfo = (PDFS_INFO_3)calloc(
  383. sizeof(DFS_INFO_3) + lCount * sizeof(DFS_STORAGE_INFO),
  384. 1);
  385. BREAK_OUTOFMEMORY_IF_NULL(*ppDfsInfo, &hr);
  386. LPDFS_STORAGE_INFO pStorage = (LPDFS_STORAGE_INFO)((BYTE*)*ppDfsInfo + sizeof(DFS_INFO_3));
  387. (*ppDfsInfo)->EntryPath = pArray_2[0].bstrVal;
  388. (*ppDfsInfo)->NumberOfStorages = lCount;
  389. (*ppDfsInfo)->Storage = pStorage;
  390. VARIANT HUGEP *pArray_1;
  391. SafeArrayAccessData(psa_1, (void HUGEP **)&pArray_1);
  392. for (long i = 0; i < lCount; i++, pStorage++)
  393. {
  394. if (V_VT(&(pArray_1[i])) != (VT_ARRAY | VT_VARIANT))
  395. {
  396. hr = E_INVALIDARG;
  397. break;
  398. }
  399. SAFEARRAY *psa_0 = V_ARRAY(&(pArray_1[i]));
  400. SafeArrayGetLBound(psa_0, 1, &lLowerBound );
  401. SafeArrayGetUBound(psa_0, 1, &lUpperBound );
  402. if (ARRAY_COUNT_FOR_DFS_STORAGE_INFO != (lUpperBound - lLowerBound + 1))
  403. {
  404. hr = E_INVALIDARG;
  405. break;
  406. }
  407. VARIANT HUGEP *pArray_0;
  408. SafeArrayAccessData(psa_0, (void HUGEP **)&pArray_0);
  409. if (V_VT(&(pArray_0[0])) != VT_BSTR ||
  410. V_VT(&(pArray_0[1])) != VT_BSTR ||
  411. V_VT(&(pArray_0[2])) != VT_I4)
  412. {
  413. hr = E_INVALIDARG;
  414. } else
  415. {
  416. pStorage->ServerName = pArray_0[0].bstrVal;
  417. pStorage->ShareName = pArray_0[1].bstrVal;
  418. pStorage->State = pArray_0[2].lVal;
  419. }
  420. SafeArrayUnaccessData(psa_0);
  421. }
  422. SafeArrayUnaccessData(psa_1);
  423. } while (0);
  424. SafeArrayUnaccessData(psa_2);
  425. if (FAILED(hr) && *ppDfsInfo)
  426. free((void *)*ppDfsInfo);
  427. return hr;
  428. }
  429. STDMETHODIMP CDfsJunctionPoint :: InitializeEx
  430. (
  431. IUnknown *piDfsRoot,
  432. VARIANT *pVar,
  433. BOOL bReplicaSetExist,
  434. BSTR bstrReplicaSetDN
  435. )
  436. {
  437. RETURN_INVALIDARG_IF_NULL(piDfsRoot);
  438. RETURN_INVALIDARG_IF_NULL(pVar);
  439. if ((IDfsRoot *)m_spiDfsRoot)
  440. m_spiDfsRoot.Release();
  441. piDfsRoot->QueryInterface(IID_IDfsRoot, (void **)&m_spiDfsRoot);
  442. PDFS_INFO_3 pDfsInfo = NULL;
  443. HRESULT hr = VariantToDfsInfoLevel3(pVar, &pDfsInfo);
  444. if (SUCCEEDED(hr))
  445. {
  446. hr = _Init(pDfsInfo, bReplicaSetExist, bstrReplicaSetDN);
  447. free((void *)pDfsInfo);
  448. }
  449. return hr;
  450. }
  451. /////////////////////////////////////////////////////////////////////////////////////////////////
  452. STDMETHODIMP CDfsJunctionPoint :: get_CountOfDfsReplicas
  453. (
  454. long* pVal
  455. )
  456. {
  457. if (!pVal)
  458. return(E_INVALIDARG);
  459. *pVal = m_Replicas.size();
  460. return S_OK;
  461. }
  462. /////////////////////////////////////////////////////////////////////////////////////////////////
  463. void CDfsJunctionPoint :: _FreeMemberVariables
  464. (
  465. )
  466. {
  467. m_bstrEntryPath.Empty();
  468. m_bstrJunctionName.Empty();
  469. m_bstrJunctionNameEx.Empty();
  470. m_bstrReplicaSetDN.Empty();
  471. m_bReplicaSetExist = FALSE;
  472. FreeReplicas(&m_Replicas);
  473. }
  474. /////////////////////////////////////////////////////////////////////////////////////////////////
  475. HRESULT CDfsJunctionPoint :: _GetReplicaSetDN
  476. (
  477. BSTR i_szEntryPath
  478. )
  479. {
  480. // as an example, given an entry path \\dom\public\dir1\dir2
  481. // set m_bstrReplicaSetDN to be:
  482. // "CN=public|dir1|dir2,CN=public,CN=DFS Volumes,
  483. // CN=File Replication Service,CN=System"
  484. CComBSTR bstrDfsName; // e.g., "public"
  485. HRESULT hr = GetUNCPathComponent(i_szEntryPath, &bstrDfsName, 3, 4);
  486. RETURN_IF_FAILED(hr);
  487. CComBSTR bstrDfsRootDN = _T("CN=");
  488. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN);
  489. bstrDfsRootDN += bstrDfsName;
  490. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN);
  491. bstrDfsRootDN += CN_DFSVOLUMES_PREFIX;
  492. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrDfsRootDN);
  493. hr = ExtendDNIfLongJunctionName(m_bstrJunctionNameEx, bstrDfsRootDN, &m_bstrReplicaSetDN);
  494. return hr;
  495. }
  496. /////////////////////////////////////////////////////////////////////////////////////////////////
  497. STDMETHODIMP CDfsJunctionPoint :: get__NewEnum
  498. (
  499. LPUNKNOWN* pVal
  500. )
  501. {
  502. /*++
  503. Routine Description:
  504. This property gets a new replica enumerator pointer.
  505. Arguments:
  506. pVal - Pointer in which the pointer to IEnumVARIANT pointer will be returned.
  507. --*/
  508. if (!pVal)
  509. return E_INVALIDARG;
  510. *pVal = NULL;
  511. // Create a new ReplicaEnum object which implements IEnumVARIANT
  512. // and return the pointer to IEnumVARIANT.
  513. CComObject<CReplicaEnum> *pReplicaEnum = new CComObject<CReplicaEnum>();
  514. if (!pReplicaEnum)
  515. return E_OUTOFMEMORY;
  516. // Initialize the enumerator with the list of replicas and the entrypath.
  517. HRESULT hr = pReplicaEnum->Initialize(&m_Replicas, m_bstrEntryPath);
  518. // Get the enumerator pointer.
  519. if (SUCCEEDED(hr))
  520. hr = pReplicaEnum->QueryInterface(IID_IEnumVARIANT, (void **)pVal);
  521. if (FAILED(hr))
  522. {
  523. delete pReplicaEnum;
  524. return hr;
  525. }
  526. return hr;
  527. }
  528. /////////////////////////////////////////////////////////////////////////////////////////////////
  529. /////////////////////////////////////////////////////////////////////////////////////////////////
  530. // AddReplica
  531. HRESULT CDfsJunctionPoint::_AddToReplicaList(BSTR bstrServerName, BSTR bstrShareName, long lDfsStorageState)
  532. {
  533. REPLICAINFO* pDfsReplica = new REPLICAINFO;
  534. RETURN_OUTOFMEMORY_IF_NULL(pDfsReplica);
  535. HRESULT hr = pDfsReplica->Init(bstrServerName, bstrShareName, lDfsStorageState);
  536. if (FAILED(hr))
  537. {
  538. delete pDfsReplica;
  539. return hr;
  540. }
  541. m_Replicas.push_back(pDfsReplica);
  542. return S_OK;
  543. }
  544. void CDfsJunctionPoint::_DeleteFromReplicaList(BSTR bstrServerName, BSTR bstrShareName)
  545. {
  546. for (REPLICAINFOLIST::iterator i = m_Replicas.begin(); i != m_Replicas.end(); i++)
  547. {
  548. if (0 == lstrcmpi(bstrServerName, (*i)->m_bstrServerName) &&
  549. 0 == lstrcmpi(bstrShareName, (*i)->m_bstrShareName))
  550. {
  551. delete (*i);
  552. m_Replicas.erase(i);
  553. break;
  554. }
  555. }
  556. }
  557. HRESULT CDfsJunctionPoint::_GetDfsStorageState
  558. (
  559. BSTR i_szServerName,
  560. BSTR i_szShareName,
  561. long* o_pVal
  562. )
  563. {
  564. if (!i_szServerName || !i_szShareName || !o_pVal)
  565. return E_INVALIDARG;
  566. *o_pVal = DFS_STORAGE_STATE_OFFLINE;
  567. PDFS_INFO_3 pDfsInfo = NULL;
  568. NET_API_STATUS nstatRetVal = NetDfsGetInfo (
  569. m_bstrEntryPath,
  570. i_szServerName,
  571. i_szShareName,
  572. 3,
  573. (LPBYTE*)&pDfsInfo
  574. );
  575. dfsDebugOut((_T("NetDfsGetInfo entry=%s, server=%s, share=%s, level 3 for State, nRet=%d\n"),
  576. m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal));
  577. if (nstatRetVal != NERR_Success)
  578. {
  579. if (nstatRetVal == NERR_DfsNoSuchVolume)
  580. return S_FALSE;
  581. else
  582. return HRESULT_FROM_WIN32 (nstatRetVal);
  583. }
  584. BOOL bFound = FALSE;
  585. LPDFS_STORAGE_INFO pStorageInfo = pDfsInfo->Storage;
  586. for (UINT i=0; i < pDfsInfo->NumberOfStorages; i++, pStorageInfo++)
  587. {
  588. if ( !lstrcmpi(pStorageInfo->ServerName, i_szServerName) &&
  589. !lstrcmpi(pStorageInfo->ShareName, i_szShareName) )
  590. {
  591. bFound = TRUE;
  592. *o_pVal = pStorageInfo->State;
  593. break;
  594. }
  595. }
  596. NetApiBufferFree(pDfsInfo);
  597. return (bFound ? S_OK : S_FALSE);
  598. }
  599. STDMETHODIMP CDfsJunctionPoint :: AddReplica
  600. (
  601. BSTR i_szServerName,
  602. BSTR i_szShareName,
  603. VARIANT* o_pvarReplicaObject
  604. )
  605. {
  606. /*++
  607. Routine Description:
  608. This method adds a Replica to an existing Junction Point.
  609. Arguments:
  610. i_szServerName - The name of the server which hosts the share that the junction point should point to.
  611. i_szShareName - The name of the share that the junction point should point to.
  612. o_pvarReplicaObject - The Newly Created Replica's Object is returned here.
  613. --*/
  614. if (!i_szServerName || !i_szShareName || !o_pvarReplicaObject)
  615. return E_INVALIDARG;
  616. HRESULT hr = S_OK;
  617. long lDfsStorageState = DFS_STORAGE_STATE_OFFLINE;
  618. NET_API_STATUS nstatRetVal = NetDfsAdd (
  619. m_bstrEntryPath,
  620. i_szServerName,
  621. i_szShareName,
  622. NULL,
  623. DFS_RESTORE_VOLUME
  624. );
  625. dfsDebugOut((_T("NetDfsAdd entry=%s, server=%s, share=%s, DFS_RESTORE_VOLUME, nRet=%d\n"),
  626. m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal));
  627. if (NERR_Success != nstatRetVal)
  628. {
  629. return HRESULT_FROM_WIN32 (nstatRetVal);
  630. } else
  631. {
  632. hr = _GetDfsStorageState(i_szServerName, i_szShareName, &lDfsStorageState);
  633. if (S_OK != hr)
  634. {
  635. // something is wrong, we failed to find the target we just added
  636. return E_FAIL;
  637. }
  638. }
  639. // Gets the IReplica interface pointer.
  640. IDfsReplica* pIReplicaPtr = NULL;
  641. hr = CoCreateInstance(CLSID_DfsReplica, NULL, CLSCTX_INPROC_SERVER,
  642. IID_IDfsReplica, (void **)&pIReplicaPtr);
  643. RETURN_IF_FAILED(hr);
  644. // Initialize the replica object.
  645. hr = pIReplicaPtr->Initialize(
  646. m_bstrEntryPath,
  647. i_szServerName,
  648. i_szShareName,
  649. lDfsStorageState
  650. );
  651. if (SUCCEEDED(hr))
  652. hr = _AddToReplicaList(i_szServerName, i_szShareName, lDfsStorageState);
  653. if (SUCCEEDED(hr))
  654. {
  655. o_pvarReplicaObject->vt = VT_DISPATCH;
  656. o_pvarReplicaObject->pdispVal = (IDispatch*)pIReplicaPtr;
  657. } else
  658. {
  659. pIReplicaPtr->Release();
  660. }
  661. return hr;
  662. }
  663. /////////////////////////////////////////////////////////////////////////////////////////////////
  664. // RemoveReplica
  665. STDMETHODIMP CDfsJunctionPoint :: RemoveReplica
  666. (
  667. BSTR i_szServerName,
  668. BSTR i_szShareName
  669. )
  670. {
  671. /*++
  672. Routine Description:
  673. This method removes a replica for the Junction point.
  674. Arguments:
  675. i_szServerName - The name of the server hosting the share that the replica is representing.
  676. i_szShareName - The name of the share that the replica is representing
  677. --*/
  678. if (!i_szServerName || !i_szShareName)
  679. return E_INVALIDARG;
  680. NET_API_STATUS nstatRetVal = NetDfsRemove(
  681. m_bstrEntryPath,
  682. i_szServerName,
  683. i_szShareName
  684. );
  685. dfsDebugOut((_T("NetDfsRemove entrypath=%s, server=%s, share=%s, nRet=%d\n"),
  686. m_bstrEntryPath, i_szServerName, i_szShareName, nstatRetVal));
  687. if (ERROR_NOT_FOUND == nstatRetVal)
  688. nstatRetVal = NERR_Success;
  689. if (NERR_Success == nstatRetVal)
  690. _DeleteFromReplicaList(i_szServerName, i_szShareName);
  691. return HRESULT_FROM_WIN32 (nstatRetVal);
  692. }
  693. STDMETHODIMP CDfsJunctionPoint::RemoveAllReplicas()
  694. {
  695. /*++
  696. Routine Description:
  697. This method deletes the Junction point.
  698. --*/
  699. if (m_Replicas.empty())
  700. return S_OK;
  701. //
  702. // DFS DCR: allow link deletion happen at once
  703. //
  704. NET_API_STATUS nstatRetVal = NetDfsRemove(
  705. m_bstrEntryPath,
  706. NULL,
  707. NULL
  708. );
  709. dfsDebugOut((_T("NetDfsRemove at once entrypath=%s, nRet=%d\n"), m_bstrEntryPath, nstatRetVal));
  710. if (ERROR_NOT_FOUND == nstatRetVal)
  711. nstatRetVal = NERR_Success;
  712. if (NERR_Success == nstatRetVal)
  713. FreeReplicas(&m_Replicas);
  714. return HRESULT_FROM_WIN32 (nstatRetVal);
  715. }
  716. /////////////////////////////////////////////////////////////////////////////////////////////////
  717. // DeleteRootReplica
  718. STDMETHODIMP CDfsJunctionPoint::DeleteRootReplica
  719. (
  720. BSTR i_bstrDomainName,
  721. BSTR i_bstrDfsName,
  722. BSTR i_bstrServerName,
  723. BSTR i_bstrShareName,
  724. BOOL i_bForce
  725. )
  726. {
  727. RETURN_INVALIDARG_IF_TRUE(!i_bstrServerName || !*i_bstrServerName);
  728. RETURN_INVALIDARG_IF_TRUE(!i_bstrShareName || !*i_bstrShareName);
  729. NET_API_STATUS nStatus = NERR_Success;
  730. if (!i_bstrDfsName || !*i_bstrDfsName) // standalone Dfs
  731. {
  732. nStatus = NetDfsRemoveStdRoot(
  733. i_bstrServerName,
  734. i_bstrShareName,
  735. 0 // No Flags.
  736. );
  737. dfsDebugOut((_T("NetDfsRemoveStdRoot server=%s, share=%s, nRet=%d\n"),
  738. i_bstrServerName, i_bstrShareName, nStatus));
  739. } else
  740. {
  741. if (!i_bForce)
  742. {
  743. nStatus = NetDfsRemoveFtRoot(
  744. i_bstrServerName,
  745. i_bstrShareName,
  746. i_bstrDfsName,
  747. 0 // No Flags.
  748. );
  749. dfsDebugOut((_T("NetDfsRemoveFtRoot server=%s, share=%s, DfsName=%s, nRet=%d\n"),
  750. i_bstrServerName, i_bstrShareName, i_bstrDfsName, nStatus));
  751. } else
  752. {
  753. nStatus = NetDfsRemoveFtRootForced(
  754. i_bstrDomainName,
  755. i_bstrServerName,
  756. i_bstrShareName,
  757. i_bstrDfsName,
  758. 0 // No Flags.
  759. );
  760. dfsDebugOut((_T("NetDfsRemoveFtRootForced domain=%s, server=%s, share=%s, DfsName=%s, nRet=%d\n"),
  761. i_bstrDomainName, i_bstrServerName, i_bstrShareName, i_bstrDfsName, nStatus));
  762. }
  763. }
  764. if (NERR_Success == nStatus)
  765. _DeleteFromReplicaList(i_bstrServerName, i_bstrShareName);
  766. return HRESULT_FROM_WIN32(nStatus);
  767. }
  768. /////////////////////////////////////////////////////////////////////////////////////////////////
  769. // GetOneRootReplica
  770. // always return the first entry in the m_Replicas list.
  771. STDMETHODIMP CDfsJunctionPoint::GetOneRootReplica
  772. (
  773. OUT BSTR* o_pbstrServerName,
  774. OUT BSTR* o_pbstrShareName
  775. )
  776. {
  777. RETURN_INVALIDARG_IF_NULL(o_pbstrServerName);
  778. RETURN_INVALIDARG_IF_NULL(o_pbstrShareName);
  779. *o_pbstrServerName = NULL;
  780. *o_pbstrShareName = NULL;
  781. if (m_Replicas.empty())
  782. return E_INVALIDARG;
  783. REPLICAINFOLIST::iterator i = m_Replicas.begin();
  784. *o_pbstrServerName = SysAllocString((*i)->m_bstrServerName);
  785. RETURN_OUTOFMEMORY_IF_NULL(*o_pbstrServerName);
  786. *o_pbstrShareName = SysAllocString((*i)->m_bstrShareName);
  787. if (!*o_pbstrShareName)
  788. {
  789. SysFreeString(*o_pbstrServerName);
  790. *o_pbstrServerName = NULL;
  791. return E_OUTOFMEMORY;
  792. }
  793. return S_OK;
  794. }