Namestitev sem dopolnil še z možnostjo zagona/zaustavitve poljubnega sistemskega servisa (v tej fazi brez odvisnih servisov).

This commit is contained in:
Simon Rozman 2014-03-21 13:35:01 +00:00
parent 93ed14df64
commit 32ef7ddcb2
2 changed files with 103 additions and 12 deletions

View File

@ -476,14 +476,33 @@ protected:
}; };
////////////////////////////////////////////////////////////////////////////
// COpSvcControl
////////////////////////////////////////////////////////////////////////////
class COpSvcControl : public COpTypeSingleString
{
public:
COpSvcControl(LPCWSTR pszService = L"", BOOL bWait = FALSE, int iTicks = 0);
static DWORD WaitForState(CSession *pSession, SC_HANDLE hService, DWORD dwPendingState, DWORD dwFinalState);
friend inline HRESULT operator <<(ATL::CAtlFile &f, const COpSvcControl &op);
friend inline HRESULT operator >>(ATL::CAtlFile &f, COpSvcControl &op);
protected:
BOOL m_bWait;
};
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// COpSvcStart // COpSvcStart
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
class COpSvcStart : public COpTypeSingleString class COpSvcStart : public COpSvcControl
{ {
public: public:
COpSvcStart(LPCWSTR pszService = L"", int iTicks = 0); COpSvcStart(LPCWSTR pszService = L"", BOOL bWait = FALSE, int iTicks = 0);
virtual HRESULT Execute(CSession *pSession); virtual HRESULT Execute(CSession *pSession);
}; };
@ -492,10 +511,10 @@ public:
// COpSvcStop // COpSvcStop
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
class COpSvcStop : public COpTypeSingleString class COpSvcStop : public COpSvcControl
{ {
public: public:
COpSvcStop(LPCWSTR pszService = L"", int iTicks = 0); COpSvcStop(LPCWSTR pszService = L"", BOOL bWait = FALSE, int iTicks = 0);
virtual HRESULT Execute(CSession *pSession); virtual HRESULT Execute(CSession *pSession);
}; };
@ -1438,6 +1457,29 @@ inline HRESULT operator >>(ATL::CAtlFile &f, COpSvcSetStart &op)
} }
inline HRESULT operator <<(ATL::CAtlFile &f, const COpSvcControl &op)
{
HRESULT hr;
hr = f << (const COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f << (int)(op.m_bWait); if (FAILED(hr)) return hr;
return S_OK;
}
inline HRESULT operator >>(ATL::CAtlFile &f, COpSvcControl &op)
{
HRESULT hr;
int iValue;
hr = f >> (COpTypeSingleString&)op; if (FAILED(hr)) return hr;
hr = f >> iValue; if (FAILED(hr)) return hr; op.m_bWait = iValue ? TRUE : FALSE;
return S_OK;
}
inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list) inline HRESULT operator <<(ATL::CAtlFile &f, const COpList &list)
{ {
POSITION pos; POSITION pos;

View File

@ -76,11 +76,60 @@ HRESULT COpSvcSetStart::Execute(CSession *pSession)
} }
////////////////////////////////////////////////////////////////////////////
// COpSvcControl
////////////////////////////////////////////////////////////////////////////
COpSvcControl::COpSvcControl(LPCWSTR pszService, BOOL bWait, int iTicks) :
COpTypeSingleString(pszService, iTicks),
m_bWait(bWait)
{
}
DWORD COpSvcControl::WaitForState(CSession *pSession, SC_HANDLE hService, DWORD dwPendingState, DWORD dwFinalState)
{
PMSIHANDLE hRecordProg = ::MsiCreateRecord(3);
// Prepare hRecordProg for progress messages.
::MsiRecordSetInteger(hRecordProg, 1, 2);
::MsiRecordSetInteger(hRecordProg, 3, 0);
// Wait for the service to start.
for (;;) {
SERVICE_STATUS_PROCESS ssp;
DWORD dwSize;
// Check service status.
if (::QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwSize)) {
if (ssp.dwCurrentState == dwPendingState) {
// Service is pending. Wait some more ...
::Sleep(ssp.dwWaitHint < 1000 ? ssp.dwWaitHint : 1000);
} else if (ssp.dwCurrentState == dwFinalState) {
// Service is in expected state.
return NO_ERROR;
} else {
// Service is in unexpected state.
return ERROR_ASSERTION_FAILURE;
}
} else {
// Service query failed.
return ::GetLastError();
}
// Check if user cancelled installation.
::MsiRecordSetInteger(hRecordProg, 2, 0);
if (::MsiProcessMessage(pSession->m_hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL)
return ERROR_INSTALL_USEREXIT;
}
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// COpSvcStart // COpSvcStart
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpSvcStart::COpSvcStart(LPCWSTR pszService, int iTicks) : COpTypeSingleString(pszService, iTicks) COpSvcStart::COpSvcStart(LPCWSTR pszService, BOOL bWait, int iTicks) : COpSvcControl(pszService, bWait, iTicks)
{ {
} }
@ -96,15 +145,15 @@ HRESULT COpSvcStart::Execute(CSession *pSession)
SC_HANDLE hService; SC_HANDLE hService;
// Open the specified service. // Open the specified service.
hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_START); hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_START | (m_bWait ? SERVICE_QUERY_STATUS : 0));
if (hService) { if (hService) {
// Start the service. // Start the service.
if (::StartService(hService, 0, NULL)) { if (::StartService(hService, 0, NULL)) {
if (pSession->m_bRollbackEnabled) { dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_START_PENDING, SERVICE_RUNNING) : NO_ERROR;
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to stop the service. // Order rollback action to stop the service.
pSession->m_olRollback.AddHead(new COpSvcStop(m_sValue)); pSession->m_olRollback.AddHead(new COpSvcStop(m_sValue));
} }
dwError = NO_ERROR;
} else { } else {
dwError = ::GetLastError(); dwError = ::GetLastError();
if (dwError == ERROR_SERVICE_ALREADY_RUNNING) { if (dwError == ERROR_SERVICE_ALREADY_RUNNING) {
@ -134,7 +183,7 @@ HRESULT COpSvcStart::Execute(CSession *pSession)
// COpSvcStop // COpSvcStop
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
COpSvcStop::COpSvcStop(LPCWSTR pszService, int iTicks) : COpTypeSingleString(pszService, iTicks) COpSvcStop::COpSvcStop(LPCWSTR pszService, BOOL bWait, int iTicks) : COpSvcControl(pszService, bWait, iTicks)
{ {
} }
@ -150,16 +199,16 @@ HRESULT COpSvcStop::Execute(CSession *pSession)
SC_HANDLE hService; SC_HANDLE hService;
// Open the specified service. // Open the specified service.
hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_STOP); hService = ::OpenServiceW(hSCM, m_sValue, SERVICE_STOP | (m_bWait ? SERVICE_QUERY_STATUS : 0));
if (hService) { if (hService) {
SERVICE_STATUS ss; SERVICE_STATUS ss;
// Stop the service. // Stop the service.
if (::ControlService(hService, SERVICE_CONTROL_STOP, &ss)) { if (::ControlService(hService, SERVICE_CONTROL_STOP, &ss)) {
if (pSession->m_bRollbackEnabled) { dwError = m_bWait ? WaitForState(pSession, hService, SERVICE_STOP_PENDING, SERVICE_STOPPED) : NO_ERROR;
if (dwError == NO_ERROR && pSession->m_bRollbackEnabled) {
// Order rollback action to start the service. // Order rollback action to start the service.
pSession->m_olRollback.AddHead(new COpSvcStart(m_sValue)); pSession->m_olRollback.AddHead(new COpSvcStart(m_sValue));
} }
dwError = NO_ERROR;
} else { } else {
dwError = ::GetLastError(); dwError = ::GetLastError();
if (dwError == ERROR_SERVICE_NOT_ACTIVE) { if (dwError == ERROR_SERVICE_NOT_ACTIVE) {