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.

2536 lines
65 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // DS Administration MMC snapin.
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 1999
  7. //
  8. // File: query.cpp
  9. //
  10. //--------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "resource.h"
  13. #include "query.h"
  14. #include "queryui.h"
  15. #include "uiutil.h"
  16. #include "xmlutil.h"
  17. #include "ContextMenu.h"
  18. #include "dataobj.h"
  19. ////////////////////////////////////////////////////////////////////////////
  20. // CFavoritesNode
  21. CFavoritesNode::CFavoritesNode()
  22. : m_bFavoritesRoot(0)
  23. {
  24. MakeContainer();
  25. CDSColumnSet* pColumnSet = CDSColumnSet::CreateDescriptionColumnSet();
  26. if (pColumnSet != NULL)
  27. {
  28. GetFolderInfo()->SetColumnSet(pColumnSet);
  29. }
  30. }
  31. BOOL CFavoritesNode::DeepCopyChildren(CUINode* pUINodeToCopy)
  32. {
  33. if (pUINodeToCopy == NULL)
  34. {
  35. ASSERT(FALSE);
  36. return FALSE;
  37. }
  38. //
  39. // We have to do a deep copy of the children for the favorites nodes
  40. //
  41. CUINodeList* pCopyContList = pUINodeToCopy->GetFolderInfo()->GetContainerList();
  42. CUINodeList* pNewContList = GetFolderInfo()->GetContainerList();
  43. if (pCopyContList != NULL && pNewContList != NULL)
  44. {
  45. POSITION pos = pCopyContList->GetHeadPosition();
  46. while (pos != NULL)
  47. {
  48. CUINode* pUINode = pCopyContList->GetNext(pos);
  49. if (pUINode != NULL)
  50. {
  51. if (IS_CLASS(*pUINode, CFavoritesNode))
  52. {
  53. CFavoritesNode* pNewNode = new CFavoritesNode(*(dynamic_cast<CFavoritesNode*>(pUINode)));
  54. if (pNewNode != NULL)
  55. {
  56. pNewNode->DeepCopyChildren(pUINode);
  57. pNewNode->SetParent(this);
  58. pNewContList->AddTail(pNewNode);
  59. }
  60. }
  61. else if (IS_CLASS(*pUINode, CSavedQueryNode))
  62. {
  63. CSavedQueryNode* pNewNode = new CSavedQueryNode(*(dynamic_cast<CSavedQueryNode*>(pUINode)));
  64. if (pNewNode != NULL)
  65. {
  66. pNewNode->SetParent(this);
  67. pNewContList->AddTail(pNewNode);
  68. }
  69. }
  70. else
  71. {
  72. //
  73. // CFavoritesNode should only contain CFavoritesNodes and CSavedQueryNodes
  74. //
  75. ASSERT(FALSE);
  76. continue;
  77. }
  78. }
  79. }
  80. }
  81. //
  82. // There shouldn't be any leaf nodes but we will try to copy just in case
  83. //
  84. CUINodeList* pCopyLeafList = pUINodeToCopy->GetFolderInfo()->GetLeafList();
  85. CUINodeList* pNewLeafList = GetFolderInfo()->GetLeafList();
  86. if (pCopyLeafList != NULL && pNewLeafList != NULL)
  87. {
  88. POSITION pos = pCopyLeafList->GetHeadPosition();
  89. while (pos != NULL)
  90. {
  91. CUINode* pUINode = pCopyLeafList->GetNext(pos);
  92. if (pUINode != NULL)
  93. {
  94. CUINode* pNewNode = NULL;
  95. //
  96. // In the future we would add class specific creation here as is above
  97. //
  98. //
  99. // CFavoritesNode should only contain CFavoritesNodes and CSavedQueryNodes
  100. //
  101. ASSERT(FALSE);
  102. if (pNewNode != NULL)
  103. {
  104. pNewLeafList->AddTail(pNewNode);
  105. }
  106. }
  107. }
  108. }
  109. return TRUE;
  110. }
  111. void CFavoritesNode::RemoveQueryResults()
  112. {
  113. ASSERT(!IsSheetLocked());
  114. ASSERT(GetFolderInfo()->GetLeafList()->IsEmpty());
  115. CUINodeList* pContainerList = GetFolderInfo()->GetContainerList();
  116. for (POSITION pos = pContainerList->GetHeadPosition(); pos != NULL; )
  117. {
  118. CUINode* pCurrUINode = pContainerList->GetNext(pos);
  119. // we reset the expanded flag only on nodes below
  120. // the current node, because the current node is going
  121. // to get results back from the refresh command, while
  122. // the others will be added again and will be expanded as
  123. // new nodes
  124. pCurrUINode->GetFolderInfo()->ReSetExpanded();
  125. if (IS_CLASS(*pCurrUINode, CSavedQueryNode))
  126. {
  127. pCurrUINode->GetFolderInfo()->DeleteAllLeafNodes();
  128. pCurrUINode->GetFolderInfo()->DeleteAllContainerNodes();
  129. }
  130. else if (IS_CLASS(*pCurrUINode, CFavoritesNode))
  131. {
  132. // recurse down to other query folders
  133. dynamic_cast<CFavoritesNode*>(pCurrUINode)->RemoveQueryResults();
  134. }
  135. }
  136. }
  137. void CFavoritesNode::FindCookiesInQueries(LPCWSTR lpszCookieDN, CUINodeList* pNodeList)
  138. {
  139. ASSERT(GetFolderInfo()->GetLeafList()->IsEmpty());
  140. CUINodeList* pContainerList = GetFolderInfo()->GetContainerList();
  141. for (POSITION pos = pContainerList->GetHeadPosition(); pos != NULL; )
  142. {
  143. CUINode* pCurrUINode = pContainerList->GetNext(pos);
  144. if (IS_CLASS(*pCurrUINode, CSavedQueryNode))
  145. {
  146. CSavedQueryNode* pSavedQueryNode = dynamic_cast<CSavedQueryNode*>(pCurrUINode);
  147. pSavedQueryNode->FindCookieByDN(lpszCookieDN, pNodeList);
  148. }
  149. else if (IS_CLASS(*pCurrUINode, CFavoritesNode))
  150. {
  151. // recurse down to other query folders
  152. dynamic_cast<CFavoritesNode*>(pCurrUINode)->FindCookiesInQueries(lpszCookieDN, pNodeList);
  153. }
  154. }
  155. }
  156. BOOL CFavoritesNode::IsDeleteAllowed(CDSComponentData* pComponentData, BOOL* pbHide)
  157. {
  158. if (pComponentData->GetFavoritesNodeHolder()->GetFavoritesRoot() == this)
  159. {
  160. *pbHide = TRUE;
  161. return FALSE;
  162. }
  163. *pbHide = FALSE;
  164. return TRUE;
  165. }
  166. BOOL CFavoritesNode::ArePropertiesAllowed(CDSComponentData*, BOOL* pbHide)
  167. {
  168. *pbHide = FALSE;
  169. return TRUE;
  170. }
  171. BOOL CFavoritesNode::IsRenameAllowed(CDSComponentData* pComponentData, BOOL* pbHide)
  172. {
  173. if (pComponentData->GetFavoritesNodeHolder()->GetFavoritesRoot() == this)
  174. {
  175. *pbHide = TRUE;
  176. return FALSE;
  177. }
  178. *pbHide = FALSE;
  179. return TRUE;
  180. }
  181. BOOL CFavoritesNode::IsRefreshAllowed(CDSComponentData*, BOOL* pbHide)
  182. {
  183. *pbHide = FALSE;
  184. return TRUE;
  185. }
  186. BOOL CFavoritesNode::IsCutAllowed(CDSComponentData* pComponentData, BOOL* pbHide)
  187. {
  188. //
  189. // Don't allow cut on the favorites root
  190. //
  191. if (pComponentData->GetFavoritesNodeHolder()->GetFavoritesRoot() == this)
  192. {
  193. *pbHide = TRUE;
  194. return FALSE;
  195. }
  196. *pbHide = FALSE;
  197. return TRUE;
  198. }
  199. BOOL CFavoritesNode::IsCopyAllowed(CDSComponentData* pComponentData, BOOL* pbHide)
  200. {
  201. //
  202. // Don't allow copy on the favorites root
  203. //
  204. if (pComponentData->GetFavoritesNodeHolder()->GetFavoritesRoot() == this)
  205. {
  206. *pbHide = TRUE;
  207. return FALSE;
  208. }
  209. *pbHide = FALSE;
  210. return TRUE;
  211. }
  212. BOOL CFavoritesNode::IsPasteAllowed(CDSComponentData*, BOOL* pbHide)
  213. {
  214. *pbHide = FALSE;
  215. return TRUE;
  216. }
  217. void CFavoritesNode::Paste(IDataObject* pPasteData, CDSComponentData* pComponentData, LPDATAOBJECT* ppCutDataObj)
  218. {
  219. bool bIsCopy = (ppCutDataObj == 0);
  220. //
  221. // Extract the cookies from the data object
  222. //
  223. CInternalFormatCracker ifc;
  224. HRESULT hr = ifc.Extract(pPasteData);
  225. if (SUCCEEDED(hr))
  226. {
  227. //
  228. // Make sure all the nodes are either CFavoritesNode or CSavedQueryNode
  229. // and not the same node or a relative
  230. //
  231. for (UINT nCount = 0; nCount < ifc.GetCookieCount(); nCount++)
  232. {
  233. CUINode* pNode = ifc.GetCookie(nCount);
  234. if (pNode != NULL)
  235. {
  236. if (!IS_CLASS(*pNode, CFavoritesNode) && !IS_CLASS(*pNode, CSavedQueryNode))
  237. {
  238. //
  239. // Note this should be caught on the query paste
  240. //
  241. ASSERT(FALSE && L"!IS_CLASS(*pNode, CFavoritesNode) || !IS_CLASS(*pNode, CSavedQueryNode)");
  242. return;
  243. }
  244. if (pNode == this)
  245. {
  246. return;
  247. }
  248. if (IsRelative(pNode))
  249. {
  250. return;
  251. }
  252. }
  253. }
  254. //
  255. // Add the nodes to this container
  256. //
  257. CUINodeList nodesAddedList;
  258. for (UINT nCount = 0; nCount < ifc.GetCookieCount(); nCount++)
  259. {
  260. CUINode* pNode = ifc.GetCookie(nCount);
  261. if (pNode != NULL)
  262. {
  263. if (IS_CLASS(*pNode, CFavoritesNode))
  264. {
  265. //
  266. // Use the copy constructor to copy the node
  267. //
  268. CFavoritesNode* pCopyNode = new CFavoritesNode(*(dynamic_cast<CFavoritesNode*>(pNode)));
  269. if (pCopyNode != NULL)
  270. {
  271. if (bIsCopy)
  272. {
  273. //
  274. // Check to see if the name is unique and prepend "Copy of " if not
  275. //
  276. UINT nCopyOfCount = 0;
  277. CString szCopyOf;
  278. VERIFY(szCopyOf.LoadString(IDS_COPY_OF));
  279. CString szOriginalName = pCopyNode->GetName();
  280. CString szCopyName = szOriginalName;
  281. if (szCopyName.Find(szCopyOf) != -1)
  282. {
  283. nCopyOfCount = 1;
  284. }
  285. CString szMultipleCopyOf;
  286. VERIFY(szMultipleCopyOf.LoadString(IDS_MULTIPLE_COPY_OF));
  287. CUINode* pDupNode = NULL;
  288. while (!IsUniqueName(szCopyName, &pDupNode))
  289. {
  290. //
  291. // Puts the new name in the format "Copy of <original name>" or
  292. // "Copy of (#) <original name>"
  293. //
  294. if (nCopyOfCount == 0)
  295. {
  296. szCopyName = szCopyOf + szOriginalName;
  297. }
  298. else
  299. {
  300. CString szTemp;
  301. szTemp.Format(szMultipleCopyOf, nCopyOfCount+1);
  302. szCopyName = szTemp + szOriginalName;
  303. }
  304. ++nCopyOfCount;
  305. }
  306. pCopyNode->SetName(szCopyName);
  307. }
  308. else
  309. {
  310. CUINode* pDupNode = NULL;
  311. CString szNewName = pCopyNode->GetName();
  312. if (!IsUniqueName(szNewName, &pDupNode))
  313. {
  314. if (pDupNode == pCopyNode)
  315. {
  316. //
  317. // We are moving the node to the same container. Just silently ignore
  318. //
  319. continue;
  320. }
  321. CString szFormatMsg;
  322. VERIFY(szFormatMsg.LoadString(IDS_ERRMSG_NOT_UNIQUE_QUERY_NAME_INPLACE));
  323. CString szErrMsg;
  324. szErrMsg.Format(szFormatMsg, szNewName);
  325. CString szTitle;
  326. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  327. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  328. return;
  329. }
  330. }
  331. //
  332. // Make copies of all the children too
  333. //
  334. pCopyNode->DeepCopyChildren(pNode);
  335. pCopyNode->SetParent(this);
  336. //
  337. // Add it to the successfully pasted list
  338. //
  339. nodesAddedList.AddTail(pCopyNode);
  340. }
  341. }
  342. else if (IS_CLASS(*pNode, CSavedQueryNode))
  343. {
  344. CSavedQueryNode* pCopyNode = new CSavedQueryNode(*(dynamic_cast<CSavedQueryNode*>(pNode)));
  345. if (pCopyNode != NULL)
  346. {
  347. if (bIsCopy)
  348. {
  349. //
  350. // Check to see if the name is unique and prepend "Copy of " if not
  351. //
  352. UINT nCopyOfCount = 0;
  353. CString szCopyOf;
  354. VERIFY(szCopyOf.LoadString(IDS_COPY_OF));
  355. CString szOriginalName = pCopyNode->GetName();
  356. CString szCopyName = szOriginalName;
  357. if (szCopyName.Find(szCopyOf) != -1)
  358. {
  359. nCopyOfCount = 1;
  360. }
  361. CString szMultipleCopyOf;
  362. VERIFY(szMultipleCopyOf.LoadString(IDS_MULTIPLE_COPY_OF));
  363. CUINode* pDupNode = NULL;
  364. while (!IsUniqueName(szCopyName, &pDupNode))
  365. {
  366. //
  367. // Puts the new name in the format "Copy of <original name>" or
  368. // "Copy of (#) <original name>"
  369. //
  370. if (nCopyOfCount == 0)
  371. {
  372. szCopyName = szCopyOf + szOriginalName;
  373. }
  374. else
  375. {
  376. CString szTemp;
  377. szTemp.Format(szMultipleCopyOf, nCopyOfCount+1);
  378. szCopyName = szTemp + szOriginalName;
  379. }
  380. ++nCopyOfCount;
  381. }
  382. pCopyNode->SetName(szCopyName);
  383. }
  384. else
  385. {
  386. CUINode* pDupNode = NULL;
  387. CString szNewName = pCopyNode->GetName();
  388. if (!IsUniqueName(szNewName, &pDupNode))
  389. {
  390. if (pDupNode == pCopyNode)
  391. {
  392. //
  393. // We are moving the node to the same container. Just silently ignore
  394. //
  395. continue;
  396. }
  397. CString szFormatMsg;
  398. VERIFY(szFormatMsg.LoadString(IDS_ERRMSG_NOT_UNIQUE_QUERY_NAME_INPLACE));
  399. CString szErrMsg;
  400. szErrMsg.Format(szFormatMsg, szNewName);
  401. CString szTitle;
  402. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  403. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  404. return;
  405. }
  406. }
  407. pCopyNode->SetParent(this);
  408. //
  409. // Add it to the successfully pasted list
  410. //
  411. nodesAddedList.AddTail(pCopyNode);
  412. }
  413. }
  414. else
  415. {
  416. //
  417. // CFavoritesNode should only contain CFavoritesNodes and CSavedQueryNodes
  418. //
  419. ASSERT(FALSE);
  420. }
  421. }
  422. }
  423. //
  424. // if the node has been expanded then add the new nodes to the UI
  425. //
  426. if (GetFolderInfo()->IsExpanded())
  427. {
  428. //
  429. // add the items to the UI
  430. //
  431. pComponentData->AddListOfNodesToUI(this, &nodesAddedList);
  432. }
  433. else
  434. {
  435. //
  436. // If not then just add them to the folder's list of children
  437. //
  438. GetFolderInfo()->AddListofNodes(&nodesAddedList);
  439. }
  440. //
  441. // Only set the output DataObject if it is a cut operation
  442. //
  443. if (ppCutDataObj != NULL)
  444. {
  445. *ppCutDataObj = pPasteData;
  446. pPasteData->AddRef();
  447. }
  448. }
  449. }
  450. HRESULT CFavoritesNode::QueryPaste(IDataObject* pPasteData, CDSComponentData* pComponentData)
  451. {
  452. HRESULT hr = S_OK;
  453. ASSERT(pComponentData);
  454. //
  455. // Extract the cookies from the data object
  456. //
  457. CInternalFormatCracker ifc;
  458. hr = ifc.Extract(pPasteData);
  459. if (SUCCEEDED(hr))
  460. {
  461. //
  462. // Don't allow drops across instances of the snapin
  463. //
  464. if (IsSameSnapin(pPasteData, pComponentData))
  465. {
  466. //
  467. // Make sure all the nodes are either CFavoritesNode or CSavedQueryNode
  468. //
  469. for (UINT nCount = 0; nCount < ifc.GetCookieCount(); nCount++)
  470. {
  471. CUINode* pNode = ifc.GetCookie(nCount);
  472. if (pNode != NULL)
  473. {
  474. if (!IS_CLASS(*pNode, CFavoritesNode) && !IS_CLASS(*pNode, CSavedQueryNode))
  475. {
  476. hr = S_FALSE;
  477. break;
  478. }
  479. }
  480. }
  481. }
  482. else
  483. {
  484. hr = S_FALSE;
  485. }
  486. }
  487. return hr;
  488. }
  489. bool CFavoritesNode::IsSameSnapin(IDataObject* pPasteData, CDSComponentData* pComponentData)
  490. {
  491. bool bResult = true;
  492. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL };
  493. do
  494. {
  495. FORMATETC formatetc = { CDSDataObject::m_cfComponentData, NULL,
  496. DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  497. HRESULT hr = pPasteData->GetData(&formatetc, &stgmedium);
  498. if (FAILED(hr))
  499. {
  500. bResult = false;
  501. break;
  502. }
  503. CDSComponentData** pPasteComponentData = reinterpret_cast<CDSComponentData**>(stgmedium.hGlobal);
  504. if (pPasteComponentData &&
  505. pComponentData != *pPasteComponentData)
  506. {
  507. bResult = false;
  508. break;
  509. }
  510. } while(false);
  511. if (stgmedium.hGlobal)
  512. {
  513. GlobalFree(stgmedium.hGlobal);
  514. }
  515. return bResult;
  516. }
  517. CContextMenuVerbs* CFavoritesNode::GetContextMenuVerbsObject(CDSComponentData* pComponentData)
  518. {
  519. if (m_pMenuVerbs == NULL)
  520. {
  521. m_pMenuVerbs = new CFavoritesFolderMenuVerbs(pComponentData);
  522. }
  523. return m_pMenuVerbs;
  524. }
  525. HRESULT CFavoritesNode::Delete(CDSComponentData* pComponentData)
  526. {
  527. HRESULT hr = S_OK;
  528. //
  529. // this is just a message box, using ReportErrorEx for consistency of look
  530. //
  531. int answer = ReportErrorEx(pComponentData->GetHWnd(),IDS_CONFIRM_DELETE_FAVORITES,S_OK,
  532. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, NULL, 0);
  533. if (answer == IDNO)
  534. {
  535. return S_FALSE; // aborted by user
  536. }
  537. if (IsContainer())
  538. {
  539. hr = pComponentData->RemoveContainerFromUI(this);
  540. delete this;
  541. }
  542. else
  543. {
  544. CUINode* pParentNode = GetParent();
  545. ASSERT(pParentNode->IsContainer());
  546. pParentNode->GetFolderInfo()->RemoveNode(this);
  547. //
  548. // The CDSEvent::_DeleteSingleSel() handles removing the node from the UI
  549. //
  550. }
  551. return hr;
  552. }
  553. HRESULT CFavoritesNode::DeleteMultiselect(CDSComponentData* pComponentData, CInternalFormatCracker* pObjCracker)
  554. {
  555. ASSERT(pObjCracker != NULL);
  556. if (pObjCracker == NULL)
  557. {
  558. return S_FALSE;
  559. }
  560. UINT nQueryCount = 0;
  561. UINT nFolderCount = 0;
  562. for (UINT nIdx = 0; nIdx < pObjCracker->GetCookieCount(); nIdx++)
  563. {
  564. CUINode* pUINode = pObjCracker->GetCookie(nIdx);
  565. if (pUINode != NULL)
  566. {
  567. if (IS_CLASS(*pUINode, CFavoritesNode))
  568. {
  569. nFolderCount++;
  570. }
  571. else if (IS_CLASS(*pUINode, CSavedQueryNode))
  572. {
  573. nQueryCount++;
  574. }
  575. else
  576. {
  577. //
  578. // CFavoritesNode should only contain CFavoritesNodes and CSavedQueryNodes
  579. //
  580. ASSERT(FALSE);
  581. continue;
  582. }
  583. }
  584. }
  585. CString szFormatMessage;
  586. VERIFY(szFormatMessage.LoadString(IDS_CONFIRM_MULTI_DELETE_FAVORITES));
  587. if (!szFormatMessage.IsEmpty())
  588. {
  589. CString szConfirmMessage;
  590. szConfirmMessage.Format(szFormatMessage, nFolderCount, nQueryCount);
  591. CString szCaption;
  592. VERIFY(szCaption.LoadString(IDS_DSSNAPINNAME));
  593. //
  594. // this is just a message box, using ReportErrorEx for consistency of look
  595. //
  596. int answer = MessageBox(pComponentData->GetHWnd(),szConfirmMessage,szCaption,
  597. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2);
  598. if (answer == IDNO)
  599. {
  600. return S_FALSE; // aborted by user
  601. }
  602. }
  603. else
  604. {
  605. return S_FALSE;
  606. }
  607. return CUINode::DeleteMultiselect(pComponentData, pObjCracker);
  608. }
  609. HRESULT CFavoritesNode::OnCommand(long lCommandID, CDSComponentData* pComponentData)
  610. {
  611. HRESULT hr = S_OK;
  612. switch (lCommandID)
  613. {
  614. case IDM_NEW_FAVORITES_FOLDER:
  615. OnNewFavoritesFolder(pComponentData);
  616. break;
  617. case IDM_NEW_QUERY_FOLDER:
  618. OnNewSavedQuery(pComponentData);
  619. break;
  620. case IDM_IMPORT_QUERY:
  621. OnImportQuery(pComponentData);
  622. break;
  623. case IDM_GEN_TASK_MOVE:
  624. break;
  625. case IDM_VIEW_ADVANCED:
  626. {
  627. if (pComponentData->CanRefreshAll())
  628. {
  629. ASSERT( SNAPINTYPE_SITE != pComponentData->QuerySnapinType() );
  630. pComponentData->GetQueryFilter()->ToggleAdvancedView();
  631. pComponentData->SetDirty(TRUE);
  632. pComponentData->RefreshAll();
  633. }
  634. }
  635. break;
  636. default :
  637. ASSERT(FALSE);
  638. break;
  639. }
  640. return hr;
  641. }
  642. //
  643. // Checks to see if any existing children of this container
  644. // already exist with the passed in name
  645. //
  646. BOOL CFavoritesNode::IsUniqueName(PCWSTR pszName, CUINode** ppDuplicateNode)
  647. {
  648. BOOL bUnique = TRUE;
  649. CString szNewName = pszName;
  650. //
  651. // Trim whitespace
  652. //
  653. szNewName.TrimLeft();
  654. szNewName.TrimRight();
  655. //
  656. // Make sure the name is unique
  657. //
  658. CUINodeList* pNodeList = GetFolderInfo()->GetContainerList();
  659. if (pNodeList != NULL)
  660. {
  661. POSITION pos = pNodeList->GetHeadPosition();
  662. while (pos != NULL)
  663. {
  664. CUINode* pNode = pNodeList->GetNext(pos);
  665. if (pNode != NULL)
  666. {
  667. if (_wcsicmp(szNewName, pNode->GetName()) == 0)
  668. {
  669. bUnique = FALSE;
  670. //
  671. // Return the node that was found to have the duplicate name
  672. //
  673. if (ppDuplicateNode != NULL)
  674. {
  675. *ppDuplicateNode = pNode;
  676. }
  677. break;
  678. }
  679. }
  680. }
  681. }
  682. return bUnique;
  683. }
  684. HRESULT CFavoritesNode::Rename(LPCWSTR lpszNewName, CDSComponentData* pComponentData)
  685. {
  686. HRESULT hr = S_OK;
  687. CString szNewName = lpszNewName;
  688. CString szTitle;
  689. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  690. //
  691. // Trim whitespace
  692. //
  693. szNewName.TrimLeft();
  694. szNewName.TrimRight();
  695. if (szNewName.IsEmpty())
  696. {
  697. //
  698. // Don't allow empty names
  699. //
  700. CString szMessage;
  701. VERIFY(szMessage.LoadString(IDS_ERRMSG_NO_EMPTY_NAMES));
  702. MessageBox(pComponentData->GetHWnd(), szMessage, szTitle, MB_OK | MB_ICONSTOP);
  703. return S_FALSE;
  704. }
  705. CUINode* pDupNode = NULL;
  706. if (GetFavoritesNode() != NULL && !GetFavoritesNode()->IsUniqueName(szNewName, &pDupNode))
  707. {
  708. if (pDupNode == this)
  709. {
  710. //
  711. // We are renaming the node to the same name. Just silently ignore
  712. //
  713. return S_FALSE;
  714. }
  715. CString szFormatMsg;
  716. VERIFY(szFormatMsg.LoadString(IDS_ERRMSG_NOT_UNIQUE_QUERY_NAME_INPLACE));
  717. CString szErrMsg;
  718. szErrMsg.Format(szFormatMsg, szNewName);
  719. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  720. return S_FALSE;
  721. }
  722. //
  723. // Set the name
  724. //
  725. SetName(szNewName);
  726. hr = pComponentData->UpdateItem(this);
  727. return hr;
  728. }
  729. void CFavoritesNode::OnImportQuery(CDSComponentData* pComponentData)
  730. {
  731. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  732. //
  733. // Title for error message box
  734. //
  735. CString szTitle;
  736. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  737. CString szFilter;
  738. VERIFY(szFilter.LoadString(IDS_QUERY_EXPORT_FILTER));
  739. CString szFileExt(L"xml");
  740. CString szFileView(L"*.xml");
  741. CFileDialog* pFileDlg = new CFileDialog(TRUE,
  742. szFileExt,
  743. szFileView,
  744. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST,
  745. szFilter);
  746. if (pFileDlg == NULL)
  747. {
  748. return;
  749. }
  750. if (pFileDlg->DoModal() == IDOK)
  751. {
  752. //
  753. // create an instance of the XML document
  754. //
  755. CComPtr<IXMLDOMDocument> spXMLDoc;
  756. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  757. IID_IXMLDOMDocument, (void**)&spXMLDoc);
  758. if (FAILED(hr))
  759. {
  760. TRACE(L"CoCreateInstance(CLSID_DOMDocument) failed with hr = 0x%x\n", hr);
  761. return;
  762. }
  763. //
  764. // Retrieve the file and path
  765. //
  766. CString szFileName;
  767. szFileName = pFileDlg->GetPathName();
  768. CSavedQueryNode* pNewSavedQuery = NULL;
  769. bool bQueryAdded = false;
  770. do // false loop
  771. {
  772. //
  773. // load the document from file
  774. //
  775. CComVariant xmlSource;
  776. xmlSource = szFileName;
  777. VARIANT_BOOL isSuccessful;
  778. hr = spXMLDoc->load(xmlSource, &isSuccessful);
  779. if (FAILED(hr) || !isSuccessful)
  780. {
  781. CString szErrMsg;
  782. szErrMsg.LoadString(IDS_ERRMSG_FAILED_LOAD_QUERY);
  783. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  784. break;
  785. }
  786. //
  787. // Get the node interface to the beginning of the document
  788. //
  789. CComPtr<IXMLDOMNode> spXDOMNode;
  790. hr = spXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&spXDOMNode);
  791. if (FAILED(hr))
  792. {
  793. CString szErrMsg;
  794. szErrMsg.LoadString(IDS_ERRMSG_FAILED_LOAD_QUERY);
  795. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  796. break;
  797. }
  798. //
  799. // Get its child
  800. //
  801. CComPtr<IXMLDOMNode> spXDOMChild;
  802. hr = spXDOMNode->get_firstChild(&spXDOMChild);
  803. if (FAILED(hr) || !spXDOMChild)
  804. {
  805. CString szErrMsg;
  806. szErrMsg.LoadString(IDS_ERRMSG_FAILED_LOAD_QUERY);
  807. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  808. break;
  809. }
  810. //
  811. // Load the saved query node from this child
  812. //
  813. hr = CSavedQueryNode::XMLLoad(pComponentData, spXDOMChild, &pNewSavedQuery);
  814. if (FAILED(hr) || !pNewSavedQuery)
  815. {
  816. CString szErrMsg;
  817. szErrMsg.LoadString(IDS_ERRMSG_FAILED_LOAD_QUERY);
  818. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  819. break;
  820. }
  821. //
  822. // Open query in edit mode
  823. //
  824. CQueryDialog dlg(pNewSavedQuery, this, pComponentData, FALSE, TRUE);
  825. if (dlg.DoModal() == IDOK)
  826. {
  827. //
  828. // Add the node to the ui and select it
  829. //
  830. GetFolderInfo()->AddNode(pNewSavedQuery);
  831. pComponentData->AddScopeItemToUI(pNewSavedQuery, TRUE);
  832. bQueryAdded = true;
  833. }
  834. } while (false);
  835. //
  836. // There was an error or the user cancelled the dialog.
  837. // Clean up the memory
  838. //
  839. if (!bQueryAdded && pNewSavedQuery)
  840. {
  841. delete pNewSavedQuery;
  842. pNewSavedQuery = 0;
  843. }
  844. }
  845. if (pFileDlg != NULL)
  846. {
  847. delete pFileDlg;
  848. pFileDlg = NULL;
  849. }
  850. }
  851. void CFavoritesNode::OnNewFavoritesFolder(CDSComponentData* pComponentData)
  852. {
  853. CFavoritesNode* pFav = new CFavoritesNode;
  854. CString szNewFolder;
  855. VERIFY(szNewFolder.LoadString(IDS_NEW_FOLDER));
  856. CUINodeList* pContainerList = GetFolderInfo()->GetContainerList();
  857. if (pContainerList != NULL)
  858. {
  859. CString szSearchString;
  860. szSearchString.Format(L"%s (%%u)", szNewFolder);
  861. //
  862. // Search for containers under this node that start with "New Folder (<number>)"
  863. //
  864. UINT nLargestNum = 0;
  865. POSITION pos = pContainerList->GetHeadPosition();
  866. while (pos != NULL)
  867. {
  868. CUINode* pUINode = pContainerList->GetNext(pos);
  869. UINT nFolderNum = 0;
  870. CString szNodeName;
  871. szNodeName = pUINode->GetName();
  872. if (szNodeName == szNewFolder)
  873. {
  874. if (nLargestNum < 1)
  875. {
  876. nLargestNum = 1;
  877. }
  878. continue;
  879. }
  880. if (swscanf(szNodeName, szSearchString, &nFolderNum) == 1)
  881. {
  882. if (nFolderNum > nLargestNum)
  883. {
  884. nLargestNum = nFolderNum;
  885. }
  886. }
  887. }
  888. CString szNewName;
  889. if (nLargestNum == 0)
  890. {
  891. szNewName = szNewFolder;
  892. }
  893. else
  894. {
  895. szNewName.Format(L"%s (%u)", szNewFolder, nLargestNum + 1);
  896. }
  897. pFav->SetName(szNewName);
  898. }
  899. else
  900. {
  901. pFav->SetName(szNewFolder);
  902. }
  903. pFav->SetDesc(L"");
  904. GetFolderInfo()->AddNode(pFav);
  905. //
  906. // Add node to UI and select it
  907. //
  908. pComponentData->AddScopeItemToUI(pFav, TRUE);
  909. //
  910. // Put the folder into rename mode
  911. //
  912. pComponentData->SetRenameMode(pFav);
  913. }
  914. void CFavoritesNode::OnNewSavedQuery(CDSComponentData* pComponentData)
  915. {
  916. CSavedQueryNode* pQuery = new CSavedQueryNode(pComponentData->GetBasePathsInfo(),
  917. pComponentData->QuerySnapinType());
  918. CQueryDialog dlg(pQuery, this, pComponentData, TRUE);
  919. if (dlg.DoModal() == IDOK)
  920. {
  921. GetFolderInfo()->AddNode(pQuery);
  922. //
  923. // Add new node to UI and select it
  924. //
  925. pComponentData->AddScopeItemToUI(pQuery, TRUE);
  926. }
  927. }
  928. LPCWSTR CFavoritesNode::g_szObjXMLTag = L"FOLDER";
  929. //
  930. // This is used to start the loading at the embedded favorites root.
  931. // All other favorites folders are loaded through the static method XMLLoad
  932. //
  933. HRESULT CFavoritesNode::Load(IXMLDOMNode* pXDN,
  934. CDSComponentData* pComponentData)
  935. {
  936. //
  937. // check the name of the node
  938. //
  939. if (!XMLIsNodeName(pXDN, CFavoritesNode::g_szObjXMLTag))
  940. {
  941. //
  942. // should have checked before calling...
  943. //
  944. ASSERT(FALSE);
  945. return E_INVALIDARG;
  946. }
  947. //
  948. // get the list of child nodes
  949. //
  950. CComPtr<IXMLDOMNode> spCurrChild;
  951. pXDN->get_firstChild(&spCurrChild);
  952. if (spCurrChild == NULL)
  953. {
  954. return E_INVALIDARG;
  955. }
  956. //
  957. // recurse down on children
  958. //
  959. while (spCurrChild != NULL)
  960. {
  961. CComBSTR bstrName, bstrDescription;
  962. CComBSTR bstrChildName;
  963. spCurrChild->get_nodeName(&bstrChildName);
  964. if (CompareXMLTags(bstrChildName, CFavoritesNode::g_szObjXMLTag))
  965. {
  966. //
  967. // we got a subfolder, need to build the subtree
  968. //
  969. CFavoritesNode* pSubNode = NULL;
  970. CFavoritesNode::XMLLoad(pComponentData, spCurrChild, &pSubNode);
  971. if (pSubNode != NULL)
  972. {
  973. //
  974. // got a subtree, add it to the list of children
  975. //
  976. GetFolderInfo()->AddNode(pSubNode);
  977. }
  978. }
  979. else if (CompareXMLTags(bstrChildName, CGenericUINode::g_szNameXMLTag))
  980. {
  981. XML_GetNodeText(spCurrChild, &bstrName);
  982. // Don't overwrite the name from the saved console if this is the query
  983. // root because the default saved console is always english. In other
  984. // languages we need to use the string from the resource file.
  985. if (!IsFavoritesRoot())
  986. {
  987. SetName(bstrName);
  988. }
  989. }
  990. else if (CompareXMLTags(bstrChildName, CGenericUINode::g_szDecriptionXMLTag))
  991. {
  992. XML_GetNodeText(spCurrChild, &bstrDescription);
  993. // Don't overwrite the description from the saved console if this is the query
  994. // root because the default saved console is always english. In other
  995. // languages we need to use the string from the resource file.
  996. if (!IsFavoritesRoot())
  997. {
  998. SetDesc(bstrDescription);
  999. }
  1000. else
  1001. {
  1002. // If it is the favorites root and the description is not the same as the
  1003. // default english description, then set it. The user has the option to
  1004. // change the description. If IDS_SAVED_QUERIES_DESC gets changed this has
  1005. // to be changed as well.
  1006. if (_wcsicmp(bstrDescription, L"Folder to store your favorite queries") !=0)
  1007. {
  1008. SetDesc(bstrDescription);
  1009. }
  1010. }
  1011. }
  1012. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szObjXMLTag))
  1013. {
  1014. CSavedQueryNode* pQuery = NULL;
  1015. CSavedQueryNode::XMLLoad(pComponentData, spCurrChild, &pQuery);
  1016. if (pQuery != NULL)
  1017. {
  1018. GetFolderInfo()->AddNode(pQuery);
  1019. }
  1020. }
  1021. CComPtr<IXMLDOMNode> temp = spCurrChild;
  1022. spCurrChild = NULL;
  1023. temp->get_nextSibling(&spCurrChild);
  1024. }
  1025. return S_OK;
  1026. }
  1027. HRESULT CFavoritesNode::XMLLoad(CDSComponentData* pComponentData,
  1028. IXMLDOMNode* pXDN,
  1029. CFavoritesNode** ppNode)
  1030. {
  1031. // check the name of the node
  1032. if (!XMLIsNodeName(pXDN, CFavoritesNode::g_szObjXMLTag))
  1033. {
  1034. // should have checked before calling...
  1035. ASSERT(FALSE);
  1036. return E_INVALIDARG;
  1037. }
  1038. // get the list of child nodes
  1039. CComPtr<IXMLDOMNode> spCurrChild;
  1040. pXDN->get_firstChild(&spCurrChild);
  1041. if (spCurrChild == NULL)
  1042. {
  1043. return E_INVALIDARG;
  1044. }
  1045. // create a temporary node
  1046. (*ppNode) = new CFavoritesNode;
  1047. // recurse down on children
  1048. while (spCurrChild != NULL)
  1049. {
  1050. CComBSTR bstrName, bstrDescription;
  1051. CComBSTR bstrChildName;
  1052. spCurrChild->get_nodeName(&bstrChildName);
  1053. if (CompareXMLTags(bstrChildName, CFavoritesNode::g_szObjXMLTag))
  1054. {
  1055. // we got a subfolder, need to build the subtree
  1056. CFavoritesNode* pSubNode = NULL;
  1057. CFavoritesNode::XMLLoad(pComponentData, spCurrChild, &pSubNode);
  1058. if (pSubNode != NULL)
  1059. {
  1060. // got a subtree, add it to the list of children
  1061. (*ppNode)->GetFolderInfo()->AddNode(pSubNode);
  1062. }
  1063. }
  1064. else if (CompareXMLTags(bstrChildName, CGenericUINode::g_szNameXMLTag))
  1065. {
  1066. XML_GetNodeText(spCurrChild, &bstrName);
  1067. (*ppNode)->SetName(bstrName);
  1068. }
  1069. else if (CompareXMLTags(bstrChildName, CGenericUINode::g_szDecriptionXMLTag))
  1070. {
  1071. XML_GetNodeText(spCurrChild, &bstrDescription);
  1072. (*ppNode)->SetDesc(bstrDescription);
  1073. }
  1074. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szObjXMLTag))
  1075. {
  1076. CSavedQueryNode* pQuery = NULL;
  1077. CSavedQueryNode::XMLLoad(pComponentData, spCurrChild, &pQuery);
  1078. if (pQuery != NULL)
  1079. {
  1080. (*ppNode)->GetFolderInfo()->AddNode(pQuery);
  1081. }
  1082. }
  1083. CComPtr<IXMLDOMNode> temp = spCurrChild;
  1084. spCurrChild = NULL;
  1085. temp->get_nextSibling(&spCurrChild);
  1086. }
  1087. return S_OK;
  1088. }
  1089. HRESULT CFavoritesNode::XMLSave(IXMLDOMDocument* pXMLDoc,
  1090. IXMLDOMNode** ppXMLDOMNode)
  1091. {
  1092. CComPtr<IXMLDOMNode> spXMLDOMNode;
  1093. HRESULT hr = XML_CreateDOMNode(pXMLDoc, NODE_ELEMENT, CFavoritesNode::g_szObjXMLTag, &spXMLDOMNode);
  1094. if (FAILED(hr))
  1095. {
  1096. return hr;
  1097. }
  1098. hr = XMLSaveBase(pXMLDoc, spXMLDOMNode);
  1099. if (FAILED(hr))
  1100. {
  1101. return hr;
  1102. }
  1103. // save the child nodes
  1104. CUINodeList* pNodeList = GetFolderInfo()->GetContainerList();
  1105. for (POSITION pos = pNodeList->GetHeadPosition(); pos != NULL; )
  1106. {
  1107. CGenericUINode* pCurrChildNode = dynamic_cast<CGenericUINode*>(pNodeList->GetNext(pos));
  1108. if (pCurrChildNode == NULL)
  1109. {
  1110. ASSERT(FALSE); // should never happen
  1111. continue;
  1112. }
  1113. CComPtr<IXMLDOMNode> spXMLDOMChildNode;
  1114. hr = pCurrChildNode->XMLSave(pXMLDoc, &spXMLDOMChildNode);
  1115. if (SUCCEEDED(hr))
  1116. {
  1117. CComPtr<IXMLDOMNode> p;
  1118. CComVariant after;
  1119. after.vt = VT_EMPTY;
  1120. hr = spXMLDOMNode->appendChild(spXMLDOMChildNode, &p);
  1121. }
  1122. } // for
  1123. (*ppXMLDOMNode) = spXMLDOMNode;
  1124. (*ppXMLDOMNode)->AddRef();
  1125. return S_OK;
  1126. }
  1127. HRESULT CFavoritesNode::CreatePropertyPages(LPPROPERTYSHEETCALLBACK pCall,
  1128. LONG_PTR lNotifyHandle,
  1129. LPDATAOBJECT pDataObject,
  1130. CDSComponentData* pComponentData)
  1131. {
  1132. HRESULT hr = S_FALSE;
  1133. CFavoritesNodePropertyPage* pPropertyPage =
  1134. new CFavoritesNodePropertyPage(this, lNotifyHandle, pComponentData, pDataObject);
  1135. if (pPropertyPage != NULL)
  1136. {
  1137. HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&pPropertyPage->m_psp);
  1138. if (hPage != NULL)
  1139. {
  1140. hr = pCall->AddPage(hPage);
  1141. }
  1142. else
  1143. {
  1144. hr = E_UNEXPECTED;
  1145. }
  1146. }
  1147. else
  1148. {
  1149. hr = E_OUTOFMEMORY;
  1150. }
  1151. return hr;
  1152. }
  1153. //
  1154. // Function used in a recursive search through the saved query tree looking
  1155. // for saved queries that contain objects with any of the DNs in the list
  1156. // and invalidates that query
  1157. //
  1158. void CFavoritesNode::InvalidateSavedQueriesContainingObjects(CDSComponentData* pComponentData,
  1159. const CStringList& refDNList)
  1160. {
  1161. ASSERT(IsContainer());
  1162. //
  1163. // Note favorites nodes should only contain containers, so we only have to look
  1164. // through the folder list
  1165. //
  1166. CUINodeList* pContainerList = GetFolderInfo()->GetContainerList();
  1167. POSITION pos = pContainerList->GetHeadPosition();
  1168. while (pos)
  1169. {
  1170. CGenericUINode* pGenericUINode = dynamic_cast<CGenericUINode*>(pContainerList->GetNext(pos));
  1171. if (pGenericUINode)
  1172. {
  1173. pGenericUINode->InvalidateSavedQueriesContainingObjects(pComponentData,
  1174. refDNList);
  1175. }
  1176. }
  1177. }
  1178. ////////////////////////////////////////////////////////////////////////////
  1179. // CSavedQueryNode
  1180. BOOL CSavedQueryNode::IsFilterLastLogon()
  1181. {
  1182. return m_bLastLogonFilter && m_dwLastLogonDays != (DWORD)-1;
  1183. }
  1184. CSavedQueryNode::CSavedQueryNode(MyBasePathsInfo* pBasePathsInfo,
  1185. SnapinType snapinType)
  1186. : m_szRelativeRootPath(L""),
  1187. m_szCurrentFullPath(L""),
  1188. m_szQueryString(L""),
  1189. m_szColumnID(L""),
  1190. m_bOneLevel(FALSE),
  1191. m_bQueryValid(TRUE),
  1192. m_pPersistQueryImpl(NULL),
  1193. m_bLastLogonFilter(FALSE),
  1194. m_dwLastLogonDays((DWORD)-1),
  1195. m_pBasePathsInfo(pBasePathsInfo)
  1196. {
  1197. MakeContainer();
  1198. CDSColumnSet* pColumnSet = NULL;
  1199. pColumnSet = CDSColumnSet::CreateColumnSetFromString(NULL, snapinType);
  1200. GUID guid = GUID_NULL;
  1201. HRESULT hr = ::CoCreateGuid(&guid);
  1202. if (SUCCEEDED(hr))
  1203. {
  1204. WCHAR lpszGuid[40];
  1205. int iRet = ::StringFromGUID2(guid, lpszGuid, sizeof(lpszGuid)/sizeof(WCHAR));
  1206. if (iRet > 0)
  1207. {
  1208. m_szColumnID = lpszGuid;
  1209. pColumnSet->SetColumnID(lpszGuid);
  1210. GetFolderInfo()->SetColumnSet(pColumnSet);
  1211. }
  1212. }
  1213. }
  1214. CSavedQueryNode::CSavedQueryNode(const CSavedQueryNode& copyNode) : CGenericUINode(copyNode)
  1215. {
  1216. m_szRelativeRootPath = copyNode.m_szRelativeRootPath;
  1217. m_szQueryString = copyNode.m_szQueryString;
  1218. m_bOneLevel = copyNode.m_bOneLevel;
  1219. m_pBasePathsInfo = copyNode.m_pBasePathsInfo;
  1220. //
  1221. // Create the IPersistQuery object
  1222. //
  1223. CComObject<CDSAdminPersistQueryFilterImpl>::CreateInstance(&m_pPersistQueryImpl);
  1224. ASSERT(m_pPersistQueryImpl != NULL);
  1225. if (m_pPersistQueryImpl != NULL)
  1226. {
  1227. //
  1228. // created with zero refcount,need to AddRef() to one
  1229. //
  1230. m_pPersistQueryImpl->AddRef();
  1231. copyNode.m_pPersistQueryImpl->Clone(m_pPersistQueryImpl);
  1232. }
  1233. m_bQueryValid = TRUE;
  1234. m_bLastLogonFilter = copyNode.m_bLastLogonFilter;
  1235. m_dwLastLogonDays = copyNode.m_dwLastLogonDays;
  1236. //
  1237. // Generate a new column set and new column set ID for the new node
  1238. //
  1239. CDSColumnSet* pColumnSet = NULL;
  1240. pColumnSet = CDSColumnSet::CreateColumnSetFromString(NULL, SNAPINTYPE_DS);
  1241. if (pColumnSet)
  1242. {
  1243. GUID guid = GUID_NULL;
  1244. HRESULT hr = ::CoCreateGuid(&guid);
  1245. if (SUCCEEDED(hr))
  1246. {
  1247. WCHAR lpszGuid[40];
  1248. int iRet = ::StringFromGUID2(guid, lpszGuid, sizeof(lpszGuid)/sizeof(WCHAR));
  1249. if (iRet > 0)
  1250. {
  1251. m_szColumnID = lpszGuid;
  1252. pColumnSet->SetColumnID(lpszGuid);
  1253. GetFolderInfo()->SetColumnSet(pColumnSet);
  1254. }
  1255. }
  1256. }
  1257. }
  1258. void CSavedQueryNode::SetColumnID(CDSComponentData* pComponentData, PCWSTR pszColumnID)
  1259. {
  1260. m_szColumnID = pszColumnID;
  1261. GetColumnSet(pComponentData)->SetColumnID(pszColumnID);
  1262. }
  1263. void CSavedQueryNode::AppendLastLogonQuery(CString& szQuery, DWORD dwDays)
  1264. {
  1265. LARGE_INTEGER li;
  1266. GetCurrentTimeStampMinusInterval(dwDays, &li);
  1267. CString szTime;
  1268. litow(li, szTime);
  1269. szQuery.Format(L"%s(lastLogonTimestamp<=%s)",szQuery, szTime);
  1270. }
  1271. LPCWSTR CSavedQueryNode::GetRootPath()
  1272. {
  1273. m_szCurrentFullPath = m_szRelativeRootPath + m_pBasePathsInfo->GetDefaultRootNamingContext();
  1274. return m_szCurrentFullPath;
  1275. }
  1276. void CSavedQueryNode::SetRootPath(LPCWSTR lpszRootPath)
  1277. {
  1278. //
  1279. // Strip the name down to make it a RDN to the defaultNamingContext
  1280. //
  1281. CString szTempPath = lpszRootPath;
  1282. ASSERT(m_pBasePathsInfo != NULL);
  1283. if (m_pBasePathsInfo != NULL)
  1284. {
  1285. //
  1286. // We now have a full DN. Strip the default root naming context to get the RDN.
  1287. //
  1288. CString szDefaultRootNamingContext = m_pBasePathsInfo->GetDefaultRootNamingContext();
  1289. int iRootDN = szTempPath.Find(szDefaultRootNamingContext);
  1290. if (iRootDN != -1)
  1291. {
  1292. szTempPath = szTempPath.Left(iRootDN);
  1293. }
  1294. }
  1295. m_szRelativeRootPath = szTempPath;
  1296. }
  1297. LPCWSTR CSavedQueryNode::GetQueryString()
  1298. {
  1299. //
  1300. // If we are doing a last logon query we have to check to be sure
  1301. // the lastLogonTimestamp is part of the query string. If not, we have
  1302. // to add it. There is a case when we load that the lastLogonTimestamp
  1303. // might not be present.
  1304. //
  1305. if (IsFilterLastLogon())
  1306. {
  1307. int iFindLast = m_szQueryString.Find(L"lastLogonTimestamp");
  1308. if (iFindLast == -1)
  1309. {
  1310. //
  1311. // we didn't find it
  1312. //
  1313. CString szTemp;
  1314. szTemp = m_szQueryString.Left(m_szQueryString.GetLength() - 1);
  1315. AppendLastLogonQuery(szTemp, m_dwLastLogonDays);
  1316. szTemp += L")";
  1317. m_szQueryString = szTemp;
  1318. }
  1319. }
  1320. return m_szQueryString;
  1321. }
  1322. void CSavedQueryNode::FindCookieByDN(LPCWSTR lpszCookieDN, CUINodeList* pNodeList)
  1323. {
  1324. ASSERT(IsContainer());
  1325. ASSERT(GetFolderInfo()->GetContainerList()->IsEmpty());
  1326. CUINodeList* pList = GetFolderInfo()->GetLeafList();
  1327. for (POSITION pos = pList->GetHeadPosition(); pos != NULL; )
  1328. {
  1329. CUINode* pCurrentNode = pList->GetNext(pos);
  1330. ASSERT(!pCurrentNode->IsContainer());
  1331. if (!IS_CLASS(*pCurrentNode, CDSUINode))
  1332. {
  1333. // not a node with a cookie, just skip
  1334. ASSERT(FALSE); // should not be there
  1335. continue;
  1336. }
  1337. // is this the right cookie?
  1338. CDSCookie* pCurrentCookie = GetDSCookieFromUINode(pCurrentNode);
  1339. LPCWSTR lpszCurrentPath = pCurrentCookie->GetPath();
  1340. if (_wcsicmp(lpszCurrentPath, lpszCookieDN) == 0)
  1341. {
  1342. // found, add to list and bail out (cannot have more than one)
  1343. pNodeList->AddTail(pCurrentNode);
  1344. return;
  1345. }
  1346. } // for
  1347. }
  1348. BOOL CSavedQueryNode::IsDeleteAllowed(CDSComponentData*, BOOL* pbHide)
  1349. {
  1350. *pbHide = FALSE;
  1351. return TRUE;
  1352. }
  1353. BOOL CSavedQueryNode::IsRenameAllowed(CDSComponentData*, BOOL* pbHide)
  1354. {
  1355. *pbHide = FALSE;
  1356. return TRUE;
  1357. }
  1358. BOOL CSavedQueryNode::IsRefreshAllowed(CDSComponentData*, BOOL* pbHide)
  1359. {
  1360. *pbHide = FALSE;
  1361. return TRUE;
  1362. }
  1363. BOOL CSavedQueryNode::IsCutAllowed(CDSComponentData*, BOOL* pbHide)
  1364. {
  1365. *pbHide = FALSE;
  1366. return TRUE;
  1367. }
  1368. BOOL CSavedQueryNode::IsCopyAllowed(CDSComponentData*, BOOL* pbHide)
  1369. {
  1370. *pbHide = FALSE;
  1371. return TRUE;
  1372. }
  1373. BOOL CSavedQueryNode::IsPasteAllowed(CDSComponentData*, BOOL* pbHide)
  1374. {
  1375. *pbHide = FALSE;
  1376. return TRUE;
  1377. }
  1378. CContextMenuVerbs* CSavedQueryNode::GetContextMenuVerbsObject(CDSComponentData* pComponentData)
  1379. {
  1380. if (m_pMenuVerbs == NULL)
  1381. {
  1382. m_pMenuVerbs = new CSavedQueryMenuVerbs(pComponentData);
  1383. }
  1384. return m_pMenuVerbs;
  1385. }
  1386. HRESULT CSavedQueryNode::Delete(CDSComponentData* pComponentData)
  1387. {
  1388. HRESULT hr = S_OK;
  1389. //
  1390. // this is just a message box, using ReportErrorEx for consistency of look
  1391. //
  1392. int answer = ReportErrorEx(pComponentData->GetHWnd(),IDS_CONFIRM_DELETE_QUERY,S_OK,
  1393. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, NULL, 0);
  1394. if (answer == IDNO)
  1395. {
  1396. return S_FALSE; // aborted by user
  1397. }
  1398. if (IsContainer())
  1399. {
  1400. hr = pComponentData->RemoveContainerFromUI(this);
  1401. delete this;
  1402. }
  1403. else
  1404. {
  1405. CUINode* pParentNode = GetParent();
  1406. ASSERT(pParentNode->IsContainer());
  1407. pParentNode->GetFolderInfo()->RemoveNode(this);
  1408. //
  1409. // The CDSEvent::_DeleteSingleSel() handles removing the node from the UI
  1410. //
  1411. }
  1412. return hr;
  1413. }
  1414. HRESULT CSavedQueryNode::OnCommand(long lCommandID, CDSComponentData* pComponentData)
  1415. {
  1416. HRESULT hr = S_OK;
  1417. switch (lCommandID)
  1418. {
  1419. case IDM_EXPORT_QUERY:
  1420. OnExportQuery(pComponentData);
  1421. break;
  1422. case IDM_EDIT_QUERY:
  1423. OnEditQuery(pComponentData);
  1424. break;
  1425. case IDM_VIEW_ADVANCED:
  1426. {
  1427. if (pComponentData->CanRefreshAll())
  1428. {
  1429. ASSERT( SNAPINTYPE_SITE != pComponentData->QuerySnapinType() );
  1430. pComponentData->GetQueryFilter()->ToggleAdvancedView();
  1431. pComponentData->SetDirty(TRUE);
  1432. pComponentData->RefreshAll();
  1433. }
  1434. }
  1435. break;
  1436. default:
  1437. ASSERT(FALSE);
  1438. break;
  1439. }
  1440. return hr;
  1441. }
  1442. void CSavedQueryNode::OnEditQuery(CDSComponentData* pComponentData)
  1443. {
  1444. CFavoritesNode* pFavNode = dynamic_cast<CFavoritesNode*>(GetParent());
  1445. if (pFavNode != NULL)
  1446. {
  1447. CQueryDialog dlg(this, pFavNode, pComponentData, FALSE);
  1448. if (dlg.DoModal() == IDOK)
  1449. {
  1450. pComponentData->UpdateItem(this);
  1451. //
  1452. // Removed on 11/06/2000 due to Whistler bug #120727:
  1453. // DS Admin snapin - query executes immediately after editting, even when editted from results pane
  1454. //
  1455. //pComponentData->Refresh(this);
  1456. }
  1457. }
  1458. else
  1459. {
  1460. //
  1461. // This should always succeed. Query nodes are only allowed as children of CFavoritesNode
  1462. //
  1463. ASSERT(FALSE);
  1464. }
  1465. }
  1466. HRESULT CSavedQueryNode::Rename(LPCWSTR lpszNewName, CDSComponentData* pComponentData)
  1467. {
  1468. HRESULT hr = S_OK;
  1469. CString szNewName = lpszNewName;
  1470. CString szTitle;
  1471. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  1472. //
  1473. // Trim whitespace
  1474. //
  1475. szNewName.TrimLeft();
  1476. szNewName.TrimRight();
  1477. if (szNewName.IsEmpty())
  1478. {
  1479. //
  1480. // Don't allow empty names
  1481. //
  1482. CString szMessage;
  1483. VERIFY(szMessage.LoadString(IDS_ERRMSG_NO_EMPTY_NAMES));
  1484. MessageBox(pComponentData->GetHWnd(), szMessage, szTitle, MB_OK | MB_ICONSTOP);
  1485. return S_FALSE;
  1486. }
  1487. CUINode* pDupNode = NULL;
  1488. CFavoritesNode* pParent = GetFavoritesNode();
  1489. if (pParent != NULL && !pParent->IsUniqueName(szNewName, &pDupNode))
  1490. {
  1491. if (pDupNode == this)
  1492. {
  1493. //
  1494. // We are renaming the node to the same name. Just silently ignore.
  1495. //
  1496. return S_FALSE;
  1497. }
  1498. CString szFormatMsg;
  1499. VERIFY(szFormatMsg.LoadString(IDS_ERRMSG_NOT_UNIQUE_QUERY_NAME_INPLACE));
  1500. CString szErrMsg;
  1501. szErrMsg.Format(szFormatMsg, szNewName);
  1502. MessageBox(pComponentData->GetHWnd(), szErrMsg, szTitle, MB_OK | MB_ICONSTOP);
  1503. return S_FALSE;
  1504. }
  1505. //
  1506. // Set the name
  1507. //
  1508. SetName(szNewName);
  1509. hr = pComponentData->UpdateItem(this);
  1510. return hr;
  1511. }
  1512. void CSavedQueryNode::OnExportQuery(CDSComponentData*)
  1513. {
  1514. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1515. CString szFilter;
  1516. VERIFY(szFilter.LoadString(IDS_QUERY_EXPORT_FILTER));
  1517. CString szFileExt(L"xml");
  1518. CString szFileView(L"*.xml");
  1519. CFileDialog* pFileDlg = new CFileDialog(FALSE,
  1520. szFileExt,
  1521. szFileView,
  1522. OFN_HIDEREADONLY | OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT,
  1523. szFilter);
  1524. if (pFileDlg == NULL)
  1525. {
  1526. return;
  1527. }
  1528. if (pFileDlg->DoModal() == IDOK)
  1529. {
  1530. //
  1531. // create an instance of the XML document
  1532. //
  1533. CComPtr<IXMLDOMDocument> spXMLDoc;
  1534. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  1535. IID_IXMLDOMDocument, (void**)&spXMLDoc);
  1536. if (FAILED(hr))
  1537. {
  1538. TRACE(L"CoCreateInstance(CLSID_DOMDocument) failed with hr = 0x%x\n", hr);
  1539. return;
  1540. }
  1541. //
  1542. // Retrieve the file and path
  1543. //
  1544. CString szFileName;
  1545. szFileName = pFileDlg->GetPathName();
  1546. //
  1547. // save the node to the document
  1548. //
  1549. CComVariant xmlSource;
  1550. xmlSource = szFileName;
  1551. CComPtr<IXMLDOMNode> spXMLDOMChildNode;
  1552. hr = XMLSave(spXMLDoc, &spXMLDOMChildNode);
  1553. if (SUCCEEDED(hr))
  1554. {
  1555. CComPtr<IXMLDOMNode> spXDOMNode;
  1556. hr = spXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&spXDOMNode);
  1557. if (SUCCEEDED(hr))
  1558. {
  1559. CComPtr<IXMLDOMNode> spXDOMNewNode;
  1560. hr = spXDOMNode->appendChild(spXMLDOMChildNode, &spXDOMNewNode);
  1561. if (SUCCEEDED(hr))
  1562. {
  1563. //
  1564. // save the document to the file
  1565. //
  1566. hr = spXMLDoc->save(xmlSource);
  1567. TRACE(L"Save returned with hr = 0x%x\n", hr);
  1568. }
  1569. }
  1570. }
  1571. }
  1572. if (pFileDlg != NULL)
  1573. {
  1574. delete pFileDlg;
  1575. pFileDlg = NULL;
  1576. }
  1577. }
  1578. LPCWSTR CSavedQueryNode::g_szObjXMLTag = L"QUERY";
  1579. LPCWSTR CSavedQueryNode::g_szDnXMLTag = L"DN";
  1580. LPCWSTR CSavedQueryNode::g_szOneLevelXMLTag = L"ONELEVEL";
  1581. LPCWSTR CSavedQueryNode::g_szQueryStringXMLTag = L"LDAPQUERY";
  1582. LPCWSTR CSavedQueryNode::g_szLastLogonFilterTag = L"FILTERLASTLOGON";
  1583. LPCWSTR CSavedQueryNode::g_szDSQueryPersistTag = L"DSQUERYUIDATA";
  1584. LPCWSTR CSavedQueryNode::g_szColumnIDTag = L"COLUMNID";
  1585. HRESULT CSavedQueryNode::XMLLoad(CDSComponentData* pComponentData,
  1586. IXMLDOMNode* pXDN,
  1587. CSavedQueryNode** ppQuery)
  1588. {
  1589. *ppQuery = NULL;
  1590. // check the name of the node
  1591. if (!XMLIsNodeName(pXDN, CSavedQueryNode::g_szObjXMLTag))
  1592. {
  1593. // should have checked before calling...
  1594. ASSERT(FALSE);
  1595. return E_INVALIDARG;
  1596. }
  1597. // get the list of child nodes
  1598. CComPtr<IXMLDOMNode> spCurrChild;
  1599. pXDN->get_firstChild(&spCurrChild);
  1600. if (spCurrChild == NULL)
  1601. {
  1602. return E_INVALIDARG;
  1603. }
  1604. // allocate a query object
  1605. *ppQuery = new CSavedQueryNode(pComponentData->GetBasePathsInfo());
  1606. CComBSTR bstrName, bstrDescription, bstrDN, bstrQueryString, bstrColumnID;
  1607. CComBSTR bstrChildName;
  1608. bool bGotName = false;
  1609. bool bGotDN = false;
  1610. bool bGotQuery = false;
  1611. bool bGotScope = false;
  1612. while (spCurrChild != NULL)
  1613. {
  1614. spCurrChild->get_nodeName(&bstrChildName);
  1615. if (CompareXMLTags(bstrChildName, CGenericUINode::g_szNameXMLTag))
  1616. {
  1617. if (SUCCEEDED(XML_GetNodeText(spCurrChild, &bstrName)))
  1618. {
  1619. (*ppQuery)->SetName(bstrName);
  1620. bGotName = true;
  1621. }
  1622. }
  1623. else if (CompareXMLTags(bstrChildName, CGenericUINode::g_szDecriptionXMLTag))
  1624. {
  1625. if (SUCCEEDED(XML_GetNodeText(spCurrChild, &bstrDescription)))
  1626. {
  1627. (*ppQuery)->SetDesc(bstrDescription);
  1628. }
  1629. }
  1630. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szDnXMLTag))
  1631. {
  1632. if (SUCCEEDED(XML_GetNodeText(spCurrChild, &bstrDN)))
  1633. {
  1634. (*ppQuery)->SetRootPath(bstrDN);
  1635. bGotDN = true;
  1636. }
  1637. }
  1638. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szQueryStringXMLTag))
  1639. {
  1640. if (SUCCEEDED(XML_GetNodeText(spCurrChild, &bstrQueryString)))
  1641. {
  1642. (*ppQuery)->SetQueryString(bstrQueryString);
  1643. bGotQuery = true;
  1644. }
  1645. }
  1646. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szOneLevelXMLTag))
  1647. {
  1648. BOOL b;
  1649. if (SUCCEEDED(XML_GetNodeBOOL(spCurrChild, &b)))
  1650. {
  1651. (*ppQuery)->SetOneLevel(b);
  1652. bGotScope = true;
  1653. }
  1654. }
  1655. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szLastLogonFilterTag))
  1656. {
  1657. DWORD dwDays;
  1658. if (SUCCEEDED(XML_GetNodeDWORD(spCurrChild, &dwDays)))
  1659. {
  1660. (*ppQuery)->SetLastLogonQuery(dwDays);
  1661. }
  1662. else
  1663. {
  1664. (*ppQuery)->SetLastLogonQuery((DWORD)-1);
  1665. }
  1666. }
  1667. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szColumnIDTag))
  1668. {
  1669. if (SUCCEEDED(XML_GetNodeText(spCurrChild, &bstrColumnID)))
  1670. {
  1671. (*ppQuery)->SetColumnID(pComponentData, bstrColumnID);
  1672. }
  1673. }
  1674. else if (CompareXMLTags(bstrChildName, CSavedQueryNode::g_szDSQueryPersistTag))
  1675. {
  1676. BYTE* pByteArray = NULL;
  1677. ULONG nByteCount = 0;
  1678. if (SUCCEEDED(XML_GetNodeBlob(spCurrChild, &pByteArray, &nByteCount)))
  1679. {
  1680. if (pByteArray != NULL && nByteCount > 0)
  1681. {
  1682. //
  1683. // Create a dummy stream object
  1684. //
  1685. CComObject<CDummyStream>* pDummyStream;
  1686. CComObject<CDummyStream>::CreateInstance(&pDummyStream);
  1687. if (pDummyStream != NULL)
  1688. {
  1689. HRESULT hr = pDummyStream->SetStreamData(pByteArray, nByteCount);
  1690. if (SUCCEEDED(hr))
  1691. {
  1692. //
  1693. // Create a temporary CDSAdminPersistQueryFilterImpl object
  1694. //
  1695. CComObject<CDSAdminPersistQueryFilterImpl>* pPersistQueryImpl;
  1696. CComObject<CDSAdminPersistQueryFilterImpl>::CreateInstance(&pPersistQueryImpl);
  1697. if (pPersistQueryImpl != NULL)
  1698. {
  1699. //
  1700. // Load the CDSAdminPersistQueryFilterImpl from the dummy stream
  1701. //
  1702. hr = pPersistQueryImpl->Load(pDummyStream);
  1703. if (SUCCEEDED(hr))
  1704. {
  1705. //
  1706. // Save the CDSAdminPersistQueryFilterImpl into the new query node
  1707. //
  1708. (*ppQuery)->SetQueryPersist(pPersistQueryImpl);
  1709. }
  1710. }
  1711. }
  1712. }
  1713. }
  1714. }
  1715. }
  1716. // iterate to next item
  1717. CComPtr<IXMLDOMNode> temp = spCurrChild;
  1718. spCurrChild = NULL;
  1719. temp->get_nextSibling(&spCurrChild);
  1720. }
  1721. if (!bGotName ||
  1722. !bGotDN ||
  1723. !bGotQuery ||
  1724. !bGotScope)
  1725. {
  1726. return E_FAIL;
  1727. }
  1728. return S_OK;
  1729. }
  1730. HRESULT CSavedQueryNode::XMLSave(IXMLDOMDocument* pXMLDoc,
  1731. IXMLDOMNode** ppXMLDOMNode)
  1732. {
  1733. // create the node for the object itself
  1734. CComPtr<IXMLDOMNode> spXMLDOMNode;
  1735. HRESULT hr = XML_CreateDOMNode(pXMLDoc, NODE_ELEMENT, CSavedQueryNode::g_szObjXMLTag, &spXMLDOMNode);
  1736. RETURN_IF_FAILED(hr);
  1737. // create inner nodes with member variables
  1738. hr = XMLSaveBase(pXMLDoc, spXMLDOMNode);
  1739. RETURN_IF_FAILED(hr);
  1740. //
  1741. // Root path
  1742. //
  1743. hr = XML_AppendTextDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szDnXMLTag, m_szRelativeRootPath);
  1744. RETURN_IF_FAILED(hr);
  1745. //
  1746. // Filter on last logon timestamp
  1747. //
  1748. hr = XML_AppendDWORDDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szLastLogonFilterTag, m_dwLastLogonDays);
  1749. RETURN_IF_FAILED(hr);
  1750. //
  1751. // Query string
  1752. //
  1753. //
  1754. // Have to remove the last logon timestamp if its there
  1755. //
  1756. CString szSaveQueryString;
  1757. if (IsFilterLastLogon())
  1758. {
  1759. int iFindLast = m_szQueryString.Find(L"lastLogonTimestamp");
  1760. if (iFindLast != -1)
  1761. {
  1762. szSaveQueryString = m_szQueryString.Left(iFindLast - 1);
  1763. szSaveQueryString += L")";
  1764. }
  1765. else
  1766. {
  1767. szSaveQueryString = m_szQueryString;
  1768. }
  1769. }
  1770. else
  1771. {
  1772. szSaveQueryString = m_szQueryString;
  1773. }
  1774. hr = XML_AppendTextDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szQueryStringXMLTag, szSaveQueryString);
  1775. RETURN_IF_FAILED(hr);
  1776. //
  1777. // Is one level query flag
  1778. //
  1779. hr = XML_AppendBOOLDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szOneLevelXMLTag, IsOneLevel());
  1780. RETURN_IF_FAILED(hr);
  1781. //
  1782. // Column ID
  1783. //
  1784. hr = XML_AppendTextDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szColumnIDTag, m_szColumnID);
  1785. RETURN_IF_FAILED(hr);
  1786. //
  1787. // Create a dummy stream object to write the saved query UI info into
  1788. //
  1789. CComObject<CDummyStream>* pDummyStream;
  1790. CComObject<CDummyStream>::CreateInstance(&pDummyStream);
  1791. if (pDummyStream != NULL)
  1792. {
  1793. if (m_pPersistQueryImpl != NULL)
  1794. {
  1795. hr = m_pPersistQueryImpl->Save(pDummyStream);
  1796. if (SUCCEEDED(hr))
  1797. {
  1798. BYTE* pByteArray = NULL;
  1799. ULONG nByteCount = 0;
  1800. nByteCount = pDummyStream->GetStreamData(&pByteArray);
  1801. if (nByteCount > 0 && pByteArray != NULL)
  1802. {
  1803. hr = XML_AppendStructDataNode(pXMLDoc, spXMLDOMNode, CSavedQueryNode::g_szDSQueryPersistTag, pByteArray, nByteCount);
  1804. RETURN_IF_FAILED(hr);
  1805. delete[] pByteArray;
  1806. }
  1807. }
  1808. }
  1809. }
  1810. (*ppXMLDOMNode) = spXMLDOMNode;
  1811. (*ppXMLDOMNode)->AddRef();
  1812. return hr;
  1813. }
  1814. void CSavedQueryNode::SetQueryPersist(CComObject<CDSAdminPersistQueryFilterImpl>* pPersistQueryImpl)
  1815. {
  1816. if (m_pPersistQueryImpl != NULL)
  1817. {
  1818. m_pPersistQueryImpl->Release();
  1819. m_pPersistQueryImpl = NULL;
  1820. }
  1821. m_pPersistQueryImpl = pPersistQueryImpl;
  1822. m_pPersistQueryImpl->AddRef();
  1823. }
  1824. //
  1825. // Function used in a recursive search through the saved query tree looking
  1826. // for saved queries that contain objects with any of the DNs in the list
  1827. // and invalidates that query
  1828. //
  1829. void CSavedQueryNode::InvalidateSavedQueriesContainingObjects(CDSComponentData* pComponentData,
  1830. const CStringList& refDNList)
  1831. {
  1832. ASSERT(IsContainer());
  1833. CUINodeList nodeList;
  1834. POSITION pos = refDNList.GetHeadPosition();
  1835. while (pos)
  1836. {
  1837. CString szDN = refDNList.GetNext(pos);
  1838. FindCookieByDN(szDN, &nodeList);
  1839. if (nodeList.GetCount() > 0)
  1840. {
  1841. //
  1842. // An object from the list was found, make the saved query invalid and
  1843. // break
  1844. //
  1845. SetValid(FALSE);
  1846. pComponentData->ChangeScopeItemIcon(this);
  1847. break;
  1848. }
  1849. }
  1850. }
  1851. ////////////////////////////////////////////////////////////////////////////
  1852. // CFavoritesNodesHolder
  1853. /* For test purposes Only
  1854. void CFavoritesNodesHolder::BuildTestTree(LPCWSTR lpszXMLFileName, SnapinType snapinType)
  1855. {
  1856. if (lpszXMLFileName == NULL)
  1857. {
  1858. // no file name passed, build the hardwired version
  1859. BuildTestTreeHardWired(snapinType);
  1860. return;
  1861. }
  1862. if (!BuildTestTreefromXML(lpszXMLFileName, snapinType))
  1863. {
  1864. // we failed, use hardwired
  1865. BuildTestTreeHardWired(snapinType);
  1866. }
  1867. }
  1868. BOOL CFavoritesNodesHolder::BuildTestTreefromXML(LPCWSTR lpszXMLFileName, SnapinType)
  1869. {
  1870. // create an instance of the XML document
  1871. CComPtr<IXMLDOMDocument> spXMLDoc;
  1872. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  1873. IID_IXMLDOMDocument, (void**)&spXMLDoc);
  1874. if (FAILED(hr))
  1875. {
  1876. TRACE(L"CoCreateInstance(CLSID_DOMDocument) failed with hr = 0x%x\n", hr);
  1877. return FALSE;
  1878. }
  1879. // load the document from file
  1880. CComVariant xmlSource;
  1881. xmlSource = lpszXMLFileName;
  1882. VARIANT_BOOL isSuccessful;
  1883. hr = spXMLDoc->load(xmlSource, &isSuccessful);
  1884. if (FAILED(hr))
  1885. {
  1886. CString szMsg;
  1887. szMsg.Format(L"spXMLDoc->load() failed with hr = 0x%x\n", hr);
  1888. TRACE((LPCWSTR)szMsg);
  1889. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1890. AfxMessageBox(szMsg);
  1891. return FALSE;
  1892. }
  1893. // get the root of the document
  1894. CComPtr<IXMLDOMNode> spXDN;
  1895. hr = spXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&spXDN);
  1896. if (FAILED(hr))
  1897. {
  1898. TRACE(L"spXMLDoc->QueryInterface(IID_IXMLDOMNode() failed with hr = 0x%x\n", hr);
  1899. return FALSE;
  1900. }
  1901. // find where the FOLDER tree starts in the document
  1902. CComPtr<IXMLDOMNode> spXMLFolderRootnode;
  1903. hr = XML_FindSubtreeNode(spXDN, CFavoritesNode::g_szObjXMLTag, &spXMLFolderRootnode);
  1904. if (FAILED(hr))
  1905. {
  1906. wprintf(L"XML_FindSubtreeNode() on FOLDER failed with hr = 0x%x\n", hr);
  1907. return FALSE;
  1908. }
  1909. CFavoritesNode* pRootNode = NULL;
  1910. if (spXMLFolderRootnode != NULL)
  1911. {
  1912. // have an XML root folder node, load it into the
  1913. // in memory tree
  1914. CFavoritesNode::XMLLoad(pComponentData, spXMLFolderRootnode, &pRootNode);
  1915. }
  1916. else
  1917. {
  1918. TRACE(L"XML_FindSubtreeNode() returned a NULL root folder node");
  1919. }
  1920. if (pRootNode == NULL)
  1921. {
  1922. TRACE(L"CFavoritesNode::XMLLoad() returned NULL root node\n");
  1923. return FALSE;
  1924. }
  1925. // REVIEW_MARCOC: this is a hack to get things ported,
  1926. // need to review XML schema
  1927. // now we have a tree, need to graft underneath the folder root node
  1928. // move the first level of children
  1929. CUINodeList* pNodeList = pRootNode->GetFolderInfo()->GetContainerList();
  1930. while (!pNodeList->IsEmpty())
  1931. {
  1932. CUINode* p = pNodeList->RemoveHead();
  1933. p->ClearParent();
  1934. m_favoritesRoot.GetFolderInfo()->AddNode(p);
  1935. }
  1936. // copy the info in the root
  1937. m_favoritesRoot.SetName(pRootNode->GetName());
  1938. m_favoritesRoot.SetDesc(pRootNode->GetDesc());
  1939. // delete root
  1940. delete pRootNode;
  1941. return TRUE;
  1942. }
  1943. */
  1944. /* For testing purposes only
  1945. void CFavoritesNodesHolder::BuildTestTreeHardWired(SnapinType snapinType)
  1946. {
  1947. // fill in the root
  1948. m_favoritesRoot.SetName(L"Saved Queries");
  1949. m_favoritesRoot.SetDesc(L"Folder to store your favorite queries");
  1950. // first level of children
  1951. CFavoritesNode* pMostUsed = new CFavoritesNode;
  1952. pMostUsed->SetName(L"Most Used");
  1953. pMostUsed->SetDesc(L"Very handy queries, used all the time");
  1954. m_favoritesRoot.GetFolderInfo()->AddNode(pMostUsed);
  1955. CFavoritesNode* pMarketing = new CFavoritesNode;
  1956. pMarketing->SetName(L"Marketing");
  1957. m_favoritesRoot.GetFolderInfo()->AddNode(pMarketing);
  1958. CFavoritesNode* pDevelopment = new CFavoritesNode;
  1959. pDevelopment->SetName(L"Development");
  1960. m_favoritesRoot.GetFolderInfo()->AddNode(pDevelopment);
  1961. CFavoritesNode* pCustomerSupport = new CFavoritesNode;
  1962. pCustomerSupport->SetName(L"Customer Support");
  1963. m_favoritesRoot.GetFolderInfo()->AddNode(pCustomerSupport);
  1964. // fill in under most used
  1965. CSavedQueryNode* pQuery = new CSavedQueryNode(snapinType);
  1966. pQuery->SetName(L"My contacts");
  1967. pQuery->SetDesc(L"All the contacts in this domain");
  1968. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  1969. pQuery->SetOneLevel(FALSE);
  1970. pQuery->SetQueryString(L"(objectClass=contact)");
  1971. pMostUsed->GetFolderInfo()->AddNode(pQuery);
  1972. CFavoritesNode* pMyComputersFolder = new CFavoritesNode;
  1973. pMyComputersFolder->SetName(L"My Computers");
  1974. pMostUsed->GetFolderInfo()->AddNode(pMyComputersFolder);
  1975. pQuery = new CSavedQueryNode(snapinType);
  1976. pQuery->SetName(L"Workstations");
  1977. pQuery->SetDesc(L"");
  1978. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  1979. pQuery->SetOneLevel(FALSE);
  1980. pQuery->SetQueryString(L"(objectClass=computer)");
  1981. pMyComputersFolder->GetFolderInfo()->AddNode(pQuery);
  1982. pQuery = new CSavedQueryNode(snapinType);
  1983. pQuery->SetName(L"Servers");
  1984. pQuery->SetDesc(L"");
  1985. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  1986. pQuery->SetOneLevel(FALSE);
  1987. pQuery->SetQueryString(L"(objectClass=computer)");
  1988. pMyComputersFolder->GetFolderInfo()->AddNode(pQuery);
  1989. pQuery = new CSavedQueryNode(snapinType);
  1990. pQuery->SetName(L"All");
  1991. pQuery->SetDesc(L"");
  1992. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  1993. pQuery->SetOneLevel(FALSE);
  1994. pQuery->SetQueryString(L"(objectClass=computer)");
  1995. pMyComputersFolder->GetFolderInfo()->AddNode(pQuery);
  1996. // fill in under development
  1997. pQuery = new CSavedQueryNode(snapinType);
  1998. pQuery->SetName(L"Users");
  1999. pQuery->SetDesc(L"");
  2000. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  2001. pQuery->SetOneLevel(TRUE);
  2002. pQuery->SetQueryString(L"(objectClass=users)");
  2003. pDevelopment->GetFolderInfo()->AddNode(pQuery);
  2004. pQuery = new CSavedQueryNode(snapinType);
  2005. pQuery->SetName(L"Computers");
  2006. pQuery->SetDesc(L"");
  2007. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  2008. pQuery->SetOneLevel(TRUE);
  2009. pQuery->SetQueryString(L"(objectClass=computer)");
  2010. pDevelopment->GetFolderInfo()->AddNode(pQuery);
  2011. pQuery = new CSavedQueryNode(snapinType);
  2012. pQuery->SetName(L"Groups");
  2013. pQuery->SetDesc(L"");
  2014. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  2015. pQuery->SetOneLevel(TRUE);
  2016. pQuery->SetQueryString(L"(objectClass=group)");
  2017. pDevelopment->GetFolderInfo()->AddNode(pQuery);
  2018. pQuery = new CSavedQueryNode(snapinType);
  2019. pQuery->SetName(L"Managers");
  2020. pQuery->SetDesc(L"");
  2021. pQuery->SetRootPath(L"DC=marcocdev;DC=nttest;DC=microsoft;DC=com");
  2022. pQuery->SetOneLevel(TRUE);
  2023. pQuery->SetQueryString(L"(objectClass=user)");
  2024. pDevelopment->GetFolderInfo()->AddNode(pQuery);
  2025. }
  2026. */
  2027. HRESULT CFavoritesNodesHolder::Save(IStream* pStm)
  2028. {
  2029. //
  2030. // create an instance of the XML document
  2031. //
  2032. CComPtr<IXMLDOMDocument> spXMLDoc;
  2033. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  2034. IID_IXMLDOMDocument, (void**)&spXMLDoc);
  2035. if (FAILED(hr))
  2036. {
  2037. TRACE(L"CoCreateInstance(CLSID_DOMDocument) failed with hr = 0x%x\n", hr);
  2038. return hr;
  2039. }
  2040. CComPtr<IXMLDOMNode> spXMLDOMChildNode;
  2041. hr = m_favoritesRoot.XMLSave(spXMLDoc, &spXMLDOMChildNode);
  2042. if (SUCCEEDED(hr))
  2043. {
  2044. if (SUCCEEDED(hr))
  2045. {
  2046. CComPtr<IXMLDOMNode> spXDOMNode;
  2047. hr = spXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&spXDOMNode);
  2048. if (SUCCEEDED(hr))
  2049. {
  2050. CComPtr<IXMLDOMNode> spXDOMNewNode;
  2051. hr = spXDOMNode->appendChild(spXMLDOMChildNode, &spXDOMNewNode);
  2052. if (SUCCEEDED(hr))
  2053. {
  2054. //
  2055. // save the document to the file
  2056. //
  2057. CComVariant xmlSource;
  2058. xmlSource = pStm;
  2059. hr = spXMLDoc->save(xmlSource);
  2060. TRACE(L"Save returned with hr = 0x%x\n", hr);
  2061. }
  2062. }
  2063. }
  2064. }
  2065. return hr;
  2066. }
  2067. HRESULT CFavoritesNodesHolder::Load(IStream* pStm,
  2068. CDSComponentData* pComponentData)
  2069. {
  2070. //
  2071. // create an instance of the XML document
  2072. //
  2073. CComPtr<IXMLDOMDocument> spXMLDoc;
  2074. HRESULT hr = ::CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER,
  2075. IID_IXMLDOMDocument, (void**)&spXMLDoc);
  2076. if (FAILED(hr))
  2077. {
  2078. TRACE(L"CoCreateInstance(CLSID_DOMDocument) failed with hr = 0x%x\n", hr);
  2079. return hr;
  2080. }
  2081. CComPtr<IUnknown> spUnknown;
  2082. hr = pStm->QueryInterface(IID_IUnknown, (void**)&spUnknown);
  2083. if (SUCCEEDED(hr))
  2084. {
  2085. CComVariant xmlSource;
  2086. xmlSource = spUnknown;
  2087. VARIANT_BOOL isSuccess;
  2088. hr = spXMLDoc->load(xmlSource, &isSuccess);
  2089. if (SUCCEEDED(hr))
  2090. {
  2091. //
  2092. // get the root of the document
  2093. //
  2094. CComPtr<IXMLDOMNode> spXDN;
  2095. hr = spXMLDoc->QueryInterface(IID_IXMLDOMNode, (void **)&spXDN);
  2096. if (SUCCEEDED(hr))
  2097. {
  2098. //
  2099. // find where the FOLDER tree starts in the document
  2100. //
  2101. CComPtr<IXMLDOMNode> spXMLFolderRootnode;
  2102. hr = XML_FindSubtreeNode(spXDN, CFavoritesNode::g_szObjXMLTag, &spXMLFolderRootnode);
  2103. if (SUCCEEDED(hr))
  2104. {
  2105. if (spXMLFolderRootnode != NULL)
  2106. {
  2107. //
  2108. // have an XML root folder node, load it into the
  2109. // in memory tree
  2110. //
  2111. hr = m_favoritesRoot.Load(spXMLFolderRootnode, pComponentData);
  2112. if (FAILED(hr))
  2113. {
  2114. //
  2115. // REVIEW_JEFFJON : provide a meaningful error message
  2116. //
  2117. }
  2118. }
  2119. }
  2120. }
  2121. }
  2122. }
  2123. return hr;
  2124. }
  2125. //
  2126. // Starts a recursive search through the saved query tree looking for saved queries that
  2127. // contain objects with any of the DNs in the list and invalidates that query
  2128. //
  2129. void CFavoritesNodesHolder::InvalidateSavedQueriesContainingObjects(CDSComponentData* pComponentData,
  2130. const CStringList& refDNList)
  2131. {
  2132. GetFavoritesRoot()->InvalidateSavedQueriesContainingObjects(pComponentData,
  2133. refDNList);
  2134. }
  2135. ////////////////////////////////////////////////////////////////////////////////////
  2136. HRESULT CDummyStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
  2137. {
  2138. if (m_pByteArray == NULL || m_nByteCount == 0)
  2139. {
  2140. *pcbRead = 0;
  2141. return S_FALSE;
  2142. }
  2143. if (pv == NULL)
  2144. {
  2145. *pcbRead = 0;
  2146. return STG_E_INVALIDPOINTER;
  2147. }
  2148. ULONG nBytesPossible = m_nByteCount - m_nReadIndex;
  2149. if (nBytesPossible <= 0)
  2150. {
  2151. *pcbRead = 0;
  2152. return S_FALSE;
  2153. }
  2154. ULONG nBytesToRead = 0;
  2155. if (nBytesPossible >= cb)
  2156. {
  2157. nBytesToRead = cb;
  2158. }
  2159. else
  2160. {
  2161. nBytesToRead = nBytesPossible;
  2162. }
  2163. memcpy(pv, &(m_pByteArray[m_nReadIndex]), nBytesToRead);
  2164. *pcbRead = nBytesToRead;
  2165. m_nReadIndex += nBytesToRead;
  2166. return S_OK;
  2167. }
  2168. HRESULT CDummyStream::Write(void const *pv, ULONG cb, ULONG *pcbWritten)
  2169. {
  2170. BYTE* pNewByteArray = new BYTE[m_nByteCount + cb];
  2171. if (pNewByteArray == NULL)
  2172. {
  2173. *pcbWritten = 0;
  2174. return E_OUTOFMEMORY;
  2175. }
  2176. if (m_pByteArray != NULL && m_nByteCount > 0)
  2177. {
  2178. memcpy(pNewByteArray, m_pByteArray, m_nByteCount);
  2179. }
  2180. memcpy(&(pNewByteArray[m_nByteCount]), pv, cb);
  2181. if (m_pByteArray != NULL)
  2182. {
  2183. delete[] m_pByteArray;
  2184. }
  2185. m_pByteArray = pNewByteArray;
  2186. *pcbWritten = cb;
  2187. m_nByteCount = m_nByteCount + cb;
  2188. return S_OK;
  2189. }
  2190. ULONG CDummyStream::GetStreamData(BYTE** ppByteArray)
  2191. {
  2192. if (m_pByteArray == NULL)
  2193. {
  2194. *ppByteArray = NULL;
  2195. return 0;
  2196. }
  2197. *ppByteArray = new BYTE[m_nByteCount];
  2198. if (*ppByteArray == NULL)
  2199. {
  2200. return 0;
  2201. }
  2202. memcpy(*ppByteArray, m_pByteArray, m_nByteCount);
  2203. return m_nByteCount;
  2204. }
  2205. HRESULT CDummyStream::SetStreamData(BYTE* pByteArray, ULONG nByteCount)
  2206. {
  2207. if (m_pByteArray != NULL)
  2208. {
  2209. delete[] m_pByteArray;
  2210. m_pByteArray = NULL;
  2211. }
  2212. m_pByteArray = pByteArray;
  2213. m_nByteCount = nByteCount;
  2214. m_nReadIndex = 0;
  2215. return S_OK;
  2216. }