Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

541 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: idle.cpp
  7. //
  8. // Contents: Idle notification routines.
  9. //
  10. // Classes:
  11. //
  12. // Notes:
  13. //
  14. // History: 23-Feb-98 rogerg Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "precomp.h"
  18. // msidle DLL and function strings
  19. STRING_FILENAME(szMsIdleDll, "MsIdle.dll");
  20. #define BEGINIDLEDETECTIONORD 3
  21. #define ENDIDLEDETECTIONORD 4
  22. #define SETIDLETIMEOUTORD 5
  23. #define SETIDLENOTIFYORD 6
  24. #define SETBUSYNOTIFYORD 7
  25. #define GETIDLEMINUTESORD 8
  26. CSyncMgrIdle *g_SyncMgrIdle = NULL; // idle that has a current callback.
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Member: IdleCallback, private
  30. //
  31. // Synopsis: callback function for Idle, Only one idle registration
  32. // is allowed per SyncMgrInstance.
  33. //
  34. // Arguments:
  35. //
  36. // Returns:
  37. //
  38. // Modifies:
  39. //
  40. // History: 23-Feb-98 rogerg Created.
  41. //
  42. //----------------------------------------------------------------------------
  43. void WINAPI IdleCallback(DWORD dwState)
  44. {
  45. if (STATE_USER_IDLE_END == dwState)
  46. {
  47. if (g_SyncMgrIdle)
  48. {
  49. g_SyncMgrIdle->m_fReceivedOffIdle = TRUE;
  50. // if we have a registered timer for reset Idle remove it.
  51. if (g_SyncMgrIdle->m_dwRegisteredTimer)
  52. {
  53. KillTimer(0,g_SyncMgrIdle->m_dwRegisteredTimer);
  54. }
  55. g_SyncMgrIdle->m_pSetBusyNotify(FALSE,0); // only allow one busy to come through
  56. g_SyncMgrIdle->m_pSetIdleNotify(FALSE,0); // don't allow an Idle through after get a busy.
  57. g_SyncMgrIdle->OffIdle();
  58. }
  59. }
  60. /*
  61. User the TimerProc instead.
  62. else if (STATE_USER_IDLE_BEGIN == dwState)
  63. {
  64. // On an Idle Begin just send another Idle.
  65. if (g_SyncMgrIdle)
  66. {
  67. g_SyncMgrIdle->m_pSetIdleNotify(FALSE,0);
  68. g_SyncMgrIdle->OnIdle();
  69. }
  70. }
  71. */
  72. }
  73. //+---------------------------------------------------------------------------
  74. //
  75. // Member: TimerCallback, private
  76. //
  77. // Synopsis: callback function for Timer when minutes have passed
  78. // for when to restart the Idle.
  79. //
  80. //
  81. // Arguments:
  82. //
  83. // Returns:
  84. //
  85. // Modifies:
  86. //
  87. // History: 23-Feb-98 rogerg Created.
  88. //
  89. //----------------------------------------------------------------------------
  90. VOID CALLBACK IdleOnTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
  91. {
  92. if (g_SyncMgrIdle && !g_SyncMgrIdle->m_fReceivedOffIdle)
  93. {
  94. DWORD_PTR dwRegTimer = g_SyncMgrIdle->m_dwRegisteredTimer;
  95. g_SyncMgrIdle->m_dwRegisteredTimer = 0;
  96. KillTimer(0,dwRegTimer);
  97. g_SyncMgrIdle->OnIdle();
  98. }
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Member: CSyncMgrIdle::CSyncMgrIdle, public
  103. //
  104. // Synopsis: Constructor
  105. //
  106. // Arguments:
  107. //
  108. // Returns:
  109. //
  110. // Modifies:
  111. //
  112. // History: 23-Feb-98 rogerg Created.
  113. //
  114. //----------------------------------------------------------------------------
  115. CSyncMgrIdle::CSyncMgrIdle()
  116. {
  117. m_hInstMsIdleDll = NULL;
  118. m_pBeginIdleDetection = NULL;
  119. m_pEndIdleDetection = NULL;
  120. m_pGetIdleMinutes = NULL;
  121. m_pSetBusyNotify = NULL;
  122. m_pSetIdleNotify = NULL;
  123. m_pSetIdleTimeout = NULL;
  124. m_pProgressDlg = NULL;
  125. m_dwRegisteredTimer = NULL;
  126. m_fInBeginIdleDetection = FALSE;
  127. m_fReceivedOffIdle = FALSE;
  128. Assert(NULL == g_SyncMgrIdle); // make sure another idle doesn't exist
  129. }
  130. //+---------------------------------------------------------------------------
  131. //
  132. // Member: CSyncMgrIdle::~CSyncMgrIdle, public
  133. //
  134. // Synopsis: destructor
  135. //
  136. // Arguments:
  137. //
  138. // Returns:
  139. //
  140. // Modifies:
  141. //
  142. // History: 23-Feb-98 rogerg Created.
  143. //
  144. //----------------------------------------------------------------------------
  145. CSyncMgrIdle::~CSyncMgrIdle()
  146. {
  147. if (m_dwRegisteredTimer) // remove our timer.
  148. {
  149. KillTimer(0,m_dwRegisteredTimer);
  150. }
  151. // if we are in an idle detection then first remove it.
  152. if (m_fInBeginIdleDetection)
  153. {
  154. m_pEndIdleDetection(0);
  155. m_pProgressDlg = NULL;
  156. g_SyncMgrIdle = NULL;
  157. }
  158. else
  159. {
  160. Assert(NULL == m_pProgressDlg);
  161. Assert(NULL == g_SyncMgrIdle);
  162. }
  163. // if have the dll then free it.
  164. if (m_hInstMsIdleDll)
  165. {
  166. FreeLibrary(m_hInstMsIdleDll);
  167. }
  168. }
  169. //+---------------------------------------------------------------------------
  170. //
  171. // Member: CSyncMgrIdle::Initialize, public
  172. //
  173. // Synopsis: Initializes class, must be called before any other member.
  174. //
  175. // Arguments:
  176. //
  177. // Returns:
  178. //
  179. // Modifies:
  180. //
  181. // History: 23-Feb-98 rogerg Created.
  182. //
  183. //----------------------------------------------------------------------------
  184. BOOL CSyncMgrIdle::Initialize()
  185. {
  186. return LoadMsIdle();
  187. }
  188. //+---------------------------------------------------------------------------
  189. //
  190. // Member: CSyncMgrIdle::BeginIdleDetection, public
  191. //
  192. // Synopsis: Registers the callback with msidle.
  193. //
  194. // Arguments:
  195. //
  196. // Returns:
  197. //
  198. // Modifies:
  199. //
  200. // History: 23-Feb-98 rogerg Created.
  201. //
  202. //----------------------------------------------------------------------------
  203. DWORD CSyncMgrIdle::BeginIdleDetection(CProgressDlg *pProgressDlg,DWORD dwIdleMin, DWORD dwReserved)
  204. {
  205. DWORD dwResult = 0;
  206. Assert(m_hInstMsIdleDll);
  207. if (!m_hInstMsIdleDll)
  208. {
  209. return -1;
  210. }
  211. // if there is already an idle registered
  212. // assert it is the same as what is trying to get registered
  213. // now and return
  214. Assert(FALSE == m_fInBeginIdleDetection);
  215. if (m_fInBeginIdleDetection)
  216. {
  217. Assert(g_SyncMgrIdle == this);
  218. Assert(m_pProgressDlg == pProgressDlg);
  219. return 0;
  220. }
  221. Assert(NULL == g_SyncMgrIdle); // should not still be another Idle.
  222. g_SyncMgrIdle = this;
  223. m_pProgressDlg = pProgressDlg;
  224. dwResult = m_pBeginIdleDetection(IdleCallback,30,0);
  225. if (0 != dwResult)
  226. {
  227. g_SyncMgrIdle = NULL;
  228. m_pProgressDlg = NULL;
  229. }
  230. else
  231. {
  232. m_pSetBusyNotify(TRUE,0);
  233. m_pSetIdleNotify(FALSE,0);
  234. m_fInBeginIdleDetection = TRUE;
  235. }
  236. return dwResult;
  237. }
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Member: CSyncMgrIdle::ReRegisterIdleDetection, public
  241. //
  242. // Synopsis: ReRegisters an existing callback with MSIdle. Currently MSIdle
  243. // only allows one idle registration per process. If a handler comes
  244. // along and also wants Idle they will remove our calback. Therefore
  245. // until MSIdle allows multiple registrations per process we
  246. // reregister for Idle after each handler is called.
  247. //
  248. // Arguments:
  249. //
  250. // Returns:
  251. //
  252. // Modifies:
  253. //
  254. // History: 01-April-98 rogerg Created.
  255. //
  256. //----------------------------------------------------------------------------
  257. DWORD CSyncMgrIdle::ReRegisterIdleDetection(CProgressDlg *pProgressDlg)
  258. {
  259. DWORD dwResult = 0;
  260. Assert(m_hInstMsIdleDll);
  261. // this funciton should only be called after we have already begun an existing Idle detection.
  262. // If IdleDetection if already off for any reason don't reregister.
  263. if (!m_hInstMsIdleDll || !m_fInBeginIdleDetection)
  264. {
  265. return -1;
  266. }
  267. Assert(g_SyncMgrIdle == this);
  268. Assert(m_pProgressDlg == pProgressDlg);
  269. g_SyncMgrIdle = this;
  270. m_pProgressDlg = pProgressDlg;
  271. m_pEndIdleDetection(0); // Review - Need to call EndIdleDetection or MSIdle.dll will leak WindowsHooks on NT 4.0.
  272. dwResult = m_pBeginIdleDetection(IdleCallback,30,0);
  273. if (0 != dwResult)
  274. {
  275. g_SyncMgrIdle = NULL;
  276. m_pProgressDlg = NULL;
  277. }
  278. else
  279. {
  280. m_pSetBusyNotify(TRUE,0);
  281. m_pSetIdleNotify(FALSE,0);
  282. }
  283. return dwResult;
  284. }
  285. //+---------------------------------------------------------------------------
  286. //
  287. // Member: CSyncMgrIdle::ResetIdle, public
  288. //
  289. // Synopsis: Resets the idle Counter.
  290. //
  291. // Arguments:
  292. //
  293. // Returns:
  294. //
  295. // Modifies:
  296. //
  297. // History: 23-Feb-98 rogerg Created.
  298. //
  299. //----------------------------------------------------------------------------
  300. DWORD CSyncMgrIdle::ResetIdle(ULONG ulIdleRetryMinutes)
  301. {
  302. Assert(ulIdleRetryMinutes);
  303. // assert we have a callback.
  304. Assert(g_SyncMgrIdle);
  305. Assert(m_pProgressDlg );
  306. Assert(0 == m_dwRegisteredTimer); // don't allow nested
  307. // if zero is passed in then set to an hour
  308. if (!ulIdleRetryMinutes)
  309. ulIdleRetryMinutes = 60;
  310. m_dwRegisteredTimer = SetTimer(NULL,0,1000*60*ulIdleRetryMinutes,(TIMERPROC) IdleOnTimerProc);
  311. return 0;
  312. }
  313. //+---------------------------------------------------------------------------
  314. //
  315. // Member: CSyncMgrIdle::OffIdle, public
  316. //
  317. // Synopsis: Gets Called when an OnIdle Occurs,.
  318. //
  319. // Arguments:
  320. //
  321. // Returns:
  322. //
  323. // Modifies:
  324. //
  325. // History: 23-Feb-98 rogerg Created.
  326. //
  327. //----------------------------------------------------------------------------
  328. void CSyncMgrIdle::OffIdle()
  329. {
  330. // when get an offIdle first thing revoke our Idle handlers
  331. if (g_SyncMgrIdle->m_dwRegisteredTimer)
  332. {
  333. KillTimer(0,g_SyncMgrIdle->m_dwRegisteredTimer);
  334. g_SyncMgrIdle->m_dwRegisteredTimer = 0;
  335. }
  336. Assert(m_fInBeginIdleDetection);
  337. if (m_fInBeginIdleDetection)
  338. {
  339. m_pEndIdleDetection(0);
  340. m_fInBeginIdleDetection = FALSE;
  341. g_SyncMgrIdle = NULL;
  342. }
  343. if (m_pProgressDlg)
  344. m_pProgressDlg->OffIdle();
  345. m_pProgressDlg = NULL;
  346. }
  347. //+---------------------------------------------------------------------------
  348. //
  349. // Member: CSyncMgrIdle::OnIdle, public
  350. //
  351. // Synopsis: Gets Called when an OffIdle Occurs,.
  352. //
  353. // Arguments:
  354. //
  355. // Returns:
  356. //
  357. // Modifies:
  358. //
  359. // History: 23-Feb-98 rogerg Created.
  360. //
  361. //----------------------------------------------------------------------------
  362. void CSyncMgrIdle::OnIdle()
  363. {
  364. if (m_pProgressDlg)
  365. m_pProgressDlg->OnIdle();
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Member: CSyncMgrIdle::CheckForIdle, public
  370. //
  371. // Synopsis: Gets Called by progress once in a while to make sure
  372. // an offIdle happened but our notification missed it.
  373. //
  374. // Arguments:
  375. //
  376. // Returns:
  377. //
  378. // Modifies:
  379. //
  380. // History: 23-Feb-98 rogerg Created.
  381. //
  382. //----------------------------------------------------------------------------
  383. void CSyncMgrIdle::CheckForIdle()
  384. {
  385. // currently don't do anything for this case. If we miss the off-Idle we
  386. // just continue. This function is a placeholder in case
  387. // we need to add this support.
  388. }
  389. //+---------------------------------------------------------------------------
  390. //
  391. // Member: CSyncMgrIdle::LoadMsIdle, private
  392. //
  393. // Synopsis: attempts to load the necessary msIdle exports.
  394. //
  395. // Arguments:
  396. //
  397. // Returns:
  398. //
  399. // Modifies:
  400. //
  401. // History: 23-Feb-98 rogerg Created.
  402. //
  403. //----------------------------------------------------------------------------
  404. BOOL CSyncMgrIdle::LoadMsIdle()
  405. {
  406. m_hInstMsIdleDll = LoadLibrary(szMsIdleDll);
  407. if (m_hInstMsIdleDll)
  408. {
  409. // for now, don't return an error is GetProc Fails but check in each function.
  410. m_pBeginIdleDetection = (_BEGINIDLEDETECTION)
  411. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) BEGINIDLEDETECTIONORD);
  412. m_pEndIdleDetection = (_ENDIDLEDETECTION)
  413. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) ENDIDLEDETECTIONORD);
  414. m_pGetIdleMinutes = (_GETIDLEMINUTES)
  415. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) GETIDLEMINUTESORD);
  416. m_pSetBusyNotify = (_SETBUSYNOTIFY)
  417. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETBUSYNOTIFYORD);
  418. m_pSetIdleNotify = (_SETIDLENOTIFY)
  419. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETIDLENOTIFYORD);
  420. m_pSetIdleTimeout = (_SETIDLETIMEOUT)
  421. GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETIDLETIMEOUTORD);
  422. }
  423. if (m_hInstMsIdleDll &&
  424. m_pBeginIdleDetection &&
  425. m_pEndIdleDetection &&
  426. m_pGetIdleMinutes &&
  427. m_pSetBusyNotify &&
  428. m_pSetIdleNotify &&
  429. m_pSetIdleTimeout
  430. )
  431. {
  432. return TRUE;
  433. }
  434. return FALSE;
  435. }