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.

437 lines
12 KiB

  1. //============================================================================
  2. // Copyright (C) Microsoft Corporation, 1997 - 1999
  3. //
  4. // File: refresh.h
  5. //
  6. // History:
  7. // Kenn Takara Sept. 16, 1997 Created.
  8. //
  9. //============================================================================
  10. #ifndef _REFRESH_H_
  11. #define _REFRESH_H_
  12. #include <afxmt.h>
  13. #include <list>
  14. #include "infoi.h"
  15. #include "router.h"
  16. #ifndef _HANDLERS_H_
  17. #include "handlers.h"
  18. #endif
  19. /*---------------------------------------------------------------------------
  20. Defines
  21. ---------------------------------------------------------------------------*/
  22. #define DEFAULT_REFRESH_INTERVAL 60
  23. /*---------------------------------------------------------------------------
  24. Forward declarations
  25. ---------------------------------------------------------------------------*/
  26. class RouterRefreshQueryElement; // COM
  27. class RefreshItem;
  28. class DomainStatusHandler;
  29. struct MachineNodeData;
  30. /*---------------------------------------------------------------------------
  31. Class: RouterRefreshQueryElementList
  32. ---------------------------------------------------------------------------*/
  33. class RouterRefreshQueryElementList
  34. {
  35. public:
  36. ~RouterRefreshQueryElementList();
  37. HRESULT AddRefreshItem(RefreshItem* pItem); // no ref
  38. HRESULT RemoveRefreshItem(RefreshItem& Item); // no ref
  39. RouterRefreshQueryElement* Next(RouterRefreshQueryElement* pEle); // AddRef
  40. protected:
  41. CList<RouterRefreshQueryElement*, RouterRefreshQueryElement*> m_list;
  42. CCriticalSection m_cs;
  43. };
  44. /*---------------------------------------------------------------------------
  45. Class: RouterRefreshObjectGroup
  46. Do refresh on a group, all it's members DoRefresh is called
  47. ---------------------------------------------------------------------------*/
  48. class RouterRefreshObjectGroup
  49. {
  50. public:
  51. RouterRefreshObjectGroup()
  52. {
  53. DEBUG_INCREMENT_INSTANCE_COUNTER(RouterRefreshObjectGroup);
  54. }
  55. ~RouterRefreshObjectGroup();
  56. HRESULT Join(RouterRefreshObject* pRefresh);
  57. HRESULT Leave(RouterRefreshObject* pRefresh);
  58. HRESULT Refresh();
  59. protected:
  60. CList<RouterRefreshObject*, RouterRefreshObject*> m_list;
  61. };
  62. /*---------------------------------------------------------------------------
  63. Class: RouterRefreshObject
  64. class RouterRefreshObject implements IRouterRefresh interface,
  65. and also other two functions used by Status node refresh:
  66. HRESULT AddStatusNode;
  67. HRESULT RemoveStatusNode;
  68. Internally to this object, it maitains a list of RefreshElements,
  69. in this implementation, the element could be either build
  70. from IRouterInfo pointer or, an machine status node pointer
  71. The items are maintained by
  72. thread safe list object RouterRefreshQueryElementList
  73. ---------------------------------------------------------------------------*/
  74. class RouterRefreshObject :
  75. public IRouterRefresh,
  76. public IRouterRefreshModify,
  77. public ThreadHandler
  78. {
  79. friend void RouterRefreshObjectTimerProc(LPARAM lParam, DWORD dwTime);
  80. public:
  81. DeclareIUnknownMembers(IMPL);
  82. DeclareIRouterRefreshMembers(IMPL);
  83. DeclareIRouterRefreshModifyMembers(IMPL);
  84. DeclareITFSThreadHandlerMembers(IMPL);
  85. RouterRefreshObject(/*IRouterInfo *pRouter, */HWND hWndSync);
  86. ~RouterRefreshObject();
  87. // Interface in refresh Router Status nodes
  88. HRESULT AddStatusNode(DomainStatusHandler* pStatusHandler, ITFSNode *pServerNode);
  89. HRESULT RemoveStatusNode(ITFSNode *pServerNode);
  90. HRESULT DoRefresh();
  91. void SetGroup(RouterRefreshObjectGroup* pGroup) { m_pRefreshGroup = pGroup;};
  92. protected:
  93. void ExecuteRefresh();
  94. AdviseDataList m_AdviseList; // list of advises
  95. // Number of seconds between refresh intervals
  96. DWORD m_dwSeconds;
  97. // TRUE if we are currently in a refresh cycle
  98. BOOL m_fInRefresh;
  99. // TRUE if we have started the refresh mechanism
  100. BOOL m_fStarted;
  101. // Id returned by CTimerMgr::AllocateTimer()
  102. int m_iEventId;
  103. // This is tied directly to the IRouterInfo, it does not AddRef()
  104. RouterRefreshQueryElementList m_listElements;
  105. HWND m_hWndSync;
  106. CRITICAL_SECTION m_critsec;
  107. RouterRefreshObjectGroup* m_pRefreshGroup;
  108. };
  109. DeclareSmartPointer(SPRouterRefreshObject, RouterRefreshObject, if(m_p) m_p->Release());
  110. typedef void (*REFRESHPROC)(LPARAM lParam, DWORD dwTime);
  111. /*---------------------------------------------------------------------------
  112. Class: CTimerDesc
  113. This holds some of the per-refresh proc information.
  114. ---------------------------------------------------------------------------*/
  115. class CTimerDesc
  116. {
  117. public:
  118. LPARAM lParam;
  119. UINT_PTR uTimerId;
  120. UINT uTimerInterval;
  121. REFRESHPROC refreshProc;
  122. };
  123. typedef CArray<CTimerDesc *, CTimerDesc *> CTimerArrayBase;
  124. class CTimerMgr : protected CTimerArrayBase
  125. {
  126. public:
  127. CTimerMgr();
  128. ~CTimerMgr();
  129. public:
  130. int AllocateTimer(REFRESHPROC procRefresh,
  131. LPARAM lParam,
  132. UINT uTimerInterval);
  133. void FreeTimer(int uEventId);
  134. void ChangeInterval(int uEventId, UINT uNewInterval);
  135. //
  136. // Function: GetTimerDesc
  137. // Finds the TimerDesc based on the uTimerd (the one that is
  138. // returned by SetTimer()).
  139. //
  140. CTimerDesc * GetTimerDesc(INT_PTR uTimerId);
  141. CRITICAL_SECTION m_critsec;
  142. };
  143. extern CTimerMgr g_timerMgr;
  144. enum RouterRefreshQueryElementStatus
  145. {
  146. RouterQuery_NoAction = 0,
  147. RouterQuery_NeedQuery,
  148. RouterQuery_Working,
  149. RouterQuery_ToNotify,
  150. };
  151. /*---------------------------------------------------------------------------
  152. Class: RefreshItem
  153. RefreshItem generalize the interface for background refresh task to
  154. DoQuery, and NotifyQueryResult
  155. ---------------------------------------------------------------------------*/
  156. class RefreshItem
  157. {
  158. public:
  159. RefreshItem(){
  160. m_hBlockingThread = INVALID_HANDLE_VALUE;
  161. DEBUG_INCREMENT_INSTANCE_COUNTER(RefreshItem);
  162. };
  163. virtual ~RefreshItem()
  164. {
  165. // this should be called in Destructor of derived class, to be safe, do it here again.
  166. TerminateBlockingThread();
  167. DEBUG_DECREMENT_INSTANCE_COUNTER(RefreshItem);
  168. }
  169. // helper function,
  170. // Terminate Blocking Thread before Delete ..
  171. // Should be called in Destructor of derived object
  172. BOOL TerminateBlockingThread()
  173. {
  174. BOOL r = FALSE;
  175. m_csBlockingThread.Lock();
  176. if(m_hBlockingThread != INVALID_HANDLE_VALUE)
  177. {
  178. Assert(0); // just to notify some thread is still runing
  179. r = TerminateThread(m_hBlockingThread, 1);
  180. CloseHandle(m_hBlockingThread);
  181. m_hBlockingThread = INVALID_HANDLE_VALUE;
  182. }
  183. m_csBlockingThread.Unlock();
  184. return r;
  185. };
  186. void ResetBlockingThread()
  187. {
  188. SetBlockingThread(INVALID_HANDLE_VALUE);
  189. };
  190. BOOL SetBlockingThread(HANDLE hThread)
  191. {
  192. BOOL r = FALSE;
  193. m_csBlockingThread.Lock();
  194. if(m_hBlockingThread != INVALID_HANDLE_VALUE)
  195. CloseHandle(m_hBlockingThread);
  196. m_hBlockingThread = INVALID_HANDLE_VALUE;
  197. if(hThread != INVALID_HANDLE_VALUE)
  198. r = DuplicateHandle(GetCurrentProcess(),
  199. hThread,
  200. GetCurrentProcess(),
  201. &m_hBlockingThread,
  202. DUPLICATE_SAME_ACCESS,
  203. FALSE,
  204. DUPLICATE_SAME_ACCESS);
  205. else
  206. m_hBlockingThread = INVALID_HANDLE_VALUE;
  207. m_csBlockingThread.Unlock();
  208. return r;
  209. }
  210. // to detect if the query done, yet to Notify
  211. virtual HRESULT NotifyQueryResult() = 0;
  212. // this happens in background worker thread
  213. virtual HRESULT DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler) = 0;
  214. // used to compare if two items are the same
  215. virtual LONG_PTR GetKey() = 0;
  216. private:
  217. HANDLE m_hBlockingThread;
  218. CCriticalSection m_csBlockingThread;
  219. };
  220. /*---------------------------------------------------------------------------
  221. Class: CRouterInfoRefreshItem
  222. CRouterInfoRefreshItem implements the refresh task item for IRouterInfo
  223. ---------------------------------------------------------------------------*/
  224. class CRouterInfoRefreshItem : public RefreshItem
  225. {
  226. public:
  227. CRouterInfoRefreshItem(IRouterInfo* pRouter) : m_pRouter(pRouter){ASSERT(pRouter);};
  228. virtual ~CRouterInfoRefreshItem()
  229. {
  230. TerminateBlockingThread();
  231. };
  232. // to detect if the query done, yet to Notify
  233. virtual HRESULT NotifyQueryResult();
  234. // this happens in background worker thread
  235. virtual HRESULT DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler);
  236. // used to compare if two items are the same
  237. virtual LONG_PTR GetKey() {return (LONG_PTR)m_pRouter;};
  238. protected:
  239. // This is tied directly to the IRouterInfo, it does not AddRef()
  240. IRouterInfo* m_pRouter;
  241. SPIRouterInfo m_spRouterNew;
  242. CCriticalSection m_cs;
  243. };
  244. /*---------------------------------------------------------------------------
  245. Class: CStatusNodeRefreshItem
  246. Implements the refresh task item fo the machine status node.
  247. ---------------------------------------------------------------------------*/
  248. class CStatusNodeRefreshItem: public RefreshItem
  249. {
  250. public:
  251. CStatusNodeRefreshItem(DomainStatusHandler* pStatusHandler,
  252. ITFSNode *pServerNode);
  253. virtual ~CStatusNodeRefreshItem();
  254. // to detect if the query done, yet to Notify
  255. virtual HRESULT NotifyQueryResult();
  256. // this happens in background worker thread
  257. virtual HRESULT DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler);
  258. // used to compare if two items are the same
  259. virtual LONG_PTR GetKey() { return (LONG_PTR)m_pNode;};
  260. protected:
  261. MachineNodeData* m_pData;
  262. ITFSNode* m_pNode; //since this lives within the life time of node, so no ref count
  263. DomainStatusHandler* m_pStatusHandler; // no ref count
  264. CString m_strMachineName;
  265. CCriticalSection m_cs;
  266. };
  267. /*---------------------------------------------------------------------------
  268. Class: RouterRefreshQueryElement
  269. RouterRefreshQueryElement is the unit of refresh, it is constructed by
  270. using RefreshItem object. Each refresh item implements function
  271. for DoQuery, and NotifyQueryResult
  272. ---------------------------------------------------------------------------*/
  273. class ATL_NO_VTABLE RouterRefreshQueryElement :
  274. public CComObjectRoot,
  275. public IUnknown
  276. {
  277. BEGIN_COM_MAP(RouterRefreshQueryElement)
  278. COM_INTERFACE_ENTRY(IUnknown)
  279. END_COM_MAP()
  280. public:
  281. RouterRefreshQueryElement() : m_Status(RouterQuery_NoAction), m_pItem(NULL) {};
  282. ~RouterRefreshQueryElement(){ delete m_pItem; m_pItem = NULL;};
  283. HRESULT SetRefreshItem(RefreshItem* pRouterInfo);
  284. RefreshItem* GetRefreshItem();
  285. RouterRefreshQueryElementStatus GetStatus()
  286. {
  287. RouterRefreshQueryElementStatus s;
  288. m_cs.Lock();
  289. s = m_Status;
  290. m_cs.Unlock();
  291. return s;
  292. };
  293. void SetStatus(RouterRefreshQueryElementStatus s)
  294. {
  295. m_cs.Lock();
  296. m_Status = s;
  297. m_cs.Unlock();
  298. };
  299. // to detect if the query done, yet to Notify
  300. HRESULT TryNotifyQueryResult();
  301. // set notify after query
  302. void PostNotify(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler);
  303. // this happens in background worker thread
  304. HRESULT DoQuery(HWND hwndHidden, UINT uMsgBase, ITFSThreadHandler* pHandler);
  305. protected:
  306. // This is tied directly to the IRouterInfo, it does not AddRef()
  307. // we may need to change this in the future OPT
  308. RefreshItem* m_pItem;
  309. RouterRefreshQueryElementStatus m_Status;
  310. CCriticalSection m_cs;
  311. };
  312. DeclareSmartPointer(SPRouterRefreshQueryElement, RouterRefreshQueryElement, if(m_p) m_p->Release());
  313. /*---------------------------------------------------------------------------
  314. Class: RouterRefreshQueryObject
  315. RouterRefreshQueryObject is the worker of RouterRefreshObject, it execute
  316. RefreshElements DoQuery in backgroud process
  317. ---------------------------------------------------------------------------*/
  318. class RouterRefreshQueryObject : public CQueryObject
  319. {
  320. public:
  321. RouterRefreshQueryObject();
  322. void Init(RouterRefreshQueryElementList* plist)
  323. {
  324. ASSERT(plist);
  325. m_plistElements = plist;
  326. };
  327. // Override the ITFSQueryObject::Execute
  328. STDMETHOD(Execute)();
  329. STDMETHOD(OnThreadExit)();
  330. protected:
  331. RouterRefreshQueryElementList* m_plistElements;
  332. };
  333. #endif _REFRESH_H_