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.

1287 lines
34 KiB

  1. /*++
  2. Module Name:
  3. DfsRoot.cpp
  4. --*/
  5. #include "stdafx.h"
  6. #include "DfsCore.h"
  7. #include "DfsRoot.h"
  8. #include "JPEnum.h"
  9. #include <dsgetdc.h>
  10. #include <dsrole.h> // DsRoleGetPrimaryDomainInformation
  11. #include "netutils.h"
  12. #include "ldaputils.h"
  13. /////////////////////////////////////////////////////////////////////////////////////////////////
  14. // CDfsRoot constructor
  15. CDfsRoot::CDfsRoot() :
  16. m_pDfsJP(NULL),
  17. m_dwDfsType(DFS_TYPE_UNASSIGNED),
  18. m_lCountOfDfsJunctionPointsFiltered(0),
  19. m_lLinkFilterType(FILTERDFSLINKS_TYPE_NO_FILTER)
  20. {
  21. dfsDebugOut((_T("CDfsRoot::CDfsRoot this=%p\n"), this));
  22. }
  23. /////////////////////////////////////////////////////////////////////////////////////////////////
  24. // CDfsRoot destructor
  25. CDfsRoot::~CDfsRoot()
  26. {
  27. _FreeMemberVariables();
  28. dfsDebugOut((_T("CDfsRoot::~CDfsRoot this=%p\n"), this));
  29. }
  30. /////////////////////////////////////////////////////////////////////////////////////////////////
  31. // get_DomainName
  32. STDMETHODIMP CDfsRoot :: get_DomainName
  33. (
  34. BSTR* pVal
  35. )
  36. {
  37. if (!pVal)
  38. return E_INVALIDARG;
  39. *pVal = m_bstrDomainName.Copy ();
  40. if (!*pVal)
  41. return E_OUTOFMEMORY;
  42. return S_OK;
  43. }
  44. /////////////////////////////////////////////////////////////////////////////////////////////////
  45. // get_DomainGuid
  46. STDMETHODIMP CDfsRoot :: get_DomainGuid
  47. (
  48. BSTR* pVal
  49. )
  50. {
  51. if (!pVal)
  52. return E_INVALIDARG;
  53. *pVal = m_bstrDomainGuid.Copy ();
  54. if (!*pVal)
  55. return E_OUTOFMEMORY;
  56. return S_OK;
  57. }
  58. /////////////////////////////////////////////////////////////////////////////////////////////////
  59. // get_DomainDN
  60. STDMETHODIMP CDfsRoot :: get_DomainDN
  61. (
  62. BSTR* pVal
  63. )
  64. {
  65. if (!pVal)
  66. return E_INVALIDARG;
  67. *pVal = m_bstrDomainDN.Copy ();
  68. if (!*pVal)
  69. return E_OUTOFMEMORY;
  70. return S_OK;
  71. }
  72. /////////////////////////////////////////////////////////////////////////////////////////////////
  73. // get_DfsType
  74. STDMETHODIMP CDfsRoot :: get_DfsType
  75. (
  76. long* pVal
  77. )
  78. {
  79. if (!pVal)
  80. return E_INVALIDARG;
  81. *pVal = m_dwDfsType;
  82. return S_OK;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////////////////////////
  85. // get_State
  86. STDMETHODIMP CDfsRoot :: get_State
  87. (
  88. long* pVal
  89. )
  90. {
  91. return m_pDfsJP->get_State(pVal);
  92. }
  93. /////////////////////////////////////////////////////////////////////////////////////////////////
  94. // get_DfsName
  95. STDMETHODIMP CDfsRoot :: get_DfsName
  96. (
  97. BSTR* pVal
  98. )
  99. {
  100. if (!pVal)
  101. return E_INVALIDARG ;
  102. *pVal = m_bstrDfsName.Copy ();
  103. if (!*pVal)
  104. return E_OUTOFMEMORY;
  105. return S_OK;
  106. }
  107. /////////////////////////////////////////////////////////////////////////////////////////////////
  108. // get_ReplicaSetDN
  109. STDMETHODIMP CDfsRoot :: get_ReplicaSetDN
  110. (
  111. BSTR* pVal
  112. )
  113. {
  114. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  115. return m_pDfsJP->get_ReplicaSetDN(pVal);
  116. }
  117. STDMETHODIMP CDfsRoot :: get_ReplicaSetExist
  118. (
  119. BOOL* pVal
  120. )
  121. {
  122. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  123. return m_pDfsJP->get_ReplicaSetExist(pVal);
  124. }
  125. STDMETHODIMP CDfsRoot :: get_ReplicaSetExistEx
  126. (
  127. BSTR* o_pbstrDC,
  128. BOOL* pVal
  129. )
  130. {
  131. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  132. return m_pDfsJP->get_ReplicaSetExistEx(o_pbstrDC, pVal);
  133. }
  134. STDMETHODIMP CDfsRoot :: put_ReplicaSetExist
  135. (
  136. BOOL newVal
  137. )
  138. {
  139. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  140. return m_pDfsJP->put_ReplicaSetExist(newVal);
  141. }
  142. /////////////////////////////////////////////////////////////////////////////////////////////////
  143. // get_CountOfDfsJunctionPoints
  144. STDMETHODIMP CDfsRoot :: get_CountOfDfsJunctionPoints
  145. (
  146. long* pVal
  147. )
  148. {
  149. if (!pVal)
  150. return E_INVALIDARG;
  151. *pVal = m_JunctionPoints.size();
  152. return S_OK;
  153. }
  154. /////////////////////////////////////////////////////////////////////////////////////////////////
  155. // get_CountOfDfsJunctionPointsFiltered
  156. STDMETHODIMP CDfsRoot :: get_CountOfDfsJunctionPointsFiltered
  157. (
  158. long* pVal
  159. )
  160. {
  161. if (!pVal)
  162. return E_INVALIDARG;
  163. *pVal = m_lCountOfDfsJunctionPointsFiltered;
  164. return S_OK;
  165. }
  166. HRESULT DfsInfo3ToVariant(PDFS_INFO_3 pDfsInfo, OUT VARIANT *pVal)
  167. {
  168. RETURN_INVALIDARG_IF_NULL(pDfsInfo);
  169. RETURN_INVALIDARG_IF_NULL(pVal);
  170. HRESULT hr = S_OK;
  171. int cStorages = pDfsInfo->NumberOfStorages;
  172. // create an array of array of variants to hold all storage data
  173. SAFEARRAY* psa_1 = NULL;
  174. if (cStorages > 0 )
  175. {
  176. SAFEARRAYBOUND bounds_1 = {cStorages, 0};
  177. psa_1 = SafeArrayCreate(VT_VARIANT, 1, &bounds_1);
  178. RETURN_OUTOFMEMORY_IF_NULL(psa_1);
  179. VARIANT* varArray_1 = NULL;
  180. SafeArrayAccessData(psa_1, (void**)&varArray_1);
  181. for (int i = 0; i < cStorages; i++)
  182. {
  183. // create an array of variants to hold each Storage data (3 elements)
  184. SAFEARRAYBOUND bounds_0 = {ARRAY_COUNT_FOR_DFS_STORAGE_INFO, 0};
  185. SAFEARRAY* psa_0 = SafeArrayCreate(VT_VARIANT, 1, &bounds_0);
  186. BREAK_OUTOFMEMORY_IF_NULL(psa_0, &hr);
  187. VARIANT* varArray_0 = NULL;
  188. SafeArrayAccessData(psa_0, (void**)&varArray_0);
  189. do
  190. {
  191. varArray_0[0].vt = VT_BSTR;
  192. varArray_0[0].bstrVal = SysAllocString(pDfsInfo->Storage[i].ServerName);
  193. BREAK_OUTOFMEMORY_IF_NULL(varArray_0[0].bstrVal, &hr);
  194. varArray_0[1].vt = VT_BSTR;
  195. varArray_0[1].bstrVal = SysAllocString(pDfsInfo->Storage[i].ShareName);
  196. BREAK_OUTOFMEMORY_IF_NULL(varArray_0[1].bstrVal, &hr);
  197. varArray_0[2].vt = VT_I4;
  198. varArray_0[2].lVal = pDfsInfo->Storage[i].State;
  199. } while (0);
  200. SafeArrayUnaccessData(psa_0);
  201. if (FAILED(hr))
  202. {
  203. SafeArrayDestroy(psa_0);
  204. break;
  205. }
  206. // add this array to be an element
  207. varArray_1[i].vt = VT_ARRAY | VT_VARIANT;
  208. varArray_1[i].parray = psa_0;
  209. }
  210. SafeArrayUnaccessData(psa_1);
  211. }
  212. if (SUCCEEDED(hr))
  213. {
  214. // now create an array of variants to hold DfsInfoLevel
  215. SAFEARRAYBOUND bounds_2 = {ARRAY_COUNT_FOR_DFS_INFO_3, 0};
  216. SAFEARRAY* psa_2 = SafeArrayCreate(VT_VARIANT, 1, &bounds_2);
  217. if (!psa_2)
  218. {
  219. hr = E_OUTOFMEMORY;
  220. } else
  221. {
  222. VARIANT* varArray_2 = NULL;
  223. SafeArrayAccessData(psa_2, (void**)&varArray_2);
  224. do
  225. {
  226. varArray_2[0].vt = VT_BSTR;
  227. varArray_2[0].bstrVal = SysAllocString(pDfsInfo->EntryPath);
  228. BREAK_OUTOFMEMORY_IF_NULL(varArray_2[0].bstrVal, &hr);
  229. varArray_2[1].vt = VT_ARRAY | VT_VARIANT;
  230. varArray_2[1].parray = psa_1;
  231. } while (0);
  232. SafeArrayUnaccessData(psa_2);
  233. if (FAILED(hr))
  234. SafeArrayDestroy(psa_2);
  235. }
  236. if (SUCCEEDED(hr))
  237. {
  238. VariantInit(pVal);
  239. pVal->vt = VT_ARRAY | VT_VARIANT;
  240. pVal->parray = psa_2;
  241. }
  242. }
  243. if (FAILED(hr))
  244. SafeArrayDestroy(psa_1);
  245. return hr;
  246. }
  247. /////////////////////////////////////////////////////////////////////////////////////////////////
  248. // Initialize
  249. HRESULT CDfsRoot::_Init(
  250. PDFS_INFO_3 pDfsInfo,
  251. StringMap* pMap)
  252. {
  253. RETURN_INVALIDARG_IF_NULL(pDfsInfo);
  254. RETURN_INVALIDARG_IF_NULL(pMap);
  255. HRESULT hr = S_OK;
  256. do {
  257. hr = GetUNCPathComponent(pDfsInfo->EntryPath, &m_bstrDfsName, 3, 4);
  258. BREAK_IF_FAILED(hr);
  259. // decide whether it's a domain-based or standalone
  260. CComBSTR bstrScope;
  261. hr = GetUNCPathComponent(pDfsInfo->EntryPath, &bstrScope, 2, 3);
  262. BREAK_IF_FAILED(hr);
  263. if ((pDfsInfo->State & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_STANDALONE)
  264. {
  265. m_dwDfsType = DFS_TYPE_STANDALONE;
  266. } else if ((pDfsInfo->State & DFS_VOLUME_FLAVORS) == DFS_VOLUME_FLAVOR_AD_BLOB)
  267. {
  268. m_dwDfsType = DFS_TYPE_FTDFS;
  269. } else
  270. {
  271. // flavor flag is not set, we're dealing with old version of metadata blob
  272. // see if bstrScope is a domain name
  273. #ifdef DEBUG
  274. SYSTEMTIME time0 = {0};
  275. GetSystemTime(&time0);
  276. #endif // DEBUG
  277. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  278. DWORD nRet = DsGetDcName(
  279. NULL,
  280. bstrScope,
  281. NULL,
  282. NULL,
  283. DS_DIRECTORY_SERVICE_REQUIRED | DS_RETURN_DNS_NAME,
  284. &pDCInfo
  285. );
  286. #ifdef DEBUG
  287. SYSTEMTIME time1 = {0};
  288. GetSystemTime(&time1);
  289. PrintTimeDelta(_T("CDfsRoot::_Init-DsGetDcName"), &time0, &time1);
  290. #endif // DEBUG
  291. if (ERROR_SUCCESS == nRet)
  292. {
  293. NetApiBufferFree(pDCInfo);
  294. m_dwDfsType = DFS_TYPE_FTDFS;
  295. } else
  296. { // check to see if it's a valid server name
  297. PWKSTA_INFO_100 wki100 = NULL;
  298. nRet = NetWkstaGetInfo(bstrScope, 100, (LPBYTE *)&wki100 );
  299. if (ERROR_SUCCESS == nRet)
  300. {
  301. m_dwDfsType = DFS_TYPE_STANDALONE;
  302. NetApiBufferFree((LPVOID)wki100);
  303. } else
  304. {
  305. hr = HRESULT_FROM_WIN32(nRet);
  306. }
  307. }
  308. }
  309. if (SUCCEEDED(hr) && m_dwDfsType == DFS_TYPE_FTDFS)
  310. {
  311. hr = GetDomainInfo( bstrScope,
  312. NULL, // DC
  313. &m_bstrDomainName,
  314. &m_bstrDomainDN,
  315. NULL, // LDAPDomainPath
  316. &m_bstrDomainGuid);
  317. }
  318. BREAK_IF_FAILED(hr);
  319. if (m_dwDfsType == DFS_TYPE_FTDFS)
  320. {
  321. (void) _GetAllReplicaSets(pMap);
  322. }
  323. CComVariant varData;
  324. hr = DfsInfo3ToVariant(pDfsInfo, &varData);
  325. BREAK_IF_FAILED(hr);
  326. hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER,
  327. IID_IDfsJunctionPoint, (void **)&m_pDfsJP);
  328. BREAK_IF_FAILED(hr);
  329. if (m_dwDfsType == DFS_TYPE_FTDFS)
  330. {
  331. CComBSTR bstrDfsLinkName;
  332. hr = GetUNCPathComponent(pDfsInfo->EntryPath, &bstrDfsLinkName, 3, 0);
  333. BREAK_IF_FAILED(hr);
  334. StringMap::iterator it = pMap->find(bstrDfsLinkName);
  335. if (it != pMap->end())
  336. hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, TRUE, (*it).second);
  337. else
  338. hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, FALSE, NULL);
  339. } else
  340. {
  341. hr = m_pDfsJP->InitializeEx((IUnknown *)this, &varData, FALSE, NULL);
  342. }
  343. } while (0);
  344. return hr;
  345. }
  346. int __cdecl CompareJPs(const void *arg1, const void *arg2 )
  347. {
  348. return lstrcmpi( (*(PDFS_INFO_3 *)arg1)->EntryPath, (*(PDFS_INFO_3 *)arg2)->EntryPath );
  349. }
  350. STDMETHODIMP CDfsRoot :: Initialize
  351. (
  352. BSTR i_szDfsName
  353. )
  354. {
  355. /*++
  356. Routine Description:
  357. This method intializes the newly created object and previously initialised
  358. DfsRoot object.
  359. Arguments:
  360. i_szDfsName - The Dfs name which can be any of the following type:
  361. 1. \\domain.dns.name\FtDfs,
  362. 2. \\domain\FtDfs,
  363. 3. \\server\share,
  364. 4. \\server,
  365. 5. server.
  366. Notes:
  367. Initialize performs the following:
  368. 1. Gets the name of the domain for the server hosting / participating in the Dfs Root.
  369. 2. Gets all child junction points and root level replicas for this Dfs.
  370. 3. Gets the type (standalone or fault tolerant) of the DFS.
  371. 4. Gets the display name of the DFS, \\domain.dns.name\FtDfs or \\server\share and Dfs Name which
  372. is FtDfs or server..
  373. Return:
  374. S_FALSE if i_szDfsName doesn't host any dfs root
  375. --*/
  376. RETURN_INVALIDARG_IF_NULL(i_szDfsName);
  377. _FreeMemberVariables();
  378. LPBYTE pBuffer = NULL;
  379. DWORD dwEntriesRead = 0;
  380. DWORD dwResumeHandle = 0;
  381. NET_API_STATUS nRet = NetDfsEnum(
  382. i_szDfsName,
  383. 3, // level 3
  384. 0xffffffff,
  385. &pBuffer,
  386. &dwEntriesRead,
  387. &dwResumeHandle);
  388. dfsDebugOut((_T("NetDfsEnum DfsName=%s, level 3 for Root Initialization, nRet=%d\n"),
  389. i_szDfsName, nRet));
  390. if (NERR_Success != nRet)
  391. {
  392. return (ERROR_NO_MORE_ITEMS == nRet || ERROR_NOT_FOUND == nRet) ? S_FALSE : HRESULT_FROM_WIN32(nRet);
  393. } else if (0 == dwEntriesRead)
  394. {
  395. if (pBuffer)
  396. NetApiBufferFree(pBuffer);
  397. return S_FALSE;
  398. }
  399. HRESULT hr = S_OK;
  400. do {
  401. DWORD i = 0;
  402. PDFS_INFO_3 pDfsInfo = (PDFS_INFO_3)pBuffer;
  403. //
  404. // root may not be the 1st entry, find the root entry, switch it to the top
  405. //
  406. for (i = 0; i < dwEntriesRead; i++)
  407. {
  408. if (pDfsInfo[i].State & DFS_VOLUME_FLAVORS)
  409. break; // the i-th entry is the root entry
  410. }
  411. if (i != 0 && i != dwEntriesRead)
  412. {
  413. DFS_INFO_3 tmpInfo = {0};
  414. memcpy(&tmpInfo, pDfsInfo, sizeof(DFS_INFO_3));
  415. memcpy(pDfsInfo, pDfsInfo + i, sizeof(DFS_INFO_3));
  416. memcpy(pDfsInfo + i, &tmpInfo, sizeof(DFS_INFO_3));
  417. }
  418. // i=0 is the Root info
  419. StringMap mapReplicaSets;
  420. hr = _Init(pDfsInfo, &mapReplicaSets);
  421. BREAK_IF_FAILED(hr);
  422. if (dwEntriesRead > 1)
  423. {
  424. pDfsInfo++;
  425. PDFS_INFO_3 *pArray = (PDFS_INFO_3 *)calloc(dwEntriesRead - 1, sizeof(PDFS_INFO_3));
  426. BREAK_OUTOFMEMORY_IF_NULL(pArray, &hr);
  427. PDFS_INFO_3 *pArrayElem = NULL;
  428. for (i = 1, pArrayElem = pArray; i < dwEntriesRead; i++, pDfsInfo++, pArrayElem++)
  429. *pArrayElem = pDfsInfo;
  430. qsort((void *)pArray, dwEntriesRead - 1, sizeof(PDFS_INFO_3), CompareJPs);
  431. StringMap::iterator it;
  432. for (i = 1, pArrayElem = pArray; i < dwEntriesRead; i++, pArrayElem++)
  433. {
  434. if (m_dwDfsType == DFS_TYPE_FTDFS)
  435. {
  436. CComBSTR bstrDfsLinkName;
  437. hr = GetUNCPathComponent((*pArrayElem)->EntryPath, &bstrDfsLinkName, 3, 0);
  438. BREAK_IF_FAILED(hr);
  439. it = mapReplicaSets.find(bstrDfsLinkName);
  440. if (it != mapReplicaSets.end())
  441. hr = _AddToJPList(*pArrayElem, TRUE, (*it).second);
  442. else
  443. hr = _AddToJPList(*pArrayElem, FALSE, NULL);
  444. } else
  445. {
  446. hr = _AddToJPList(*pArrayElem, FALSE, NULL);
  447. }
  448. BREAK_IF_FAILED(hr);
  449. }
  450. free((void *)pArray);
  451. }
  452. } while (0);
  453. NetApiBufferFree(pBuffer);
  454. if (FAILED(hr))
  455. _FreeMemberVariables();
  456. return hr;
  457. }
  458. void _FreeStringMap(IN StringMap* pMap)
  459. {
  460. if (pMap && !pMap->empty()) {
  461. for (StringMap::iterator i = pMap->begin(); i != pMap->end(); i++)
  462. {
  463. if ((*i).first)
  464. free( (void *)((*i).first) );
  465. if ((*i).second)
  466. free( (void *)((*i).second) );
  467. }
  468. pMap->clear();
  469. }
  470. }
  471. HRESULT CDfsRoot :: _GetAllReplicaSets(
  472. OUT StringMap* pMap
  473. )
  474. {
  475. _FreeStringMap(pMap);
  476. RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDomainName);
  477. RETURN_INVALIDARG_IF_NULL((BSTR)m_bstrDomainDN);
  478. HRESULT hr = S_OK;
  479. PLDAP pldap = NULL;
  480. do {
  481. hr = ConnectToDS(m_bstrDomainName, &pldap);
  482. BREAK_IF_FAILED(hr);
  483. CComBSTR bstrContainerDN = _T("CN=");
  484. BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr);
  485. bstrContainerDN += m_bstrDfsName;
  486. BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr);
  487. bstrContainerDN += CN_DFSVOLUMES_PREFIX_COMMA;
  488. BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr);
  489. bstrContainerDN += m_bstrDomainDN;
  490. BREAK_OUTOFMEMORY_IF_NULL((BSTR)bstrContainerDN, &hr);
  491. //
  492. // get all the replica sets under the container
  493. //
  494. PCTSTR ppszAttributes[] = {ATTR_DISTINGUISHEDNAME, 0};
  495. LListElem* pElem = NULL;
  496. hr = GetValuesEx(
  497. pldap,
  498. bstrContainerDN,
  499. LDAP_SCOPE_SUBTREE,
  500. _T("(&(objectCategory=nTFRSReplicaSet)(frsReplicaSetType=3))"),
  501. ppszAttributes,
  502. &pElem);
  503. BREAK_IF_FAILED(hr);
  504. LListElem* pCurElem = pElem;
  505. while (pCurElem)
  506. {
  507. PTSTR** pppszValues = pCurElem->pppszAttrValues;
  508. if (!pppszValues ||
  509. !pppszValues[0] || !*(pppszValues[0]))
  510. {
  511. hr = E_FAIL;
  512. break;
  513. }
  514. PTSTR pszDN = *(pppszValues[0]);
  515. PTSTR p = _tcsstr(pszDN, _T(",DC="));
  516. if (!p)
  517. {
  518. hr = E_INVALIDARG;
  519. break;
  520. }
  521. *p = _T('\0');
  522. PTSTR pszReplicaSetDN = _tcsdup(pszDN);
  523. *p = _T(',');
  524. BREAK_OUTOFMEMORY_IF_NULL(pszReplicaSetDN, &hr);
  525. CComBSTR bstrDfsLinkName;
  526. hr = GetDfsLinkNameFromDN(pszReplicaSetDN, &bstrDfsLinkName);
  527. PTSTR pszDfsLinkName = NULL;
  528. if (SUCCEEDED(hr))
  529. {
  530. pszDfsLinkName = _tcsdup(bstrDfsLinkName);
  531. if (!pszDfsLinkName)
  532. hr = E_OUTOFMEMORY;
  533. }
  534. if (FAILED(hr))
  535. {
  536. free(pszReplicaSetDN);
  537. break;
  538. }
  539. pMap->insert(StringMap::value_type(pszDfsLinkName, pszReplicaSetDN));
  540. pCurElem = pCurElem->Next;
  541. }
  542. FreeLListElem(pElem);
  543. BREAK_IF_FAILED(hr);
  544. } while (0);
  545. if (pldap)
  546. CloseConnectionToDS(pldap);
  547. if (FAILED(hr))
  548. _FreeStringMap(pMap);
  549. return hr;
  550. }
  551. /////////////////////////////////////////////////////////////////////////////////////////////////
  552. // CreateJunctionPoint
  553. STDMETHODIMP CDfsRoot :: CreateJunctionPoint
  554. (
  555. BSTR i_szJPName,
  556. BSTR i_szServerName,
  557. BSTR i_szShareName,
  558. BSTR i_szComment,
  559. long i_lTimeout,
  560. VARIANT* o_pIDfsJunctionPoint
  561. )
  562. {
  563. if (!i_szJPName || !i_szServerName || !i_szShareName || !o_pIDfsJunctionPoint)
  564. return E_INVALIDARG;
  565. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  566. CComBSTR bstrEntryPath; // Start with the root entry path.
  567. HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath);
  568. RETURN_IF_FAILED(hr);
  569. bstrEntryPath += _T("\\");
  570. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath);
  571. bstrEntryPath += i_szJPName;
  572. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath);
  573. NET_API_STATUS nstatRetVal = NetDfsAdd(
  574. bstrEntryPath,
  575. i_szServerName,
  576. i_szShareName,
  577. i_szComment,
  578. DFS_ADD_VOLUME | DFS_RESTORE_VOLUME
  579. );
  580. dfsDebugOut((_T("NetDfsAdd entry=%s, server=%s, share=%s, comment=%s, DFS_ADD_VOLUME | DFS_RESTORE_VOLUME, nRet=%d\n"),
  581. bstrEntryPath, i_szServerName, i_szShareName, i_szComment, nstatRetVal));
  582. if (nstatRetVal != NERR_Success)
  583. return HRESULT_FROM_WIN32 (nstatRetVal);
  584. // Get the interface pointer
  585. IDfsJunctionPoint* pIJunctionPointPtr = NULL;
  586. hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER,
  587. IID_IDfsJunctionPoint, (void **)&pIJunctionPointPtr);
  588. RETURN_IF_FAILED(hr);
  589. hr = pIJunctionPointPtr->Initialize((IUnknown *)this, bstrEntryPath, FALSE, NULL);
  590. if (SUCCEEDED(hr))
  591. {
  592. hr = pIJunctionPointPtr->put_Timeout(i_lTimeout);
  593. if (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) == hr)
  594. {
  595. // we're most probably managing NT4 here, which doesn't support Timeout
  596. hr = S_OK;
  597. }
  598. }
  599. if (SUCCEEDED(hr))
  600. hr = _AddToJPListEx(pIJunctionPointPtr, TRUE);
  601. if (SUCCEEDED(hr))
  602. {
  603. o_pIDfsJunctionPoint->vt = VT_DISPATCH;
  604. o_pIDfsJunctionPoint->pdispVal = pIJunctionPointPtr;
  605. } else
  606. {
  607. pIJunctionPointPtr->Release();
  608. }
  609. return hr;
  610. }
  611. /////////////////////////////////////////////////////////////////////////////////////////////////
  612. // DeleteJunctionPoint
  613. STDMETHODIMP CDfsRoot::DeleteJunctionPoint
  614. (
  615. BSTR i_szJPName
  616. )
  617. {
  618. if (!i_szJPName)
  619. return E_INVALIDARG;
  620. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  621. CComBSTR bstrEntryPath; // Start with the root entry path.
  622. HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath);
  623. RETURN_IF_FAILED(hr);
  624. bstrEntryPath += _T("\\");
  625. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath);
  626. bstrEntryPath += i_szJPName;
  627. RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrEntryPath);
  628. // Get the interface pointer
  629. JUNCTIONNAMELIST::iterator i;
  630. for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++)
  631. {
  632. if (!lstrcmpi((*i)->m_bstrJPName, i_szJPName))
  633. break;
  634. }
  635. if (i != m_JunctionPoints.end())
  636. {
  637. hr = ((*i)->m_piDfsJunctionPoint)->RemoveAllReplicas();
  638. if (SUCCEEDED(hr))
  639. {
  640. delete (*i);
  641. m_JunctionPoints.erase(i);
  642. }
  643. }
  644. return hr;
  645. }
  646. /////////////////////////////////////////////////////////////////////////////////////////////////
  647. // DeleteDfsHost
  648. STDMETHODIMP CDfsRoot::DeleteDfsHost
  649. (
  650. BSTR i_bstrServerName,
  651. BSTR i_bstrShareName,
  652. BOOL i_bForce
  653. )
  654. {
  655. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  656. switch (m_dwDfsType)
  657. {
  658. case DFS_TYPE_STANDALONE:
  659. return m_pDfsJP->DeleteRootReplica(NULL, NULL, i_bstrServerName, i_bstrShareName, i_bForce);
  660. case DFS_TYPE_FTDFS:
  661. return m_pDfsJP->DeleteRootReplica(m_bstrDomainName, m_bstrDfsName, i_bstrServerName, i_bstrShareName, i_bForce);
  662. default:
  663. return E_INVALIDARG;
  664. }
  665. }
  666. /////////////////////////////////////////////////////////////////////////////////////////////////
  667. // GetOneDfsHost
  668. STDMETHODIMP CDfsRoot::GetOneDfsHost
  669. (
  670. OUT BSTR* o_pbstrServerName,
  671. OUT BSTR* o_pbstrShareName
  672. )
  673. {
  674. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  675. return m_pDfsJP->GetOneRootReplica(o_pbstrServerName, o_pbstrShareName);
  676. }
  677. /////////////////////////////////////////////////////////////////////////////////////////////////
  678. // _FreeMemberVariables
  679. void CDfsRoot :: _FreeMemberVariables
  680. (
  681. )
  682. {
  683. m_bstrDfsName.Empty();
  684. m_bstrDomainName.Empty();
  685. m_bstrDomainGuid.Empty();
  686. m_bstrDomainDN.Empty();
  687. m_lLinkFilterType = FILTERDFSLINKS_TYPE_NO_FILTER;
  688. m_bstrEnumFilter.Empty();
  689. FreeJunctionNames(&m_JunctionPoints);
  690. if (m_pDfsJP)
  691. {
  692. m_pDfsJP->Release();
  693. m_pDfsJP = NULL;
  694. }
  695. }
  696. /////////////////////////////////////////////////////////////////////////////////////////////////
  697. // get__NewEnum
  698. STDMETHODIMP CDfsRoot :: get__NewEnum
  699. (
  700. LPUNKNOWN* pVal
  701. )
  702. {
  703. /*++
  704. Routine Description:
  705. Returns a new enumerator interface (IEnumVARIANT) to enumerate Junction points.
  706. This depends upon the EnumFilter value.
  707. Arguments:
  708. pVal - Pointer to a Variant in which the enumerator will be returned.
  709. --*/
  710. if (!pVal)
  711. return E_INVALIDARG;
  712. *pVal = NULL;
  713. //Create a Junction point enumerator and initialize it with
  714. //the internal list.
  715. CComObject<CJunctionPointEnum> *pJunctionPointEnum = new CComObject<CJunctionPointEnum>();
  716. if (!pJunctionPointEnum)
  717. return E_OUTOFMEMORY;
  718. HRESULT hr = pJunctionPointEnum->Initialize(&m_JunctionPoints, m_lLinkFilterType, m_bstrEnumFilter, (ULONG*)&m_lCountOfDfsJunctionPointsFiltered);
  719. if (SUCCEEDED(hr))
  720. hr = pJunctionPointEnum->QueryInterface(IID_IEnumVARIANT, (void **)pVal);
  721. if (FAILED(hr))
  722. delete pJunctionPointEnum;
  723. return hr;
  724. }
  725. /////////////////////////////////////////////////////////////////////////////////////////////////
  726. // get_RootReplicaEnum
  727. STDMETHODIMP CDfsRoot :: get_RootReplicaEnum
  728. (
  729. LPUNKNOWN* pVal
  730. )
  731. {
  732. /*++
  733. Routine Description:
  734. Call the inner junction point to return a new enumerator interface (IEnumVARIANT)
  735. to enumerate root replicas.
  736. Arguments:
  737. pVal - Pointer to a Variant in which the enumerator will be returned.
  738. --*/
  739. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  740. return m_pDfsJP->get__NewEnum(pVal);
  741. }
  742. /////////////////////////////////////////////////////////////////////////////////////////////////
  743. // GetRootJP
  744. STDMETHODIMP CDfsRoot :: GetRootJP
  745. (
  746. VARIANT* o_pIDfsJunctionPoint
  747. )
  748. {
  749. RETURN_INVALIDARG_IF_NULL(o_pIDfsJunctionPoint);
  750. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  751. m_pDfsJP->AddRef();
  752. o_pIDfsJunctionPoint->vt = VT_DISPATCH;
  753. o_pIDfsJunctionPoint->pdispVal = m_pDfsJP;
  754. return S_OK;
  755. }
  756. /////////////////////////////////////////////////////////////////////////////////////////////////
  757. // get_RootEntryPath
  758. STDMETHODIMP CDfsRoot :: get_RootEntryPath
  759. (
  760. BSTR* pVal
  761. )
  762. {
  763. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  764. return m_pDfsJP->get_EntryPath(pVal);
  765. }
  766. /////////////////////////////////////////////////////////////////////////////////////////////////
  767. // Comment
  768. STDMETHODIMP CDfsRoot :: get_Comment(BSTR *pVal)
  769. {
  770. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  771. return m_pDfsJP->get_Comment(pVal);
  772. }
  773. STDMETHODIMP CDfsRoot :: put_Comment(BSTR newVal)
  774. {
  775. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  776. return m_pDfsJP->put_Comment(newVal);
  777. }
  778. /////////////////////////////////////////////////////////////////////////////////////////////////
  779. // Timeout
  780. STDMETHODIMP CDfsRoot::get_Timeout(long *pVal)
  781. {
  782. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  783. return m_pDfsJP->get_Timeout(pVal);
  784. }
  785. STDMETHODIMP CDfsRoot::put_Timeout(long newVal)
  786. {
  787. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  788. return m_pDfsJP->put_Timeout(newVal);
  789. }
  790. /////////////////////////////////////////////////////////////////////////////////////////////////
  791. // DeleteAllJunctionPoints
  792. HRESULT CDfsRoot :: DeleteAllJunctionPoints()
  793. {
  794. /*++
  795. Routine Description:
  796. Deletes all Junction junction points.
  797. --*/
  798. HRESULT hr = S_OK;
  799. for (JUNCTIONNAMELIST::iterator i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++)
  800. {
  801. hr = DeleteJunctionPoint((*i)->m_bstrJPName);
  802. BREAK_IF_FAILED(hr);
  803. }
  804. return hr;
  805. }
  806. //
  807. // gets/puts the type of Enumerator Filter.
  808. //
  809. STDMETHODIMP CDfsRoot::get_EnumFilterType
  810. (
  811. long* pVal
  812. )
  813. {
  814. if (!pVal)
  815. return E_INVALIDARG;
  816. *pVal = m_lLinkFilterType;
  817. return S_OK;
  818. }
  819. STDMETHODIMP CDfsRoot::put_EnumFilterType
  820. (
  821. long newVal
  822. )
  823. {
  824. m_lLinkFilterType = (FILTERDFSLINKS_TYPE)newVal;
  825. return S_OK;
  826. }
  827. //
  828. // gets/puts the Enumerator Filter
  829. //
  830. STDMETHODIMP CDfsRoot::get_EnumFilter
  831. (
  832. BSTR* pVal
  833. )
  834. {
  835. if (!pVal)
  836. return E_INVALIDARG;
  837. *pVal = NULL;
  838. if ((BSTR)m_bstrEnumFilter)
  839. {
  840. *pVal = m_bstrEnumFilter.Copy ();
  841. if (!*pVal)
  842. return E_OUTOFMEMORY;
  843. }
  844. return S_OK;
  845. }
  846. STDMETHODIMP CDfsRoot::put_EnumFilter
  847. (
  848. BSTR newVal
  849. )
  850. {
  851. // we require newVal points to a non-empty string
  852. if (!newVal || !*newVal)
  853. return E_INVALIDARG;
  854. m_bstrEnumFilter = newVal;
  855. if (!m_bstrEnumFilter)
  856. return E_OUTOFMEMORY;
  857. return S_OK;
  858. }
  859. /////////////////////////////////////////////////////////////////////////////////////////////////
  860. // get_CountOfDfsRootReplicas
  861. STDMETHODIMP CDfsRoot :: get_CountOfDfsRootReplicas
  862. (
  863. long* pVal
  864. )
  865. {
  866. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  867. return m_pDfsJP->get_CountOfDfsReplicas(pVal);
  868. }
  869. /////////////////////////////////////////////////////////////////////////////////////////////////
  870. // IsJPExisted
  871. STDMETHODIMP CDfsRoot :: IsJPExisted
  872. (
  873. BSTR i_bstrJPName
  874. )
  875. {
  876. RETURN_INVALIDARG_IF_NULL(i_bstrJPName);
  877. for (JUNCTIONNAMELIST::iterator i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++)
  878. {
  879. if (!lstrcmpi((*i)->m_bstrJPName, i_bstrJPName))
  880. return S_OK;
  881. }
  882. return S_FALSE;
  883. }
  884. /////////////////////////////////////////////////////////////////////////////////////////////////
  885. // RefreshRootReplicas: used to pick up new Dfs hosts
  886. STDMETHODIMP CDfsRoot :: RefreshRootReplicas
  887. (
  888. )
  889. {
  890. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  891. CComBSTR bstrEntryPath;
  892. HRESULT hr = m_pDfsJP->get_EntryPath(&bstrEntryPath);
  893. RETURN_IF_FAILED(hr);
  894. BOOL bReplicaSetExist = FALSE;
  895. hr = m_pDfsJP->get_ReplicaSetExist(&bReplicaSetExist);
  896. RETURN_IF_FAILED(hr);
  897. CComBSTR bstrReplicaSetDN;
  898. hr = m_pDfsJP->get_ReplicaSetDN(&bstrReplicaSetDN);
  899. RETURN_IF_FAILED(hr);
  900. hr = m_pDfsJP->Initialize((IUnknown *)this, bstrEntryPath, bReplicaSetExist, bstrReplicaSetDN);
  901. return hr;
  902. }
  903. /////////////////////////////////////////////////////////////////////////////////////////////////
  904. // DeleteAllReplicaSets: delete all replica sets related to this Dfs root
  905. STDMETHODIMP CDfsRoot :: DeleteAllReplicaSets
  906. (
  907. )
  908. {
  909. RETURN_INVALIDARG_IF_NULL(m_pDfsJP);
  910. if (m_dwDfsType != DFS_TYPE_FTDFS)
  911. return S_OK;
  912. //
  913. // delete replica sets associated with this Dfs root
  914. //
  915. HRESULT hr = S_OK;
  916. BOOL bReplicaSetExist = FALSE;
  917. JUNCTIONNAMELIST::iterator i;
  918. for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++)
  919. {
  920. bReplicaSetExist = FALSE;
  921. (void)(*i)->m_piDfsJunctionPoint->get_ReplicaSetExist(&bReplicaSetExist);
  922. if (bReplicaSetExist)
  923. {
  924. CComBSTR bstrReplicaSetDN;
  925. hr = (*i)->m_piDfsJunctionPoint->get_ReplicaSetDN(&bstrReplicaSetDN);
  926. BREAK_IF_FAILED(hr);
  927. CComPtr<IReplicaSet> piReplicaSet;
  928. hr = CoCreateInstance(CLSID_ReplicaSet, NULL, CLSCTX_INPROC_SERVER, IID_IReplicaSet, (void**)&piReplicaSet);
  929. BREAK_IF_FAILED(hr);
  930. hr = piReplicaSet->Initialize(m_bstrDomainName, bstrReplicaSetDN);
  931. if (SUCCEEDED(hr))
  932. piReplicaSet->Delete();
  933. }
  934. }
  935. return hr;
  936. }
  937. /////////////////////////////////////////////////////////////////////////////////////////////////
  938. // FreeJunctionNames
  939. void FreeJunctionNames (JUNCTIONNAMELIST* pJPList)
  940. {
  941. if (NULL == pJPList)
  942. return;
  943. if (!pJPList->empty())
  944. {
  945. for (JUNCTIONNAMELIST::iterator i = pJPList->begin(); i != pJPList->end(); i++)
  946. {
  947. delete (*i);
  948. }
  949. pJPList->clear();
  950. }
  951. _ASSERT(pJPList->empty());
  952. }
  953. /////////////////////////////////////////////////////////////////////////////////////////////////
  954. void FreeReplicas(REPLICAINFOLIST* pRepList)
  955. {
  956. if (NULL == pRepList)
  957. return;
  958. if (!pRepList->empty())
  959. {
  960. for (REPLICAINFOLIST::iterator i = pRepList->begin(); i != pRepList->end(); i++)
  961. {
  962. delete (*i);
  963. }
  964. pRepList->clear();
  965. }
  966. _ASSERT(pRepList->empty());
  967. }
  968. HRESULT CDfsRoot::_AddToJPList(
  969. PDFS_INFO_3 pDfsInfo,
  970. BOOL bReplicaSetExist,
  971. BSTR bstrReplicaSetDN)
  972. {
  973. HRESULT hr = S_OK;
  974. CComPtr<IDfsJunctionPoint> piDfsJunctionPoint;
  975. hr = CoCreateInstance(CLSID_DfsJunctionPoint, NULL, CLSCTX_INPROC_SERVER,
  976. IID_IDfsJunctionPoint, (void **)&piDfsJunctionPoint);
  977. RETURN_IF_FAILED(hr);
  978. CComVariant varData;
  979. hr = DfsInfo3ToVariant(pDfsInfo, &varData);
  980. RETURN_IF_FAILED(hr);
  981. hr = piDfsJunctionPoint->InitializeEx((IUnknown *)this, &varData, bReplicaSetExist, bstrReplicaSetDN);
  982. RETURN_IF_FAILED(hr);
  983. return _AddToJPListEx(piDfsJunctionPoint);
  984. }
  985. HRESULT CDfsRoot::_AddToJPListEx(
  986. IDfsJunctionPoint * piDfsJunctionPoint,
  987. BOOL bSort)
  988. {
  989. JUNCTIONNAME* pDfsJP = new JUNCTIONNAME;
  990. RETURN_OUTOFMEMORY_IF_NULL(pDfsJP);
  991. HRESULT hr = pDfsJP->Init(piDfsJunctionPoint);
  992. if (FAILED(hr))
  993. {
  994. delete pDfsJP;
  995. return hr;
  996. }
  997. if (bSort)
  998. {
  999. JUNCTIONNAMELIST::iterator i;
  1000. for (i = m_JunctionPoints.begin(); i != m_JunctionPoints.end(); i++)
  1001. {
  1002. if (lstrcmpi(pDfsJP->m_bstrJPName, (*i)->m_bstrJPName) < 0)
  1003. break;
  1004. }
  1005. m_JunctionPoints.insert(i, pDfsJP);
  1006. } else
  1007. {
  1008. m_JunctionPoints.push_back(pDfsJP);
  1009. }
  1010. return hr;
  1011. }