From 71cb6b0b4da4703fd3bf99ca1a181d4701f12947 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Tue, 14 Jun 2016 20:34:21 +0000 Subject: [PATCH] [SC] - Add the 'failure' command. The 'actions' option is not implemented yet. svn path=/trunk/; revision=71638 --- reactos/base/applications/sc/CMakeLists.txt | 1 + reactos/base/applications/sc/failure.c | 70 +++++++++++++++++++++ reactos/base/applications/sc/misc.c | 67 ++++++++++++++++++++ reactos/base/applications/sc/sc.c | 4 ++ reactos/base/applications/sc/sc.h | 9 +++ reactos/base/applications/sc/usage.c | 19 ++++++ 6 files changed, 170 insertions(+) create mode 100644 reactos/base/applications/sc/failure.c diff --git a/reactos/base/applications/sc/CMakeLists.txt b/reactos/base/applications/sc/CMakeLists.txt index 0b87178a4ab..e719bb66079 100644 --- a/reactos/base/applications/sc/CMakeLists.txt +++ b/reactos/base/applications/sc/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND SOURCE create.c delete.c description.c + failure.c misc.c print.c qfailure.c diff --git a/reactos/base/applications/sc/failure.c b/reactos/base/applications/sc/failure.c new file mode 100644 index 00000000000..badeca2079e --- /dev/null +++ b/reactos/base/applications/sc/failure.c @@ -0,0 +1,70 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/applications/sc/failure.c + * PURPOSE: Set the service failure actions + * COPYRIGHT: Copyright 2016 Eric Kohl + */ + +#include "sc.h" + +BOOL +SetFailure( + LPCTSTR *ServiceArgs, + INT ArgCount) +{ + SC_HANDLE hManager = NULL; + SC_HANDLE hService = NULL; + BOOL bResult = TRUE; + SERVICE_FAILURE_ACTIONS FailureActions; + LPCTSTR lpServiceName = NULL; + + if (!ParseFailureArguments(ServiceArgs, ArgCount, &lpServiceName, &FailureActions)) + { + SetFailureUsage(); + return FALSE; + } + + hManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_CONNECT); + if (hManager == NULL) + { + _tprintf(_T("[SC] OpenSCManager FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + hService = OpenService(hManager, + lpServiceName, + SERVICE_CHANGE_CONFIG); + if (hService == NULL) + { + _tprintf(_T("[SC] OpenService FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + if (!ChangeServiceConfig2(hService, + SERVICE_CONFIG_FAILURE_ACTIONS, + (LPBYTE)&FailureActions)) + { + _tprintf(_T("[SC] ChangeServiceConfig2 FAILED %lu:\n\n"), GetLastError()); + bResult = FALSE; + goto done; + } + + _tprintf(_T("[SC] ChangeServiceConfig2 SUCCESS\n\n")); + +done: + if (bResult == FALSE) + ReportLastError(); + + if (hService) + CloseServiceHandle(hService); + + if (hManager) + CloseServiceHandle(hManager); + + return bResult; +} diff --git a/reactos/base/applications/sc/misc.c b/reactos/base/applications/sc/misc.c index d1eff9cb154..24e4595a42a 100644 --- a/reactos/base/applications/sc/misc.c +++ b/reactos/base/applications/sc/misc.c @@ -158,3 +158,70 @@ ParseCreateConfigArguments( return (ArgCount == 0); } + + +BOOL +ParseFailureArguments( + IN LPCTSTR *ServiceArgs, + IN INT ArgCount, + OUT LPCTSTR *ppServiceName, + OUT LPSERVICE_FAILURE_ACTIONS pFailureActions) +{ + INT /*i,*/ ArgIndex = 1; + LPCTSTR lpActions = NULL; + LPCTSTR lpReset = NULL; + + if (ArgCount < 1) + return FALSE; + + ZeroMemory(pFailureActions, sizeof(SERVICE_FAILURE_ACTIONS)); + + *ppServiceName = ServiceArgs[0]; + + ArgCount--; + + while (ArgCount > 1) + { + if (!lstrcmpi(ServiceArgs[ArgIndex], _T("actions="))) + { + lpActions = (LPTSTR)ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("command="))) + { + pFailureActions->lpCommand = (LPTSTR)ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("reboot="))) + { + pFailureActions->lpRebootMsg = (LPTSTR)ServiceArgs[ArgIndex + 1]; + } + else if (!lstrcmpi(ServiceArgs[ArgIndex], _T("reset="))) + { + lpReset = (LPTSTR)ServiceArgs[ArgIndex + 1]; + } + + ArgIndex += 2; + ArgCount -= 2; + } + + if ((lpReset == NULL && lpActions != NULL) || + (lpReset != NULL && lpActions == NULL)) + { + _tprintf(_T("ERROR: The reset and actions options must be used simultaneously.\n\n")); + return FALSE; + } + + if (lpReset != NULL) + { + if (!lstrcmpi(lpReset, _T("infinite"))) + pFailureActions->dwResetPeriod = INFINITE; + else + pFailureActions->dwResetPeriod = _ttoi(lpReset); + } + + if (lpActions != NULL) + { + /* FIXME */ + } + + return (ArgCount == 0); +} diff --git a/reactos/base/applications/sc/sc.c b/reactos/base/applications/sc/sc.c index 215f2ee421c..b31c7cf5b45 100644 --- a/reactos/base/applications/sc/sc.c +++ b/reactos/base/applications/sc/sc.c @@ -268,6 +268,10 @@ ScControl(LPCTSTR Server, // remote machine name { SetConfig(ServiceArgs, ArgCount); } + else if (!lstrcmpi(Command, _T("failure"))) + { + SetFailure(ServiceArgs, ArgCount); + } else { MainUsage(); diff --git a/reactos/base/applications/sc/sc.h b/reactos/base/applications/sc/sc.h index 4a611c3a9a1..908f834de8a 100644 --- a/reactos/base/applications/sc/sc.h +++ b/reactos/base/applications/sc/sc.h @@ -44,6 +44,7 @@ BOOL SetConfig(LPCTSTR *ServiceArgs, INT ArgCount); BOOL QueryDescription(LPCTSTR ServiceName); BOOL SetDescription(LPCTSTR ServiceName, LPCTSTR Description); BOOL QueryFailure(LPCTSTR ServiceName); +BOOL SetFailure(LPCTSTR *ServiceArgs, INT ArgCount); /* print and error functions */ VOID PrintService(LPCTSTR ServiceName, LPSERVICE_STATUS_PROCESS pStatus, BOOL bExtended); @@ -57,6 +58,13 @@ ParseCreateConfigArguments( BOOL bChangeService, OUT LPSERVICE_CREATE_INFO lpServiceInfo); +BOOL +ParseFailureArguments( + LPCTSTR *ServiceArgs, + INT ArgCount, + OUT LPCTSTR *ppServiceName, + OUT LPSERVICE_FAILURE_ACTIONS pFailureActions); + /* usage functions */ VOID MainUsage(VOID); VOID StartUsage(VOID); @@ -74,5 +82,6 @@ VOID QueryDescriptionUsage(VOID); VOID QueryFailureUsage(VOID); VOID SetDescriptionUsage(VOID); VOID SetConfigUsage(VOID); +VOID SetFailureUsage(VOID); #endif /* _SC_PCH_ */ diff --git a/reactos/base/applications/sc/usage.c b/reactos/base/applications/sc/usage.c index 3132ed808dc..d50bad14534 100644 --- a/reactos/base/applications/sc/usage.c +++ b/reactos/base/applications/sc/usage.c @@ -243,3 +243,22 @@ VOID SetConfigUsage(VOID) _T(" DisplayName= \n") _T(" password= \n")); } + +VOID SetFailureUsage(VOID) +{ + _tprintf(_T("DESCRIPTION:\n") + _T(" Changes the actions upon failure.\n") + _T("USAGE:\n") + _T(" sc failure [service name] ...\n") + _T("\n") + _T("OPTIONS:\n") + _T(" reset= \n") + _T(" (Must be used in conjunction with actions= )\n") + _T(" reboot= \n") + _T(" command= \n") + _T(" actions= >\n") + _T(" (Must be used in conjunction with the reset= option)\n")); +}