|
|
// svcprop1.cpp : implementation file
//
// Implementation of page "General" of service property.
//
// HISTORY
// 30-Sep-96 t-danmo Creation
//
#include "stdafx.h"
#include "progress.h"
#include "cookie.h"
#include "dataobj.h"
#include "DynamLnk.h" // DynamicDLL
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
/*
// ISSUE-2002/03/06-JonN no longer used
/////////////////////////////////////////////////////////////////////
// WM_COMPARE_IDATAOBJECT
//
// wParam = (WPARAM)(IDataObject *)pDataObject;
// lParam = 0;
//
// Return TRUE if content of pDataObject matches current data object,
// otherwise return FALSE.
//
// USAGE
// This message is sent to a property page asking to
// compare content pDataObject with its current data object.
// The comparison is done by comparing data strings from
// the various clipboard formats supported by pDataObject.
//
#define WM_COMPARE_IDATAOBJECT (WM_USER+1234)
*/
/////////////////////////////////////////////////////////////////////
// WM_UPDATE_SERVICE_STATUS
//
// wParam = (WPARAM)(BOOL *)rgfEnableButton;
// lParam = (LPARAM)dwCurrentState;
//
// Notification message of the current service status.
//
#define WM_UPDATE_SERVICE_STATUS (WM_USER+1235)
/////////////////////////////////////////////////////////////////////
static const TStringParamEntry rgzspeStartupType[] = { { IDS_SVC_STARTUP_AUTOMATIC, SERVICE_AUTO_START }, { IDS_SVC_STARTUP_MANUAL, SERVICE_DEMAND_START }, { IDS_SVC_STARTUP_DISABLED, SERVICE_DISABLED }, { 0, 0 } };
#ifdef EDIT_DISPLAY_NAME_373025
const UINT rgzidDisableServiceDescription[] = { IDC_STATIC_DESCRIPTION, IDC_EDIT_DESCRIPTION, 0, }; #endif // EDIT_DISPLAY_NAME_373025
const UINT rgzidDisableStartupParameters[] = { IDC_STATIC_STARTUP_PARAMETERS, IDC_EDIT_STARTUP_PARAMETERS, 0, };
/////////////////////////////////////////////////////////////////////
// CServicePageGeneral property page
IMPLEMENT_DYNCREATE(CServicePageGeneral, CPropertyPage)
CServicePageGeneral::CServicePageGeneral() : CPropertyPage(CServicePageGeneral::IDD) , m_dwCurrentStatePrev( 0 ) // 581167-2002/03/06-JonN initialize
{ //{{AFX_DATA_INIT(CServicePageGeneral)
//}}AFX_DATA_INIT
m_pData = NULL; m_hThread = NULL; m_pThreadProcInit = NULL; }
CServicePageGeneral::~CServicePageGeneral() { }
void CServicePageGeneral::DoDataExchange(CDataExchange* pDX) { Assert(m_pData != NULL);
HWND hwndCombo = HGetDlgItem(m_hWnd, IDC_COMBO_STARTUP_TYPE); if (!pDX->m_bSaveAndValidate) { //
// Initialize data from m_pData into UI
//
ComboBox_FlushContent(hwndCombo); (void)ComboBox_FFill(hwndCombo, IN rgzspeStartupType, m_pData->m_paQSC->dwStartType);
//
// JonN 4/10/00
// 89823: RPC Service:Cannot restart the service when you disable it
//
// Do not allow the RpcSs service to change from Automatic
//
// JonN 10/23/01 472867 also the PlugPlay service
//
if ( ( !lstrcmpi(m_pData->m_strServiceName,L"RpcSs") || !lstrcmpi(m_pData->m_strServiceName,L"PlugPlay") ) && SERVICE_AUTO_START == m_pData->m_paQSC->dwStartType ) { EnableDlgItem(IDC_COMBO_STARTUP_TYPE, FALSE); }
#ifndef EDIT_DISPLAY_NAME_373025
DDX_Text(pDX, IDC_EDIT_DISPLAY_NAME, m_pData->m_strServiceDisplayName); DDX_Text(pDX, IDC_EDIT_DESCRIPTION, m_pData->m_strDescription); #endif // EDIT_DISPLAY_NAME_373025
} // if
CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CServicePageGeneral)
//}}AFX_DATA_MAP
#ifdef EDIT_DISPLAY_NAME_373025
DDX_Text(pDX, IDC_EDIT_DISPLAY_NAME, m_pData->m_strServiceDisplayName); DDV_MaxChars(pDX, m_pData->m_strServiceDisplayName, 255); DDX_Text(pDX, IDC_EDIT_DESCRIPTION, m_pData->m_strDescription); DDV_MaxChars(pDX, m_pData->m_strDescription, 2047); #endif // EDIT_DISPLAY_NAME_373025
if (pDX->m_bSaveAndValidate) { //
// Write data from UI into m_pData
//
#ifdef EDIT_DISPLAY_NAME_373025
if (m_pData->m_strServiceDisplayName.IsEmpty()) { DoServicesErrMsgBox(m_hWnd, MB_OK | MB_ICONEXCLAMATION, 0, IDS_MSG_PLEASE_ENTER_DISPLAY_NAME); pDX->PrepareEditCtrl(IDC_EDIT_DISPLAY_NAME); pDX->Fail(); } #endif // EDIT_DISPLAY_NAME_373025
m_pData->m_paQSC->dwStartType = (DWORD)ComboBox_GetSelectedItemData(hwndCombo); } // if
} // CServicePageGeneral::DoDataExchange()
BEGIN_MESSAGE_MAP(CServicePageGeneral, CPropertyPage) //{{AFX_MSG_MAP(CServicePageGeneral)
#ifdef EDIT_DISPLAY_NAME_373025
ON_EN_CHANGE(IDC_EDIT_DISPLAY_NAME, OnChangeEditDisplayName) ON_EN_CHANGE(IDC_EDIT_DESCRIPTION, OnChangeEditDescription) #endif // EDIT_DISPLAY_NAME_373025
ON_CBN_SELCHANGE(IDC_COMBO_STARTUP_TYPE, OnSelchangeComboStartupType) ON_BN_CLICKED(IDC_BUTTON_PAUSE, OnButtonPauseService) ON_BN_CLICKED(IDC_BUTTON_START, OnButtonStartService) ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStopService) ON_BN_CLICKED(IDC_BUTTON_RESUME, OnButtonResumeService) ON_WM_DESTROY() ON_MESSAGE(WM_HELP, OnHelp) ON_MESSAGE(WM_CONTEXTMENU, OnContextHelp) // ON_MESSAGE(WM_COMPARE_IDATAOBJECT, OnCompareIDataObject)
ON_MESSAGE(WM_UPDATE_SERVICE_STATUS, OnUpdateServiceStatus) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CServicePageGeneral message handlers
BOOL CServicePageGeneral::OnInitDialog() { CPropertyPage::OnInitDialog(); Assert(m_pData != NULL); Assert(m_pData->m_paQSC != NULL); m_pData->m_hwndPropertySheet = ::GetParent(m_hWnd); m_pData->UpdateCaption(); SetDlgItemText(IDC_STATIC_SERVICE_NAME, m_pData->m_pszServiceName); SetDlgItemText(IDC_STATIC_PATH_TO_EXECUTABLE, m_pData->m_paQSC->lpBinaryPathName); #ifdef EDIT_DISPLAY_NAME_373025
EnableDlgItemGroup(m_hWnd, rgzidDisableServiceDescription, m_pData->m_fQueryServiceConfig2); #endif // EDIT_DISPLAY_NAME_373025
RefreshServiceStatusButtons();
// Create a thread for periodic update
m_pThreadProcInit = new CThreadProcInit(this); // Note the object will be freed by the thread
m_pThreadProcInit->m_strServiceName = m_pData->m_strServiceName;
Assert(m_hThread == NULL); m_hThread = ::CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcPeriodicServiceStatusUpdate, m_pThreadProcInit, 0, NULL); Report(m_hThread != NULL && "Unable to create thread"); return TRUE; }
/////////////////////////////////////////////////////////////////////
void CServicePageGeneral::OnDestroy() { { CSingleLock lock(&m_pThreadProcInit->m_CriticalSection, TRUE); m_pThreadProcInit->m_hwnd = NULL; m_pThreadProcInit->m_fAutoDestroy = TRUE; } if (NULL != m_hThread) { VERIFY(::CloseHandle(m_hThread)); m_hThread = NULL; } CPropertyPage::OnDestroy(); delete m_pData; m_pData = NULL; // 581167-2002/03/07-JonN set m_pData to NULL
}
/////////////////////////////////////////////////////////////////////
BOOL CServicePageGeneral::OnSetActive() { Assert(m_pData != NULL); if (m_pData->m_hScManager == NULL) { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); // required for CWaitCursor
CWaitCursor wait; (void)m_pData->FOpenScManager(); // Re-open the service control manager database (if previously closed)
} { CSingleLock lock(&m_pThreadProcInit->m_CriticalSection, TRUE); m_pThreadProcInit->m_hScManager = m_pData->m_hScManager; m_pThreadProcInit->m_hwnd = m_hWnd; } return CPropertyPage::OnSetActive(); }
/////////////////////////////////////////////////////////////////////
BOOL CServicePageGeneral::OnKillActive() { if (!CPropertyPage::OnKillActive()) return FALSE; { CSingleLock lock(&m_pThreadProcInit->m_CriticalSection, TRUE); m_pThreadProcInit->m_hwnd = NULL; } return TRUE; }
#ifdef EDIT_DISPLAY_NAME_373025
void CServicePageGeneral::OnChangeEditDisplayName() { m_pData->SetDirty(CServicePropertyData::mskfDirtyDisplayName); SetModified(); }
void CServicePageGeneral::OnChangeEditDescription() { m_pData->SetDirty(CServicePropertyData::mskfDirtyDescription); SetModified(); } #endif // EDIT_DISPLAY_NAME_373025
void CServicePageGeneral::OnSelchangeComboStartupType() { m_pData->SetDirty(CServicePropertyData::mskfDirtyStartupType); SetModified(); }
void CServicePageGeneral::SetDlgItemFocus(INT nIdDlgItem) { ::SetDlgItemFocus(m_hWnd, nIdDlgItem); }
void CServicePageGeneral::EnableDlgItem(INT nIdDlgItem, BOOL fEnable) { ::EnableDlgItem(m_hWnd, nIdDlgItem, fEnable); }
/////////////////////////////////////////////////////////////////////
// RefreshServiceStatusButtons()
//
// Query the service manager to get the status of the service, and
// enable/disable buttons Start, Stop, Pause and Continue accordingly.
//
void CServicePageGeneral::RefreshServiceStatusButtons() { BOOL rgfEnableButton[iServiceActionMax]; DWORD dwCurrentState; // ISSUE-2002/03/07-JonN Don't we need to call AFX_MANAGE_STATE before
// CWaitCursor?
CWaitCursor wait; if (!Service_FGetServiceButtonStatus( m_pData->m_hScManager, m_pData->m_pszServiceName, OUT rgfEnableButton, OUT &dwCurrentState)) { // let's not do this m_pData->m_hScManager = NULL;
} m_dwCurrentStatePrev = !dwCurrentState; // Force a refresh
OnUpdateServiceStatus((WPARAM)rgfEnableButton, dwCurrentState); } // CServicePageGeneral::RefreshServiceStatusButtons()
typedef enum _SVCPROP_Shell32ApiIndex { CMDLINE_ENUM = 0 };
// not subject to localization
static LPCSTR g_apchShell32FunctionNames[] = { "CommandLineToArgvW", NULL };
typedef LPWSTR * (*COMMANDLINETOARGVWPROC)(LPCWSTR, int*);
// not subject to localization
DynamicDLL g_SvcpropShell32DLL( _T("SHELL32.DLL"), g_apchShell32FunctionNames );
/////////////////////////////////////////////////////////////////////
void CServicePageGeneral::OnButtonStartService() { CString strStartupParameters; LPCWSTR * lpServiceArgVectors = NULL; // Array of pointers to strings
int cArgs = 0; // Count of arguments
// Get the startup parameters
GetDlgItemText(IDC_EDIT_STARTUP_PARAMETERS, OUT strStartupParameters); if ( !strStartupParameters.IsEmpty() ) { #ifndef UNICODE
#error CODEWORK t-danmo: CommandLineToArgvW will only work for unicode strings
#endif
if ( !g_SvcpropShell32DLL.LoadFunctionPointers() ) { ASSERT(FALSE); return; } lpServiceArgVectors = (LPCWSTR *)((COMMANDLINETOARGVWPROC)g_SvcpropShell32DLL[CMDLINE_ENUM]) (strStartupParameters, OUT &cArgs); if (lpServiceArgVectors == NULL) { DoServicesErrMsgBox(m_hWnd, MB_OK | MB_ICONEXCLAMATION, 0, IDS_MSG_INVALID_STARTUP_PARAMETERS); SetDlgItemFocus(IDC_EDIT_STARTUP_PARAMETERS); return; } } // Disable the edit control for better UI
EnableDlgItemGroup(m_hWnd, rgzidDisableStartupParameters, FALSE); DWORD dwErr = CServiceControlProgress::S_EStartService( m_hWnd, m_pData->m_hScManager, m_pData->m_strUiMachineName, m_pData->m_pszServiceName, m_pData->m_strServiceDisplayName, cArgs, lpServiceArgVectors);
// ISSUE-2002/03/07-JonN MSDN says we should use GlobalFree here
if (NULL != lpServiceArgVectors) LocalFree(lpServiceArgVectors); if (dwErr == CServiceControlProgress::errUserAbort) return; RefreshServiceStatusButtons(); SetDlgItemFocus(IDC_BUTTON_STOP); m_pData->NotifySnapInParent(); }
/////////////////////////////////////////////////////////////////////
void CServicePageGeneral::OnButtonStopService() { DWORD dwErr = CServiceControlProgress::S_EControlService( m_hWnd, m_pData->m_hScManager, m_pData->m_strUiMachineName, m_pData->m_pszServiceName, m_pData->m_strServiceDisplayName, SERVICE_CONTROL_STOP); if (dwErr == CServiceControlProgress::errUserAbort) return; RefreshServiceStatusButtons(); SetDlgItemFocus(IDC_BUTTON_START); m_pData->NotifySnapInParent(); }
/////////////////////////////////////////////////////////////////////
void CServicePageGeneral::OnButtonPauseService() { DWORD dwErr = CServiceControlProgress::S_EControlService( m_hWnd, m_pData->m_hScManager, m_pData->m_strUiMachineName, m_pData->m_pszServiceName, m_pData->m_strServiceDisplayName, SERVICE_CONTROL_PAUSE); if (dwErr == CServiceControlProgress::errUserAbort) return; RefreshServiceStatusButtons(); SetDlgItemFocus(IDC_BUTTON_RESUME); m_pData->NotifySnapInParent(); }
/////////////////////////////////////////////////////////////////////
void CServicePageGeneral::OnButtonResumeService() { DWORD dwErr = CServiceControlProgress::S_EControlService( m_hWnd, m_pData->m_hScManager, m_pData->m_strUiMachineName, m_pData->m_pszServiceName, m_pData->m_strServiceDisplayName, SERVICE_CONTROL_CONTINUE); if (dwErr == CServiceControlProgress::errUserAbort) return; RefreshServiceStatusButtons(); SetDlgItemFocus(IDC_BUTTON_PAUSE); m_pData->NotifySnapInParent(); }
/////////////////////////////////////////////////////////////////////
BOOL CServicePageGeneral::OnApply() { // Write the data into the service control database
if (!m_pData->FOnApply()) { // Unable to write the information
return FALSE; } UpdateData(FALSE); RefreshServiceStatusButtons(); m_pData->UpdateCaption(); return CPropertyPage::OnApply(); }
/*
/////////////////////////////////////////////////////////////////////
// OnCompareIDataObject()
//
// Return TRUE if 'service name' and 'machine name' of pDataObject
// matches 'service name' and 'machine name' of current property sheet.
//
LRESULT CServicePageGeneral::OnCompareIDataObject(WPARAM wParam, LPARAM lParam) { IDataObject * pDataObject; CString strServiceName; CString strMachineName; HRESULT hr;
pDataObject = reinterpret_cast<IDataObject *>(wParam); Assert(pDataObject != NULL);
// Get the service name from IDataObject
hr = ::ExtractString( pDataObject, CFileMgmtDataObject::m_CFServiceName, OUT &strServiceName, 255); if (FAILED(hr)) return FALSE; if (0 != lstrcmpi(strServiceName, m_pData->m_strServiceName)) { // Service name do not match
return FALSE; }
// Get the machine name (computer name) from IDataObject
hr = ::ExtractString( pDataObject, CFileMgmtDataObject::m_CFMachineName, OUT &strMachineName, 255); if (FAILED(hr)) return FALSE; return FCompareMachineNames(m_pData->m_strMachineName, strMachineName); } // CServicePageGeneral::OnCompareIDataObject()
*/
/////////////////////////////////////////////////////////////////////
LRESULT CServicePageGeneral::OnUpdateServiceStatus(WPARAM wParam, LPARAM lParam) { const BOOL * rgfEnableButton = (BOOL *)wParam; const DWORD dwCurrentState = (DWORD)lParam;
Assert(rgfEnableButton != NULL); if (dwCurrentState != m_dwCurrentStatePrev) { m_dwCurrentStatePrev = dwCurrentState; SetDlgItemText(IDC_STATIC_CURRENT_STATUS, Service_PszMapStateToName(dwCurrentState, TRUE)); EnableDlgItem(IDC_BUTTON_START, rgfEnableButton[iServiceActionStart]); EnableDlgItem(IDC_BUTTON_STOP, rgfEnableButton[iServiceActionStop]); EnableDlgItem(IDC_BUTTON_PAUSE, rgfEnableButton[iServiceActionPause]); EnableDlgItem(IDC_BUTTON_RESUME, rgfEnableButton[iServiceActionResume]); // Enable/disable the edit box of the startup parameter according
// to the state of the 'start' button
EnableDlgItemGroup(m_hWnd, rgzidDisableStartupParameters, rgfEnableButton[iServiceActionStart]); if (dwCurrentState == 0) { // Service state is unknown
m_pData->m_hScManager = NULL; DoServicesErrMsgBox(m_hWnd, MB_OK | MB_ICONEXCLAMATION, 0, IDS_MSG_ss_UNABLE_TO_QUERY_SERVICE_STATUS, (LPCTSTR)m_pData->m_strServiceDisplayName, (LPCTSTR)m_pData->m_strUiMachineName); } } return 0; } // CServicePageGeneral::OnUpdateServiceStatus()
/////////////////////////////////////////////////////////////////////
// Periodically update the service status.
//
// Send a message to CServicePageGeneral object to notify the update.
//
// INTERFACE NOTES
// The thread is responsible of deleting the paThreadProcInit object
// before terminating itself.
//
DWORD CServicePageGeneral::ThreadProcPeriodicServiceStatusUpdate(CThreadProcInit * paThreadProcInit) { Assert(paThreadProcInit != NULL); Assert(paThreadProcInit->m_pThis != NULL); Assert(paThreadProcInit->m_fAutoDestroy == FALSE); BOOL rgfEnableButton[iServiceActionMax]; DWORD dwCurrentState;
// Infinite loop querying the service status
while (!paThreadProcInit->m_fAutoDestroy) { if (paThreadProcInit->m_hwnd != NULL) { SC_HANDLE hScManager; { CSingleLock lock(&paThreadProcInit->m_CriticalSection, TRUE); hScManager = paThreadProcInit->m_hScManager; } BOOL fSuccess = Service_FGetServiceButtonStatus( hScManager, paThreadProcInit->m_strServiceName, OUT rgfEnableButton, OUT &dwCurrentState, TRUE /* fSilentError */);
HWND hwnd = NULL; { CSingleLock lock(&paThreadProcInit->m_CriticalSection, TRUE); hwnd = paThreadProcInit->m_hwnd; } if (hwnd != NULL) { Assert(IsWindow(hwnd)); ::SendMessage(hwnd, WM_UPDATE_SERVICE_STATUS, (WPARAM)rgfEnableButton, (LPARAM)dwCurrentState); } if (!fSuccess) { CSingleLock lock(&paThreadProcInit->m_CriticalSection, TRUE); paThreadProcInit->m_hwnd = NULL; } } Sleep(1000); } // while
delete paThreadProcInit; return 0; } // CServicePageGeneral::ThreadProcPeriodicServiceStatusUpdate()
/////////////////////////////////////////////////////////////////////
// Help
BOOL CServicePageGeneral::OnHelp(WPARAM /*wParam*/, LPARAM lParam) { return DoHelp(lParam, HELP_DIALOG_TOPIC(IDD_PROPPAGE_SERVICE_GENERAL)); }
BOOL CServicePageGeneral::OnContextHelp(WPARAM wParam, LPARAM /*lParam*/) { return DoContextHelp(wParam, HELP_DIALOG_TOPIC(IDD_PROPPAGE_SERVICE_GENERAL)); }
|