Namestitev sem dopolnil še z možnostjo zagona/zaustavitve poljubnega sistemskega servisa (v tej fazi brez odvisnih servisov).
This commit is contained in:
parent
ed18da4ebb
commit
ddde7488fa
@ -40,6 +40,7 @@ ScheduledTask Component_ N Component 1 Identifier Component the task is part
|
||||
ServiceConfigure ServiceConfigure N Identifier Primary key, non-localized token.
|
||||
ServiceConfigure Name N Formatted Name of a service. /, \, comma and space are invalid
|
||||
ServiceConfigure StartType N DoubleInteger -1;0;1;2;3;4 Start type: -1=don't change, 0=boot, 1=system, 2=auto, 3=demand, 4=disabled
|
||||
ServiceConfigure Control N Integer 0;2;3;4;5;7 Bitwise combination of: 0=no action, 1=wait to finish, 2=start, 4=stop
|
||||
ServiceConfigure Condition Y Condition Optional expression which skips the service configuration if evaluates to expFalse. If the expression syntax is invalid, the engine will terminate, returning iesBadActionData.
|
||||
ServiceConfigure Sequence Y Number that determines the sort order in which the configurations are to be executed.
|
||||
TaskTrigger Trigger N Identifier Primary key, non-localized token.
|
||||
@ -198,8 +199,8 @@ All :: "$(LANG).$(PLAT).$(CFG).ServiceConfigure-1.idt"
|
||||
"$(LANG).$(PLAT).$(CFG).ServiceConfigure-1.idt" : "Makefile" "..\..\..\include\MSIBuildCfg.mak"
|
||||
-if exist $@ del /f /q $@
|
||||
move /y << $@ > NUL
|
||||
ServiceConfigure Name StartType Condition Sequence
|
||||
s$(MSIBUILD_LENGTH_ID) l255 i4 S255 I2
|
||||
ServiceConfigure Name StartType Control Condition Sequence
|
||||
s$(MSIBUILD_LENGTH_ID) l255 i4 i2 S255 I2
|
||||
ServiceConfigure ServiceConfigure
|
||||
<<NOKEEP
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#define MSICA_CERT_TICK_SIZE (4*1024)
|
||||
#define MSICA_SVC_SET_START_TICK_SIZE (1*1024)
|
||||
#define MSICA_SVC_START_TICK_SIZE (1*1024)
|
||||
#define MSICA_SVC_STOP_TICK_SIZE (1*1024)
|
||||
#define MSICA_TASK_TICK_SIZE (16*1024)
|
||||
|
||||
|
||||
@ -207,12 +209,12 @@ UINT MSICA_API ServiceConfigEval(MSIHANDLE hInstall)
|
||||
PMSIHANDLE hViewSC;
|
||||
|
||||
// Prepare a query to get a list/view of service configurations.
|
||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Name,StartType,Condition FROM ServiceConfigure ORDER BY Sequence"), &hViewSC);
|
||||
uiResult = ::MsiDatabaseOpenView(hDatabase, _T("SELECT Name,StartType,Control,Condition FROM ServiceConfigure ORDER BY Sequence"), &hViewSC);
|
||||
if (uiResult == NO_ERROR) {
|
||||
// Execute query!
|
||||
uiResult = ::MsiViewExecute(hViewSC, NULL);
|
||||
if (uiResult == NO_ERROR) {
|
||||
int iStartType;
|
||||
int iValue;
|
||||
|
||||
for (;;) {
|
||||
PMSIHANDLE hRecord;
|
||||
@ -226,7 +228,7 @@ UINT MSICA_API ServiceConfigEval(MSIHANDLE hInstall)
|
||||
break;
|
||||
|
||||
// Read and evaluate service configuration condition.
|
||||
uiResult = ::MsiRecordGetString(hRecord, 3, sValue);
|
||||
uiResult = ::MsiRecordGetString(hRecord, 4, sValue);
|
||||
if (uiResult != NO_ERROR) break;
|
||||
condition = ::MsiEvaluateCondition(hInstall, sValue);
|
||||
if (condition == MSICONDITION_FALSE)
|
||||
@ -241,20 +243,44 @@ UINT MSICA_API ServiceConfigEval(MSIHANDLE hInstall)
|
||||
if (uiResult != NO_ERROR) break;
|
||||
|
||||
// Read service start type.
|
||||
iStartType = ::MsiRecordGetInteger(hRecord, 2);
|
||||
if (iStartType == MSI_NULL_INTEGER) {
|
||||
iValue = ::MsiRecordGetInteger(hRecord, 2);
|
||||
if (iValue == MSI_NULL_INTEGER) {
|
||||
uiResult = ERROR_INVALID_FIELD;
|
||||
break;
|
||||
}
|
||||
if (iStartType >= 0) {
|
||||
if (iValue >= 0) {
|
||||
// Set service start type.
|
||||
olExecute.AddTail(new MSICA::COpSvcSetStart(sValue, iStartType, MSICA_SVC_SET_START_TICK_SIZE));
|
||||
olExecute.AddTail(new MSICA::COpSvcSetStart(sValue, iValue, MSICA_SVC_SET_START_TICK_SIZE));
|
||||
|
||||
// The amount of tick space to add to progress indicator.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||
::MsiRecordSetInteger(hRecordProg, 2, MSICA_SVC_SET_START_TICK_SIZE);
|
||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||
}
|
||||
|
||||
// Read service control.
|
||||
iValue = ::MsiRecordGetInteger(hRecord, 3);
|
||||
if (iValue == MSI_NULL_INTEGER) {
|
||||
uiResult = ERROR_INVALID_FIELD;
|
||||
break;
|
||||
}
|
||||
if ((iValue & 4) != 0) {
|
||||
// Stop service.
|
||||
olExecute.AddTail(new MSICA::COpSvcStop(sValue, (iValue & 1) ? TRUE : FALSE, MSICA_SVC_STOP_TICK_SIZE));
|
||||
|
||||
// The amount of tick space to add to progress indicator.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||
::MsiRecordSetInteger(hRecordProg, 2, MSICA_SVC_STOP_TICK_SIZE);
|
||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||
} else if ((iValue & 2) != 0) {
|
||||
// Start service.
|
||||
olExecute.AddTail(new MSICA::COpSvcStart(sValue, (iValue & 1) ? TRUE : FALSE, MSICA_SVC_START_TICK_SIZE));
|
||||
|
||||
// The amount of tick space to add to progress indicator.
|
||||
::MsiRecordSetInteger(hRecordProg, 1, 3 );
|
||||
::MsiRecordSetInteger(hRecordProg, 2, MSICA_SVC_START_TICK_SIZE);
|
||||
if (::MsiProcessMessage(hInstall, INSTALLMESSAGE_PROGRESS, hRecordProg) == IDCANCEL) { uiResult = ERROR_INSTALL_USEREXIT; break; }
|
||||
}
|
||||
}
|
||||
::MsiViewClose(hViewSC);
|
||||
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class COpSvcStart : public COpTypeSingleString
|
||||
class COpSvcStart : public COpSvcControl
|
||||
{
|
||||
public:
|
||||
COpSvcStart(LPCWSTR pszService = L"", int iTicks = 0);
|
||||
COpSvcStart(LPCWSTR pszService = L"", BOOL bWait = FALSE, int iTicks = 0);
|
||||
virtual HRESULT Execute(CSession *pSession);
|
||||
};
|
||||
|
||||
@ -492,10 +511,10 @@ public:
|
||||
// COpSvcStop
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class COpSvcStop : public COpTypeSingleString
|
||||
class COpSvcStop : public COpSvcControl
|
||||
{
|
||||
public:
|
||||
COpSvcStop(LPCWSTR pszService = L"", int iTicks = 0);
|
||||
COpSvcStop(LPCWSTR pszService = L"", BOOL bWait = FALSE, int iTicks = 0);
|
||||
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)
|
||||
{
|
||||
POSITION pos;
|
||||
|
@ -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(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;
|
||||
|
||||
// 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) {
|
||||
// Start the service.
|
||||
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.
|
||||
pSession->m_olRollback.AddHead(new COpSvcStop(m_sValue));
|
||||
}
|
||||
dwError = NO_ERROR;
|
||||
} else {
|
||||
dwError = ::GetLastError();
|
||||
if (dwError == ERROR_SERVICE_ALREADY_RUNNING) {
|
||||
@ -134,7 +183,7 @@ HRESULT COpSvcStart::Execute(CSession *pSession)
|
||||
// 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;
|
||||
|
||||
// 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) {
|
||||
SERVICE_STATUS ss;
|
||||
// Stop the service.
|
||||
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.
|
||||
pSession->m_olRollback.AddHead(new COpSvcStart(m_sValue));
|
||||
}
|
||||
dwError = NO_ERROR;
|
||||
} else {
|
||||
dwError = ::GetLastError();
|
||||
if (dwError == ERROR_SERVICE_NOT_ACTIVE) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user