Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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