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.

725 lines
23 KiB

  1. // This is a part of the Microsoft Management Console.
  2. // Copyright (C) Microsoft Corporation, 1995 - 1999
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Management Console and related
  7. // electronic documentation provided with the interfaces.
  8. #ifndef _TREEDATA_H
  9. #define _TREEDATA_H
  10. /////////////////////////////////////////////////////////////////////////////
  11. // Miscellanea
  12. extern LPCWSTR g_lpszNullString;
  13. /////////////////////////////////////////////////////////////////////////////
  14. // Generic Helper functions
  15. template<class TYPE>
  16. inline void SAFE_RELEASE(TYPE*& pObj)
  17. {
  18. if (pObj != NULL)
  19. {
  20. pObj->Release();
  21. pObj = NULL;
  22. }
  23. else
  24. {
  25. TRACE(_T("Release called on NULL interface ptr"));
  26. }
  27. }
  28. ///////////////////////////////////////////////////////////////////
  29. // Context Menu data structures and macros
  30. #define MAX_CONTEXT_MENU_STRLEN 128
  31. struct MENUDATARES
  32. {
  33. WCHAR szBuffer[MAX_CONTEXT_MENU_STRLEN*2];
  34. UINT uResID;
  35. };
  36. struct MENUMAP
  37. {
  38. MENUDATARES* dataRes;
  39. CONTEXTMENUITEM2* ctxMenu;
  40. };
  41. #define DECLARE_MENU(theClass) \
  42. class theClass \
  43. { \
  44. public: \
  45. static LPCONTEXTMENUITEM2 GetContextMenuItem() { return GetMenuMap()->ctxMenu; }; \
  46. static MENUMAP* GetMenuMap(); \
  47. };
  48. #define BEGIN_MENU(theClass) \
  49. MENUMAP* theClass::GetMenuMap() {
  50. #define BEGIN_CTX static CONTEXTMENUITEM2 ctx[] = {
  51. #define CTX_ENTRY_TOP(cmdID, languageIndependantStringID) { L"",L"", cmdID, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, 0, languageIndependantStringID},
  52. #define CTX_ENTRY_NEW(cmdID, languageIndependantStringID) { L"",L"", cmdID, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, 0, languageIndependantStringID},
  53. #define CTX_ENTRY_TASK(cmdID, languageIndependantStringID) { L"",L"", cmdID, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0, languageIndependantStringID},
  54. #define CTX_ENTRY_VIEW(cmdID, languageIndependantStringID) { L"",L"", cmdID, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, 0, languageIndependantStringID},
  55. #define END_CTX { NULL, NULL, 0, 0, 0, 0} };
  56. #define BEGIN_RES static MENUDATARES dataRes[] = {
  57. #define RES_ENTRY(resID) {L"", resID },
  58. #define END_RES { NULL, 0 } };
  59. #define END_MENU \
  60. static MENUMAP menuMap = { dataRes, ctx }; \
  61. return &menuMap; }
  62. BOOL LoadContextMenuResources(MENUMAP* pMenuMap);
  63. //
  64. // Toolbar macros
  65. //
  66. #define DECLARE_TOOLBAR_MAP() \
  67. public: \
  68. virtual HRESULT ToolbarNotify(int event, \
  69. CComponentDataObject* pComponentData, \
  70. CNodeList* pNodeList);
  71. #define BEGIN_TOOLBAR_MAP(theClass) \
  72. HRESULT theClass::ToolbarNotify(int event, \
  73. CComponentDataObject* pComponentData, \
  74. CNodeList* pNodeList) \
  75. { \
  76. HRESULT hr = S_OK; \
  77. event; \
  78. pComponentData; \
  79. pNodeList;
  80. #define TOOLBAR_EVENT(toolbar_event, function) \
  81. if (event == toolbar_event) \
  82. { \
  83. hr = function(pComponentData, pNodeList); \
  84. }
  85. #define END_TOOLBAR_MAP() \
  86. return hr; \
  87. }
  88. #define DECLARE_TOOLBAR_EVENT(toolbar_event, value) \
  89. static const int toolbar_event = value;
  90. ////////////////////////////////////////////////////////////
  91. // header control resources data structures
  92. #define MAX_RESULT_HEADER_STRLEN 128
  93. struct RESULT_HEADERMAP
  94. {
  95. WCHAR szBuffer[MAX_RESULT_HEADER_STRLEN];
  96. UINT uResID;
  97. int nFormat;
  98. int nWidth;
  99. };
  100. BOOL LoadResultHeaderResources(RESULT_HEADERMAP* pHeaderMap, int nCols);
  101. ////////////////////////////////////////////////////////////
  102. // bitmap strips resources data structures
  103. template <UINT nResID> class CBitmapHolder : public CBitmap
  104. {
  105. public:
  106. BOOL LoadBitmap() { return CBitmap::LoadBitmap(nResID);}
  107. };
  108. ///////////////////////////////////////////////////////////////////////////////
  109. // FORWARD DECLARATIONS
  110. class CComponentDataObject;
  111. class CContainerNode;
  112. class CMTContainerNode;
  113. class CLeafNode;
  114. class CPropertyPageHolderBase;
  115. class CBackgroundThread;
  116. class CQueryObj;
  117. /////////////////////////////////////////////////////////////////////
  118. // CObjBase
  119. // base class for all objects relying on RTTI and class type info
  120. class CObjBase
  121. {
  122. public:
  123. CObjBase() {}
  124. virtual ~CObjBase() {}
  125. };
  126. /////////////////////////////////////////////////////////////////////
  127. // CTreeNode
  128. // cannot construct objects of this class, have to derive from it
  129. #define DECLARE_NODE_GUID() \
  130. static const GUID NodeTypeGUID; \
  131. virtual const GUID* GetNodeType() { return &NodeTypeGUID;}
  132. // use the HIWORD for generic flags and leave the LOWORD for application specific data
  133. #define TN_FLAG_HIDDEN (0x00010000) // does not appear in the UI
  134. #define TN_FLAG_NO_WRITE (0x00020000) // cannot edit or create
  135. #define TN_FLAG_NO_DELETE (0x00040000) // cannot delete
  136. #define TN_FLAG_HAS_SHEET (0x00080000) // this node or a child has a property sheet up
  137. #define TN_FLAG_CONTAINER (0x00100000) // container (i.e. not leaf)
  138. #define TN_FLAG_CONTAINER_ENUM (0x00200000) // container node has been enumerated (back end)
  139. #define TN_FLAG_CONTAINER_EXP (0x00400000) // container node has been expanded (UI node)
  140. class CTreeNode : public CObjBase
  141. {
  142. public:
  143. virtual ~CTreeNode() {}
  144. CContainerNode* GetContainer() { return m_pContainer; }
  145. void SetContainer(CContainerNode* pContainer) { m_pContainer = pContainer; }
  146. BOOL HasContainer(CContainerNode* pContainerNode);
  147. virtual LPCWSTR GetDisplayName() { return m_szDisplayName; }
  148. virtual void SetDisplayName(LPCWSTR lpszDisplayName) { m_szDisplayName = lpszDisplayName;}
  149. //
  150. // Data Object related data
  151. //
  152. virtual const GUID* GetNodeType() { return NULL;}
  153. virtual HRESULT GetDataHere(CLIPFORMAT,
  154. LPSTGMEDIUM,
  155. CDataObject*) { return DV_E_CLIPFORMAT;}
  156. virtual HRESULT GetData(CLIPFORMAT,
  157. LPSTGMEDIUM,
  158. CDataObject*) { return DV_E_CLIPFORMAT;}
  159. virtual HRESULT GetResultViewType(CComponentDataObject* pComponentData,
  160. LPOLESTR* ppViewType,
  161. long* pViewOptions);
  162. virtual HRESULT OnShow(LPCONSOLE) { return S_OK; }
  163. //
  164. // flag manipulation API's
  165. //
  166. BOOL IsContainer() { return (m_dwNodeFlags & TN_FLAG_CONTAINER) ? TRUE : FALSE;}
  167. BOOL IsVisible() { return (m_dwNodeFlags & TN_FLAG_HIDDEN) ? FALSE : TRUE;}
  168. BOOL CanDelete() { return (m_dwNodeFlags & TN_FLAG_NO_DELETE) ? FALSE : TRUE;}
  169. virtual void SetFlagsDown(DWORD dwNodeFlags, BOOL bSet);
  170. void SetFlagsUp(DWORD dwNodeFlags, BOOL bSet);
  171. DWORD GetFlags() { return m_dwNodeFlags;}
  172. virtual BOOL CanExpandSync() { return FALSE; }
  173. virtual void Show(BOOL bShow, CComponentDataObject* pComponentData);
  174. //
  175. // Verb handlers
  176. //
  177. virtual HRESULT OnRename(CComponentDataObject*,
  178. LPWSTR) { return S_FALSE; }
  179. virtual void OnDelete(CComponentDataObject* pComponentData,
  180. CNodeList* pNodeList) = 0;
  181. virtual BOOL OnRefresh(CComponentDataObject*,
  182. CNodeList*) { return FALSE; }
  183. virtual HRESULT OnCommand(long,
  184. DATA_OBJECT_TYPES,
  185. CComponentDataObject*,
  186. CNodeList*) { return S_OK; };
  187. virtual HRESULT OnAddMenuItems(IContextMenuCallback2* pContextMenuCallback2,
  188. DATA_OBJECT_TYPES type,
  189. long *pInsertionAllowed,
  190. CNodeList* pNodeList);
  191. virtual HRESULT OnAddMenuItemsMultipleSelect(IContextMenuCallback2*,
  192. DATA_OBJECT_TYPES,
  193. long*,
  194. CNodeList*) { return S_OK; }
  195. virtual MMC_CONSOLE_VERB GetDefaultVerb(DATA_OBJECT_TYPES type,
  196. CNodeList* pNodeList);
  197. virtual void OnSetVerbState(LPCONSOLEVERB pConsoleVerb,
  198. DATA_OBJECT_TYPES type,
  199. CNodeList* pNodeList);
  200. virtual HRESULT OnSetToolbarVerbState(IToolbar* pToolbar,
  201. CNodeList* pNodeList);
  202. virtual BOOL OnSetRenameVerbState(DATA_OBJECT_TYPES type,
  203. BOOL* pbHide,
  204. CNodeList* pNodeList);
  205. virtual BOOL OnSetDeleteVerbState(DATA_OBJECT_TYPES type,
  206. BOOL* pbHide,
  207. CNodeList* pNodeList);
  208. virtual BOOL OnSetRefreshVerbState(DATA_OBJECT_TYPES type,
  209. BOOL* pbHide,
  210. CNodeList* pNodeList);
  211. virtual BOOL OnSetCutVerbState(DATA_OBJECT_TYPES type,
  212. BOOL* pbHide,
  213. CNodeList* pNodeList);
  214. virtual BOOL OnSetCopyVerbState(DATA_OBJECT_TYPES type,
  215. BOOL* pbHide,
  216. CNodeList* pNodeList);
  217. virtual BOOL OnSetPasteVerbState(DATA_OBJECT_TYPES type,
  218. BOOL* pbHide,
  219. CNodeList* pNodeList);
  220. virtual BOOL OnSetPrintVerbState(DATA_OBJECT_TYPES type,
  221. BOOL* pbHide,
  222. CNodeList* pNodeList);
  223. //
  224. // Property Page methods
  225. //
  226. virtual BOOL DelegatesPPToContainer() { return FALSE; }
  227. virtual void ShowPageForNode(CComponentDataObject* pComponentDataObject);
  228. virtual BOOL HasPropertyPages(DATA_OBJECT_TYPES type,
  229. BOOL* pbHideVerb,
  230. CNodeList* pNodeList);
  231. virtual HRESULT CreatePropertyPages(LPPROPERTYSHEETCALLBACK,
  232. LONG_PTR,
  233. CNodeList*) { return E_FAIL; }
  234. virtual void OnPropertyChange(CComponentDataObject* pComponentData,
  235. BOOL bScopePane,long changeMask);
  236. virtual BOOL CanCloseSheets() { return TRUE;}
  237. void OnCreateSheet();
  238. void OnDeleteSheet();
  239. BOOL HasSheet() { return (m_dwNodeFlags & TN_FLAG_HAS_SHEET) ? TRUE : FALSE;}
  240. BOOL GetSheetCount() { return m_nSheetCount;}
  241. virtual void IncrementSheetLockCount();
  242. virtual void DecrementSheetLockCount();
  243. BOOL IsSheetLocked() { return m_nSheetLockCount > 0;}
  244. BOOL IsNodeForPropSheet(){ return m_bNodeForPropSheet;}
  245. void NodeForPropSheet(){ m_bNodeForPropSheet = TRUE;}
  246. //
  247. // Misc.
  248. //
  249. virtual LPWSTR GetDescriptionBarText() { return L""; }
  250. virtual LPCWSTR GetString(int nCol) = 0;
  251. virtual int GetImageIndex(BOOL bOpenImage) = 0;
  252. virtual void Trace() { TRACE(_T("Name %s "), (LPCTSTR)m_szDisplayName);}
  253. void DeleteHelper(CComponentDataObject* pComponentData);
  254. protected:
  255. CString m_szDisplayName; // name of the item
  256. CContainerNode* m_pContainer; // back pointer to the container the node is in
  257. DWORD m_dwNodeFlags;
  258. LONG m_nSheetLockCount; // keeps track if a node has been locked by a property sheet
  259. LONG m_nSheetCount; // keeps track of the # of sheets the node has up
  260. BOOL m_bNodeForPropSheet; // This node is created for property sheet display only
  261. // Once the propertysheet is destroyed, node should be deleted.
  262. CTreeNode()
  263. {
  264. m_pContainer = NULL;
  265. m_nSheetLockCount = 0;
  266. m_dwNodeFlags = 0x0; //m_dwNodeFlags |= TN_FLAG_HIDDEN;
  267. m_nSheetCount = 0;
  268. m_bNodeForPropSheet = FALSE;
  269. }
  270. virtual LPCONTEXTMENUITEM2 OnGetContextMenuItemTable() { return NULL;}
  271. virtual BOOL OnAddMenuItem(LPCONTEXTMENUITEM2,
  272. long*) { return TRUE;}
  273. friend class CContainerNode; // to get access to the m_pContainer member
  274. //
  275. // Provides a default implementation for toolbar support
  276. //
  277. DECLARE_TOOLBAR_MAP()
  278. };
  279. ///////////////////////////////////////////////////////////////////////
  280. // CNodeList
  281. // collection of nodes
  282. typedef CList<CTreeNode*,CTreeNode*> CNodeListBase;
  283. class CNodeList : public CNodeListBase
  284. {
  285. public:
  286. BOOL RemoveNode(CTreeNode* p)
  287. {
  288. POSITION pos = Find(p);
  289. if (pos == NULL)
  290. return FALSE;
  291. RemoveAt(pos);
  292. return TRUE;
  293. }
  294. void RemoveAllNodes()
  295. {
  296. while (!IsEmpty())
  297. delete RemoveTail();
  298. }
  299. BOOL HasNode(CTreeNode* p)
  300. {
  301. return NULL != Find(p);
  302. }
  303. INT_PTR GetVisibleCount();
  304. };
  305. ////////////////////////////////////////////////////////////////////////
  306. // CContainerNode
  307. // node that can be a container of other nodes
  308. class CContainerNode : public CTreeNode
  309. {
  310. public:
  311. CContainerNode()
  312. {
  313. m_ID = 0;
  314. m_dwNodeFlags |= TN_FLAG_CONTAINER;
  315. m_nState = -1;
  316. m_dwErr = 0x0;
  317. m_nThreadLockCount = 0;
  318. }
  319. virtual ~CContainerNode() { ASSERT(m_nSheetLockCount == 0); RemoveAllChildrenFromList(); }
  320. CContainerNode* GetRootContainer()
  321. { return (m_pContainer != NULL) ? m_pContainer->GetRootContainer() : this; }
  322. //
  323. // Thread Helpers
  324. //
  325. void IncrementThreadLockCount();
  326. void DecrementThreadLockCount();
  327. BOOL IsThreadLocked() { return m_nThreadLockCount > 0;}
  328. virtual BOOL OnEnumerate(CComponentDataObject*, BOOL bAsync = TRUE)
  329. { bAsync; return TRUE;} // TRUE = add children in the list to UI
  330. //
  331. // Node state helpers
  332. //
  333. BOOL HasChildren() { return !m_containerChildList.IsEmpty() || !m_leafChildList.IsEmpty(); }
  334. void ForceEnumeration(CComponentDataObject* pComponentData);
  335. void MarkEnumerated(BOOL bEnum = TRUE);
  336. BOOL IsEnumerated() { ASSERT(IsContainer()); return (m_dwNodeFlags & TN_FLAG_CONTAINER_ENUM) ? TRUE : FALSE;}
  337. void MarkExpanded() { ASSERT(IsContainer()); m_dwNodeFlags |= TN_FLAG_CONTAINER_EXP; }
  338. BOOL IsExpanded() { ASSERT(IsContainer()); return (m_dwNodeFlags & TN_FLAG_CONTAINER_EXP) ? TRUE : FALSE;}
  339. void MarkEnumeratedAndLoaded(CComponentDataObject* pComponentData);
  340. void SetScopeID(HSCOPEITEM ID) { m_ID = ID;}
  341. HSCOPEITEM GetScopeID() { return m_ID;}
  342. BOOL AddedToScopePane() { return GetScopeID() != 0;}
  343. virtual CColumnSet* GetColumnSet() = 0;
  344. virtual LPCWSTR GetColumnID() = 0;
  345. virtual void SetFlagsDown(DWORD dwNodeFlags, BOOL bSet);
  346. void SetFlagsOnNonContainers(DWORD dwNodeFlags,BOOL bSet);
  347. //
  348. // child list mainpulation API's
  349. //
  350. CNodeList* GetContainerChildList() { return &m_containerChildList; }
  351. CNodeList* GetLeafChildList() { return &m_leafChildList; }
  352. BOOL AddChildToList(CTreeNode* p);
  353. BOOL AddChildToListSorted(CTreeNode* p, CComponentDataObject* pComponentData);
  354. BOOL RemoveChildFromList(CTreeNode* p);
  355. void RemoveAllChildrenFromList();
  356. void RemoveAllContainersFromList() { m_containerChildList.RemoveAllNodes(); }
  357. void RemoveAllLeavesFromList() { m_leafChildList.RemoveAllNodes(); }
  358. //
  359. // given a node, it searches for it recursively and if successful it returns the
  360. // container the node is in
  361. //
  362. BOOL FindChild(CTreeNode* pNode, CTreeNode** ppContainer);
  363. BOOL AddChildToListAndUI(CTreeNode* pChildToAdd, CComponentDataObject* pComponentData);
  364. BOOL AddChildToListAndUISorted(CTreeNode* pChildToAdd, CComponentDataObject* pComponentData);
  365. virtual int Compare(CTreeNode* pNodeA, CTreeNode* pNodeB, int nCol, LPARAM lUserParam);
  366. virtual HRESULT CreatePropertyPagesHelper(LPPROPERTYSHEETCALLBACK,
  367. LONG_PTR,
  368. long) { return E_FAIL;}
  369. virtual BOOL OnRefresh(CComponentDataObject* pComponentData,
  370. CNodeList* pNodeList);
  371. virtual void OnColumnsChanged(int*, int) {}
  372. void RemoveAllChildrenHelper(CComponentDataObject* pComponentData);
  373. protected:
  374. virtual void OnChangeState(CComponentDataObject*) {}
  375. void AddCurrentChildrenToUI(CComponentDataObject* pComponentData);
  376. LONG m_nThreadLockCount;
  377. CNodeList m_leafChildList; // leaf contents of the node
  378. CNodeList m_containerChildList; // container contents of the node
  379. HSCOPEITEM m_ID; // ID when the item is inserted in the master tree
  380. int m_nState; // for general purpose finite state machine implementation
  381. DWORD m_dwErr; // for general purpose error handling
  382. };
  383. ////////////////////////////////////////////////////////////////////////
  384. // CLeafNode
  385. // node that is not a container of other nodes
  386. class CLeafNode : public CTreeNode
  387. {
  388. public:
  389. };
  390. ///////////////////////////////////////////////////////////////////
  391. // data nodes
  392. // the root, with folders in it
  393. class CRootData : public CContainerNode
  394. {
  395. public:
  396. CRootData(CComponentDataObject* pComponentData)
  397. {
  398. ASSERT(pComponentData != NULL);
  399. m_pComponentData = pComponentData;
  400. m_bDirty = FALSE;
  401. }
  402. virtual LPCWSTR GetString(int nCol)
  403. {
  404. if (nCol == 0)
  405. return GetDisplayName();
  406. return g_lpszNullString;
  407. }
  408. CComponentDataObject* GetComponentDataObject(){ return m_pComponentData;}
  409. CTreeNode* GetNodeFromCookie(MMC_COOKIE cookie)
  410. {
  411. // cookie == 0 means root to enumerate
  412. if (cookie == NULL)
  413. {
  414. return (CTreeNode*)this;
  415. }
  416. else
  417. {
  418. CTreeNode* pNode = (CTreeNode*)cookie;
  419. CTreeNode* pContainer;
  420. if (FindChild(pNode,&pContainer))
  421. {
  422. return pNode;
  423. }
  424. }
  425. return NULL;
  426. }
  427. // IStream manipulation helpers
  428. virtual HRESULT IsDirty() { return m_bDirty ? S_OK : S_FALSE; }
  429. virtual HRESULT Load(IStream*) { return S_OK; }
  430. virtual HRESULT Save(IStream*, BOOL) { return S_OK; }
  431. void SetDirtyFlag(BOOL bDirty) { m_bDirty = bDirty ;}
  432. private:
  433. CComponentDataObject* m_pComponentData;
  434. BOOL m_bDirty;
  435. CString m_szSnapinType; // constant part of the name loaded from resources
  436. };
  437. //////////////////////////////////////////////////////////////////////
  438. // CBackgroundThread
  439. class CBackgroundThread : public CWinThread
  440. {
  441. public:
  442. CBackgroundThread();
  443. virtual ~CBackgroundThread();
  444. void SetQueryObj(CQueryObj* pQueryObj);
  445. BOOL Start(CMTContainerNode* pNode, CComponentDataObject* pComponentData);
  446. virtual BOOL InitInstance() { return TRUE; } // MFC override
  447. virtual int Run(); // MFC override
  448. // REVIEWED-2002/03/08-JeffJon-There appears to be no danger
  449. // of getting stuck in the critical section
  450. void Lock() { ::EnterCriticalSection(&m_cs); }
  451. void Unlock() { ::LeaveCriticalSection(&m_cs); }
  452. void Abandon();
  453. BOOL IsAbandoned();
  454. BOOL OnAddToQueue(INT_PTR nCount);
  455. CObjBase* RemoveFromQueue();
  456. BOOL IsQueueEmpty();
  457. BOOL PostHaveData();
  458. BOOL PostError(DWORD dwErr);
  459. BOOL PostExiting();
  460. void AcknowledgeExiting() { VERIFY(0 != ::SetEvent(m_hEventHandle));}
  461. private:
  462. // communication with ComponentData object
  463. BOOL PostMessageToComponentDataRaw(UINT Msg, WPARAM wParam, LPARAM lParam);
  464. void WaitForExitAcknowledge();
  465. CRITICAL_SECTION m_cs; // critical section to sync access to data
  466. HANDLE m_hEventHandle; // syncronization handle for shutdown notification
  467. CMTContainerNode* m_pContNode; // back pointer to node the thread is executing for
  468. CQueryObj* m_pQueryObj; // query object the thread is executing
  469. INT_PTR m_nQueueCountMax; // max size of the queue
  470. HWND m_hHiddenWnd; // handle to window to post messages
  471. BOOL m_bAbandoned;
  472. };
  473. //////////////////////////////////////////////////////////////////////
  474. // CQueryObj
  475. typedef CList<CObjBase*,CObjBase*> CObjBaseList;
  476. class CQueryObj
  477. {
  478. public:
  479. CQueryObj() { m_dwErr = 0; m_pThread = NULL;}
  480. virtual ~CQueryObj()
  481. {
  482. while (!m_objQueue.IsEmpty())
  483. delete m_objQueue.RemoveTail();
  484. };
  485. void SetThread(CBackgroundThread* pThread)
  486. {
  487. ASSERT(pThread != NULL);
  488. m_pThread = pThread;
  489. }
  490. CBackgroundThread* GetThread() {return m_pThread;}
  491. virtual BOOL Enumerate() { return FALSE;}
  492. virtual BOOL AddQueryResult(CObjBase* pObj)
  493. {
  494. BOOL bRes = FALSE;
  495. if (m_pThread != NULL)
  496. {
  497. BOOL bPostedHaveDataMessage = FALSE;
  498. m_pThread->Lock();
  499. bRes = NULL != m_objQueue.AddTail(pObj);
  500. bPostedHaveDataMessage = m_pThread->OnAddToQueue(m_objQueue.GetCount());
  501. m_pThread->Unlock();
  502. // wait for the queue length to go down to zero
  503. if (bPostedHaveDataMessage)
  504. {
  505. INT_PTR nQueueCount = 0;
  506. do
  507. {
  508. m_pThread->Lock();
  509. nQueueCount = m_objQueue.GetCount();
  510. m_pThread->Unlock();
  511. if (m_pThread->IsAbandoned())
  512. {
  513. break;
  514. }
  515. if (nQueueCount > 0)
  516. {
  517. ::Sleep(100);
  518. }
  519. }
  520. while (nQueueCount > 0);
  521. } // if
  522. }
  523. else
  524. {
  525. bRes = NULL != m_objQueue.AddTail(pObj);
  526. }
  527. ASSERT(bRes);
  528. return bRes;
  529. }
  530. virtual void OnError(DWORD dwErr)
  531. {
  532. if (m_pThread != NULL)
  533. {
  534. m_pThread->Lock();
  535. m_dwErr = dwErr;
  536. m_pThread->Unlock();
  537. m_pThread->PostError(dwErr);
  538. }
  539. else
  540. {
  541. m_dwErr = dwErr;
  542. }
  543. }
  544. CObjBaseList* GetQueue() { return &m_objQueue;}
  545. DWORD GetError()
  546. {
  547. if (m_pThread != NULL)
  548. {
  549. m_pThread->Lock();
  550. DWORD dwErr = m_dwErr;
  551. m_pThread->Unlock();
  552. return dwErr;
  553. }
  554. else
  555. {
  556. return m_dwErr;
  557. }
  558. }
  559. private:
  560. CBackgroundThread* m_pThread; // back pointer, if in the context of a thread
  561. CObjBaseList m_objQueue; // queue for results
  562. DWORD m_dwErr; // error code, if any
  563. };
  564. ////////////////////////////////////////////////////////////////////////
  565. // CMTContainerNode
  566. // container that can do operations from a secondary thread
  567. class CMTContainerNode : public CContainerNode
  568. {
  569. public:
  570. CMTContainerNode()
  571. {
  572. m_pThread = NULL;
  573. }
  574. virtual ~CMTContainerNode();
  575. virtual BOOL OnEnumerate(CComponentDataObject* pComponentData, BOOL bAsync = TRUE);
  576. virtual BOOL OnRefresh(CComponentDataObject* pComponentData,
  577. CNodeList* pNodeList);
  578. protected:
  579. // thread creation
  580. virtual CBackgroundThread* CreateThreadObject()
  581. {
  582. return new CBackgroundThread(); // override if need derived tipe of object
  583. }
  584. // query creation
  585. virtual CQueryObj* OnCreateQuery() // override to create a user defined query object
  586. {
  587. return new CQueryObj(); // return a do-nothing query
  588. }
  589. // main message handler for thread messages
  590. virtual void OnThreadHaveDataNotification(CComponentDataObject* pComponentDataObject);
  591. virtual void OnThreadErrorNotification(DWORD dwErr, CComponentDataObject* pComponentDataObject);
  592. virtual void OnThreadExitingNotification(CComponentDataObject* pComponentDataObject);
  593. virtual void OnHaveData(CObjBase*, CComponentDataObject*) {}
  594. virtual void OnError(DWORD dwErr) { m_dwErr = dwErr; }
  595. BOOL StartBackgroundThread(CComponentDataObject* pComponentData, BOOL bAsync = TRUE);
  596. CBackgroundThread* GetThread() { ASSERT(m_pThread != NULL); return m_pThread;}
  597. void AbandonThread(CComponentDataObject* pComponentData);
  598. private:
  599. CBackgroundThread* m_pThread; // pointer to thread object executing the code
  600. friend class CHiddenWnd; // to get OnThreadNotification()
  601. friend class CRunningThreadTable; // to get AbandonThread()
  602. };
  603. #endif // _TREEDATA_H