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.

229 lines
5.7 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997
  5. //
  6. // File: idle.cpp
  7. //
  8. // Contents: user idle detection
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 05-14-1997 darrenmi (Darren Mitchell) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "private.h"
  18. #include "throttle.h"
  19. typedef void (WINAPI* _IDLECALLBACK) (DWORD dwState);
  20. typedef DWORD (WINAPI* _BEGINIDLEDETECTION) (_IDLECALLBACK, DWORD, DWORD);
  21. typedef BOOL (WINAPI* _ENDIDLEDETECTION) (DWORD);
  22. #define TF_THISMODULE TF_WEBCHECKCORE
  23. HINSTANCE g_hinstMSIDLE = NULL;
  24. _BEGINIDLEDETECTION g_pfnBegin = NULL;
  25. _ENDIDLEDETECTION g_pfnEnd = NULL;
  26. //
  27. // extra stuff so we don't need msidle.dll on win95
  28. //
  29. BOOL g_fWin95PerfWin = FALSE; // using msidle.dll or not?
  30. UINT_PTR g_uIdleTimer = 0; // timer handle if not
  31. HANDLE g_hSageVxd = INVALID_HANDLE_VALUE; // vxd handle if not
  32. DWORD g_dwIdleMin = 3; // inactivity mins before idle
  33. BOOL g_fIdle = FALSE; // are we idle?
  34. DWORD g_dwIdleBeginTicks = 0; // when did idle begin?
  35. VOID CALLBACK OnIdleTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
  36. //
  37. // A little code copied from msidle.dll. We use this on Win95 with sage.vxd
  38. // so we don't have to load msidle.dll.
  39. //
  40. //
  41. // SetIdleTimer - decide how often to poll and set the timer appropriately
  42. //
  43. void SetIdleTimer(void)
  44. {
  45. UINT uInterval = 1000 * 60;
  46. //
  47. // If we're idle and looking for busy, check every 2 seconds
  48. //
  49. if(g_fIdle) {
  50. uInterval = 1000 * 4;
  51. }
  52. //
  53. // kill off the old timer
  54. //
  55. if(g_uIdleTimer) {
  56. KillTimer(NULL, g_uIdleTimer);
  57. }
  58. //
  59. // Set the timer
  60. //
  61. TraceMsg(TF_THISMODULE,"SetIdleTimer uInterval=%d", uInterval);
  62. g_uIdleTimer = SetTimer(NULL, 0, uInterval, OnIdleTimer);
  63. }
  64. //
  65. // OnIdleTimer - idle timer has gone off
  66. //
  67. VOID CALLBACK OnIdleTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  68. {
  69. DWORD dwDiff, dwLastActivityTicks;
  70. //
  71. // get last activity ticks from sage
  72. //
  73. DeviceIoControl(g_hSageVxd, 2, &dwLastActivityTicks, sizeof(DWORD),
  74. NULL, 0, NULL, NULL);
  75. //
  76. // check to see if we've changed state
  77. //
  78. if(g_fIdle) {
  79. //
  80. // currently in idle state
  81. //
  82. if(dwLastActivityTicks != g_dwIdleBeginTicks) {
  83. // activity since we became idle - stop being idle!
  84. g_fIdle = FALSE;
  85. // set timer
  86. SetIdleTimer();
  87. // call back client
  88. CThrottler::OnIdleStateChange(STATE_USER_IDLE_END);
  89. }
  90. } else {
  91. //
  92. // currently not in idle state
  93. //
  94. dwDiff = GetTickCount() - dwLastActivityTicks;
  95. if(dwDiff > 1000 * 60 * g_dwIdleMin) {
  96. // Nothing's happened for our threshold time. We're now idle.
  97. g_fIdle = TRUE;
  98. // save time we became idle
  99. g_dwIdleBeginTicks = dwLastActivityTicks;
  100. // set timer
  101. SetIdleTimer();
  102. // call back client
  103. CThrottler::OnIdleStateChange(STATE_USER_IDLE_BEGIN);
  104. }
  105. }
  106. }
  107. BOOL LoadSageVxd(void)
  108. {
  109. int inpVXD[3];
  110. if(INVALID_HANDLE_VALUE != g_hSageVxd)
  111. return TRUE;
  112. g_hSageVxd = CreateFile(TEXT("\\\\.\\sage.vxd"), 0, 0, NULL, 0,
  113. FILE_FLAG_DELETE_ON_CLOSE, NULL);
  114. // can't open it? can't use it
  115. if(INVALID_HANDLE_VALUE == g_hSageVxd)
  116. return FALSE;
  117. // start it monitoring
  118. inpVXD[0] = -1; // no window - will query
  119. inpVXD[1] = 0; // unused
  120. inpVXD[2] = 0; // post delay - not used without a window
  121. DeviceIoControl(g_hSageVxd, 1, &inpVXD, sizeof(inpVXD), NULL, 0, NULL, NULL);
  122. return TRUE;
  123. }
  124. BOOL UnloadSageVxd(void)
  125. {
  126. if(INVALID_HANDLE_VALUE != g_hSageVxd) {
  127. CloseHandle(g_hSageVxd);
  128. g_hSageVxd = INVALID_HANDLE_VALUE;
  129. }
  130. return TRUE;
  131. }
  132. void IdleBegin(HWND hwndParent)
  133. {
  134. DWORD dwValue;
  135. // Override idle minutes with reg value if present
  136. if(ReadRegValue(HKEY_CURRENT_USER,
  137. c_szRegKey,
  138. TEXT("IdleMinutes"),
  139. &dwValue,
  140. sizeof(DWORD)) &&
  141. dwValue) {
  142. g_dwIdleMin = dwValue;
  143. }
  144. if(FALSE == g_fIsWinNT && LoadSageVxd()) {
  145. // using optimal win95 configuration
  146. g_fWin95PerfWin = TRUE;
  147. SetIdleTimer();
  148. return;
  149. }
  150. // Bail out if the DebuggerFriendly registry value is set on NT4.
  151. OSVERSIONINFOA vi;
  152. vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
  153. GetVersionExA(&vi);
  154. if( vi.dwPlatformId == VER_PLATFORM_WIN32_NT
  155. && vi.dwMajorVersion == 4
  156. && ReadRegValue(HKEY_CURRENT_USER, c_szRegKey, TEXT("DebuggerFriendly"), &dwValue, sizeof(DWORD))
  157. && dwValue)
  158. {
  159. return;
  160. }
  161. // load msidle.dll
  162. g_hinstMSIDLE = LoadLibrary(TEXT("msidle.dll"));
  163. // get begin and end functions
  164. if(g_hinstMSIDLE) {
  165. g_pfnBegin = (_BEGINIDLEDETECTION)GetProcAddress(g_hinstMSIDLE, (LPSTR)3);
  166. g_pfnEnd = (_ENDIDLEDETECTION)GetProcAddress(g_hinstMSIDLE, (LPSTR)4);
  167. // call start monitoring
  168. if(g_pfnBegin)
  169. (g_pfnBegin)(CThrottler::OnIdleStateChange, g_dwIdleMin, 0);
  170. }
  171. }
  172. void IdleEnd(void)
  173. {
  174. if(g_fWin95PerfWin) {
  175. // clean up timer
  176. KillTimer(NULL, g_uIdleTimer);
  177. UnloadSageVxd();
  178. } else {
  179. // clean up msidle.dll
  180. if(g_pfnEnd) {
  181. (g_pfnEnd)(0);
  182. FreeLibrary(g_hinstMSIDLE);
  183. g_hinstMSIDLE = NULL;
  184. g_pfnBegin = NULL;
  185. g_pfnEnd = NULL;
  186. }
  187. }
  188. }