This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-daemon.git
commit 840e29005da54f82ba7ca49332bfe67bbd6b9dd0 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Jun 13 11:06:43 2019 +0100 Fix https://issues.apache.org/jira/browse/DAEMON-303 Add an option to configure the service to start using the "Automatic (Delayed Start)" mode. --- src/changes/changes.xml | 6 +++- src/native/windows/apps/prunmgr/prunmgr.c | 32 ++++++++++++----- src/native/windows/apps/prunsrv/prunsrv.c | 9 ++++- src/native/windows/include/service.h | 4 ++- src/native/windows/src/service.c | 58 ++++++++++++++++++++++++++----- src/site/xdoc/procrun.xml | 2 +- 6 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 19d0720..40c11e1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -38,7 +38,7 @@ <title>Apache Commons Daemon Release Notes</title> </properties> <body> - <release version="1.1.1" date="TBD" description="Bug fix release"> + <release version="1.1.1" date="TBD" description="Feature and bug fix release"> <action type="fix" dev="markt" due-to="mturk" > Procrun. Add to OPT_LFLAGS rather than overwrite OPT_LFLAGS when setting /OPT:REF in the make file for Windows. @@ -122,6 +122,10 @@ JNI to create the JVM as a workaround for startup error messages not being visible on stdout or stderr. </action> + <action issue="DAEMON-303" type="add" dev="markt"> + Procrun. Add an option to configure the service to use the 'Automatic + (Delayed Start)' startup mode. + </action> </release> <release version="1.1.0" date="2017-11-15" description="Feature and bug fix release"> <action issue="DAEMON-368" type="add" dev="ggregory"> diff --git a/src/native/windows/apps/prunmgr/prunmgr.c b/src/native/windows/apps/prunmgr/prunmgr.c index 0b520c6..afae8c7 100644 --- a/src/native/windows/apps/prunmgr/prunmgr.c +++ b/src/native/windows/apps/prunmgr/prunmgr.c @@ -51,6 +51,7 @@ LPAPXGUISTORE _gui_store = NULL; #define LOGL_INFO L"Info" #define LOGL_WARN L"Warn" +#define START_DELAYED L"Automatic (Delayed Start)" #define START_AUTO L"Automatic" #define START_MANUAL L"Manual" #define START_DISABLED L"Disabled" @@ -298,6 +299,8 @@ BOOL __generalPropertySave(HWND hDlg) WCHAR szN[SIZ_RESLEN]; WCHAR szD[SIZ_DESLEN]; DWORD dwStartType = SERVICE_NO_CHANGE; + BOOL bDelayedStart = FALSE; + int i; if (!(TST_BIT_FLAG(_propertyChanged, 1))) @@ -309,14 +312,18 @@ BOOL __generalPropertySave(HWND hDlg) GetDlgItemTextW(hDlg, IDC_PPSGDISP, szN, SIZ_RESMAX); GetDlgItemTextW(hDlg, IDC_PPSGDESC, szD, SIZ_DESMAX); i = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST)); - if (i == 0) + if (i == 0) { dwStartType = SERVICE_AUTO_START; + bDelayedStart = TRUE; + } else if (i == 1) - dwStartType = SERVICE_DEMAND_START; + dwStartType = SERVICE_AUTO_START; else if (i == 2) + dwStartType = SERVICE_DEMAND_START; + else if (i == 3) dwStartType = SERVICE_DISABLED; apxServiceSetNames(hService, NULL, szN, szD, NULL, NULL); - apxServiceSetOptions(hService, SERVICE_NO_CHANGE, dwStartType, SERVICE_NO_CHANGE); + apxServiceSetOptions(hService, SERVICE_NO_CHANGE, dwStartType, bDelayedStart, SERVICE_NO_CHANGE); if (!(TST_BIT_FLAG(_propertyChanged, 2))) PostMessage(_gui_store->hMainWnd, WM_COMMAND, MAKEWPARAM(IDMS_REFRESH, 0), 0); @@ -355,12 +362,12 @@ BOOL __generalLogonSave(HWND hDlg) if (IsDlgButtonChecked(hDlg, IDC_PPSLID) == BST_CHECKED) { apxServiceSetOptions(hService, _currentEntry->stServiceStatus.dwServiceType | SERVICE_INTERACTIVE_PROCESS, - SERVICE_NO_CHANGE, SERVICE_NO_CHANGE); + SERVICE_NO_CHANGE, FALSE, SERVICE_NO_CHANGE); } else { apxServiceSetOptions(hService, _currentEntry->stServiceStatus.dwServiceType & ~SERVICE_INTERACTIVE_PROCESS, - SERVICE_NO_CHANGE, SERVICE_NO_CHANGE); + SERVICE_NO_CHANGE, FALSE, SERVICE_NO_CHANGE); } } else { if (szP[0] != L' ' && szC[0] != L' ' && !lstrcmpW(szP, szC)) { @@ -607,15 +614,22 @@ LRESULT CALLBACK __generalProperty(HWND hDlg, SendMessage(GetDlgItem(hDlg, IDC_PPSGDISP), EM_LIMITTEXT, SIZ_RESMAX, 0); SendMessage(GetDlgItem(hDlg, IDC_PPSGDESC), EM_LIMITTEXT, SIZ_DESMAX, 0); + ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_DELAYED); ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_AUTO); ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_MANUAL); ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_DISABLED); - if (_currentEntry->lpConfig->dwStartType == SERVICE_AUTO_START) - ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 0); + if (_currentEntry->lpConfig->dwStartType == SERVICE_AUTO_START) { + if (_currentEntry->bDelayedStart) { + ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 0); + } + else { + ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 1); + } + } else if (_currentEntry->lpConfig->dwStartType == SERVICE_DEMAND_START) - ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 1); - else if (_currentEntry->lpConfig->dwStartType == SERVICE_DISABLED) ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 2); + else if (_currentEntry->lpConfig->dwStartType == SERVICE_DISABLED) + ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 3); SetDlgItemTextW(hDlg, IDC_PPSGNAME, _currentEntry->szServiceName); SetDlgItemTextW(hDlg, IDC_PPSGDISP, _currentEntry->lpConfig->lpDisplayName); diff --git a/src/native/windows/apps/prunsrv/prunsrv.c b/src/native/windows/apps/prunsrv/prunsrv.c index dab90e5..cf1ef48 100644 --- a/src/native/windows/apps/prunsrv/prunsrv.c +++ b/src/native/windows/apps/prunsrv/prunsrv.c @@ -64,6 +64,7 @@ static LPCWSTR PRSRV_JAVA = L"java"; static LPCWSTR PRSRV_JVM = L"jvm"; static LPCWSTR PRSRV_JDK = L"jdk"; static LPCWSTR PRSRV_JRE = L"jre"; +static LPCWSTR PRSRV_DELAYED = L"delayed"; static LPCWSTR PRSRV_MANUAL = L"manual"; static LPCWSTR PRSRV_JBIN = L"\\bin\\java.exe"; static LPCWSTR PRSRV_PBIN = L"\\bin"; @@ -834,6 +835,7 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline) } else { DWORD dwStart = SERVICE_NO_CHANGE; + BOOL bDelayedStart = FALSE; DWORD dwType = SERVICE_NO_CHANGE; LPCWSTR su = NULL; LPCWSTR sp = NULL; @@ -855,7 +857,11 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline) sp)); /* Update the --Startup mode */ if (ST_STARTUP & APXCMDOPT_FOUND) { - if (!lstrcmpiW(SO_STARTUP, PRSRV_AUTO)) + if (!lstrcmpiW(SO_STARTUP, PRSRV_DELAYED)) { + dwStart = SERVICE_AUTO_START; + bDelayedStart = TRUE; + } + else if (!lstrcmpiW(SO_STARTUP, PRSRV_AUTO)) dwStart = SERVICE_AUTO_START; else if (!lstrcmpiW(SO_STARTUP, PRSRV_MANUAL)) dwStart = SERVICE_DEMAND_START; @@ -867,6 +873,7 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline) rv = (rv && apxServiceSetOptions(hService, dwType, dwStart, + bDelayedStart, SERVICE_NO_CHANGE)); apxLogWrite(APXLOG_MARK_INFO "Service '%S' updated", diff --git a/src/native/windows/include/service.h b/src/native/windows/include/service.h index faebef4..8da60f4 100644 --- a/src/native/windows/include/service.h +++ b/src/native/windows/include/service.h @@ -24,6 +24,7 @@ typedef struct APXSERVENTRY { WCHAR szObjectName[SIZ_RESLEN]; WCHAR szServiceDescription[SIZ_DESLEN]; LPQUERY_SERVICE_CONFIGW lpConfig; + BOOL bDelayedStart; SERVICE_STATUS stServiceStatus; SERVICE_STATUS_PROCESS stStatusProcess; @@ -41,7 +42,8 @@ BOOL apxServiceSetNames(APXHANDLE hService, LPCWSTR szImagePath, LPCWSTR szUsername, LPCWSTR szPassword); BOOL apxServiceSetOptions(APXHANDLE hService, DWORD dwServiceType, - DWORD dwStartType, DWORD dwErrorControl); + DWORD dwStartType, BOOL bDelayedStart, + DWORD dwErrorControl); BOOL apxServiceControl(APXHANDLE hService, DWORD dwControl, UINT uMsg, LPAPXFNCALLBACK fnControlCallback, diff --git a/src/native/windows/src/service.c b/src/native/windows/src/service.c index 1fcc1c3..6317d58 100644 --- a/src/native/windows/src/service.c +++ b/src/native/windows/src/service.c @@ -107,6 +107,7 @@ apxServiceOpen(APXHANDLE hService, LPCWSTR szServiceName, DWORD dwOptions) { LPAPXSERVICE lpService; DWORD dwNeeded; + LPSERVICE_DELAYED_AUTO_START_INFO lpDelayedInfo; if (hService->dwType != APXHANDLE_TYPE_SERVICE) return FALSE; @@ -157,11 +158,36 @@ apxServiceOpen(APXHANDLE hService, LPCWSTR szServiceName, DWORD dwOptions) apxLogWrite(APXLOG_MARK_SYSERR); } } - lpService->stServiceEntry.lpConfig = (LPQUERY_SERVICE_CONFIGW)apxPoolAlloc(hService->hPool, - dwNeeded); - return QueryServiceConfigW(lpService->hService, - lpService->stServiceEntry.lpConfig, - dwNeeded, &dwNeeded); + lpService->stServiceEntry.lpConfig = (LPQUERY_SERVICE_CONFIGW)apxPoolAlloc(hService->hPool, + dwNeeded); + if (!QueryServiceConfigW(lpService->hService, + lpService->stServiceEntry.lpConfig, + dwNeeded, &dwNeeded)) { + return FALSE; + } + + if (!QueryServiceConfig2W(lpService->hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + NULL, 0, &dwNeeded)) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + // This is expected. The call is expected to fail with the required + // buffer size set in dwNeeded. + // Clear the last error to prevent it being logged if a genuine + // error occurs + SetLastError(ERROR_SUCCESS); + } else { + apxLogWrite(APXLOG_MARK_SYSERR); + } + } + lpDelayedInfo = (LPSERVICE_DELAYED_AUTO_START_INFO) apxPoolAlloc(hService->hPool, dwNeeded); + + if (!QueryServiceConfig2W(lpService->hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + (LPBYTE) lpDelayedInfo, dwNeeded, &dwNeeded)) { + return FALSE; + } + + lpService->stServiceEntry.bDelayedStart = lpDelayedInfo->fDelayedAutostart; + apxFree(lpDelayedInfo); + return TRUE; } LPAPXSERVENTRY @@ -240,9 +266,11 @@ BOOL apxServiceSetOptions(APXHANDLE hService, DWORD dwServiceType, DWORD dwStartType, + BOOL bDelayedStart, DWORD dwErrorControl) { LPAPXSERVICE lpService; + SERVICE_DELAYED_AUTO_START_INFO sDelayedInfo; if (hService->dwType != APXHANDLE_TYPE_SERVICE) return FALSE; @@ -254,10 +282,22 @@ apxServiceSetOptions(APXHANDLE hService, /* Check if the ServixeOpen has been called */ if (IS_INVALID_HANDLE(lpService->hService)) return FALSE; - return ChangeServiceConfig(lpService->hService, dwServiceType, - dwStartType, dwErrorControl, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL); + + if (!ChangeServiceConfig(lpService->hService, dwServiceType, + dwStartType, dwErrorControl, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL)) { + return FALSE; + } + + if (dwStartType == SERVICE_AUTO_START) { + sDelayedInfo.fDelayedAutostart = bDelayedStart; + return ChangeServiceConfig2A(lpService->hService, + SERVICE_CONFIG_DELAYED_AUTO_START_INFO, + &sDelayedInfo); + } + + return TRUE; } static BOOL diff --git a/src/site/xdoc/procrun.xml b/src/site/xdoc/procrun.xml index 5838b24..9a49b81 100644 --- a/src/site/xdoc/procrun.xml +++ b/src/site/xdoc/procrun.xml @@ -312,7 +312,7 @@ will add the new value(s) to any existing value(s). <tr> <td>--Startup</td> <td>manual</td> - <td>Service startup mode can be either <b>auto</b> or <b>manual</b></td> + <td>Service startup mode can be either <b>delayed</b>, <b>auto</b> or <b>manual</b></td> </tr> <tr> <td>--Type</td>