windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/exe/idle.cpp
2020-09-26 16:20:57 +08:00

542 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// 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();
}
}
/*
User the TimerProc instead.
else if (STATE_USER_IDLE_BEGIN == dwState)
{
// On an Idle Begin just send another Idle.
if (g_SyncMgrIdle)
{
g_SyncMgrIdle->m_pSetIdleNotify(FALSE,0);
g_SyncMgrIdle->OnIdle();
}
}
*/
}
//+---------------------------------------------------------------------------
//
// 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 (0 != 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 (0 != 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()
{
m_hInstMsIdleDll = LoadLibrary(szMsIdleDll);
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;
}