|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/
/*
svcctrl.cpp Implementation for the dialog that pops up while waiting for the server to start. FILE HISTORY: */
#include "stdafx.h"
#include "cluster.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CServiceCtrlDlg dialog
CServiceCtrlDlg::CServiceCtrlDlg ( SC_HANDLE hService, LPCTSTR pServerName, LPCTSTR pszServiceDesc, BOOL bStart, CWnd* pParent /*=NULL*/ ) : CDialog(CServiceCtrlDlg::IDD, pParent) { //{{AFX_DATA_INIT(CServiceCtrlDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_hService = hService; m_hResource = NULL; m_nTickCounter = TIMER_MULT; m_nTotalTickCount = 0; m_strServerName = pServerName; m_strServerName.MakeUpper(); m_strServiceDesc = pszServiceDesc; m_bStart = bStart; m_timerId = 0; m_dwErr = 0; m_dwLastCheckPoint = -1; }
CServiceCtrlDlg::CServiceCtrlDlg ( HRESOURCE hResource, LPCTSTR pServerName, LPCTSTR pszServiceDesc, BOOL bStart, CWnd* pParent /*=NULL*/ ) : CDialog(CServiceCtrlDlg::IDD, pParent) { //{{AFX_DATA_INIT(CServiceCtrlDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_hService = NULL; m_hResource = hResource; m_nTickCounter = TIMER_MULT; m_nTotalTickCount = 0; m_strServerName = pServerName; m_strServerName.MakeUpper(); m_strServiceDesc = pszServiceDesc; m_bStart = bStart; m_timerId = 0; m_dwErr = 0; m_dwLastCheckPoint = -1; }
void CServiceCtrlDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServiceCtrlDlg)
DDX_Control(pDX, IDC_STATIC_MESSAGE, m_staticMessage); DDX_Control(pDX, IDC_ICON_PROGRESS, m_iconProgress); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CServiceCtrlDlg, CDialog) //{{AFX_MSG_MAP(CServiceCtrlDlg)
ON_WM_TIMER() ON_WM_CLOSE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServiceCtrlDlg message handlers
BOOL CServiceCtrlDlg::OnInitDialog() { CDialog::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_timerId = SetTimer(TIMER_ID, TIMER_FREQ, NULL);
CString strTemp; CString strTitle; UINT idsTitle; if (m_bStart) { AfxFormatString2(strTemp, IDS_STARTING_SERVICE_NOW, m_strServerName, m_strServiceDesc); idsTitle = IDS_START_SERVICE_TITLE; } else { AfxFormatString2(strTemp, IDS_STOPPING_SERVICE_NOW, m_strServerName, m_strServiceDesc); idsTitle = IDS_STOP_SERVICE_TITLE; }
m_staticMessage.SetWindowText(strTemp);
// Setup the title of the window
strTitle.Format(idsTitle, (LPCTSTR) m_strServiceDesc); SetWindowText(strTitle);
UpdateIndicator();
m_dwTickBegin = GetTickCount();
if (m_hService) { // get the wait period
SERVICE_STATUS serviceStatus; ::ZeroMemory(&serviceStatus, sizeof(serviceStatus));
if (QueryServiceStatus(m_hService, &serviceStatus)) { m_dwWaitPeriod = serviceStatus.dwWaitHint; } } else { GetClusterResourceTimeout(); }
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CServiceCtrlDlg::OnClose() { if (m_timerId) KillTimer(m_timerId); CDialog::OnClose(); }
void CServiceCtrlDlg::OnTimer(UINT nIDEvent) { //
// Bag-out if it's not our timer.
//
if(nIDEvent != TIMER_ID) { return; }
//
// Advance the progress indicator.
//
UpdateIndicator();
//
// No need to continue if we're just amusing the user.
//
if(--m_nTickCounter > 0) { return; }
m_nTickCounter = TIMER_MULT;
//
// Poll the service to see if the operation is
// either complete or continuing as expected.
//
if (m_hService) { CheckService(); } else { CheckClusterService(); }
}
void CServiceCtrlDlg::GetClusterResourceTimeout() { DWORD dwError = 0; DWORD cPropListSize = 0; DWORD cPropListAlloc = MAX_NAME_SIZE; DWORD dwPendingTimeout = 0;
// set the default
m_dwWaitPeriod = 18000;
if ( !g_ClusDLL.LoadFunctionPointers() ) return;
if ( !g_ResUtilsDLL.LoadFunctionPointers() ) return;
PCLUSPROP_LIST pPropList = (PCLUSPROP_LIST)LocalAlloc(LPTR, MAX_NAME_SIZE);
//
// get the wait timeout value
//
dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( m_hResource, NULL, CLUSCTL_RESOURCE_GET_COMMON_PROPERTIES, NULL, 0, pPropList, cPropListAlloc, &cPropListSize); //
// Reallocation routine if pPropList is too small
//
if ( dwError == ERROR_MORE_DATA ) { LocalFree( pPropList );
cPropListAlloc = cPropListSize;
pPropList = (PCLUSPROP_LIST) LocalAlloc( LPTR, cPropListAlloc );
dwError = ((CLUSTERRESOURCECONTROL) g_ClusDLL[CLUS_CLUSTER_RESOURCE_CONTROL])( m_hResource, NULL, CLUSCTL_RESOURCE_GET_COMMON_PROPERTIES, NULL, 0, pPropList, cPropListAlloc, &cPropListSize); }
//
// find the pending timeout property
//
dwError = ((RESUTILSFINDDWORDPROPERTY) g_ResUtilsDLL[RESUTILS_FIND_DWORD_PROPERTY])(pPropList, cPropListSize, _T("PendingTimeout"), &dwPendingTimeout);
if (dwError == ERROR_SUCCESS) { m_dwWaitPeriod = dwPendingTimeout; }
LocalFree( pPropList ); }
BOOL CServiceCtrlDlg::CheckForError(SERVICE_STATUS * pServiceStats) { BOOL fError = FALSE;
DWORD dwTickCurrent = GetTickCount();
if (pServiceStats->dwCheckPoint == 0) { // the service is in some state, not pending anything.
// before calling this function the code should check to see if
// the service is in the correct state. This means it is in
// some unexpected state.
fError = TRUE; } else if ((dwTickCurrent - m_dwTickBegin) > m_dwWaitPeriod) { // ok to check the dwCheckPoint field to see if
// everything is going ok
if (m_dwLastCheckPoint == -1) { m_dwLastCheckPoint = pServiceStats->dwCheckPoint; } else { if (m_dwLastCheckPoint >= pServiceStats->dwCheckPoint) { fError = TRUE; } }
m_dwLastCheckPoint = pServiceStats->dwCheckPoint; m_dwTickBegin = dwTickCurrent; m_dwWaitPeriod = pServiceStats->dwWaitHint; }
return fError; }
BOOL CServiceCtrlDlg::CheckForClusterError(SERVICE_STATUS * pServiceStats) { BOOL fError = FALSE;
DWORD dwTickCurrent = GetTickCount();
if ((dwTickCurrent - m_dwTickBegin) > m_dwWaitPeriod) { // ok to check the dwCheckPoint field to see if
// everything is going ok
if (m_dwLastCheckPoint == -1) { m_dwLastCheckPoint = pServiceStats->dwCheckPoint; } else { if (m_dwLastCheckPoint >= pServiceStats->dwCheckPoint) { fError = TRUE; } }
m_dwLastCheckPoint = pServiceStats->dwCheckPoint; m_dwTickBegin = dwTickCurrent; m_dwWaitPeriod = pServiceStats->dwWaitHint; }
return fError; }
void CServiceCtrlDlg::UpdateIndicator() { AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_nTotalTickCount % (1000 / TIMER_FREQ) == 0) { int nTempTickCount = m_nTotalTickCount / (1000 / TIMER_FREQ); HICON hIcon;
hIcon = AfxGetApp()->LoadIcon(IDI_PROGRESS_ICON_0 + (nTempTickCount % PROGRESS_ICON_COUNT)); m_iconProgress.SetIcon(hIcon); } m_nTotalTickCount++; }
void CServiceCtrlDlg::CheckService() { SERVICE_STATUS serviceStatus;
::ZeroMemory(&serviceStatus, sizeof(serviceStatus));
if (!QueryServiceStatus(m_hService, &serviceStatus)) { //
// Either an error occurred retrieving the
// service status OR the service is returning
// bogus state information.
//
CDialog::OnOK(); }
// If the dwCheckpoint value is 0, then there is no start/stop/pause
// or continue action pending (in which case we can exit no matter
// what happened).
if (m_bStart) { if (serviceStatus.dwCurrentState == SERVICE_RUNNING) { //
// The operation is complete.
//
CDialog::OnOK(); } else { if (CheckForError(&serviceStatus)) { // Something failed. Report an error.
CString strTemp;
// Kill the timer so that we don't get any messages
// while the message box is up.
if (m_timerId) KillTimer(m_timerId); AfxFormatString2(strTemp, IDS_ERR_STARTING_SERVICE, m_strServerName, m_strServiceDesc); AfxMessageBox(strTemp);
if (serviceStatus.dwWin32ExitCode) m_dwErr = serviceStatus.dwWin32ExitCode; else m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
CDialog::OnOK(); }
} } else { if (serviceStatus.dwCurrentState == SERVICE_STOPPED) { //
// The operation is complete.
//
CDialog::OnOK(); } else { if (CheckForError(&serviceStatus)) { // Something failed. Report an error.
CString strTemp; // Kill the timer so that we don't get any messages
// while the message box is up.
if (m_timerId) KillTimer(m_timerId); AfxFormatString2(strTemp, IDS_ERR_STOPPING_SERVICE, m_strServerName, m_strServiceDesc); AfxMessageBox(strTemp); if (serviceStatus.dwWin32ExitCode) m_dwErr = serviceStatus.dwWin32ExitCode; else m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
CDialog::OnOK(); } } } }
void CServiceCtrlDlg::CheckClusterService() { SERVICE_STATUS serviceStatus = {0}; DWORD dwError = ERROR_SUCCESS; CLUSTER_RESOURCE_STATE crs;
if ( !g_ClusDLL.LoadFunctionPointers() ) return;
// Check the state before we check the notification port.
crs = ((GETCLUSTERRESOURCESTATE) g_ClusDLL[CLUS_GET_CLUSTER_RESOURCE_STATE])( m_hResource, NULL, NULL, NULL, NULL );
if (crs == ClusterResourceStateUnknown) { // get cluster resource state failed
m_dwErr = GetLastError(); CDialog::OnOK(); }
if (m_bStart) { if (crs == ClusterResourceOnline) { //
// The operation is complete.
//
CDialog::OnOK(); } else if (crs == ClusterResourceFailed) { //
// resource failed to start. now error code available
//
m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT; CDialog::OnOK(); } else { Assert(crs == ClusterResourcePending || crs == ClusterResourceOnlinePending);
if (CheckForClusterError(&serviceStatus)) { // Something failed. Report an error.
CString strTemp;
// Kill the timer so that we don't get any messages
// while the message box is up.
if (m_timerId) KillTimer(m_timerId); AfxFormatString2(strTemp, IDS_ERR_STARTING_SERVICE, m_strServerName, m_strServiceDesc); AfxMessageBox(strTemp);
if (serviceStatus.dwWin32ExitCode) m_dwErr = serviceStatus.dwWin32ExitCode; else m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
CDialog::OnOK(); } } } else { if (crs == ClusterResourceOffline) { //
// The operation is complete.
//
CDialog::OnOK(); } if (crs == ClusterResourceFailed) { //
// resource failed to start. now error code available
//
m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT; CDialog::OnOK(); } else { Assert(crs == ClusterResourcePending || crs == ClusterResourceOfflinePending);
if (CheckForClusterError(&serviceStatus)) { // Something failed. Report an error.
CString strTemp; // Kill the timer so that we don't get any messages
// while the message box is up.
if (m_timerId) KillTimer(m_timerId); AfxFormatString2(strTemp, IDS_ERR_STOPPING_SERVICE, m_strServerName, m_strServiceDesc); AfxMessageBox(strTemp); if (serviceStatus.dwWin32ExitCode) m_dwErr = serviceStatus.dwWin32ExitCode; else m_dwErr = ERROR_SERVICE_REQUEST_TIMEOUT;
CDialog::OnOK(); } } } }
/////////////////////////////////////////////////////////////////////////////
// CWaitDlg dialog
CWaitDlg::CWaitDlg ( LPCTSTR pServerName, LPCTSTR pszText, LPCTSTR pszTitle, CWnd* pParent /*=NULL*/ ) : CDialog(CWaitDlg::IDD, pParent) { //{{AFX_DATA_INIT(CWaitDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_nTickCounter = TIMER_MULT; m_nTotalTickCount = 0; m_strServerName = pServerName; m_strServerName.MakeUpper(); m_strText = pszText; m_strTitle = pszTitle; m_timerId = 0; }
void CWaitDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CWaitDlg)
DDX_Control(pDX, IDC_STATIC_MESSAGE, m_staticMessage); DDX_Control(pDX, IDC_ICON_PROGRESS, m_iconProgress); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CWaitDlg, CDialog) //{{AFX_MSG_MAP(CWaitDlg)
ON_WM_TIMER() ON_WM_CLOSE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWaitDlg message handlers
BOOL CWaitDlg::OnInitDialog() { CDialog::OnInitDialog();
AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_timerId = SetTimer(TIMER_ID, TIMER_FREQ, NULL);
m_staticMessage.SetWindowText(m_strText);
SetWindowText(m_strTitle);
UpdateIndicator();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CWaitDlg::OnClose() { CloseTimer(); CDialog::OnClose(); }
void CWaitDlg::CloseTimer() { if (m_timerId) KillTimer(m_timerId); m_timerId = 0; }
void CWaitDlg::OnTimer(UINT nIDEvent) { //
// Bag-out if it's not our timer.
//
if(nIDEvent != TIMER_ID) { return; }
//
// Advance the progress indicator.
//
UpdateIndicator();
//
// No need to continue if we're just amusing the user.
//
if(--m_nTickCounter > 0) { return; }
m_nTickCounter = TIMER_MULT;
// check here to see if we can exit out
OnTimerTick(); }
void CWaitDlg::UpdateIndicator() { AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_nTotalTickCount % (1000 / TIMER_FREQ) == 0) { int nTempTickCount = m_nTotalTickCount / (1000 / TIMER_FREQ); HICON hIcon;
hIcon = AfxGetApp()->LoadIcon(IDI_PROGRESS_ICON_0 + (nTempTickCount % PROGRESS_ICON_COUNT)); m_iconProgress.SetIcon(hIcon); } m_nTotalTickCount++; }
|