230 lines
5.7 KiB
C++
230 lines
5.7 KiB
C++
//----------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997
|
|
//
|
|
// File: idle.cpp
|
|
//
|
|
// Contents: user idle detection
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 05-14-1997 darrenmi (Darren Mitchell) Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "private.h"
|
|
#include "throttle.h"
|
|
|
|
typedef void (WINAPI* _IDLECALLBACK) (DWORD dwState);
|
|
typedef DWORD (WINAPI* _BEGINIDLEDETECTION) (_IDLECALLBACK, DWORD, DWORD);
|
|
typedef BOOL (WINAPI* _ENDIDLEDETECTION) (DWORD);
|
|
|
|
#define TF_THISMODULE TF_WEBCHECKCORE
|
|
|
|
HINSTANCE g_hinstMSIDLE = NULL;
|
|
_BEGINIDLEDETECTION g_pfnBegin = NULL;
|
|
_ENDIDLEDETECTION g_pfnEnd = NULL;
|
|
|
|
//
|
|
// extra stuff so we don't need msidle.dll on win95
|
|
//
|
|
BOOL g_fWin95PerfWin = FALSE; // using msidle.dll or not?
|
|
UINT_PTR g_uIdleTimer = 0; // timer handle if not
|
|
HANDLE g_hSageVxd = INVALID_HANDLE_VALUE; // vxd handle if not
|
|
DWORD g_dwIdleMin = 3; // inactivity mins before idle
|
|
BOOL g_fIdle = FALSE; // are we idle?
|
|
DWORD g_dwIdleBeginTicks = 0; // when did idle begin?
|
|
|
|
VOID CALLBACK OnIdleTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
|
|
|
|
//
|
|
// A little code copied from msidle.dll. We use this on Win95 with sage.vxd
|
|
// so we don't have to load msidle.dll.
|
|
//
|
|
|
|
//
|
|
// SetIdleTimer - decide how often to poll and set the timer appropriately
|
|
//
|
|
void SetIdleTimer(void)
|
|
{
|
|
UINT uInterval = 1000 * 60;
|
|
|
|
//
|
|
// If we're idle and looking for busy, check every 2 seconds
|
|
//
|
|
if(g_fIdle) {
|
|
uInterval = 1000 * 4;
|
|
}
|
|
|
|
//
|
|
// kill off the old timer
|
|
//
|
|
if(g_uIdleTimer) {
|
|
KillTimer(NULL, g_uIdleTimer);
|
|
}
|
|
|
|
//
|
|
// Set the timer
|
|
//
|
|
TraceMsg(TF_THISMODULE,"SetIdleTimer uInterval=%d", uInterval);
|
|
g_uIdleTimer = SetTimer(NULL, 0, uInterval, OnIdleTimer);
|
|
}
|
|
|
|
//
|
|
// OnIdleTimer - idle timer has gone off
|
|
//
|
|
VOID CALLBACK OnIdleTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
|
{
|
|
DWORD dwDiff, dwLastActivityTicks;
|
|
|
|
//
|
|
// get last activity ticks from sage
|
|
//
|
|
DeviceIoControl(g_hSageVxd, 2, &dwLastActivityTicks, sizeof(DWORD),
|
|
NULL, 0, NULL, NULL);
|
|
|
|
//
|
|
// check to see if we've changed state
|
|
//
|
|
if(g_fIdle) {
|
|
//
|
|
// currently in idle state
|
|
//
|
|
if(dwLastActivityTicks != g_dwIdleBeginTicks) {
|
|
// activity since we became idle - stop being idle!
|
|
g_fIdle = FALSE;
|
|
|
|
// set timer
|
|
SetIdleTimer();
|
|
|
|
// call back client
|
|
CThrottler::OnIdleStateChange(STATE_USER_IDLE_END);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// currently not in idle state
|
|
//
|
|
dwDiff = GetTickCount() - dwLastActivityTicks;
|
|
|
|
if(dwDiff > 1000 * 60 * g_dwIdleMin) {
|
|
// Nothing's happened for our threshold time. We're now idle.
|
|
g_fIdle = TRUE;
|
|
|
|
// save time we became idle
|
|
g_dwIdleBeginTicks = dwLastActivityTicks;
|
|
|
|
// set timer
|
|
SetIdleTimer();
|
|
|
|
// call back client
|
|
CThrottler::OnIdleStateChange(STATE_USER_IDLE_BEGIN);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL LoadSageVxd(void)
|
|
{
|
|
int inpVXD[3];
|
|
|
|
if(INVALID_HANDLE_VALUE != g_hSageVxd)
|
|
return TRUE;
|
|
|
|
g_hSageVxd = CreateFile(TEXT("\\\\.\\sage.vxd"), 0, 0, NULL, 0,
|
|
FILE_FLAG_DELETE_ON_CLOSE, NULL);
|
|
|
|
// can't open it? can't use it
|
|
if(INVALID_HANDLE_VALUE == g_hSageVxd)
|
|
return FALSE;
|
|
|
|
// start it monitoring
|
|
inpVXD[0] = -1; // no window - will query
|
|
inpVXD[1] = 0; // unused
|
|
inpVXD[2] = 0; // post delay - not used without a window
|
|
|
|
DeviceIoControl(g_hSageVxd, 1, &inpVXD, sizeof(inpVXD), NULL, 0, NULL, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL UnloadSageVxd(void)
|
|
{
|
|
if(INVALID_HANDLE_VALUE != g_hSageVxd) {
|
|
CloseHandle(g_hSageVxd);
|
|
g_hSageVxd = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void IdleBegin(HWND hwndParent)
|
|
{
|
|
DWORD dwValue;
|
|
|
|
// Override idle minutes with reg value if present
|
|
if(ReadRegValue(HKEY_CURRENT_USER,
|
|
c_szRegKey,
|
|
TEXT("IdleMinutes"),
|
|
&dwValue,
|
|
sizeof(DWORD)) &&
|
|
dwValue) {
|
|
|
|
g_dwIdleMin = dwValue;
|
|
}
|
|
|
|
if(FALSE == g_fIsWinNT && LoadSageVxd()) {
|
|
// using optimal win95 configuration
|
|
g_fWin95PerfWin = TRUE;
|
|
SetIdleTimer();
|
|
return;
|
|
}
|
|
|
|
// Bail out if the DebuggerFriendly registry value is set on NT4.
|
|
OSVERSIONINFOA vi;
|
|
vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
|
GetVersionExA(&vi);
|
|
|
|
if( vi.dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& vi.dwMajorVersion == 4
|
|
&& ReadRegValue(HKEY_CURRENT_USER, c_szRegKey, TEXT("DebuggerFriendly"), &dwValue, sizeof(DWORD))
|
|
&& dwValue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
// load msidle.dll
|
|
g_hinstMSIDLE = LoadLibrary(TEXT("msidle.dll"));
|
|
|
|
// get begin and end functions
|
|
if(g_hinstMSIDLE) {
|
|
g_pfnBegin = (_BEGINIDLEDETECTION)GetProcAddress(g_hinstMSIDLE, (LPSTR)3);
|
|
g_pfnEnd = (_ENDIDLEDETECTION)GetProcAddress(g_hinstMSIDLE, (LPSTR)4);
|
|
|
|
// call start monitoring
|
|
if(g_pfnBegin)
|
|
(g_pfnBegin)(CThrottler::OnIdleStateChange, g_dwIdleMin, 0);
|
|
}
|
|
}
|
|
|
|
void IdleEnd(void)
|
|
{
|
|
if(g_fWin95PerfWin) {
|
|
// clean up timer
|
|
KillTimer(NULL, g_uIdleTimer);
|
|
UnloadSageVxd();
|
|
} else {
|
|
// clean up msidle.dll
|
|
if(g_pfnEnd) {
|
|
(g_pfnEnd)(0);
|
|
FreeLibrary(g_hinstMSIDLE);
|
|
g_hinstMSIDLE = NULL;
|
|
g_pfnBegin = NULL;
|
|
g_pfnEnd = NULL;
|
|
}
|
|
}
|
|
}
|