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.

3158 lines
90 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: editor.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.h"
  11. #include <shlobj.h> // needed for dsclient.h
  12. #include <dsclient.h>
  13. #include <SnapBase.h>
  14. #include "resource.h"
  15. #include "adsiedit.h"
  16. #include "editor.h"
  17. #include "editorui.h"
  18. #include "snapdata.h"
  19. #include "common.h"
  20. #include "connection.h"
  21. #include "createwiz.h"
  22. #include "query.h"
  23. #include "querynode.h"
  24. #include "queryui.h"
  25. #include "renameui.h"
  26. #ifdef DEBUG_ALLOCATOR
  27. #ifdef _DEBUG
  28. #define new DEBUG_NEW
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. #endif
  33. //////////////////////////////////////////////////////////////////////////
  34. LPCWSTR g_lpszGC = L"GC://";
  35. LPCWSTR g_lpszLDAP = L"LDAP://";
  36. LPCWSTR g_lpszRootDSE = L"RootDSE";
  37. //////////////////////////////////////////////////////////////////////////
  38. CADsObject::CADsObject()
  39. {
  40. m_bContainer = FALSE;
  41. m_bIntermediate = FALSE;
  42. m_pConnectionNode = NULL;
  43. m_sName = _T("");
  44. m_sDN = _T("");
  45. m_sPath = _T("");
  46. m_sClass = _T("");
  47. m_bComplete = FALSE;
  48. }
  49. CADsObject::CADsObject(CADSIEditConnectionNode* pConnectNode)
  50. {
  51. m_bContainer = FALSE;
  52. m_bIntermediate = FALSE;
  53. m_pConnectionNode = pConnectNode;
  54. m_bComplete = FALSE;
  55. }
  56. CADsObject::CADsObject(CADsObject* pADsObject)
  57. {
  58. m_sName = pADsObject->m_sName;
  59. m_sDN = pADsObject->m_sDN;
  60. m_sPath = pADsObject->m_sPath;
  61. m_sClass = pADsObject->m_sClass;
  62. m_bContainer = pADsObject->m_bContainer;
  63. m_bIntermediate = pADsObject->m_bIntermediate;
  64. m_pConnectionNode = pADsObject->m_pConnectionNode;
  65. m_bComplete = pADsObject->m_bComplete;
  66. }
  67. void CADsObject::SetName(LPCWSTR lpszName)
  68. {
  69. CString sPrefix, sRemaining, sTemp;
  70. sTemp = lpszName;
  71. int idx = sTemp.Find(L'=');
  72. if (idx != -1)
  73. {
  74. sPrefix = sTemp.Left(idx);
  75. sPrefix.MakeUpper();
  76. int iCount = sTemp.GetLength();
  77. sRemaining = sTemp.Right(iCount - idx);
  78. sTemp = sPrefix + sRemaining;
  79. }
  80. m_sName = sTemp;
  81. }
  82. /////////////////////////////////////////////////////////////////////////
  83. // CConnectionData
  84. //
  85. CConnectionData::CConnectionData()
  86. {
  87. ConstructorHelper();
  88. }
  89. CConnectionData::CConnectionData(CADSIEditConnectionNode* pConnectNode) : CADsObject(pConnectNode)
  90. {
  91. ConstructorHelper();
  92. }
  93. void CConnectionData::ConstructorHelper()
  94. {
  95. m_pFilterObject = new CADSIFilterObject();
  96. m_pCredentialsObject = new CCredentialObject();
  97. m_sBasePath = _T("");
  98. m_sDomainServer = _T("");
  99. m_sPort = _T("");
  100. m_sDistinguishedName = _T("");
  101. m_sNamingContext = _T("Domain");
  102. m_sLDAP = g_lpszLDAP;
  103. m_sSchemaPath = _T("");
  104. m_sAbstractSchemaPath = _T("");
  105. m_bRootDSE = FALSE;
  106. m_bUserDefinedServer = FALSE;
  107. m_pDirObject = NULL;
  108. m_nMaxObjectCount = ADSIEDIT_QUERY_OBJ_COUNT_DEFAULT;
  109. }
  110. CConnectionData::CConnectionData(CConnectionData* pConnectData) : CADsObject(pConnectData)
  111. {
  112. // Path data
  113. //
  114. m_sBasePath = pConnectData->m_sBasePath;
  115. m_sDomainServer = pConnectData->m_sDomainServer;
  116. m_sPort = pConnectData->m_sPort;
  117. m_sDistinguishedName = pConnectData->m_sDistinguishedName;
  118. m_sNamingContext = pConnectData->m_sNamingContext;
  119. m_sLDAP = pConnectData->m_sLDAP;
  120. m_sSchemaPath = pConnectData->m_sSchemaPath;
  121. m_sAbstractSchemaPath = pConnectData->m_sAbstractSchemaPath;
  122. // Filter
  123. //
  124. m_pFilterObject = new CADSIFilterObject(pConnectData->m_pFilterObject);
  125. // Credentials
  126. //
  127. m_pCredentialsObject = new CCredentialObject(pConnectData->m_pCredentialsObject);
  128. m_bRootDSE = pConnectData->m_bRootDSE;
  129. m_bUserDefinedServer = pConnectData->m_bUserDefinedServer;
  130. m_pDirObject = NULL;
  131. m_nMaxObjectCount = pConnectData->m_nMaxObjectCount;
  132. }
  133. CConnectionData::~CConnectionData()
  134. {
  135. if (m_pDirObject != NULL)
  136. {
  137. m_pDirObject->Release();
  138. }
  139. delete m_pCredentialsObject;
  140. delete m_pFilterObject;
  141. }
  142. void CConnectionData::Save(IStream* pStm)
  143. {
  144. SaveStringToStream(pStm, m_sBasePath);
  145. if (m_bUserDefinedServer)
  146. {
  147. SaveStringToStream(pStm, m_sDomainServer);
  148. }
  149. else
  150. {
  151. SaveStringToStream(pStm, _T(""));
  152. }
  153. SaveStringToStream(pStm, m_sPort);
  154. SaveStringToStream(pStm, m_sDistinguishedName);
  155. SaveStringToStream(pStm, m_sNamingContext);
  156. SaveStringToStream(pStm, m_sLDAP);
  157. CString sName;
  158. GetName(sName);
  159. SaveStringToStream(pStm, sName);
  160. if (m_bUserDefinedServer)
  161. {
  162. CString sPath;
  163. GetPath(sPath);
  164. SaveStringToStream(pStm, sPath);
  165. }
  166. else
  167. {
  168. SaveStringToStream(pStm, _T(""));
  169. }
  170. CString sClass;
  171. GetClass(sClass);
  172. SaveStringToStream(pStm, sClass);
  173. ULONG cbWrite;
  174. BOOL bUseCredentials = m_pCredentialsObject->UseCredentials();
  175. VERIFY(SUCCEEDED(pStm->Write((void*)&bUseCredentials, sizeof(UINT),&cbWrite)));
  176. ASSERT(cbWrite == sizeof(UINT));
  177. VERIFY(SUCCEEDED(pStm->Write((void*)&m_bRootDSE, sizeof(UINT),&cbWrite)));
  178. ASSERT(cbWrite == sizeof(UINT));
  179. GetFilter()->Save(pStm);
  180. BOOL bContainer = GetContainer();
  181. VERIFY(SUCCEEDED(pStm->Write((void*)&bContainer, sizeof(UINT),&cbWrite)));
  182. ASSERT(cbWrite == sizeof(UINT));
  183. ULONG nMaxNum = GetMaxObjectCount();
  184. VERIFY(SUCCEEDED(pStm->Write((void*)&nMaxNum, sizeof(ULONG),&cbWrite)));
  185. ASSERT(cbWrite == sizeof(ULONG));
  186. }
  187. CConnectionData* CConnectionData::Load(IStream* pStm)
  188. {
  189. // FUTURE-2002/03/04-artm Variable szBuffer does not appear to be used.
  190. WCHAR szBuffer[256]; // REVIEW_MARCOC: hardcoded
  191. ULONG nLen; // WCHAR counting NULL
  192. ULONG cbRead;
  193. CConnectionData* pConnectData = new CConnectionData();
  194. LoadStringFromStream(pStm, pConnectData->m_sBasePath);
  195. LoadStringFromStream(pStm, pConnectData->m_sDomainServer);
  196. LoadStringFromStream(pStm, pConnectData->m_sPort);
  197. LoadStringFromStream(pStm, pConnectData->m_sDistinguishedName);
  198. LoadStringFromStream(pStm, pConnectData->m_sNamingContext);
  199. LoadStringFromStream(pStm, pConnectData->m_sLDAP);
  200. CString sString;
  201. CString szConnectionName;
  202. LoadStringFromStream(pStm, szConnectionName);
  203. pConnectData->SetName(szConnectionName);
  204. LoadStringFromStream(pStm, sString);
  205. pConnectData->SetPath(sString);
  206. LoadStringFromStream(pStm, sString);
  207. pConnectData->SetClass(sString);
  208. VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
  209. ASSERT(cbRead == sizeof(UINT));
  210. pConnectData->GetCredentialObject()->SetUseCredentials(nLen);
  211. VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
  212. ASSERT(cbRead == sizeof(UINT));
  213. pConnectData->SetRootDSE(nLen);
  214. CADSIFilterObject* pFilterObject;
  215. HRESULT hr = CADSIFilterObject::CreateFilterFromStream(pStm, &pFilterObject);
  216. if (SUCCEEDED(hr))
  217. {
  218. pConnectData->SetFilter(pFilterObject);
  219. }
  220. VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
  221. ASSERT(cbRead == sizeof(UINT));
  222. pConnectData->SetContainer(nLen);
  223. ULONG nMaxCount;
  224. VERIFY(SUCCEEDED(pStm->Read((void*)&nMaxCount,sizeof(ULONG), &cbRead)));
  225. ASSERT(cbRead == sizeof(ULONG));
  226. pConnectData->SetMaxObjectCount(nMaxCount);
  227. if (pConnectData->m_sNamingContext != L"")
  228. {
  229. hr = LoadBasePathFromContext(pConnectData, pConnectData->m_sNamingContext);
  230. if (FAILED(hr))
  231. {
  232. CString szHrErr;
  233. GetErrorMessage(hr, szHrErr);
  234. CString szFormatErr;
  235. VERIFY(szFormatErr.LoadString(IDS_ERRMSG_FAILED_CONNECTION));
  236. CString szMessage;
  237. szMessage.Format(szFormatErr, szConnectionName, szHrErr);
  238. ADSIEditErrorMessage(szMessage);
  239. return pConnectData;
  240. }
  241. }
  242. if (pConnectData->m_sDomainServer == L"")
  243. {
  244. hr = GetServerNameFromDefault(pConnectData);
  245. if (FAILED(hr))
  246. {
  247. CString szHrErr;
  248. GetErrorMessage(hr, szHrErr);
  249. CString szFormatErr;
  250. VERIFY(szFormatErr.LoadString(IDS_ERRMSG_FAILED_CONNECTION));
  251. CString szMessage;
  252. szMessage.Format(szFormatErr, szConnectionName, szHrErr);
  253. ADSIEditErrorMessage(szMessage);
  254. }
  255. pConnectData->BuildPath();
  256. }
  257. return pConnectData;
  258. }
  259. void CConnectionData::BuildPath()
  260. {
  261. // Get data from connection node
  262. //
  263. CString sServer, sLDAP, sPort, path;
  264. GetDomainServer(sServer);
  265. GetLDAP(sLDAP);
  266. GetPort(sPort);
  267. if (sServer == _T(""))
  268. {
  269. path = sLDAP + path;
  270. }
  271. else
  272. {
  273. if (sPort == _T(""))
  274. {
  275. path = sServer + _T("/") + path;
  276. }
  277. else
  278. {
  279. path = sServer + _T(":") + sPort + _T("/") + path;
  280. }
  281. path = sLDAP + path;
  282. }
  283. path += m_sBasePath;
  284. if (IsRootDSE())
  285. {
  286. path += g_lpszRootDSE;
  287. }
  288. SetPath(path);
  289. }
  290. HRESULT CConnectionData::GetServerNameFromDefault(CConnectionData* pConnectData)
  291. {
  292. CString sSchemaPath, szServerName;
  293. HRESULT hr = pConnectData->GetSchemaPath(sSchemaPath);
  294. if (FAILED(hr))
  295. {
  296. return hr;
  297. }
  298. CComPtr<IADs> spConfig;
  299. hr = OpenObjectWithCredentials (pConnectData->GetCredentialObject(),
  300. sSchemaPath,
  301. IID_IADs,
  302. (LPVOID*)&spConfig
  303. );
  304. if (FAILED(hr))
  305. {
  306. TRACE(L"Failed ADsOpenObject(%s) on naming context\n", (LPCWSTR)sSchemaPath);
  307. return hr;
  308. }
  309. hr = pConnectData->GetADSIServerName(szServerName, spConfig);
  310. if (FAILED(hr))
  311. {
  312. TRACE(L"Failed GetADSIServerName(%s)\n", (LPCWSTR)szServerName);
  313. return hr;
  314. }
  315. pConnectData->SetDomainServer(szServerName);
  316. pConnectData->SetUserDefinedServer(FALSE);
  317. return hr;
  318. }
  319. HRESULT CConnectionData::GetADSIServerName(OUT CString& szServer, IN IUnknown* pUnk)
  320. {
  321. szServer.Empty();
  322. CComPtr<IADsObjectOptions> spIADsObjectOptions;
  323. HRESULT hr = pUnk->QueryInterface(IID_IADsObjectOptions, (void**)&spIADsObjectOptions);
  324. if (FAILED(hr))
  325. return hr;
  326. CComVariant var;
  327. hr = spIADsObjectOptions->GetOption(ADS_OPTION_SERVERNAME, &var);
  328. if (FAILED(hr))
  329. return hr;
  330. ASSERT(var.vt == VT_BSTR);
  331. szServer = V_BSTR(&var);
  332. return hr;
  333. }
  334. HRESULT CConnectionData::LoadBasePathFromContext(CConnectionData* pConnectData, const CString sContext)
  335. {
  336. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  337. CString sContextPath, szSchema, szDomain, szConfig, szRootDSE;
  338. if ( !szSchema.LoadString(IDS_SCHEMA) ||
  339. !szDomain.LoadString(IDS_DOMAIN_NC) ||
  340. !szConfig.LoadString(IDS_CONFIG_CONTAINER) ||
  341. !szRootDSE.LoadString(IDS_ROOTDSE))
  342. {
  343. ADSIEditMessageBox(IDS_MSG_FAIL_TO_LOAD, MB_OK);
  344. return S_FALSE;
  345. }
  346. if (sContext == szSchema)
  347. {
  348. sContextPath = L"schemaNamingContext";
  349. }
  350. else if (sContext == szDomain)
  351. {
  352. sContextPath = L"defaultNamingContext";
  353. }
  354. else if (sContext == szConfig)
  355. {
  356. sContextPath = L"configurationNamingContext";
  357. }
  358. else // RootDSE
  359. {
  360. return S_FALSE;
  361. }
  362. // Get data from connection node
  363. //
  364. CString sRootDSE, sServer, sPort, sLDAP;
  365. pConnectData->GetDomainServer(sServer);
  366. pConnectData->GetLDAP(sLDAP);
  367. pConnectData->GetPort(sPort);
  368. if (sServer != _T(""))
  369. {
  370. sRootDSE = sLDAP + sServer;
  371. if (sPort != _T(""))
  372. {
  373. sRootDSE = sRootDSE + _T(":") + sPort + _T("/");
  374. }
  375. else
  376. {
  377. sRootDSE = sRootDSE + _T("/");
  378. }
  379. sRootDSE = sRootDSE + g_lpszRootDSE;
  380. }
  381. else
  382. {
  383. sRootDSE = sLDAP + g_lpszRootDSE;
  384. }
  385. CComPtr<IADs> pADs;
  386. HRESULT hr, hCredResult;
  387. hr = OpenObjectWithCredentials(
  388. pConnectData,
  389. pConnectData->GetCredentialObject()->UseCredentials(),
  390. sRootDSE,
  391. IID_IADs,
  392. (LPVOID*) &pADs,
  393. NULL,
  394. hCredResult
  395. );
  396. if ( FAILED(hr) )
  397. {
  398. if (SUCCEEDED(hCredResult))
  399. {
  400. return hr;
  401. }
  402. return hCredResult;
  403. }
  404. VARIANT var;
  405. VariantInit(&var);
  406. hr = pADs->Get( CComBSTR(sContextPath), &var );
  407. if ( FAILED(hr) )
  408. {
  409. VariantClear(&var);
  410. return hr;
  411. }
  412. BSTR bstrItem = V_BSTR(&var);
  413. pConnectData->m_sBasePath = bstrItem;
  414. VariantClear(&var);
  415. return hr;
  416. }
  417. HRESULT CConnectionData::GetSchemaPath(CString& sSchemaPath)
  418. {
  419. CString sLDAP, sServer, sPort, sTemp;
  420. GetLDAP(sLDAP);
  421. GetDomainServer(sServer);
  422. GetPort(sPort);
  423. HRESULT hr = GetItemFromRootDSE(_T("schemaNamingContext"), sSchemaPath, this);
  424. if (FAILED(hr))
  425. {
  426. return hr;
  427. }
  428. if (sServer != _T(""))
  429. {
  430. sTemp = sLDAP + sServer;
  431. if (sPort != _T(""))
  432. {
  433. sTemp = sTemp + _T(":") + sPort + _T("/");
  434. }
  435. else
  436. {
  437. sTemp = sTemp + _T("/");
  438. }
  439. sSchemaPath = sTemp + sSchemaPath;
  440. }
  441. else
  442. {
  443. sSchemaPath = sLDAP + sSchemaPath;
  444. }
  445. m_sSchemaPath = sSchemaPath;
  446. return S_OK;
  447. }
  448. void CConnectionData::GetAbstractSchemaPath(CString& sSchemaPath)
  449. {
  450. if (m_sAbstractSchemaPath == _T(""))
  451. {
  452. if (m_sDomainServer != _T(""))
  453. {
  454. sSchemaPath = m_sLDAP + m_sDomainServer;
  455. if (m_sPort != _T(""))
  456. {
  457. sSchemaPath = sSchemaPath + _T(":") + m_sPort + _T("/");
  458. }
  459. else
  460. {
  461. sSchemaPath = sSchemaPath + _T("/");
  462. }
  463. sSchemaPath = sSchemaPath + _T("schema") + _T("/");
  464. }
  465. else
  466. {
  467. sSchemaPath = m_sLDAP + _T("schema") + _T("/");
  468. }
  469. m_sAbstractSchemaPath = sSchemaPath;
  470. }
  471. else
  472. {
  473. sSchemaPath = m_sAbstractSchemaPath;
  474. }
  475. }
  476. void CConnectionData::GetBaseLDAPPath(CString& sBasePath)
  477. {
  478. if (m_sDomainServer == _T(""))
  479. {
  480. sBasePath = m_sLDAP + sBasePath;
  481. }
  482. else
  483. {
  484. if (m_sPort == _T(""))
  485. {
  486. sBasePath = m_sDomainServer + _T("/") + sBasePath;
  487. }
  488. else
  489. {
  490. sBasePath = m_sDomainServer + _T(":") + m_sPort + _T("/") + sBasePath;
  491. }
  492. sBasePath = m_sLDAP + sBasePath;
  493. }
  494. }
  495. void CConnectionData::SetIDirectoryInterface(IDirectoryObject* pDirObject)
  496. {
  497. if (m_pDirObject != NULL)
  498. {
  499. m_pDirObject->Release();
  500. m_pDirObject = NULL;
  501. }
  502. if (pDirObject != NULL)
  503. {
  504. m_pDirObject = pDirObject;
  505. m_pDirObject->AddRef();
  506. }
  507. }
  508. ///////////////////////////////////////////////////////////////////////////////
  509. // CADSIFilterObject
  510. CADSIFilterObject::CADSIFilterObject()
  511. {
  512. m_bInUse = FALSE;
  513. }
  514. CADSIFilterObject::CADSIFilterObject(CADSIFilterObject* pFilterObject)
  515. {
  516. m_sFilterString = pFilterObject->m_sFilterString;
  517. m_sUserFilter = pFilterObject->m_sUserFilter;
  518. CopyStringList(&m_ContainerList, &(pFilterObject->m_ContainerList));
  519. m_bInUse = pFilterObject->m_bInUse;
  520. }
  521. void CADSIFilterObject::GetFilterString(CString& sFilterString)
  522. {
  523. if (m_bInUse)
  524. {
  525. if (m_ContainerList.GetCount() != 0)
  526. {
  527. sFilterString = _T("(|") + m_sUserFilter;
  528. POSITION pos = m_ContainerList.GetHeadPosition();
  529. while (pos != NULL)
  530. {
  531. CString sContainer = m_ContainerList.GetNext(pos);
  532. sFilterString += _T("(objectCategory=") + sContainer + _T(")");
  533. }
  534. sFilterString += _T(")");
  535. }
  536. else
  537. {
  538. sFilterString = m_sUserFilter;
  539. }
  540. m_sFilterString = sFilterString;
  541. }
  542. else
  543. {
  544. sFilterString = L"(objectClass=*)";
  545. }
  546. }
  547. void CADSIFilterObject::Save(IStream* pStm)
  548. {
  549. ULONG cbWrite;
  550. ULONG nLen;
  551. BOOL bInUse = InUse();
  552. VERIFY(SUCCEEDED(pStm->Write((void*)&bInUse, sizeof(UINT),&cbWrite)));
  553. ASSERT(cbWrite == sizeof(UINT));
  554. if (InUse())
  555. {
  556. SaveStringToStream(pStm, m_sUserFilter);
  557. SaveStringListToStream(pStm, m_ContainerList);
  558. }
  559. }
  560. HRESULT CADSIFilterObject::CreateFilterFromStream(IStream* pStm,
  561. CADSIFilterObject** ppFilterObject)
  562. {
  563. ULONG nLen; // WCHAR counting NULL
  564. ULONG cbRead;
  565. *ppFilterObject = new CADSIFilterObject();
  566. VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
  567. ASSERT(cbRead == sizeof(UINT));
  568. (*ppFilterObject)->SetInUse(nLen);
  569. if ((*ppFilterObject)->InUse())
  570. {
  571. CString sUserFilter;
  572. LoadStringFromStream(pStm, sUserFilter);
  573. (*ppFilterObject)->SetUserDefinedFilter(sUserFilter);
  574. CStringList sContainerFilter;
  575. LoadStringListFromStream(pStm, sContainerFilter);
  576. (*ppFilterObject)->SetContainerList(&sContainerFilter);
  577. }
  578. return S_OK;
  579. }
  580. ////////////////////////////////////////////////////////////////////////
  581. // CADSIEditContainerNode
  582. //
  583. // {8690ABBB-CFF7-11d2-8801-00C04F72ED31}
  584. const GUID CADSIEditContainerNode::NodeTypeGUID =
  585. { 0x8690abbb, 0xcff7, 0x11d2, { 0x88, 0x1, 0x0, 0xc0, 0x4f, 0x72, 0xed, 0x31 } };
  586. CADSIEditContainerNode::CADSIEditContainerNode(CADsObject* pADsObject)
  587. : m_pPartitionsColumnSet(NULL)
  588. {
  589. m_pADsObject = pADsObject;
  590. m_nState = notLoaded;
  591. m_szDescriptionText = L"";
  592. }
  593. CADSIEditContainerNode::CADSIEditContainerNode(CADSIEditContainerNode* pContNode)
  594. : m_pPartitionsColumnSet(NULL)
  595. {
  596. m_pADsObject = new CADsObject(pContNode->m_pADsObject);
  597. m_nState = notLoaded;
  598. CString sName;
  599. m_pADsObject->GetName(sName);
  600. SetDisplayName(sName);
  601. m_szDescriptionText = L"";
  602. }
  603. HRESULT CADSIEditContainerNode::OnCommand(long nCommandID,
  604. DATA_OBJECT_TYPES type,
  605. CComponentDataObject* pComponentData,
  606. CNodeList* pNodeList)
  607. {
  608. ASSERT(pNodeList->GetCount() == 1); // for now I am not allowing multiple selection for any of these
  609. switch (nCommandID)
  610. {
  611. case IDM_MOVE :
  612. OnMove(pComponentData);
  613. break;
  614. case IDM_NEW_OBJECT :
  615. OnCreate(pComponentData);
  616. break;
  617. case IDM_NEW_CONNECT_FROM_HERE :
  618. OnConnectFromHere(pComponentData);
  619. break;
  620. case IDM_NEW_NC_CONNECT_FROM_HERE :
  621. OnConnectToNCFromHere(pComponentData);
  622. break;
  623. default:
  624. ASSERT(FALSE); // Unknown command!
  625. return E_FAIL;
  626. }
  627. return S_OK;
  628. }
  629. void CADSIEditContainerNode::OnConnectFromHere(CComponentDataObject* pComponentData)
  630. {
  631. //
  632. // Retrieve the path to create the connection at
  633. //
  634. CADsObject* pADsObject = GetADsObject();
  635. CString szDN, szPath, szName;
  636. pADsObject->GetDN(szDN);
  637. pADsObject->GetPath(szPath);
  638. pADsObject->GetName(szName);
  639. //
  640. // Create the new connection node
  641. //
  642. CConnectionData* pConnectData = pADsObject->GetConnectionNode()->GetConnectionData();
  643. CADSIEditConnectionNode* pNewConnectNode = new CADSIEditConnectionNode(pConnectData);
  644. pNewConnectNode->SetDisplayName(GetDisplayName());
  645. pNewConnectNode->GetConnectionData()->SetBasePath(szDN);
  646. pNewConnectNode->GetConnectionData()->SetDistinguishedName(szDN);
  647. pNewConnectNode->GetConnectionData()->SetNamingContext(L"");
  648. pNewConnectNode->GetConnectionData()->SetDN(szDN);
  649. pNewConnectNode->GetConnectionData()->SetPath(szPath);
  650. pNewConnectNode->GetConnectionData()->SetName(szName);
  651. //
  652. // Add the new connection node to the root container
  653. //
  654. CADSIEditRootData* pRootData = (CADSIEditRootData*)pComponentData->GetRootData();
  655. BOOL bResult = pRootData->AddChildToListAndUI(pNewConnectNode, pComponentData);
  656. ASSERT(bResult);
  657. //
  658. // Select the new connection node
  659. //
  660. pComponentData->UpdateResultPaneView(pNewConnectNode);
  661. }
  662. void CADSIEditContainerNode::OnConnectToNCFromHere(CComponentDataObject* pComponentData)
  663. {
  664. //
  665. // Retrieve the path to create the connection at
  666. //
  667. CADsObject* pADsObject = GetADsObject();
  668. CString szDN, szPath, szName, szNCName;
  669. pADsObject->GetDN(szDN);
  670. pADsObject->GetPath(szPath);
  671. pADsObject->GetName(szName);
  672. szNCName = pADsObject->GetNCName();
  673. ASSERT(!szNCName.IsEmpty());
  674. if (!szNCName.IsEmpty())
  675. {
  676. //
  677. // Create the new connection node
  678. //
  679. HRESULT hr = S_OK;
  680. CConnectionData* pConnectData = pADsObject->GetConnectionNode()->GetConnectionData();
  681. CADSIEditConnectionNode* pNewConnectNode = new CADSIEditConnectionNode(pConnectData);
  682. if (pNewConnectNode)
  683. {
  684. pNewConnectNode->SetDisplayName(GetDisplayName());
  685. pNewConnectNode->GetConnectionData()->SetBasePath(szNCName);
  686. pNewConnectNode->GetConnectionData()->SetDistinguishedName(szNCName);
  687. pNewConnectNode->GetConnectionData()->SetNamingContext(L"");
  688. pNewConnectNode->GetConnectionData()->SetDN(szNCName);
  689. pNewConnectNode->GetConnectionData()->SetName(szNCName);
  690. CString szServer, szProvider;
  691. pConnectData->GetDomainServer(szServer);
  692. pConnectData->GetLDAP(szProvider);
  693. do // false loop
  694. {
  695. //
  696. // Crack the path to get the path to the new NC
  697. //
  698. CComPtr<IADsPathname> spPathCracker;
  699. hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  700. IID_IADsPathname, (PVOID *)&(spPathCracker));
  701. if (FAILED(hr))
  702. {
  703. ADSIEditErrorMessage(hr);
  704. break;
  705. }
  706. hr = spPathCracker->Set(CComBSTR(szNCName), ADS_SETTYPE_DN);
  707. if (FAILED(hr))
  708. {
  709. ADSIEditErrorMessage(hr);
  710. break;
  711. }
  712. hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL);
  713. if (FAILED(hr))
  714. {
  715. ADSIEditErrorMessage(hr);
  716. break;
  717. }
  718. hr = spPathCracker->Set(CComBSTR((PCWSTR)szServer), ADS_SETTYPE_SERVER);
  719. if (FAILED(hr))
  720. {
  721. ADSIEditErrorMessage(hr);
  722. break;
  723. }
  724. hr = spPathCracker->Set(CComBSTR(L"LDAP"), ADS_SETTYPE_PROVIDER);
  725. if (FAILED(hr))
  726. {
  727. ADSIEditErrorMessage(hr);
  728. break;
  729. }
  730. CComBSTR sbstrNewPath;
  731. hr = spPathCracker->Retrieve(ADS_FORMAT_X500, &sbstrNewPath);
  732. if (FAILED(hr))
  733. {
  734. ADSIEditErrorMessage(hr);
  735. break;
  736. }
  737. pNewConnectNode->GetConnectionData()->SetPath(sbstrNewPath);
  738. //
  739. // Add the new connection node to the root container
  740. //
  741. CADSIEditRootData* pRootData = (CADSIEditRootData*)pComponentData->GetRootData();
  742. BOOL bResult = pRootData->AddChildToListAndUI(pNewConnectNode, pComponentData);
  743. ASSERT(bResult);
  744. //
  745. // Select the new connection node
  746. //
  747. pComponentData->UpdateResultPaneView(pNewConnectNode);
  748. } while (false);
  749. if (FAILED(hr))
  750. {
  751. delete pNewConnectNode;
  752. pNewConnectNode = 0;
  753. }
  754. }
  755. }
  756. }
  757. HRESULT CADSIEditContainerNode::OnRename(CComponentDataObject* pComponentData,
  758. LPWSTR lpszNewName)
  759. {
  760. HRESULT hr = S_OK;
  761. BOOL bLocked = IsThreadLocked();
  762. ASSERT(!bLocked); // cannot do refresh on locked node, the UI should prevent this
  763. if (bLocked)
  764. return hr;
  765. if (IsSheetLocked())
  766. {
  767. if (!CanCloseSheets())
  768. return S_FALSE;
  769. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  770. }
  771. ASSERT(!IsSheetLocked());
  772. CString szPath, szOldPath;
  773. CADsObject* pADsObject = GetADsObject();
  774. pADsObject->GetPath(szPath);
  775. szOldPath = szPath;
  776. CADSIEditConnectionNode* pConnectionNode = pADsObject->GetConnectionNode();
  777. CConnectionData* pConnectData = pConnectionNode->GetConnectionData();
  778. CComPtr<IADsPathname> spPathCracker;
  779. hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  780. IID_IADsPathname, (PVOID *)&(spPathCracker));
  781. if (FAILED(hr))
  782. {
  783. ADSIEditErrorMessage(hr);
  784. return S_FALSE;
  785. }
  786. hr = spPathCracker->Set(CComBSTR(szPath), ADS_SETTYPE_FULL);
  787. if (FAILED(hr))
  788. {
  789. ADSIEditErrorMessage(hr);
  790. return S_FALSE;
  791. }
  792. hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL);
  793. if (FAILED(hr))
  794. {
  795. ADSIEditErrorMessage(hr);
  796. return S_FALSE;
  797. }
  798. CComBSTR bstrOldLeaf;
  799. hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstrOldLeaf);
  800. if (FAILED(hr))
  801. {
  802. ADSIEditErrorMessage(hr);
  803. return S_FALSE;
  804. }
  805. CString szOldLeaf = bstrOldLeaf;
  806. CString szPrefix;
  807. szPrefix = szOldLeaf.Left(szOldLeaf.Find(L'=') + 1);
  808. hr = spPathCracker->RemoveLeafElement();
  809. if (FAILED(hr))
  810. {
  811. ADSIEditErrorMessage(hr);
  812. return S_FALSE;
  813. }
  814. CComBSTR bstrParentPath;
  815. hr = spPathCracker->Retrieve(ADS_FORMAT_X500, &bstrParentPath);
  816. if (FAILED(hr))
  817. {
  818. ADSIEditErrorMessage(hr);
  819. return S_FALSE;
  820. }
  821. CComPtr<IADsContainer> spDestination;
  822. CString sContPath(bstrParentPath);
  823. hr = OpenObjectWithCredentials(
  824. pConnectData->GetCredentialObject(),
  825. bstrParentPath,
  826. IID_IADsContainer,
  827. (LPVOID*) &spDestination
  828. );
  829. if (FAILED(hr))
  830. {
  831. ADSIEditErrorMessage(hr);
  832. return S_FALSE;
  833. }
  834. //
  835. // Place the prefix in front of the name if it wasn't typed in by
  836. // the user
  837. //
  838. CString szNewLeaf, szNewName = lpszNewName;
  839. if (szNewName.Find(L'=') == -1)
  840. {
  841. szNewLeaf = szPrefix + lpszNewName;
  842. }
  843. else
  844. {
  845. szNewLeaf = lpszNewName;
  846. }
  847. hr = spPathCracker->AddLeafElement(CComBSTR(szNewLeaf));
  848. if (FAILED(hr))
  849. {
  850. ADSIEditErrorMessage(hr);
  851. return S_FALSE;
  852. }
  853. CComPtr<IDispatch> spObject;
  854. hr = spDestination->MoveHere(CComBSTR(szOldPath),
  855. CComBSTR(szNewLeaf),
  856. &spObject);
  857. if (FAILED(hr))
  858. {
  859. ADSIEditErrorMessage(hr);
  860. return S_FALSE;
  861. }
  862. CComPtr<IADs> spIADs;
  863. hr = spObject->QueryInterface(IID_IADs, (LPVOID*)&spIADs);
  864. if (FAILED(hr))
  865. {
  866. ADSIEditErrorMessage(hr);
  867. return S_FALSE;
  868. }
  869. CComBSTR bstrPath;
  870. hr = spIADs->get_ADsPath(&bstrPath);
  871. if (FAILED(hr))
  872. {
  873. ADSIEditErrorMessage(hr);
  874. return S_FALSE;
  875. }
  876. CComBSTR bstrDN;
  877. hr = spPathCracker->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  878. if (FAILED(hr))
  879. {
  880. ADSIEditErrorMessage(hr);
  881. return S_FALSE;
  882. }
  883. CComBSTR bstrLeaf;
  884. hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstrLeaf);
  885. if (FAILED(hr))
  886. {
  887. ADSIEditErrorMessage(hr);
  888. return S_FALSE;
  889. }
  890. GetADsObject()->SetPath(bstrPath);
  891. GetADsObject()->SetName(bstrLeaf);
  892. GetADsObject()->SetDN(bstrDN);
  893. SetDisplayName(bstrLeaf);
  894. CNodeList nodeList;
  895. nodeList.AddTail(this);
  896. OnRefresh(pComponentData, &nodeList);
  897. return hr;
  898. }
  899. void CADSIEditContainerNode::RefreshOverlappedTrees(CString& szPath, CComponentDataObject* pComponentData)
  900. {
  901. //
  902. // REVIEW_JEFFJON : need to revisit this. I am getting different behavior for
  903. // different verbs
  904. //
  905. //
  906. // Refresh any other subtrees of connections that contain this node
  907. //
  908. CList<CTreeNode*, CTreeNode*> foundNodeList;
  909. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(GetRootContainer());
  910. if (pRootNode != NULL)
  911. {
  912. BOOL bFound = pRootNode->FindNode(szPath, foundNodeList);
  913. if (bFound)
  914. {
  915. POSITION pos = foundNodeList.GetHeadPosition();
  916. while (pos != NULL)
  917. {
  918. CADSIEditContainerNode* pFoundContNode = dynamic_cast<CADSIEditContainerNode*>(foundNodeList.GetNext(pos));
  919. if (pFoundContNode != NULL)
  920. {
  921. if (pFoundContNode->IsSheetLocked())
  922. {
  923. if (!pFoundContNode->CanCloseSheets())
  924. continue;
  925. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(pFoundContNode);
  926. }
  927. ASSERT(!pFoundContNode->IsSheetLocked());
  928. CNodeList nodeList;
  929. nodeList.AddTail(pFoundContNode);
  930. pFoundContNode->GetContainer()->OnRefresh(pComponentData, &nodeList);
  931. }
  932. }
  933. }
  934. }
  935. }
  936. void CADSIEditContainerNode::OnCreate(CComponentDataObject* pComponentData)
  937. {
  938. CThemeContextActivator activator;
  939. CCreatePageHolder* pHolder = new CCreatePageHolder(GetContainer(), this, pComponentData);
  940. ASSERT(pHolder != NULL);
  941. pHolder->SetSheetTitle(IDS_PROP_CONTAINER_TITLE, this);
  942. pHolder->DoModalWizard();
  943. }
  944. void CADSIEditContainerNode::OnMove(CComponentDataObject* pComponentData)
  945. {
  946. BOOL bLocked = IsThreadLocked();
  947. ASSERT(!bLocked); // cannot do refresh on locked node, the UI should prevent this
  948. if (bLocked)
  949. return;
  950. if (IsSheetLocked())
  951. {
  952. if (!CanCloseSheets())
  953. return;
  954. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  955. }
  956. ASSERT(!IsSheetLocked());
  957. HRESULT hr = S_OK, hCredResult;
  958. DWORD result;
  959. CComPtr<IADsContainer> pDSDestination = NULL;
  960. CComPtr<IDispatch> pDSObject = NULL;
  961. CString strDestPath;
  962. CString strTitle;
  963. strTitle.LoadString (IDS_MOVE_TITLE);
  964. DSBROWSEINFO dsbi;
  965. ::ZeroMemory( &dsbi, sizeof(dsbi) );
  966. TCHAR szPath[MAX_PATH+1];
  967. CString str;
  968. str.LoadString(IDS_MOVE_TARGET);
  969. CADSIEditConnectionNode* pConnectNode = GetADsObject()->GetConnectionNode();
  970. CCredentialObject* pCredObject = pConnectNode->GetConnectionData()->GetCredentialObject();
  971. CString strRootPath;
  972. GetADsObject()->GetConnectionNode()->GetADsObject()->GetPath(strRootPath);
  973. dsbi.hwndOwner = NULL;
  974. dsbi.cbStruct = sizeof (DSBROWSEINFO);
  975. dsbi.pszCaption = (LPWSTR)((LPCWSTR)strTitle); // this is actually the caption
  976. dsbi.pszTitle = (LPWSTR)((LPCWSTR)str);
  977. dsbi.pszRoot = strRootPath;
  978. dsbi.pszPath = szPath;
  979. dsbi.cchPath = (sizeof(szPath) / sizeof(TCHAR));
  980. dsbi.dwFlags = DSBI_INCLUDEHIDDEN | DSBI_RETURN_FORMAT;
  981. dsbi.pfnCallback = NULL;
  982. dsbi.lParam = 0;
  983. // dsbi.dwReturnFormat = ADS_FORMAT_X500;
  984. // Specify credentials
  985. CString sUserName;
  986. EncryptedString password;
  987. // NOTICE-NTRAID#NTBUG9-563071-2002/04/15-artm Temp. password buffer should not be held on stack.
  988. // Rewrote to use encrypted string class. This has advantage of forcing
  989. // us to zero out the clear text copy (by calling DestroyClearTextCopy()) as well
  990. // as managing the memory for the password. See bug description for why it
  991. // was a _bad_ thing to hold clear text copy on the stack.
  992. WCHAR* cleartext = NULL;
  993. if (pCredObject->UseCredentials())
  994. {
  995. pCredObject->GetUsername(sUserName);
  996. password = pCredObject->GetPassword();
  997. // This should never happen, but we'll check anyways.
  998. ASSERT(password.GetLength() <= MAX_PASSWORD_LENGTH);
  999. dsbi.dwFlags |= DSBI_HASCREDENTIALS;
  1000. dsbi.pUserName = sUserName;
  1001. cleartext = password.GetClearTextCopy();
  1002. // Clear text version of password can be NULL if we're out
  1003. // of memory. Let the user know that bad things are happening.
  1004. if (NULL == cleartext)
  1005. {
  1006. password.DestroyClearTextCopy(cleartext);
  1007. ADSIEditErrorMessage(E_OUTOFMEMORY);
  1008. return;
  1009. }
  1010. dsbi.pPassword = cleartext;
  1011. }
  1012. result = DsBrowseForContainer( &dsbi );
  1013. // Clean up any clear text copies.
  1014. if (pCredObject->UseCredentials())
  1015. {
  1016. password.DestroyClearTextCopy(cleartext);
  1017. cleartext = NULL;
  1018. }
  1019. if ( result == IDOK )
  1020. { // returns -1, 0, IDOK or IDCANCEL
  1021. // get path from BROWSEINFO struct, put in text edit field
  1022. TRACE(_T("returned from DS Browse successfully with:\n %s\n"),
  1023. dsbi.pszPath);
  1024. strDestPath = dsbi.pszPath;
  1025. // See if the destination is the same as the current parent. If so, do nothing
  1026. CADSIEditContainerNode* pContainer = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  1027. if (pContainer)
  1028. {
  1029. CString szPath;
  1030. pContainer->GetADsObject()->GetPath(szPath);
  1031. if (szPath == strDestPath)
  1032. {
  1033. // No reason to do anything if the source and the destination are the same
  1034. return;
  1035. }
  1036. }
  1037. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1038. hr = OpenObjectWithCredentials(
  1039. pConnectData,
  1040. pConnectData->GetCredentialObject()->UseCredentials(),
  1041. strDestPath,
  1042. IID_IADsContainer,
  1043. (LPVOID*) &pDSDestination,
  1044. NULL,
  1045. hCredResult
  1046. );
  1047. if (FAILED(hr))
  1048. {
  1049. if (SUCCEEDED(hCredResult))
  1050. {
  1051. ADSIEditErrorMessage(hr);
  1052. }
  1053. return;
  1054. }
  1055. CString sCurrentPath;
  1056. GetADsObject()->GetPath(sCurrentPath);
  1057. hr = pDSDestination->MoveHere(CComBSTR(sCurrentPath),
  1058. NULL,
  1059. &pDSObject);
  1060. if (FAILED(hr))
  1061. {
  1062. ADSIEditErrorMessage(hr);
  1063. return;
  1064. }
  1065. DeleteHelper(pComponentData);
  1066. // RefreshOverlappedTrees(sCurrentPath, pComponentData);
  1067. // RefreshOverlappedTrees(strDestPath, pComponentData);
  1068. delete this;
  1069. }
  1070. }
  1071. BOOL CADSIEditContainerNode::OnSetRenameVerbState(DATA_OBJECT_TYPES type,
  1072. BOOL* pbHideVerb,
  1073. CNodeList* pNodeList)
  1074. {
  1075. ASSERT(pNodeList->GetCount() == 1);
  1076. if (GetADsObject()->GetConnectionNode()->GetConnectionData()->IsGC())
  1077. {
  1078. *pbHideVerb = TRUE; // always hide the verb
  1079. return FALSE;
  1080. }
  1081. *pbHideVerb = FALSE; // always show the verb
  1082. return TRUE;
  1083. }
  1084. BOOL CADSIEditContainerNode::OnSetDeleteVerbState(DATA_OBJECT_TYPES type,
  1085. BOOL* pbHideVerb,
  1086. CNodeList* pNodeList)
  1087. {
  1088. CADsObject* pADsObject = GetADsObject();
  1089. *pbHideVerb = FALSE; // always show the verb
  1090. if (pNodeList->GetCount() > 1) // multiple selection
  1091. {
  1092. return !pADsObject->GetConnectionNode()->GetConnectionData()->IsGC();
  1093. }
  1094. if (pADsObject->IsIntermediateNode() || pADsObject->GetConnectionNode()->GetConnectionData()->IsGC())
  1095. {
  1096. return FALSE;
  1097. }
  1098. if (m_nState == loading)
  1099. {
  1100. return FALSE;
  1101. }
  1102. if (IsThreadLocked())
  1103. {
  1104. return FALSE;
  1105. }
  1106. return TRUE;
  1107. }
  1108. void CADSIEditContainerNode::OnDeleteMultiple(CComponentDataObject* pComponentData,
  1109. CNodeList* pNodeList)
  1110. {
  1111. if (ADSIEditMessageBox(IDS_MSG_DELETE_OBJECTS, MB_YESNO | MB_DEFBUTTON2) == IDYES)
  1112. {
  1113. POSITION pos = pNodeList->GetHeadPosition();
  1114. while (pos != NULL)
  1115. {
  1116. //
  1117. // Check all the nodes to be sure that none have property pages up
  1118. // or their thread is locked
  1119. //
  1120. CTreeNode* pNode = pNodeList->GetNext(pos);
  1121. ASSERT(pNode != NULL);
  1122. if (pNode->IsContainer())
  1123. {
  1124. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(pNode);
  1125. ASSERT(pContNode != NULL);
  1126. BOOL bLocked = pContNode->IsThreadLocked();
  1127. ASSERT(!bLocked); // cannot do refresh on locked node, the UI should prevent this
  1128. if (bLocked)
  1129. {
  1130. return;
  1131. }
  1132. }
  1133. if (pNode->IsSheetLocked())
  1134. {
  1135. if (!pNode->CanCloseSheets())
  1136. {
  1137. return;
  1138. }
  1139. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(pNode);
  1140. }
  1141. ASSERT(!pNode->IsSheetLocked());
  1142. }
  1143. //
  1144. // REVIEW_JEFFJON : this should really only bring up an error message after all
  1145. // the objects have attempted a delete
  1146. //
  1147. POSITION pos2 = pNodeList->GetHeadPosition();
  1148. while (pos2 != NULL)
  1149. {
  1150. CTreeNode* pNode = pNodeList->GetNext(pos2);
  1151. ASSERT(pNode != NULL);
  1152. CString sName, sClass, sPath;
  1153. if (pNode->IsContainer())
  1154. {
  1155. CADSIEditContainerNode* pContainerNode = dynamic_cast<CADSIEditContainerNode*>(pNode);
  1156. ASSERT(pContainerNode != NULL);
  1157. pContainerNode->GetADsObject()->GetPath(sPath);
  1158. pContainerNode->GetADsObject()->GetName(sName);
  1159. pContainerNode->GetADsObject()->GetClass(sClass);
  1160. }
  1161. else
  1162. {
  1163. CADSIEditLeafNode* pLeafNode = dynamic_cast<CADSIEditLeafNode*>(pNode);
  1164. ASSERT(pLeafNode != NULL);
  1165. pLeafNode->GetADsObject()->GetPath(sPath);
  1166. pLeafNode->GetADsObject()->GetName(sName);
  1167. pLeafNode->GetADsObject()->GetClass(sClass);
  1168. }
  1169. HRESULT hr = DeleteChild(sClass, sPath);
  1170. if (FAILED(hr))
  1171. {
  1172. if (HRESULT_CODE(hr) == ERROR_DS_CANT_ON_NON_LEAF)
  1173. {
  1174. hr = DeleteSubtree(sPath);
  1175. if (FAILED(hr))
  1176. {
  1177. ADSIEditErrorMessage(hr);
  1178. }
  1179. ASSERT(pComponentData != NULL);
  1180. ASSERT(pNode->GetContainer() != pNode);
  1181. CContainerNode* pCont = pNode->GetContainer();
  1182. VERIFY(pCont->RemoveChildFromList(pNode));
  1183. ASSERT(pNode->GetContainer() == NULL);
  1184. pNode->SetContainer(pCont); // not in the container's list of children, but still needed
  1185. // remove all the containers from UI only if the container is visible
  1186. // all the leaves will be removed by the framework
  1187. //
  1188. if (pCont->IsVisible())
  1189. {
  1190. if (pNode->IsContainer())
  1191. {
  1192. VERIFY(SUCCEEDED(pComponentData->DeleteNode(pNode))); // remove from the UI
  1193. }
  1194. }
  1195. pComponentData->SetDescriptionBarText(this);
  1196. delete pNode;
  1197. pNode = NULL;
  1198. }
  1199. else
  1200. {
  1201. //
  1202. //Format Error message and pop up a dialog
  1203. //
  1204. ADSIEditErrorMessage(hr);
  1205. }
  1206. }
  1207. else // Delete Succeeded
  1208. {
  1209. ASSERT(pComponentData != NULL);
  1210. ASSERT(pNode->GetContainer() != pNode);
  1211. CContainerNode* pCont = pNode->GetContainer();
  1212. VERIFY(pCont->RemoveChildFromList(pNode));
  1213. ASSERT(pNode->GetContainer() == NULL);
  1214. pNode->SetContainer(pCont); // not in the container's list of children, but still needed
  1215. // remove all the containers from UI only if the container is visible
  1216. // all the leaves will be removed by the framework
  1217. //
  1218. if (pCont->IsVisible())
  1219. {
  1220. VERIFY(SUCCEEDED(pComponentData->DeleteNode(pNode))); // remove from the UI
  1221. }
  1222. pComponentData->SetDescriptionBarText(this);
  1223. delete pNode;
  1224. pNode = NULL;
  1225. }
  1226. }
  1227. }
  1228. }
  1229. void CADSIEditContainerNode::OnDelete(CComponentDataObject* pComponentData,
  1230. CNodeList* pNodeList)
  1231. {
  1232. if (pNodeList->GetCount() > 1) // multiple selection
  1233. {
  1234. OnDeleteMultiple(pComponentData, pNodeList);
  1235. }
  1236. else if (pNodeList->GetCount() == 1) // single selection
  1237. {
  1238. if (ADSIEditMessageBox(IDS_MSG_DELETE_OBJECT, MB_YESNO | MB_DEFBUTTON2) == IDYES)
  1239. {
  1240. CString sPath;
  1241. GetADsObject()->GetPath(sPath);
  1242. BOOL bLocked = IsThreadLocked();
  1243. ASSERT(!bLocked); // cannot do refresh on locked node, the UI should prevent this
  1244. if (bLocked)
  1245. return;
  1246. if (IsSheetLocked())
  1247. {
  1248. if (!CanCloseSheets())
  1249. return;
  1250. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  1251. }
  1252. ASSERT(!IsSheetLocked());
  1253. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  1254. ASSERT(pContNode != NULL);
  1255. CString sClass;
  1256. GetADsObject()->GetClass(sClass);
  1257. HRESULT hr = pContNode->DeleteChild(sClass, sPath);
  1258. if (FAILED(hr))
  1259. {
  1260. if (HRESULT_CODE(hr) == ERROR_DS_CANT_ON_NON_LEAF)
  1261. {
  1262. if (ADSIEditMessageBox(IDS_MSG_DELETE_CONTAINER, MB_YESNO | MB_DEFBUTTON2) == IDYES)
  1263. {
  1264. hr = DeleteSubtree(sPath);
  1265. if (FAILED(hr))
  1266. {
  1267. ADSIEditErrorMessage(hr);
  1268. return;
  1269. }
  1270. }
  1271. else
  1272. {
  1273. return;
  1274. }
  1275. }
  1276. else
  1277. {
  1278. //Format Error message and pop up a dialog
  1279. ADSIEditErrorMessage(hr);
  1280. return;
  1281. }
  1282. }
  1283. DeleteHelper(pComponentData);
  1284. // RefreshOverlappedTrees(sPath, pComponentData);
  1285. pComponentData->SetDescriptionBarText(pContNode);
  1286. delete this;
  1287. }
  1288. }
  1289. }
  1290. BOOL CADSIEditContainerNode::FindNode(LPCWSTR lpszPath, CList<CTreeNode*, CTreeNode*>& foundNodeList)
  1291. {
  1292. CString szPath;
  1293. GetADsObject()->GetPath(szPath);
  1294. // NTRAID#NTBUG9-563093-2002/03/04-artm Need to validate lpszPath before using.
  1295. // Need to check that lpszPath != NULL. Should also protect against a
  1296. // string that is not null terminated.
  1297. // Finally, if a maximum path length is known, use wcsncmp() instead.
  1298. if (wcscmp(lpszPath, (LPCWSTR)szPath) == 0)
  1299. {
  1300. foundNodeList.AddHead(this);
  1301. return TRUE;
  1302. }
  1303. BOOL bFound = FALSE;
  1304. //
  1305. // Look through the leaf child list first
  1306. //
  1307. POSITION leafPos;
  1308. for (leafPos = m_leafChildList.GetHeadPosition(); leafPos != NULL; )
  1309. {
  1310. CTreeNode* pNode = m_leafChildList.GetNext(leafPos);
  1311. CADSIEditLeafNode* pLeafNode = dynamic_cast<CADSIEditLeafNode*>(pNode);
  1312. if (pLeafNode != NULL)
  1313. {
  1314. BOOL bTemp;
  1315. bTemp = pLeafNode->FindNode(lpszPath, foundNodeList);
  1316. if (!bFound)
  1317. {
  1318. bFound = bTemp;
  1319. }
  1320. }
  1321. }
  1322. POSITION pos;
  1323. for (pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  1324. {
  1325. CTreeNode* pNode = m_containerChildList.GetNext(pos);
  1326. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(pNode);
  1327. if (pContNode != NULL)
  1328. {
  1329. BOOL bTemp;
  1330. bTemp = pContNode->FindNode(lpszPath, foundNodeList);
  1331. if (!bFound)
  1332. {
  1333. bFound = bTemp;
  1334. }
  1335. }
  1336. }
  1337. return bFound;
  1338. }
  1339. HRESULT CADSIEditContainerNode::DeleteChild(LPCWSTR lpszClass, LPCWSTR lpszPath)
  1340. {
  1341. HRESULT hr, hCredResult;
  1342. //
  1343. // Get the escaped name from the path
  1344. //
  1345. CComPtr<IADsPathname> spPathCracker;
  1346. hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  1347. IID_IADsPathname, (PVOID *)&(spPathCracker));
  1348. if (FAILED(hr))
  1349. {
  1350. ADSIEditErrorMessage(hr);
  1351. return S_FALSE;
  1352. }
  1353. hr = spPathCracker->Set(CComBSTR(lpszPath), ADS_SETTYPE_FULL);
  1354. if (FAILED(hr))
  1355. {
  1356. ADSIEditErrorMessage(hr);
  1357. return S_FALSE;
  1358. }
  1359. hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL);
  1360. if (FAILED(hr))
  1361. {
  1362. ADSIEditErrorMessage(hr);
  1363. return S_FALSE;
  1364. }
  1365. hr = spPathCracker->put_EscapedMode(ADS_ESCAPEDMODE_ON);
  1366. if (FAILED(hr))
  1367. {
  1368. ADSIEditErrorMessage(hr);
  1369. return S_FALSE;
  1370. }
  1371. CComBSTR bstrChild;
  1372. hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstrChild);
  1373. if (FAILED(hr))
  1374. {
  1375. ADSIEditErrorMessage(hr);
  1376. return S_FALSE;
  1377. }
  1378. hr = spPathCracker->RemoveLeafElement();
  1379. if (FAILED(hr))
  1380. {
  1381. ADSIEditErrorMessage(hr);
  1382. return S_FALSE;
  1383. }
  1384. CComBSTR bstrParent;
  1385. hr = spPathCracker->Retrieve(ADS_FORMAT_X500, &bstrParent);
  1386. if (FAILED(hr))
  1387. {
  1388. ADSIEditErrorMessage(hr);
  1389. return S_FALSE;
  1390. }
  1391. CComPtr<IADsContainer> pContainer;
  1392. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1393. hr = OpenObjectWithCredentials(
  1394. pConnectData,
  1395. pConnectData->GetCredentialObject()->UseCredentials(),
  1396. bstrParent,
  1397. IID_IADsContainer,
  1398. (LPVOID*) &pContainer,
  1399. NULL,
  1400. hCredResult
  1401. );
  1402. if (FAILED(hr))
  1403. {
  1404. if (SUCCEEDED(hCredResult))
  1405. {
  1406. ADSIEditErrorMessage(hr);
  1407. }
  1408. return E_FAIL;
  1409. }
  1410. hr = pContainer->Delete(CComBSTR(lpszClass), bstrChild);
  1411. return hr;
  1412. }
  1413. HRESULT CADSIEditContainerNode::DeleteSubtree(LPCWSTR lpszPath)
  1414. {
  1415. HRESULT hr = S_OK, hCredResult;
  1416. CComPtr<IADsDeleteOps> pObj = NULL;
  1417. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1418. hr = OpenObjectWithCredentials(
  1419. pConnectData,
  1420. pConnectData->GetCredentialObject()->UseCredentials(),
  1421. lpszPath,
  1422. IID_IADsDeleteOps,
  1423. (LPVOID*) &pObj,
  1424. NULL,
  1425. hCredResult
  1426. );
  1427. if (FAILED(hr))
  1428. return hr;
  1429. hr = pObj->DeleteObject(NULL); //flag is reserved by ADSI
  1430. return hr;
  1431. }
  1432. LPCWSTR CADSIEditContainerNode::GetString(int nCol)
  1433. {
  1434. CString sClass, sDN;
  1435. GetADsObject()->GetClass(sClass);
  1436. GetADsObject()->GetDN(sDN);
  1437. // NOTICE-2002/03/04-artm _wcsicmp() compares a constant string w/ a
  1438. // member field; member field should be null terminated so there
  1439. // should be no problem using _wcsicmp() here
  1440. if (GetContainer()->GetColumnSet()->GetColumnID() &&
  1441. _wcsicmp(GetContainer()->GetColumnSet()->GetColumnID(), COLUMNSET_ID_PARTITIONS) == 0)
  1442. {
  1443. switch(nCol)
  1444. {
  1445. case N_PARTITIONS_HEADER_NAME :
  1446. return GetDisplayName();
  1447. case N_PARTITIONS_HEADER_NCNAME :
  1448. return GetADsObject()->GetNCName();
  1449. case N_PARTITIONS_HEADER_TYPE :
  1450. return sClass;
  1451. case N_PARTITIONS_HEADER_DN :
  1452. return sDN;
  1453. default :
  1454. return NULL;
  1455. }
  1456. }
  1457. else
  1458. {
  1459. switch(nCol)
  1460. {
  1461. case N_HEADER_NAME :
  1462. return GetDisplayName();
  1463. case N_HEADER_TYPE :
  1464. return sClass;
  1465. case N_HEADER_DN :
  1466. return sDN;
  1467. default :
  1468. return NULL;
  1469. }
  1470. }
  1471. }
  1472. BOOL CADSIEditContainerNode::HasPropertyPages(DATA_OBJECT_TYPES type,
  1473. BOOL* pbHideVerb,
  1474. CNodeList* pNodeList)
  1475. {
  1476. if (pNodeList->GetCount() == 1) // single selection
  1477. {
  1478. *pbHideVerb = FALSE; // always show the verb
  1479. return TRUE;
  1480. }
  1481. //
  1482. // Multiple selection
  1483. //
  1484. *pbHideVerb = TRUE;
  1485. return FALSE;
  1486. }
  1487. HRESULT CADSIEditContainerNode::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  1488. LONG_PTR handle,
  1489. CNodeList* pNodeList)
  1490. {
  1491. if (pNodeList->GetCount() > 1)
  1492. {
  1493. return S_OK;
  1494. }
  1495. CWaitCursor cursor;
  1496. CComponentDataObject* pComponentDataObject =
  1497. ((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
  1498. ASSERT(pComponentDataObject != NULL);
  1499. CADSIEditContainerNode* pCont = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  1500. ASSERT(pCont != NULL);
  1501. CString path;
  1502. GetADsObject()->GetPath(path);
  1503. CString sServer, sClass;
  1504. GetADsObject()->GetClass(sClass);
  1505. GetADsObject()->GetConnectionNode()->GetConnectionData()->GetDomainServer(sServer);
  1506. CADSIEditPropertyPageHolder* pHolder = new CADSIEditPropertyPageHolder(pCont,
  1507. this, pComponentDataObject, sClass, sServer, path);
  1508. ASSERT(pHolder != NULL);
  1509. pHolder->SetSheetTitle(IDS_PROP_CONTAINER_TITLE, this);
  1510. HRESULT hr = pHolder->CreateModelessSheet(lpProvider, handle);
  1511. if (FAILED(hr) ||
  1512. hr == S_FALSE)
  1513. {
  1514. delete pHolder;
  1515. pHolder = 0;
  1516. }
  1517. return hr;
  1518. }
  1519. BOOL CADSIEditContainerNode::OnAddMenuItem(LPCONTEXTMENUITEM2 pContextMenuItem,
  1520. long *pInsertionAllowed)
  1521. {
  1522. CString sNC, sClass;
  1523. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1524. pConnectData->GetNamingContext(sNC);
  1525. GetADsObject()->GetClass(sClass);
  1526. if (pConnectData->IsGC() && pContextMenuItem->lCommandID != IDM_NEW_QUERY)
  1527. {
  1528. return FALSE;
  1529. }
  1530. if ((pContextMenuItem->lCommandID == IDM_RENAME ||
  1531. pContextMenuItem->lCommandID == IDM_MOVE ||
  1532. pContextMenuItem->lCommandID == IDM_NEW_OBJECT ||
  1533. pContextMenuItem->lCommandID == IDM_NEW_QUERY ||
  1534. pContextMenuItem->lCommandID == IDM_NEW_CONNECT_FROM_HERE) &&
  1535. (m_nState == loading))
  1536. {
  1537. pContextMenuItem->fFlags = MF_GRAYED;
  1538. return TRUE;
  1539. }
  1540. CString szNCName = GetADsObject()->GetNCName();
  1541. if (pContextMenuItem->lCommandID == IDM_NEW_NC_CONNECT_FROM_HERE)
  1542. {
  1543. if (szNCName.IsEmpty())
  1544. {
  1545. return FALSE;
  1546. }
  1547. return TRUE;
  1548. }
  1549. if (IsThreadLocked() &&
  1550. (pContextMenuItem->lCommandID == IDM_RENAME ||
  1551. pContextMenuItem->lCommandID == IDM_MOVE))
  1552. {
  1553. pContextMenuItem->fFlags = MF_GRAYED;
  1554. return TRUE;
  1555. }
  1556. //
  1557. // Load the NC strings from the resource to use in the comparisons
  1558. //
  1559. CString szDomain;
  1560. CString szSchema;
  1561. CString szConfig;
  1562. CString szRootDSE;
  1563. if (!szDomain.LoadString(IDS_DOMAIN_NC))
  1564. {
  1565. szDomain = L"Domain";
  1566. }
  1567. if (!szSchema.LoadString(IDS_SCHEMA))
  1568. {
  1569. szSchema = L"Schema";
  1570. }
  1571. if (!szConfig.LoadString(IDS_CONFIG_CONTAINER))
  1572. {
  1573. szConfig = L"Configuration";
  1574. }
  1575. if (!szRootDSE.LoadString(IDS_ROOTDSE))
  1576. {
  1577. szRootDSE = g_lpszRootDSE;
  1578. }
  1579. if (GetADsObject()->IsIntermediateNode())
  1580. {
  1581. if (pContextMenuItem->lCommandID == IDM_RENAME)
  1582. {
  1583. if (sNC.CompareNoCase(szSchema) == 0 ||
  1584. sNC.CompareNoCase(szRootDSE) == 0 ||
  1585. sNC.CompareNoCase(szConfig) == 0 ||
  1586. sNC.CompareNoCase(szDomain) == 0 ||
  1587. sClass.CompareNoCase(L"domainDNS") == 0)
  1588. {
  1589. return FALSE;
  1590. }
  1591. else
  1592. {
  1593. return TRUE;
  1594. }
  1595. }
  1596. else if (pContextMenuItem->lCommandID == IDM_MOVE ||
  1597. pContextMenuItem->lCommandID == IDM_NEW_CONNECT_FROM_HERE)
  1598. {
  1599. return FALSE;
  1600. }
  1601. else if (pContextMenuItem->lCommandID == IDM_NEW_OBJECT ||
  1602. pContextMenuItem->lCommandID == IDM_NEW_QUERY)
  1603. {
  1604. // NOTICE-2002/03/04-artm wcscmp() safe here b/c
  1605. // arg1 is a CString (always null terminated) and arg2
  1606. // is a global constant
  1607. if (wcscmp(sNC, g_lpszRootDSE) == 0)
  1608. {
  1609. return FALSE;
  1610. }
  1611. else
  1612. {
  1613. return TRUE;
  1614. }
  1615. }
  1616. }
  1617. return TRUE;
  1618. }
  1619. int CADSIEditContainerNode::GetImageIndex(BOOL bOpenImage)
  1620. {
  1621. int nIndex = 0;
  1622. switch (m_nState)
  1623. {
  1624. case notLoaded:
  1625. nIndex = FOLDER_IMAGE_NOT_LOADED;
  1626. break;
  1627. case loading:
  1628. nIndex = FOLDER_IMAGE_LOADING;
  1629. break;
  1630. case loaded:
  1631. nIndex = FOLDER_IMAGE_LOADED;
  1632. break;
  1633. case unableToLoad:
  1634. nIndex = FOLDER_IMAGE_UNABLE_TO_LOAD;
  1635. break;
  1636. case accessDenied:
  1637. nIndex = FOLDER_IMAGE_ACCESS_DENIED;
  1638. break;
  1639. default:
  1640. ASSERT(FALSE);
  1641. }
  1642. return nIndex;
  1643. }
  1644. void CADSIEditContainerNode::OnChangeState(CComponentDataObject* pComponentDataObject)
  1645. {
  1646. switch (m_nState)
  1647. {
  1648. case notLoaded:
  1649. case loaded:
  1650. case unableToLoad:
  1651. case accessDenied:
  1652. {
  1653. m_nState = loading;
  1654. m_dwErr = 0;
  1655. }
  1656. break;
  1657. case loading:
  1658. {
  1659. if (m_dwErr == 0)
  1660. m_nState = loaded;
  1661. else if (m_dwErr == ERROR_ACCESS_DENIED)
  1662. m_nState = accessDenied;
  1663. else
  1664. m_nState = unableToLoad;
  1665. }
  1666. break;
  1667. default:
  1668. ASSERT(FALSE);
  1669. }
  1670. VERIFY(SUCCEEDED(pComponentDataObject->ChangeNode(this, CHANGE_RESULT_ITEM_ICON)));
  1671. VERIFY(SUCCEEDED(pComponentDataObject->UpdateVerbState(this)));
  1672. }
  1673. BOOL CADSIEditContainerNode::CanCloseSheets()
  1674. {
  1675. //
  1676. // We can't do this with the new property page since it is not derived
  1677. // from the base class in MTFRMWK.
  1678. //
  1679. //return (IDCANCEL != ADSIEditMessageBox(IDS_MSG_RECORD_CLOSE_SHEET, MB_OKCANCEL));
  1680. ADSIEditMessageBox(IDS_MSG_RECORD_SHEET_LOCKED, MB_OK);
  1681. return FALSE;
  1682. }
  1683. void CADSIEditContainerNode::OnHaveData(CObjBase* pObj, CComponentDataObject* pComponentDataObject)
  1684. {
  1685. CTreeNode* p = dynamic_cast<CTreeNode*>(pObj);
  1686. ASSERT(p != NULL);
  1687. if (p != NULL)
  1688. {
  1689. AddChildToListAndUI(p, pComponentDataObject);
  1690. pComponentDataObject->SetDescriptionBarText(this);
  1691. }
  1692. }
  1693. void CADSIEditContainerNode::OnError(DWORD dwerr)
  1694. {
  1695. if (dwerr == ERROR_TOO_MANY_NODES)
  1696. {
  1697. // need to pop message
  1698. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1699. CThemeContextActivator activator;
  1700. CString szFmt;
  1701. szFmt.LoadString(IDS_MSG_QUERY_TOO_MANY_ITEMS);
  1702. CString szMsg;
  1703. szMsg.Format(szFmt, GetDisplayName());
  1704. AfxMessageBox(szMsg);
  1705. }
  1706. else
  1707. {
  1708. ADSIEditErrorMessage(dwerr);
  1709. }
  1710. }
  1711. CQueryObj* CADSIEditContainerNode::OnCreateQuery()
  1712. {
  1713. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1714. if (!pConnectData->IsRootDSE())
  1715. {
  1716. CADSIEditRootData* pRootData = static_cast<CADSIEditRootData*>(GetRootContainer());
  1717. CComponentDataObject* pComponentData = pRootData->GetComponentDataObject();
  1718. RemoveAllChildrenHelper(pComponentData);
  1719. CString sFilter;
  1720. pConnectData->GetFilter()->GetFilterString(sFilter);
  1721. CString path;
  1722. GetADsObject()->GetPath(path);
  1723. CADSIEditQueryObject* pQuery = new CADSIEditQueryObject(path, sFilter, ADS_SCOPE_ONELEVEL,
  1724. pConnectData->GetMaxObjectCount(),
  1725. pConnectData->GetCredentialObject(),
  1726. pConnectData->IsGC(),
  1727. pConnectData->GetConnectionNode());
  1728. TRACE(_T("Sizeof query object: %i\n"),
  1729. sizeof(CADSIEditQueryObject));
  1730. return pQuery;
  1731. }
  1732. return CMTContainerNode::OnCreateQuery();
  1733. }
  1734. BOOL CADSIEditContainerNode::OnSetRefreshVerbState(DATA_OBJECT_TYPES type,
  1735. BOOL* pbHide,
  1736. CNodeList* pNodeList)
  1737. {
  1738. if (GetADsObject()->GetConnectionNode()->GetConnectionData()->IsRootDSE())
  1739. {
  1740. *pbHide = TRUE;
  1741. return FALSE;
  1742. }
  1743. *pbHide = FALSE;
  1744. if (m_nState == loading)
  1745. {
  1746. return FALSE;
  1747. }
  1748. return !IsThreadLocked();
  1749. }
  1750. BOOL CADSIEditContainerNode::GetNamingAttribute(LPCWSTR lpszClass, CStringList* sNamingAttr)
  1751. {
  1752. CString sSchemaPath;
  1753. CConnectionData* pConnectData = (GetADsObject()->GetConnectionNode())->GetConnectionData();
  1754. pConnectData->GetAbstractSchemaPath(sSchemaPath);
  1755. sSchemaPath += lpszClass;
  1756. CComPtr<IADsClass> pClass;
  1757. HRESULT hr, hCredResult;
  1758. hr = OpenObjectWithCredentials(
  1759. pConnectData,
  1760. pConnectData->GetCredentialObject()->UseCredentials(),
  1761. sSchemaPath,
  1762. IID_IADsClass,
  1763. (LPVOID*) &pClass,
  1764. NULL,
  1765. hCredResult
  1766. );
  1767. if (FAILED(hr))
  1768. {
  1769. return FALSE;
  1770. }
  1771. VARIANT var;
  1772. VariantInit(&var);
  1773. hr = pClass->get_NamingProperties( &var );
  1774. if ( FAILED(hr) )
  1775. {
  1776. VariantClear(&var);
  1777. return FALSE;
  1778. }
  1779. hr = VariantToStringList(var, *sNamingAttr);
  1780. if (FAILED(hr))
  1781. {
  1782. VariantClear(&var);
  1783. return FALSE;
  1784. }
  1785. VariantClear(&var);
  1786. return TRUE;
  1787. }
  1788. BOOL CADSIEditContainerNode::BuildSchemaPath(CString& path)
  1789. {
  1790. CString sSchemaPath, sLDAP, sServer, sPort, sTemp;
  1791. CConnectionData* m_pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1792. m_pConnectData->GetLDAP(sLDAP);
  1793. m_pConnectData->GetDomainServer(sServer);
  1794. m_pConnectData->GetPort(sPort);
  1795. HRESULT hr = m_pConnectData->GetSchemaPath(sSchemaPath);
  1796. if (FAILED(hr))
  1797. {
  1798. return FALSE;
  1799. }
  1800. if (sSchemaPath.IsEmpty())
  1801. {
  1802. if (FAILED(GetItemFromRootDSE(_T("schemaNamingContext"), sSchemaPath, m_pConnectData)))
  1803. {
  1804. return FALSE;
  1805. }
  1806. if (sServer != _T(""))
  1807. {
  1808. sTemp = sLDAP + sServer;
  1809. if (sPort != _T(""))
  1810. {
  1811. sTemp = sTemp + _T(":") + sPort + _T("/");
  1812. }
  1813. else
  1814. {
  1815. sTemp = sTemp + _T("/");
  1816. }
  1817. sSchemaPath = sTemp + sSchemaPath;
  1818. }
  1819. else
  1820. {
  1821. sSchemaPath = sLDAP + sSchemaPath;
  1822. }
  1823. m_pConnectData->SetSchemaPath(sSchemaPath);
  1824. }
  1825. path = sSchemaPath;
  1826. return TRUE;
  1827. }
  1828. CColumnSet* CADSIEditContainerNode::GetColumnSet()
  1829. {
  1830. CColumnSet* pColumnSet = NULL;
  1831. // NTRAID#NTBUG9-563235-2002/03/04-artm Need to check that GetDisplayName()
  1832. // does not return NULL before passing to _wcsicmp().
  1833. if (_wcsicmp(GetDisplayName(), L"CN=Partitions") == 0)
  1834. {
  1835. //
  1836. // Since this is the partitions container we need to use a different column set
  1837. //
  1838. if (!m_pPartitionsColumnSet)
  1839. {
  1840. m_pPartitionsColumnSet = new CADSIEditColumnSet(COLUMNSET_ID_PARTITIONS);
  1841. }
  1842. pColumnSet = m_pPartitionsColumnSet;
  1843. }
  1844. if (!pColumnSet)
  1845. {
  1846. CRootData* pRootData = (CRootData*)GetRootContainer();
  1847. pColumnSet = pRootData->GetColumnSet();
  1848. }
  1849. return pColumnSet;
  1850. }
  1851. //////////////////////////////////////////////////////////////////////////////////////
  1852. // CADSIEditLeafNode
  1853. // {70B9C151-CFF7-11d2-8801-00C04F72ED31}
  1854. const GUID CADSIEditLeafNode::NodeTypeGUID =
  1855. { 0x70b9c151, 0xcff7, 0x11d2, { 0x88, 0x1, 0x0, 0xc0, 0x4f, 0x72, 0xed, 0x31 } };
  1856. BOOL CADSIEditLeafNode::OnAddMenuItem(LPCONTEXTMENUITEM2 pContextMenuItem,
  1857. long *pInsertionAllowed)
  1858. {
  1859. CString sNC;
  1860. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  1861. pConnectData->GetNamingContext(sNC);
  1862. if ((pContextMenuItem->lCommandID == IDM_RENAME ||
  1863. pContextMenuItem->lCommandID == IDM_MOVE) &&
  1864. pConnectData->IsGC())
  1865. {
  1866. return FALSE;
  1867. }
  1868. CString szNCName = GetADsObject()->GetNCName();
  1869. if (pContextMenuItem->lCommandID == IDM_NEW_NC_CONNECT_FROM_HERE)
  1870. {
  1871. if (szNCName.IsEmpty())
  1872. {
  1873. return FALSE;
  1874. }
  1875. return TRUE;
  1876. }
  1877. // NOTICE-2002/03/04-artm wcscmp() is OK here
  1878. // arg1 is a CString (always null terminated), arg2 is global constant
  1879. if (pContextMenuItem->lCommandID == IDM_RENAME &&
  1880. (sNC == _T("Schema") ||
  1881. wcscmp(sNC, g_lpszRootDSE) == 0 ||
  1882. pConnectData->IsGC()))
  1883. {
  1884. return FALSE;
  1885. }
  1886. return TRUE;
  1887. }
  1888. HRESULT CADSIEditLeafNode::OnCommand(long nCommandID,
  1889. DATA_OBJECT_TYPES type,
  1890. CComponentDataObject* pComponentData,
  1891. CNodeList* pNodeList)
  1892. {
  1893. ASSERT(pNodeList->GetCount() == 1);
  1894. switch (nCommandID)
  1895. {
  1896. case IDM_MOVE :
  1897. OnMove(pComponentData);
  1898. break;
  1899. case IDM_NEW_NC_CONNECT_FROM_HERE :
  1900. OnConnectToNCFromHere(pComponentData);
  1901. break;
  1902. default:
  1903. ASSERT(FALSE); // Unknown command!
  1904. return E_FAIL;
  1905. }
  1906. return S_OK;
  1907. }
  1908. void CADSIEditLeafNode::OnConnectToNCFromHere(CComponentDataObject* pComponentData)
  1909. {
  1910. //
  1911. // Retrieve the path to create the connection at
  1912. //
  1913. CADsObject* pADsObject = GetADsObject();
  1914. CString szDN, szPath, szName, szNCName;
  1915. pADsObject->GetDN(szDN);
  1916. pADsObject->GetPath(szPath);
  1917. pADsObject->GetName(szName);
  1918. szNCName = pADsObject->GetNCName();
  1919. HRESULT hr = S_OK;
  1920. ASSERT(!szNCName.IsEmpty());
  1921. if (!szNCName.IsEmpty())
  1922. {
  1923. //
  1924. // Create the new connection node
  1925. //
  1926. CConnectionData* pConnectData = pADsObject->GetConnectionNode()->GetConnectionData();
  1927. CADSIEditConnectionNode* pNewConnectNode = new CADSIEditConnectionNode(pConnectData);
  1928. if (pNewConnectNode)
  1929. {
  1930. pNewConnectNode->SetDisplayName(GetDisplayName());
  1931. pNewConnectNode->GetConnectionData()->SetBasePath(szNCName);
  1932. pNewConnectNode->GetConnectionData()->SetDistinguishedName(szNCName);
  1933. pNewConnectNode->GetConnectionData()->SetNamingContext(L"");
  1934. pNewConnectNode->GetConnectionData()->SetDN(szNCName);
  1935. pNewConnectNode->GetConnectionData()->SetName(szNCName);
  1936. CString szServer, szProvider;
  1937. pConnectData->GetDomainServer(szServer);
  1938. pConnectData->GetLDAP(szProvider);
  1939. do // false loop
  1940. {
  1941. //
  1942. // Crack the path to get the path to the new NC
  1943. //
  1944. CComPtr<IADsPathname> spPathCracker;
  1945. hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  1946. IID_IADsPathname, (PVOID *)&(spPathCracker));
  1947. if (FAILED(hr))
  1948. {
  1949. ADSIEditErrorMessage(hr);
  1950. break;
  1951. }
  1952. hr = spPathCracker->Set(CComBSTR(szNCName), ADS_SETTYPE_DN);
  1953. if (FAILED(hr))
  1954. {
  1955. ADSIEditErrorMessage(hr);
  1956. break;
  1957. }
  1958. hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL);
  1959. if (FAILED(hr))
  1960. {
  1961. ADSIEditErrorMessage(hr);
  1962. break;
  1963. }
  1964. hr = spPathCracker->Set(CComBSTR(szServer), ADS_SETTYPE_SERVER);
  1965. if (FAILED(hr))
  1966. {
  1967. ADSIEditErrorMessage(hr);
  1968. break;
  1969. }
  1970. hr = spPathCracker->Set(CComBSTR(L"LDAP"), ADS_SETTYPE_PROVIDER);
  1971. if (FAILED(hr))
  1972. {
  1973. ADSIEditErrorMessage(hr);
  1974. break;
  1975. }
  1976. CComBSTR sbstrNewPath;
  1977. hr = spPathCracker->Retrieve(ADS_FORMAT_X500, &sbstrNewPath);
  1978. if (FAILED(hr))
  1979. {
  1980. ADSIEditErrorMessage(hr);
  1981. break;
  1982. }
  1983. pNewConnectNode->GetConnectionData()->SetPath(sbstrNewPath);
  1984. //
  1985. // Add the new connection node to the root container
  1986. //
  1987. CADSIEditRootData* pRootData = (CADSIEditRootData*)pComponentData->GetRootData();
  1988. BOOL bResult = pRootData->AddChildToListAndUI(pNewConnectNode, pComponentData);
  1989. ASSERT(bResult);
  1990. //
  1991. // Select the new connection node
  1992. //
  1993. pComponentData->UpdateResultPaneView(pNewConnectNode);
  1994. } while (false);
  1995. if (FAILED(hr))
  1996. {
  1997. delete pNewConnectNode;
  1998. pNewConnectNode = 0;
  1999. }
  2000. }
  2001. }
  2002. }
  2003. BOOL CADSIEditLeafNode::FindNode(LPCWSTR lpszPath, CList<CTreeNode*, CTreeNode*>& foundNodeList)
  2004. {
  2005. CString szPath;
  2006. GetADsObject()->GetPath(szPath);
  2007. // NTRAID#NTBUG9-563093-2002/03/04-artm Need to validate lpszPath before using.
  2008. // Need to check that lpszPath != NULL. Should also protect against a
  2009. // string that is not null terminated.
  2010. // Finally, if a maximum path length is known, use wcsncmp() instead.
  2011. if (wcscmp(lpszPath, (LPCWSTR)szPath) == 0)
  2012. {
  2013. foundNodeList.AddHead(this);
  2014. return TRUE;
  2015. }
  2016. return FALSE;
  2017. }
  2018. void CADSIEditLeafNode::RefreshOverlappedTrees(CString& szPath, CComponentDataObject* pComponentData)
  2019. {
  2020. // Refresh any other subtrees of connections that contain this node
  2021. //
  2022. CList<CTreeNode*, CTreeNode*> foundNodeList;
  2023. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(GetRootContainer());
  2024. if (pRootNode != NULL)
  2025. {
  2026. BOOL bFound = pRootNode->FindNode(szPath, foundNodeList);
  2027. if (bFound)
  2028. {
  2029. POSITION pos = foundNodeList.GetHeadPosition();
  2030. while (pos != NULL)
  2031. {
  2032. CADSIEditLeafNode* pFoundNode = dynamic_cast<CADSIEditLeafNode*>(foundNodeList.GetNext(pos));
  2033. // if (pFoundNode != NULL && pFoundNode != this)
  2034. if (pFoundNode != NULL)
  2035. {
  2036. if (pFoundNode->IsSheetLocked())
  2037. {
  2038. if (!pFoundNode->CanCloseSheets())
  2039. continue;
  2040. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(pFoundNode);
  2041. }
  2042. ASSERT(!pFoundNode->IsSheetLocked());
  2043. CNodeList nodeList;
  2044. nodeList.AddTail(pFoundNode);
  2045. pFoundNode->GetContainer()->OnRefresh(pComponentData, &nodeList);
  2046. }
  2047. }
  2048. }
  2049. }
  2050. }
  2051. HRESULT CADSIEditLeafNode::OnRename(CComponentDataObject* pComponentData,
  2052. LPWSTR lpszNewName)
  2053. {
  2054. HRESULT hr = S_OK;
  2055. if (IsSheetLocked())
  2056. {
  2057. if (!CanCloseSheets())
  2058. return S_FALSE;
  2059. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  2060. }
  2061. ASSERT(!IsSheetLocked());
  2062. CString szPath, szOldPath;
  2063. CADsObject* pADsObject = GetADsObject();
  2064. pADsObject->GetPath(szPath);
  2065. szOldPath = szPath;
  2066. CADSIEditConnectionNode* pConnectionNode = pADsObject->GetConnectionNode();
  2067. CConnectionData* pConnectData = pConnectionNode->GetConnectionData();
  2068. CComPtr<IADsPathname> spPathCracker;
  2069. hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  2070. IID_IADsPathname, (PVOID *)&(spPathCracker));
  2071. if (FAILED(hr))
  2072. {
  2073. ADSIEditErrorMessage(hr);
  2074. return S_FALSE;
  2075. }
  2076. hr = spPathCracker->Set(CComBSTR(szPath), ADS_SETTYPE_FULL);
  2077. if (FAILED(hr))
  2078. {
  2079. ADSIEditErrorMessage(hr);
  2080. return S_FALSE;
  2081. }
  2082. hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL);
  2083. if (FAILED(hr))
  2084. {
  2085. ADSIEditErrorMessage(hr);
  2086. return S_FALSE;
  2087. }
  2088. CComBSTR bstrOldLeaf;
  2089. hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstrOldLeaf);
  2090. if (FAILED(hr))
  2091. {
  2092. ADSIEditErrorMessage(hr);
  2093. return S_FALSE;
  2094. }
  2095. CString szOldLeaf = bstrOldLeaf;
  2096. CString szPrefix;
  2097. szPrefix = szOldLeaf.Left(szOldLeaf.Find(L'=') + 1);
  2098. hr = spPathCracker->RemoveLeafElement();
  2099. if (FAILED(hr))
  2100. {
  2101. ADSIEditErrorMessage(hr);
  2102. return S_FALSE;
  2103. }
  2104. CComBSTR bstrParentPath;
  2105. hr = spPathCracker->Retrieve(ADS_FORMAT_X500, &bstrParentPath);
  2106. if (FAILED(hr))
  2107. {
  2108. ADSIEditErrorMessage(hr);
  2109. return S_FALSE;
  2110. }
  2111. CComPtr<IADsContainer> spDestination;
  2112. CString sContPath(bstrParentPath);
  2113. hr = OpenObjectWithCredentials(
  2114. pConnectData->GetCredentialObject(),
  2115. bstrParentPath,
  2116. IID_IADsContainer,
  2117. (LPVOID*) &spDestination
  2118. );
  2119. if (FAILED(hr))
  2120. {
  2121. ADSIEditErrorMessage(hr);
  2122. return S_FALSE;
  2123. }
  2124. //
  2125. // Place the prefix in front of the name if it wasn't typed in by
  2126. // the user
  2127. //
  2128. CString szNewLeaf, szNewName = lpszNewName;
  2129. if (szNewName.Find(L'=') == -1)
  2130. {
  2131. szNewLeaf = szPrefix + lpszNewName;
  2132. }
  2133. else
  2134. {
  2135. szNewLeaf = lpszNewName;
  2136. }
  2137. hr = spPathCracker->AddLeafElement(CComBSTR(szNewLeaf));
  2138. if (FAILED(hr))
  2139. {
  2140. ADSIEditErrorMessage(hr);
  2141. return S_FALSE;
  2142. }
  2143. CComPtr<IDispatch> spObject;
  2144. hr = spDestination->MoveHere(CComBSTR(szOldPath),
  2145. CComBSTR(szNewLeaf),
  2146. &spObject);
  2147. if (FAILED(hr))
  2148. {
  2149. ADSIEditErrorMessage(hr);
  2150. return S_FALSE;
  2151. }
  2152. CComPtr<IADs> spIADs;
  2153. hr = spObject->QueryInterface(IID_IADs, (LPVOID*)&spIADs);
  2154. if (FAILED(hr))
  2155. {
  2156. ADSIEditErrorMessage(hr);
  2157. return S_FALSE;
  2158. }
  2159. CComBSTR bstrPath;
  2160. hr = spIADs->get_ADsPath(&bstrPath);
  2161. if (FAILED(hr))
  2162. {
  2163. ADSIEditErrorMessage(hr);
  2164. return S_FALSE;
  2165. }
  2166. CComBSTR bstrDN;
  2167. hr = spPathCracker->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  2168. if (FAILED(hr))
  2169. {
  2170. ADSIEditErrorMessage(hr);
  2171. return S_FALSE;
  2172. }
  2173. CComBSTR bstrLeaf;
  2174. hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstrLeaf);
  2175. if (FAILED(hr))
  2176. {
  2177. ADSIEditErrorMessage(hr);
  2178. return S_FALSE;
  2179. }
  2180. GetADsObject()->SetPath(bstrPath);
  2181. GetADsObject()->SetName(bstrLeaf);
  2182. GetADsObject()->SetDN(bstrDN);
  2183. SetDisplayName(bstrLeaf);
  2184. return hr;
  2185. }
  2186. void CADSIEditLeafNode::OnMove(CComponentDataObject* pComponentData)
  2187. {
  2188. if (IsSheetLocked())
  2189. {
  2190. if (!CanCloseSheets())
  2191. return;
  2192. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  2193. }
  2194. ASSERT(!IsSheetLocked());
  2195. HRESULT hr = S_OK, hCredResult;
  2196. DWORD result;
  2197. CComPtr<IADsContainer> pDSDestination = NULL;
  2198. CComPtr<IDispatch> pDSObject = NULL;
  2199. CString strDestPath;
  2200. CString strTitle;
  2201. strTitle.LoadString (IDS_MOVE_TITLE);
  2202. DSBROWSEINFO dsbi;
  2203. ::ZeroMemory( &dsbi, sizeof(dsbi) );
  2204. TCHAR szPath[MAX_PATH+1];
  2205. CString str;
  2206. str.LoadString(IDS_MOVE_TARGET);
  2207. CString strRootPath;
  2208. GetADsObject()->GetConnectionNode()->GetADsObject()->GetPath(strRootPath);
  2209. dsbi.hwndOwner = NULL;
  2210. dsbi.cbStruct = sizeof (DSBROWSEINFO);
  2211. dsbi.pszCaption = (LPWSTR)((LPCWSTR)strTitle); // this is actually the caption
  2212. dsbi.pszTitle = (LPWSTR)((LPCWSTR)str);
  2213. dsbi.pszRoot = strRootPath;
  2214. dsbi.pszPath = szPath;
  2215. dsbi.cchPath = (sizeof(szPath) / sizeof(TCHAR));
  2216. dsbi.dwFlags = DSBI_INCLUDEHIDDEN | DSBI_RETURN_FORMAT;
  2217. dsbi.pfnCallback = NULL;
  2218. dsbi.lParam = 0;
  2219. result = DsBrowseForContainer( &dsbi );
  2220. if ( result == IDOK )
  2221. { // returns -1, 0, IDOK or IDCANCEL
  2222. // get path from BROWSEINFO struct, put in text edit field
  2223. TRACE(_T("returned from DS Browse successfully with:\n %s\n"),
  2224. dsbi.pszPath);
  2225. strDestPath = dsbi.pszPath;
  2226. // See if the destination is the same as the current parent. If so, do nothing
  2227. CADSIEditContainerNode* pContainer = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  2228. if (pContainer)
  2229. {
  2230. CString szPath;
  2231. pContainer->GetADsObject()->GetPath(szPath);
  2232. if (szPath == strDestPath)
  2233. {
  2234. // No reason to do anything if the source and the destination are the same
  2235. return;
  2236. }
  2237. }
  2238. CConnectionData* pConnectData = GetADsObject()->GetConnectionNode()->GetConnectionData();
  2239. hr = OpenObjectWithCredentials(
  2240. pConnectData,
  2241. pConnectData->GetCredentialObject()->UseCredentials(),
  2242. strDestPath,
  2243. IID_IADsContainer,
  2244. (LPVOID*) &pDSDestination,
  2245. NULL,
  2246. hCredResult
  2247. );
  2248. if (FAILED(hr))
  2249. {
  2250. if (SUCCEEDED(hCredResult))
  2251. {
  2252. ADSIEditErrorMessage(hr);
  2253. }
  2254. return;
  2255. }
  2256. CString sCurrentPath;
  2257. GetADsObject()->GetPath(sCurrentPath);
  2258. hr = pDSDestination->MoveHere(CComBSTR(sCurrentPath),
  2259. NULL,
  2260. &pDSObject);
  2261. if (FAILED(hr))
  2262. {
  2263. ADSIEditErrorMessage(hr);
  2264. return;
  2265. }
  2266. DeleteHelper(pComponentData);
  2267. // RefreshOverlappedTrees(sCurrentPath, pComponentData);
  2268. // RefreshOverlappedTrees(strDestPath, pComponentData);
  2269. delete this;
  2270. }
  2271. }
  2272. CADSIEditLeafNode::CADSIEditLeafNode(CADSIEditLeafNode* pLeafNode)
  2273. {
  2274. m_pADsObject = new CADsObject(pLeafNode->m_pADsObject);
  2275. CString sName;
  2276. m_pADsObject->GetName(sName);
  2277. SetDisplayName(sName);
  2278. }
  2279. BOOL CADSIEditLeafNode::OnSetRenameVerbState(DATA_OBJECT_TYPES type,
  2280. BOOL* pbHideVerb,
  2281. CNodeList* pNodeList)
  2282. {
  2283. ASSERT(pNodeList->GetCount() == 1);
  2284. if (GetADsObject()->GetConnectionNode()->GetConnectionData()->IsGC())
  2285. {
  2286. *pbHideVerb = TRUE; // always hide the verb
  2287. return FALSE;
  2288. }
  2289. *pbHideVerb = FALSE; // always show the verb
  2290. return TRUE;
  2291. }
  2292. BOOL CADSIEditLeafNode::OnSetDeleteVerbState(DATA_OBJECT_TYPES type,
  2293. BOOL* pbHideVerb,
  2294. CNodeList* pNodeList)
  2295. {
  2296. ASSERT(pNodeList->GetCount() == 1);
  2297. if (GetADsObject()->GetConnectionNode()->GetConnectionData()->IsGC())
  2298. {
  2299. *pbHideVerb = TRUE; // always hide the verb
  2300. return FALSE;
  2301. }
  2302. *pbHideVerb = FALSE; // always show the verb
  2303. return TRUE;
  2304. }
  2305. void CADSIEditLeafNode::OnDelete(CComponentDataObject* pComponentData,
  2306. CNodeList* pNodeList)
  2307. {
  2308. ASSERT(pNodeList->GetCount() == 1);
  2309. if (ADSIEditMessageBox(IDS_MSG_DELETE_OBJECT, MB_YESNO | MB_DEFBUTTON2) == IDYES)
  2310. {
  2311. if (IsSheetLocked())
  2312. {
  2313. if (!CanCloseSheets())
  2314. return;
  2315. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  2316. }
  2317. ASSERT(!IsSheetLocked());
  2318. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  2319. ASSERT(pContNode != NULL);
  2320. CString sName, sClass, sPath;
  2321. GetADsObject()->GetName(sName);
  2322. GetADsObject()->GetClass(sClass);
  2323. GetADsObject()->GetPath(sPath);
  2324. HRESULT hr;
  2325. hr = pContNode->DeleteChild(sClass, sPath);
  2326. if (FAILED(hr))
  2327. {
  2328. //Format Error message and pop up a dialog
  2329. ADSIEditErrorMessage(hr);
  2330. return;
  2331. }
  2332. // RefreshOverlappedTrees(sPath, pComponentData);
  2333. DeleteHelper(pComponentData);
  2334. pComponentData->SetDescriptionBarText(pContNode);
  2335. delete this;
  2336. }
  2337. }
  2338. LPCWSTR CADSIEditLeafNode::GetString(int nCol)
  2339. {
  2340. CString sClass, sDN;
  2341. GetADsObject()->GetClass(sClass);
  2342. GetADsObject()->GetDN(sDN);
  2343. // NOTICE-2002/03/04-artm _wcsicmp() OK here
  2344. // arg1 is a member field (and should be null terminated),
  2345. // arg2 is a constant
  2346. if (GetContainer()->GetColumnSet()->GetColumnID() &&
  2347. _wcsicmp(GetContainer()->GetColumnSet()->GetColumnID(), COLUMNSET_ID_PARTITIONS) == 0)
  2348. {
  2349. switch(nCol)
  2350. {
  2351. case N_PARTITIONS_HEADER_NAME :
  2352. return GetDisplayName();
  2353. case N_PARTITIONS_HEADER_NCNAME :
  2354. return GetADsObject()->GetNCName();
  2355. case N_PARTITIONS_HEADER_TYPE :
  2356. return sClass;
  2357. case N_PARTITIONS_HEADER_DN :
  2358. return sDN;
  2359. default :
  2360. return NULL;
  2361. }
  2362. }
  2363. else
  2364. {
  2365. switch(nCol)
  2366. {
  2367. case N_HEADER_NAME :
  2368. return GetDisplayName();
  2369. case N_HEADER_TYPE :
  2370. return sClass;
  2371. case N_HEADER_DN :
  2372. return sDN;
  2373. default :
  2374. return NULL;
  2375. }
  2376. }
  2377. }
  2378. int CADSIEditLeafNode::GetImageIndex(BOOL bOpenImage)
  2379. {
  2380. return RECORD_IMAGE_BASE;
  2381. }
  2382. BOOL CADSIEditLeafNode::HasPropertyPages(DATA_OBJECT_TYPES type,
  2383. BOOL* pbHideVerb,
  2384. CNodeList* pNodeList)
  2385. {
  2386. ASSERT(pNodeList->GetCount() == 1);
  2387. *pbHideVerb = FALSE; // always show the verb
  2388. return TRUE;
  2389. }
  2390. HRESULT CADSIEditLeafNode::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  2391. LONG_PTR handle,
  2392. CNodeList* pNodeList)
  2393. {
  2394. if (pNodeList->GetCount() > 1)
  2395. {
  2396. return S_OK;
  2397. }
  2398. CComponentDataObject* pComponentDataObject =
  2399. ((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
  2400. ASSERT(pComponentDataObject != NULL);
  2401. CString path;
  2402. GetADsObject()->GetPath(path);
  2403. CString sServer, sClass;
  2404. GetADsObject()->GetClass(sClass);
  2405. GetADsObject()->GetConnectionNode()->GetConnectionData()->GetDomainServer(sServer);
  2406. CADSIEditContainerNode *pContNode = dynamic_cast<CADSIEditContainerNode*>(GetContainer());
  2407. ASSERT(pContNode != NULL);
  2408. CADSIEditPropertyPageHolder* pHolder = new CADSIEditPropertyPageHolder(pContNode, this,
  2409. pComponentDataObject, sClass, sServer, path );
  2410. ASSERT(pHolder != NULL);
  2411. pHolder->SetSheetTitle(IDS_PROP_CONTAINER_TITLE, this);
  2412. return pHolder->CreateModelessSheet(lpProvider, handle);
  2413. }
  2414. BOOL CADSIEditLeafNode::BuildSchemaPath(CString& path)
  2415. {
  2416. return ((CADSIEditContainerNode*)m_pContainer)->BuildSchemaPath(path);
  2417. }
  2418. BOOL CADSIEditLeafNode::CanCloseSheets()
  2419. {
  2420. //
  2421. // We can't do this with the new property page since it is not derived
  2422. // from the base class in MTFRMWK.
  2423. //
  2424. //return (IDCANCEL != ADSIEditMessageBox(IDS_MSG_RECORD_CLOSE_SHEET, MB_OKCANCEL));
  2425. ADSIEditMessageBox(IDS_MSG_RECORD_SHEET_LOCKED, MB_OK);
  2426. return FALSE;
  2427. }
  2428. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  2429. // CADSIEditQuery
  2430. BOOL CADSIEditQueryObject::Enumerate()
  2431. {
  2432. CADSIQueryObject enumSearch;
  2433. // Initialize search object with path, username and password
  2434. //
  2435. HRESULT hCredResult = S_OK;
  2436. HRESULT hr = enumSearch.Init(m_sPath, &m_credentialObject);
  2437. if (FAILED(hr))
  2438. {
  2439. OnError(hr);
  2440. return FALSE;
  2441. }
  2442. TRACE(_T("Sizeof CredentialObject: %i\n"), sizeof(CCredentialObject));
  2443. int cCols = 2;
  2444. LPWSTR pszAttributes[] = {L"aDSPath", L"nCName" };
  2445. hr = enumSearch.SetSearchPrefs(m_Scope, m_ulMaxObjectCount);
  2446. if (FAILED(hr))
  2447. {
  2448. OnError(hr);
  2449. return FALSE;
  2450. }
  2451. enumSearch.SetFilterString((LPWSTR)(LPCWSTR)m_sFilter);
  2452. enumSearch.SetAttributeList (pszAttributes, cCols);
  2453. hr = enumSearch.DoQuery();
  2454. if (SUCCEEDED(hr))
  2455. {
  2456. GetResults(enumSearch);
  2457. }
  2458. else
  2459. {
  2460. OnError(hr);
  2461. }
  2462. return FALSE;
  2463. }
  2464. void CADSIEditQueryObject::GetResults(CADSIQueryObject& enumSearch)
  2465. {
  2466. HRESULT hr = S_OK;
  2467. ADS_OBJECT_INFO* pInfo = NULL;
  2468. ADS_SEARCH_COLUMN ColumnData;
  2469. BOOL bNeedToFreeColumnData = FALSE;
  2470. QUERY_STATE dwErr = QUERY_OK;
  2471. ULONG nObjectCount = 0;
  2472. ASSERT(nObjectCount <= m_ulMaxObjectCount);
  2473. while (true)
  2474. {
  2475. hr = enumSearch.GetNextRow();
  2476. if (hr == S_ADS_NOMORE_ROWS)
  2477. {
  2478. break;
  2479. }
  2480. if (FAILED(hr))
  2481. {
  2482. OnError(hr);
  2483. break;
  2484. }
  2485. //
  2486. // Get the NCName. Note this will be empty for all objects except
  2487. // crossRef objects for app directory partitions (formerly known as NDNCs)
  2488. //
  2489. CString szNCName;
  2490. hr = enumSearch.GetColumn(L"nCName", &ColumnData);
  2491. if (SUCCEEDED(hr) && ColumnData.pADsValues)
  2492. {
  2493. szNCName = ColumnData.pADsValues->DNString;
  2494. enumSearch.FreeColumn(&ColumnData);
  2495. }
  2496. // Get the path column
  2497. bNeedToFreeColumnData = FALSE;
  2498. hr = enumSearch.GetColumn(L"aDSPath", &ColumnData);
  2499. if (FAILED(hr))
  2500. {
  2501. enumSearch.FreeColumn(&ColumnData);
  2502. bNeedToFreeColumnData = FALSE;
  2503. ADSIEditErrorMessage(hr);
  2504. //
  2505. // if we can't get the path there must be something extremely wrong since the
  2506. // since the path is guaranteed, so we should break instead of continuing
  2507. //
  2508. break;
  2509. }
  2510. bNeedToFreeColumnData = TRUE;
  2511. if (nObjectCount >= m_ulMaxObjectCount)
  2512. {
  2513. dwErr = ERROR_TOO_MANY_NODES;
  2514. OnError(dwErr);
  2515. break;
  2516. }
  2517. CString sPath(ColumnData.pADsValues->CaseIgnoreString);
  2518. CComPtr<IDirectoryObject> spDirObject;
  2519. hr = OpenObjectWithCredentials(
  2520. &m_credentialObject,
  2521. sPath,
  2522. IID_IDirectoryObject,
  2523. (LPVOID*) &spDirObject
  2524. );
  2525. if ( FAILED(hr) )
  2526. {
  2527. TRACE(_T("Unable to bind to new object. Creating incomplete object. hr=0x%x\n"), hr);
  2528. // Create an incomplete object
  2529. CreateNewObject(sPath, NULL, szNCName);
  2530. if (bNeedToFreeColumnData)
  2531. {
  2532. enumSearch.FreeColumn(&ColumnData);
  2533. bNeedToFreeColumnData = FALSE;
  2534. }
  2535. continue;
  2536. }
  2537. ASSERT(pInfo == NULL);
  2538. hr = spDirObject->GetObjectInformation(&pInfo);
  2539. if (FAILED(hr))
  2540. {
  2541. TRACE(_T("Unable to get object info. Creating incomplete object. hr=0x%x\n"), hr);
  2542. // Create an incomplete object
  2543. CreateNewObject(sPath, NULL, szNCName);
  2544. if (bNeedToFreeColumnData)
  2545. {
  2546. enumSearch.FreeColumn(&ColumnData);
  2547. bNeedToFreeColumnData = FALSE;
  2548. }
  2549. continue;
  2550. }
  2551. ASSERT(pInfo != NULL);
  2552. TRACE(_T("Creating complete object\n"));
  2553. // Create a complete object
  2554. CreateNewObject(sPath, pInfo, szNCName);
  2555. FreeADsMem(pInfo);
  2556. pInfo = NULL;
  2557. enumSearch.FreeColumn(&ColumnData);
  2558. bNeedToFreeColumnData = FALSE;
  2559. nObjectCount++;
  2560. } // while
  2561. if (pInfo != NULL)
  2562. {
  2563. FreeADsMem(pInfo);
  2564. }
  2565. if (bNeedToFreeColumnData)
  2566. {
  2567. enumSearch.FreeColumn(&ColumnData);
  2568. }
  2569. }
  2570. void CADSIEditQueryObject::CreateNewObject(CString& sPath,
  2571. ADS_OBJECT_INFO* pInfo,
  2572. PCWSTR pszNCName)
  2573. {
  2574. CADsObject* pObject = new CADsObject(m_pConnectNode);
  2575. if (pObject)
  2576. {
  2577. pObject->SetNCName(pszNCName);
  2578. if (pInfo != NULL)
  2579. {
  2580. // This means we have a complete object
  2581. pObject->SetPath(sPath);
  2582. // Get the leaf name via PathCracker
  2583. CString sDisplayName, sDN;
  2584. CrackPath(sPath, sDisplayName, sDN);
  2585. pObject->SetName(sDisplayName);
  2586. pObject->SetDN(sDN);
  2587. // make the prefix uppercase
  2588. int idx = sDisplayName.Find(L'=');
  2589. if (idx != -1)
  2590. {
  2591. CString sPrefix, sRemaining;
  2592. sPrefix = sDisplayName.Left(idx);
  2593. sPrefix.MakeUpper();
  2594. int iCount = sDisplayName.GetLength();
  2595. sRemaining = sDisplayName.Right(iCount - idx);
  2596. sDisplayName = sPrefix + sRemaining;
  2597. }
  2598. pObject->SetClass(pInfo->pszClassName);
  2599. pObject->SetComplete(TRUE);
  2600. if (IsContainer(pInfo->pszClassName, pInfo->pszSchemaDN))
  2601. {
  2602. TRACE(_T("IsContainer returned TRUE\n"));
  2603. CADSIEditContainerNode* pContNode = new CADSIEditContainerNode(pObject);
  2604. pObject = NULL;
  2605. pContNode->SetDisplayName(sDisplayName);
  2606. pContNode->GetADsObject()->SetConnectionNode(m_pConnectNode);
  2607. VERIFY(AddQueryResult(pContNode));
  2608. }
  2609. else
  2610. {
  2611. TRACE(_T("IsContainer returned FALSE\n"));
  2612. CADSIEditLeafNode *pLeafNode = new CADSIEditLeafNode(pObject);
  2613. pObject = NULL;
  2614. pLeafNode->SetDisplayName(sDisplayName);
  2615. pLeafNode->GetADsObject()->SetConnectionNode(m_pConnectNode);
  2616. VERIFY(AddQueryResult(pLeafNode));
  2617. }
  2618. }
  2619. else
  2620. {
  2621. // Get the leaf name and DN via PathCracker
  2622. CString sCrackPath, sDN;
  2623. CrackPath(sPath, sCrackPath, sDN);
  2624. pObject->SetName(sCrackPath);
  2625. pObject->SetDN(sDN);
  2626. pObject->SetPath(sPath);
  2627. CString sDisplayName;
  2628. sDisplayName = sPath;
  2629. // Make the prefix upper case
  2630. int idx = sDisplayName.Find(L'=');
  2631. if (idx != -1)
  2632. {
  2633. CString sPrefix, sRemaining;
  2634. sPrefix = sDisplayName.Left(idx);
  2635. sPrefix.MakeUpper();
  2636. int iCount = sDisplayName.GetLength();
  2637. sRemaining = sDisplayName.Right(iCount - idx);
  2638. sDisplayName = sPrefix + sRemaining;
  2639. }
  2640. pObject->SetComplete(FALSE);
  2641. // Make all nodes that were of undetermined type leaf nodes
  2642. CADSIEditLeafNode *pLeafNode = new CADSIEditLeafNode(pObject);
  2643. pObject = NULL;
  2644. pLeafNode->SetDisplayName(sCrackPath);
  2645. pLeafNode->GetADsObject()->SetConnectionNode(m_pConnectNode);
  2646. VERIFY(AddQueryResult(pLeafNode));
  2647. }
  2648. }
  2649. if (pObject != NULL)
  2650. {
  2651. delete pObject;
  2652. pObject = NULL;
  2653. }
  2654. }
  2655. void CADSIEditQueryObject::CrackPath(const CString sName, CString& sPath, CString& sDN)
  2656. {
  2657. HRESULT hr = PathCracker()->Set(CComBSTR(sName), ADS_SETTYPE_FULL);
  2658. if (FAILED(hr))
  2659. {
  2660. TRACE(_T("Set failed. %s"), hr);
  2661. }
  2662. //
  2663. // Get the current escaped mode
  2664. //
  2665. LONG lEscapedMode = ADS_ESCAPEDMODE_DEFAULT;
  2666. hr = PathCracker()->get_EscapedMode(&lEscapedMode);
  2667. hr = PathCracker()->put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
  2668. // Get the leaf name
  2669. CComBSTR bstrPath;
  2670. hr = PathCracker()->Retrieve(ADS_FORMAT_LEAF, &bstrPath);
  2671. if (FAILED(hr))
  2672. {
  2673. TRACE(_T("Failed to get element. %s"), hr);
  2674. sPath = L"";
  2675. }
  2676. else
  2677. {
  2678. sPath = bstrPath;
  2679. }
  2680. //
  2681. // Put the escaped mode back to what it was
  2682. //
  2683. hr = PathCracker()->put_EscapedMode(lEscapedMode);
  2684. // Get the leaf DN
  2685. CComBSTR bstrDN;
  2686. hr = PathCracker()->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  2687. if (FAILED(hr))
  2688. {
  2689. TRACE(_T("Failed to get element. %s"), hr);
  2690. sDN = L"";
  2691. }
  2692. else
  2693. {
  2694. sDN = bstrDN;
  2695. }
  2696. }
  2697. IADsPathname* CADSIEditQueryObject::PathCracker()
  2698. {
  2699. if (m_pPathCracker == NULL)
  2700. {
  2701. HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  2702. IID_IADsPathname, (PVOID *)&(m_pPathCracker));
  2703. ASSERT((S_OK == hr) && ((m_pPathCracker) != NULL));
  2704. }
  2705. return m_pPathCracker;
  2706. }
  2707. bool CADSIEditQueryObject::IsContainer(PCWSTR pszClass, PCWSTR pszPath)
  2708. {
  2709. return m_pConnectNode->IsClassAContainer(&m_credentialObject, pszClass, pszPath);
  2710. }