Source code of Windows XP (NT5)
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.

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