windows-nt/Source/XPSP1/NT/shell/ext/webcheck/idle.cpp
2020-09-26 16:20:57 +08:00

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;
}
}
}