|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: idle.cpp
//
// Contents: Idle notification routines.
//
// Classes:
//
// Notes:
//
// History: 23-Feb-98 rogerg Created.
//
//--------------------------------------------------------------------------
#include "precomp.h"
// msidle DLL and function strings
STRING_FILENAME(szMsIdleDll, "MsIdle.dll");
#define BEGINIDLEDETECTIONORD 3
#define ENDIDLEDETECTIONORD 4
#define SETIDLETIMEOUTORD 5
#define SETIDLENOTIFYORD 6
#define SETBUSYNOTIFYORD 7
#define GETIDLEMINUTESORD 8
CSyncMgrIdle *g_SyncMgrIdle = NULL; // idle that has a current callback.
//+---------------------------------------------------------------------------
//
// Member: IdleCallback, private
//
// Synopsis: callback function for Idle, Only one idle registration
// is allowed per SyncMgrInstance.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
void WINAPI IdleCallback(DWORD dwState) { if (STATE_USER_IDLE_END == dwState) { if (g_SyncMgrIdle) { g_SyncMgrIdle->m_fReceivedOffIdle = TRUE;
// if we have a registered timer for reset Idle remove it.
if (g_SyncMgrIdle->m_dwRegisteredTimer) { KillTimer(0,g_SyncMgrIdle->m_dwRegisteredTimer); }
g_SyncMgrIdle->m_pSetBusyNotify(FALSE,0); // only allow one busy to come through
g_SyncMgrIdle->m_pSetIdleNotify(FALSE,0); // don't allow an Idle through after get a busy.
g_SyncMgrIdle->OffIdle(); } } }
//+---------------------------------------------------------------------------
//
// Member: TimerCallback, private
//
// Synopsis: callback function for Timer when minutes have passed
// for when to restart the Idle.
//
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
VOID CALLBACK IdleOnTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime) { if (g_SyncMgrIdle && !g_SyncMgrIdle->m_fReceivedOffIdle) { DWORD_PTR dwRegTimer = g_SyncMgrIdle->m_dwRegisteredTimer;
g_SyncMgrIdle->m_dwRegisteredTimer = 0; KillTimer(0,dwRegTimer); g_SyncMgrIdle->OnIdle(); } }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::CSyncMgrIdle, public
//
// Synopsis: Constructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
CSyncMgrIdle::CSyncMgrIdle() { m_hInstMsIdleDll = NULL; m_pBeginIdleDetection = NULL; m_pEndIdleDetection = NULL; m_pGetIdleMinutes = NULL; m_pSetBusyNotify = NULL; m_pSetIdleNotify = NULL; m_pSetIdleTimeout = NULL; m_pProgressDlg = NULL; m_dwRegisteredTimer = NULL; m_fInBeginIdleDetection = FALSE; m_fReceivedOffIdle = FALSE;
Assert(NULL == g_SyncMgrIdle); // make sure another idle doesn't exist
}
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::~CSyncMgrIdle, public
//
// Synopsis: destructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
CSyncMgrIdle::~CSyncMgrIdle() { if (m_dwRegisteredTimer) // remove our timer.
{ KillTimer(0,m_dwRegisteredTimer); }
// if we are in an idle detection then first remove it.
if (m_fInBeginIdleDetection) { m_pEndIdleDetection(0); m_pProgressDlg = NULL; g_SyncMgrIdle = NULL; } else { Assert(NULL == m_pProgressDlg); Assert(NULL == g_SyncMgrIdle); }
// if have the dll then free it.
if (m_hInstMsIdleDll) { FreeLibrary(m_hInstMsIdleDll); } }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::Initialize, public
//
// Synopsis: Initializes class, must be called before any other member.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
BOOL CSyncMgrIdle::Initialize() { return LoadMsIdle(); }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::BeginIdleDetection, public
//
// Synopsis: Registers the callback with msidle.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
DWORD CSyncMgrIdle::BeginIdleDetection(CProgressDlg *pProgressDlg,DWORD dwIdleMin, DWORD dwReserved) { DWORD dwResult = 0;
Assert(m_hInstMsIdleDll);
if (!m_hInstMsIdleDll) { return -1; }
// if there is already an idle registered
// assert it is the same as what is trying to get registered
// now and return
Assert(FALSE == m_fInBeginIdleDetection);
if (m_fInBeginIdleDetection) { Assert(g_SyncMgrIdle == this); Assert(m_pProgressDlg == pProgressDlg); return 0; }
Assert(NULL == g_SyncMgrIdle); // should not still be another Idle.
g_SyncMgrIdle = this; m_pProgressDlg = pProgressDlg;
dwResult = m_pBeginIdleDetection(IdleCallback,30,0);
if (dwResult) { g_SyncMgrIdle = NULL; m_pProgressDlg = NULL; } else { m_pSetBusyNotify(TRUE,0); m_pSetIdleNotify(FALSE,0);
m_fInBeginIdleDetection = TRUE; }
return dwResult; }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::ReRegisterIdleDetection, public
//
// Synopsis: ReRegisters an existing callback with MSIdle. Currently MSIdle
// only allows one idle registration per process. If a handler comes
// along and also wants Idle they will remove our calback. Therefore
// until MSIdle allows multiple registrations per process we
// reregister for Idle after each handler is called.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 01-April-98 rogerg Created.
//
//----------------------------------------------------------------------------
DWORD CSyncMgrIdle::ReRegisterIdleDetection(CProgressDlg *pProgressDlg) { DWORD dwResult = 0;
Assert(m_hInstMsIdleDll);
// this funciton should only be called after we have already begun an existing Idle detection.
// If IdleDetection if already off for any reason don't reregister.
if (!m_hInstMsIdleDll || !m_fInBeginIdleDetection) { return -1; }
Assert(g_SyncMgrIdle == this); Assert(m_pProgressDlg == pProgressDlg);
g_SyncMgrIdle = this; m_pProgressDlg = pProgressDlg;
m_pEndIdleDetection(0); // Review - Need to call EndIdleDetection or MSIdle.dll will leak WindowsHooks on NT 4.0.
dwResult = m_pBeginIdleDetection(IdleCallback,30,0);
if (dwResult) { g_SyncMgrIdle = NULL; m_pProgressDlg = NULL; } else { m_pSetBusyNotify(TRUE,0); m_pSetIdleNotify(FALSE,0); }
return dwResult; }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::ResetIdle, public
//
// Synopsis: Resets the idle Counter.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
DWORD CSyncMgrIdle::ResetIdle(ULONG ulIdleRetryMinutes) { Assert(ulIdleRetryMinutes);
// assert we have a callback.
Assert(g_SyncMgrIdle); Assert(m_pProgressDlg );
Assert(0 == m_dwRegisteredTimer); // don't allow nested
// if zero is passed in then set to an hour
if (!ulIdleRetryMinutes) ulIdleRetryMinutes = 60;
m_dwRegisteredTimer = SetTimer(NULL, 0, 1000*60*ulIdleRetryMinutes, (TIMERPROC) IdleOnTimerProc);
return 0; }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::OffIdle, public
//
// Synopsis: Gets Called when an OnIdle Occurs,.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
void CSyncMgrIdle::OffIdle() { // when get an offIdle first thing revoke our Idle handlers
if (g_SyncMgrIdle->m_dwRegisteredTimer) { KillTimer(0, g_SyncMgrIdle->m_dwRegisteredTimer); g_SyncMgrIdle->m_dwRegisteredTimer = 0; }
Assert(m_fInBeginIdleDetection);
if (m_fInBeginIdleDetection) { m_pEndIdleDetection(0); m_fInBeginIdleDetection = FALSE; g_SyncMgrIdle = NULL; }
if (m_pProgressDlg) m_pProgressDlg->OffIdle();
m_pProgressDlg = NULL; }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::OnIdle, public
//
// Synopsis: Gets Called when an OffIdle Occurs,.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
void CSyncMgrIdle::OnIdle() { if (m_pProgressDlg) m_pProgressDlg->OnIdle(); }
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::CheckForIdle, public
//
// Synopsis: Gets Called by progress once in a while to make sure
// an offIdle happened but our notification missed it.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
void CSyncMgrIdle::CheckForIdle() {
// currently don't do anything for this case. If we miss the off-Idle we
// just continue. This function is a placeholder in case
// we need to add this support.
}
//+---------------------------------------------------------------------------
//
// Member: CSyncMgrIdle::LoadMsIdle, private
//
// Synopsis: attempts to load the necessary msIdle exports.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 23-Feb-98 rogerg Created.
//
//----------------------------------------------------------------------------
BOOL CSyncMgrIdle::LoadMsIdle() { TCHAR szFullPath[MAX_PATH+1];
*szFullPath = 0; if (GetSystemDirectory(szFullPath, ARRAYSIZE(szFullPath))) { if (!PathAppend(szFullPath, szMsIdleDll)) { *szFullPath = 0; } szFullPath[MAX_PATH] = 0; // Ensure NULL termination
}
if (!*szFullPath) { StringCchCopy(szFullPath, ARRAYSIZE(szFullPath), szMsIdleDll); }
m_hInstMsIdleDll = LoadLibrary(szFullPath);
if (m_hInstMsIdleDll) { // for now, don't return an error is GetProc Fails but check in each function.
m_pBeginIdleDetection = (_BEGINIDLEDETECTION) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) BEGINIDLEDETECTIONORD);
m_pEndIdleDetection = (_ENDIDLEDETECTION) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) ENDIDLEDETECTIONORD);
m_pGetIdleMinutes = (_GETIDLEMINUTES) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) GETIDLEMINUTESORD);
m_pSetBusyNotify = (_SETBUSYNOTIFY) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETBUSYNOTIFYORD);
m_pSetIdleNotify = (_SETIDLENOTIFY) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETIDLENOTIFYORD);
m_pSetIdleTimeout = (_SETIDLETIMEOUT) GetProcAddress(m_hInstMsIdleDll, (LPCSTR) SETIDLETIMEOUTORD); }
if (m_hInstMsIdleDll && m_pBeginIdleDetection && m_pEndIdleDetection && m_pGetIdleMinutes && m_pSetBusyNotify && m_pSetIdleNotify && m_pSetIdleTimeout ) { return TRUE; }
return FALSE; }
|