[SC]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 3 Jul 2016 08:56:43 +0000 (08:56 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 3 Jul 2016 08:56:43 +0000 (08:56 +0000)
Failure command:
- Parse the actions parameter.
- Adjust the shutdown privilege in order to set the failure actions.

svn path=/trunk/; revision=71772

reactos/base/applications/sc/CMakeLists.txt
reactos/base/applications/sc/failure.c
reactos/base/applications/sc/misc.c
reactos/base/applications/sc/sc.h

index e9aa7ad..9019308 100644 (file)
@@ -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)
index 45683d6..83beda2 100644 (file)
@@ -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);
 
index 24e4595..ebbe96f 100644 (file)
@@ -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);
index 496734e..3357475 100644 (file)
@@ -3,12 +3,17 @@
 
 #include <stdarg.h>
 
+#define WIN32_NO_STATUS
 #include <windef.h>
 #include <winbase.h>
 #include <winsvc.h>
 #include <sddl.h>
 #include <tchar.h>
 
+#include <ndk/rtlfuncs.h>
+#include <ndk/setypes.h>
+
+
 #define SCDBG
 
 typedef struct