|
|
//+----------------------------------------------------------------------------
//
// Scheduling Agent Service
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: events.cxx
//
// Contents: Idle and battery event code.
//
// History: 22-Mar-96 EricB created
//
//-----------------------------------------------------------------------------
#include "..\pch\headers.hxx"
#pragma hdrstop
#include "globals.hxx"
#include "svc_core.hxx"
extern "C" { #include "msidle.h"
}
#define SCH_NOIDLE_VALUE TEXT("NoIdle")
BOOL g_fOnBattery; BOOL g_fIdleInitialized; HINSTANCE g_hMsidleDll = NULL;
//
// msidle.dll function pointers.
//
_BEGINIDLEDETECTION gpfnBeginIdleDetection; _ENDIDLEDETECTION gpfnEndIdleDetection; _SETIDLETIMEOUT gpfnSetIdleTimeout; _SETIDLENOTIFY gpfnSetIdleNotify; _SETBUSYNOTIFY gpfnSetBusyNotify; _GETIDLEMINUTES gpfnGetIdleMinutes;
//+----------------------------------------------------------------------------
//
// Function: OnIdleNotification
//
// Synopsis: Called when the winproc receives idle notifications.
//
// Arguments: [wParam] - indicates whether it is for idle start or end.
//
// Returns: hresults
//
//-----------------------------------------------------------------------------
void WINAPI OnIdleNotify(DWORD dwState) { switch (dwState) { case STATE_USER_IDLE_BEGIN: //
// Received idle notification.
//
if (g_pSched != NULL) { schDebugOut((DEB_ITRACE, "*** OnIdleNotification: entering idle state. ***\n")); g_pSched->OnIdleEvent(TRUE); } break;
case STATE_USER_IDLE_END: //
// Idle has ended.
//
if (g_pSched != NULL) { schDebugOut((DEB_ITRACE, "*** OnIdleNotification: idle lost. ***\n")); g_pSched->OnIdleEvent(FALSE); } break;
default: schAssert(0); break; } }
//+----------------------------------------------------------------------------
//
// Function: SetNextIdleNotificationFn
//
// Synopsis: Set the length of time to wait for the next idle notification.
//
// Returns: TRUE for success, and FALSE if unable to make the call.
//
//-----------------------------------------------------------------------------
BOOL SetNextIdleNotificationFn(WORD wIdleWait) { schDebugOut((DEB_ITRACE, "SetNextIdleNotification(%u)\n", wIdleWait));
if (!g_fIdleInitialized) { DBG_OUT("Calling SetNextIdleNotification before idle init!"); return FALSE; }
//
// 0xffff is a flag value meaning that no idle notification is needed.
//
if (wIdleWait == 0xffff) { schDebugOut((DEB_IDLE, "Next idle wait is 0xffff, not requesting" " idle notification\n")); //
// msidle.dll makes it impossible to turn off idle notification
// completely. SetIdleNotify(FALSE, 0) will do it temporarily,
// but if we have also registered for a loss-of-idle notification,
// then as soon as we get that notification, msidle.dll turns idle
// notification back on automatically.
// So we also set a long idle wait period.
// (It doesn't have to be 0xffff, but it might as well be)
//
gpfnSetIdleTimeout(0xffff, 0); gpfnSetIdleNotify(FALSE, 0); return FALSE; }
schAssert(wIdleWait != 0); schDebugOut((DEB_IDLE, "Requesting %u-minute idle notification\n", wIdleWait));
gpfnSetIdleTimeout(wIdleWait, 0); gpfnSetIdleNotify(TRUE, 0);
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: SetIdleLossNotificationFn
//
// Synopsis: Registers for idle loss notification.
//
// Returns: TRUE for success, and FALSE if unable to make the call.
//
//-----------------------------------------------------------------------------
BOOL SetIdleLossNotificationFn() { schDebugOut((DEB_ITRACE, "SetIdleLossNotification()\n"));
if (!g_fIdleInitialized) { DBG_OUT("Calling SetIdleLossNotification before idle init!"); return FALSE; }
schDebugOut((DEB_IDLE, "Requesting idle LOSS notification\n")); gpfnSetBusyNotify(TRUE, 0);
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: GetTimeIdle
//
// Synopsis: Obtains the length of time the machine has been idle.
//
//-----------------------------------------------------------------------------
DWORD GetTimeIdle(void) { DWORD dwMinutes;
if (!g_fIdleInitialized) { DBG_OUT("Calling GetTimeIdle before idle init!"); dwMinutes = 0; } else { dwMinutes = gpfnGetIdleMinutes(0); }
schDebugOut((DEB_IDLE, "User has been idle for %u minutes\n", dwMinutes));
return dwMinutes; }
//+----------------------------------------------------------------------------
//
// Function: OnPowerChange
//
// Synopsis: Called when the machine's battery state changes.
//
// Arguments: [fGoingOnBattery] - set to true if going on battery power,
// false if going back on line power.
//
// Returns: hresults
//
//-----------------------------------------------------------------------------
HRESULT OnPowerChange(BOOL fGoingOnBattery) { schDebugOut((DEB_ITRACE, "OnPowerChange: fGoingOnBattery = %s\n", (fGoingOnBattery) ? "TRUE" : "FALSE"));
//
// Check to see if our battery state has changed, or if this is just
// a battery update
//
if (g_fOnBattery != fGoingOnBattery) { g_fOnBattery = fGoingOnBattery; //
// Signal the main thread to recalculate the next wakeup time, since
// the calculation depends on whether the machine is on batteries.
// Do this by simply signaling the wakeup timer. This will cause a
// recalc.
//
g_pSched->SignalWakeupTimer(); if (fGoingOnBattery) { //
// Notify the job processor to kill any jobs with the
// TASK_FLAG_KILL_IF_GOING_ON_BATTERIES flag set.
//
CJobProcessor * pjp; for (pjp = gpJobProcessorMgr->GetFirstProcessor(); pjp != NULL; ) { pjp->KillIfFlagSet(TASK_FLAG_KILL_IF_GOING_ON_BATTERIES); CJobProcessor * pjpNext = pjp->Next(); pjp->Release(); pjp = pjpNext; } } } return S_OK; }
//+----------------------------------------------------------------------------
//
// Function: InitBatteryNotification
//
// Synopsis: Initialize the battery event boolean.
//
// Returns: hresults
//
// Notes: Currently only Win95 supports power management.
//
//-----------------------------------------------------------------------------
HRESULT InitBatteryNotification(void) { DWORD dwErr;
//
// Check current battery state and set bool accordingly.
//
SYSTEM_POWER_STATUS PwrStatus;
if (!GetSystemPowerStatus(&PwrStatus)) { dwErr = GetLastError();
if (dwErr == ERROR_FILE_NOT_FOUND || dwErr == ERROR_CALL_NOT_IMPLEMENTED) { g_fOnBattery = FALSE; schDebugOut((DEB_ITRACE, "InitBatteryNotification: GetSystemPowerStatus" " returned %u, g_fOnBattery set to FALSE\n", dwErr)); return S_OK; } ERR_OUT("GetSystemPowerStatus", HRESULT_FROM_WIN32(dwErr)); return HRESULT_FROM_WIN32(dwErr); }
g_fOnBattery = (PwrStatus.ACLineStatus == 0) ? TRUE : FALSE;
schDebugOut((DEB_ITRACE, "InitBatteryNotification: g_fOnBattery = %s\n", (g_fOnBattery) ? "TRUE" : "FALSE")); return S_OK; }
//+----------------------------------------------------------------------------
//
// Function: InitIdleDetection
//
// Synopsis: Called after the message window is created to initialize idle
// detection and hot corners.
//
// Arguments:
//
// Returns: hresults
//
//-----------------------------------------------------------------------------
HRESULT InitIdleDetection() { TRACE_FUNCTION(InitIdleDetection); DWORD dwErr;
//
// Look in the registry to see if idle detection is disabled.
//
long lErr; HKEY hSchedKey = NULL; lErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SCH_AGENT_KEY, 0, KEY_READ, &hSchedKey); if (lErr == ERROR_SUCCESS) { TCHAR tszInit[SCH_MED0BUF_LEN + 1]; DWORD cb = SCH_MED0BUF_LEN * sizeof(TCHAR);
lErr = RegQueryValueEx(hSchedKey, SCH_NOIDLE_VALUE, NULL, NULL, (LPBYTE)tszInit, &cb);
RegCloseKey(hSchedKey);
if (lErr == ERROR_SUCCESS) { //
// The presence of the value is sufficient to disable idle
// detection. g_fIdleInitialized will remain FALSE, resulting
// in all idle operations being skipped.
//
schDebugOut((DEB_ITRACE, "Idle detection is disabled!!!!!!!!\n")); return S_OK; } }
// load msidle.dll
if (g_hMsidleDll == NULL) { g_hMsidleDll = LoadLibrary(TEXT("MSIDLE.DLL"));
if (g_hMsidleDll == NULL) { dwErr = GetLastError(); ERR_OUT("Load of msidle.dll", dwErr); return HRESULT_FROM_WIN32(dwErr); } }
// get entry points
gpfnBeginIdleDetection = (_BEGINIDLEDETECTION) GetProcAddress(g_hMsidleDll, (LPSTR)3); gpfnEndIdleDetection = (_ENDIDLEDETECTION) GetProcAddress(g_hMsidleDll, (LPSTR)4); gpfnSetIdleTimeout = (_SETIDLETIMEOUT) GetProcAddress(g_hMsidleDll, (LPSTR)5); gpfnSetIdleNotify = (_SETIDLENOTIFY) GetProcAddress(g_hMsidleDll, (LPSTR)6); gpfnSetBusyNotify = (_SETBUSYNOTIFY) GetProcAddress(g_hMsidleDll, (LPSTR)7); gpfnGetIdleMinutes = (_GETIDLEMINUTES) GetProcAddress(g_hMsidleDll, (LPSTR)8);
if (gpfnBeginIdleDetection == NULL || gpfnEndIdleDetection == NULL || gpfnSetIdleTimeout == NULL || gpfnSetIdleNotify == NULL || gpfnSetBusyNotify == NULL || gpfnGetIdleMinutes == NULL) { dwErr = GetLastError(); ERR_OUT("Getting msidle.dll entry point addresses", dwErr); goto ErrExit; }
// call start monitoring
dwErr = gpfnBeginIdleDetection(OnIdleNotify, SCH_DEFAULT_IDLE_TIME, 0); if (dwErr) { ERR_OUT("Making initial idle call", dwErr); goto ErrExit; }
g_fIdleInitialized = TRUE;
return S_OK;
ErrExit:
FreeLibrary(g_hMsidleDll); g_hMsidleDll = NULL; gpfnBeginIdleDetection = NULL; gpfnEndIdleDetection = NULL; gpfnSetIdleTimeout = NULL; gpfnSetIdleNotify = NULL; gpfnSetBusyNotify = NULL; gpfnGetIdleMinutes = NULL;
return HRESULT_FROM_WIN32(dwErr); }
//+----------------------------------------------------------------------------
//
// Function: EndIdleDetection
//
// Synopsis: Stop idle detection.
//
// Arguments: None.
//
//-----------------------------------------------------------------------------
void EndIdleDetection() { if (gpfnEndIdleDetection != NULL) { gpfnEndIdleDetection(0); } }
|