From: Eric Kohl Date: Sun, 3 Jul 2016 08:56:43 +0000 (+0000) Subject: [SC] X-Git-Tag: ReactOS-0.4.2~225 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=7507c1b2fcc02ea0c3dbe51745aa7c1895686127;ds=inline [SC] Failure command: - Parse the actions parameter. - Adjust the shutdown privilege in order to set the failure actions. svn path=/trunk/; revision=71772 --- diff --git a/reactos/base/applications/sc/CMakeLists.txt b/reactos/base/applications/sc/CMakeLists.txt index e9aa7add0c3..9019308ed2a 100644 --- a/reactos/base/applications/sc/CMakeLists.txt +++ b/reactos/base/applications/sc/CMakeLists.txt @@ -22,6 +22,6 @@ list(APPEND SOURCE add_executable(sc ${SOURCE} sc.rc) set_module_type(sc win32cui UNICODE) -add_importlibs(sc advapi32 msvcrt kernel32) +add_importlibs(sc advapi32 msvcrt kernel32 ntdll) add_pch(sc sc.h SOURCE) add_cd_file(TARGET sc DESTINATION reactos/system32 FOR all) diff --git a/reactos/base/applications/sc/failure.c b/reactos/base/applications/sc/failure.c index 45683d6d80a..83beda2d334 100644 --- a/reactos/base/applications/sc/failure.c +++ b/reactos/base/applications/sc/failure.c @@ -126,6 +126,9 @@ SetFailure( BOOL bResult = TRUE; SERVICE_FAILURE_ACTIONS FailureActions; LPCTSTR lpServiceName = NULL; + BOOLEAN Old = FALSE; + + ZeroMemory(&FailureActions, sizeof(SERVICE_FAILURE_ACTIONS)); if (!ParseFailureArguments(ServiceArgs, ArgCount, &lpServiceName, &FailureActions)) { @@ -145,7 +148,7 @@ SetFailure( hService = OpenService(hManager, lpServiceName, - SERVICE_CHANGE_CONFIG); + SERVICE_CHANGE_CONFIG | SERVICE_START); if (hService == NULL) { _tprintf(_T("[SC] OpenService FAILED %lu:\n\n"), GetLastError()); @@ -153,6 +156,8 @@ SetFailure( goto done; } + RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old); + if (!ChangeServiceConfig2(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)&FailureActions)) @@ -165,9 +170,14 @@ SetFailure( _tprintf(_T("[SC] ChangeServiceConfig2 SUCCESS\n\n")); done: + RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, Old, FALSE, &Old); + if (bResult == FALSE) ReportLastError(); + if (FailureActions.lpsaActions != NULL) + HeapFree(GetProcessHeap(), 0, FailureActions.lpsaActions); + if (hService) CloseServiceHandle(hService); diff --git a/reactos/base/applications/sc/misc.c b/reactos/base/applications/sc/misc.c index 24e4595a42a..ebbe96f62b3 100644 --- a/reactos/base/applications/sc/misc.c +++ b/reactos/base/applications/sc/misc.c @@ -160,6 +160,101 @@ ParseCreateConfigArguments( } +BOOL +ParseFailureActions( + IN LPCTSTR lpActions, + OUT DWORD *pcActions, + OUT SC_ACTION **ppActions) +{ + SC_ACTION *pActions = NULL; + LPTSTR pStringBuffer = NULL; + LPTSTR p; + INT nLength; + INT nCount = 0; + + *pcActions = 0; + *ppActions = NULL; + + nLength = _tcslen(lpActions); + + /* Allocate the string buffer */ + pStringBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 2) * sizeof(TCHAR)); + if (pStringBuffer == NULL) + { + return FALSE; + } + + /* Copy the actions string into the string buffer */ + CopyMemory(pStringBuffer, lpActions, nLength * sizeof(TCHAR)); + + /* Replace all slashes by null characters */ + p = pStringBuffer; + while (*p != 0 /*_T('\0')*/) + { + if (*p == _T('/')) + *p = 0; //_T('\0'); + p++; + } + + /* Count the arguments in the buffer */ + p = pStringBuffer; + while (*p != 0 /*_T('\0')*/) + { + nCount++; + + nLength = _tcslen(p); + p = (LPTSTR)((LONG_PTR)p + ((nLength + 1) * sizeof(TCHAR))); + } + + /* Allocate the actions buffer */ + pActions = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCount / 2 * sizeof(SC_ACTION)); + if (pActions == NULL) + { + HeapFree(GetProcessHeap(), 0, pStringBuffer); + return FALSE; + } + + /* Parse the string buffer */ + nCount = 0; + p = pStringBuffer; + while (*p != _T('\0')) + { + nLength = _tcslen(p); + + if (nCount % 2 == 0) + { + /* Action */ + if (_tcsicmp(p, _T("reboot"))) + pActions[nCount / 2].Type = SC_ACTION_REBOOT; + else if (_tcsicmp(p, _T("restart"))) + pActions[nCount / 2].Type = SC_ACTION_RESTART; + else if (_tcsicmp(p, _T("run"))) + pActions[nCount / 2].Type = SC_ACTION_RUN_COMMAND; + else + break; + } + else + { + /* Delay */ + pActions[nCount / 2].Delay = _tcstoul(p, NULL, 10); + if (pActions[nCount / 2].Delay == 0 && errno == ERANGE) + break; + } + + p = (LPTSTR)((LONG_PTR)p + ((nLength + 1) * sizeof(TCHAR))); + nCount++; + } + + /* Free the string buffer */ + HeapFree(GetProcessHeap(), 0, pStringBuffer); + + *pcActions = nCount / 2; + *ppActions = pActions; + + return TRUE; +} + + BOOL ParseFailureArguments( IN LPCTSTR *ServiceArgs, @@ -220,7 +315,12 @@ ParseFailureArguments( if (lpActions != NULL) { - /* FIXME */ + if (!ParseFailureActions(lpActions, + &pFailureActions->cActions, + &pFailureActions->lpsaActions)) + { + return FALSE; + } } return (ArgCount == 0); diff --git a/reactos/base/applications/sc/sc.h b/reactos/base/applications/sc/sc.h index 496734ec6ae..3357475d43a 100644 --- a/reactos/base/applications/sc/sc.h +++ b/reactos/base/applications/sc/sc.h @@ -3,12 +3,17 @@ #include +#define WIN32_NO_STATUS #include #include #include #include #include +#include +#include + + #define SCDBG typedef struct