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.

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