[SERVICES] RChangeServiceConfig2A(): Zero-Initialize InfoW variable
[reactos.git] / base / system / services / rpcserver.c
index a4718aa..3517937 100644 (file)
@@ -13,6 +13,7 @@
 #include "services.h"
 
 #include <winnls.h>
+#include <strsafe.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -96,6 +97,7 @@ ScmServiceMapping = {SERVICE_READ,
                      SERVICE_EXECUTE,
                      SERVICE_ALL_ACCESS};
 
+DWORD g_dwServiceBits = 0;
 
 /* FUNCTIONS ***************************************************************/
 
@@ -1111,6 +1113,11 @@ RControlService(
 
         case SERVICE_CONTROL_PAUSE:
         case SERVICE_CONTROL_CONTINUE:
+        case SERVICE_CONTROL_PARAMCHANGE:
+        case SERVICE_CONTROL_NETBINDADD:
+        case SERVICE_CONTROL_NETBINDREMOVE:
+        case SERVICE_CONTROL_NETBINDENABLE:
+        case SERVICE_CONTROL_NETBINDDISABLE:
             DesiredAccess = SERVICE_PAUSE_CONTINUE;
             break;
 
@@ -1225,10 +1232,25 @@ RControlService(
                 if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
                     return ERROR_INVALID_SERVICE_CONTROL;
                 break;
+
+            case SERVICE_CONTROL_PARAMCHANGE:
+                if ((dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE) == 0)
+                    return ERROR_INVALID_SERVICE_CONTROL;
+                break;
+
+            case SERVICE_CONTROL_NETBINDADD:
+            case SERVICE_CONTROL_NETBINDREMOVE:
+            case SERVICE_CONTROL_NETBINDENABLE:
+            case SERVICE_CONTROL_NETBINDDISABLE:
+                if ((dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE) == 0)
+                    return ERROR_INVALID_SERVICE_CONTROL;
+                break;
         }
 
         /* Send control code to the service */
-        dwError = ScmControlService(lpService,
+        dwError = ScmControlService(lpService->lpImage->hControlPipe,
+                                    lpService->lpServiceName,
+                                    (SERVICE_STATUS_HANDLE)lpService,
                                     dwControl);
 
         /* Return service status information */
@@ -1239,36 +1261,36 @@ RControlService(
 
     if (dwError == ERROR_SUCCESS)
     {
-            if (dwControl == SERVICE_CONTROL_STOP ||
-                dwControl == SERVICE_CONTROL_PAUSE ||
-                dwControl == SERVICE_CONTROL_CONTINUE)
-            {
-                /* Log a successful send control */
+        if (dwControl == SERVICE_CONTROL_STOP ||
+            dwControl == SERVICE_CONTROL_PAUSE ||
+            dwControl == SERVICE_CONTROL_CONTINUE)
+        {
+            /* Log a successful send control */
 
-                switch (dwControl)
-                {
-                    case SERVICE_CONTROL_STOP:
-                        uID = IDS_SERVICE_STOP;
-                        break;
+            switch (dwControl)
+            {
+                case SERVICE_CONTROL_STOP:
+                    uID = IDS_SERVICE_STOP;
+                    break;
 
-                    case SERVICE_CONTROL_PAUSE:
-                        uID = IDS_SERVICE_PAUSE;
-                        break;
+                case SERVICE_CONTROL_PAUSE:
+                    uID = IDS_SERVICE_PAUSE;
+                    break;
 
-                    case SERVICE_CONTROL_CONTINUE:
-                        uID = IDS_SERVICE_RESUME;
-                        break;
-                }
-                LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+                case SERVICE_CONTROL_CONTINUE:
+                    uID = IDS_SERVICE_RESUME;
+                    break;
+            }
+            LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
 
-                lpLogStrings[0] = lpService->lpDisplayName;
-                lpLogStrings[1] = szLogBuffer;
+            lpLogStrings[0] = lpService->lpDisplayName;
+            lpLogStrings[1] = szLogBuffer;
 
-                ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
-                            EVENTLOG_INFORMATION_TYPE,
-                            2,
-                            lpLogStrings);
-            }
+            ScmLogEvent(EVENT_SERVICE_CONTROL_SUCCESS,
+                        EVENTLOG_INFORMATION_TYPE,
+                        2,
+                        lpLogStrings);
+        }
     }
 
     return dwError;
@@ -1725,6 +1747,28 @@ RSetServiceStatus(
     /* Restore the previous service type */
     lpService->Status.dwServiceType = dwPreviousType;
 
+    /* Dereference a stopped service */
+    if ((lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
+        (lpServiceStatus->dwCurrentState == SERVICE_STOPPED))
+    {
+        /* Decrement the image run counter */
+        lpService->lpImage->dwImageRunCount--;
+
+        /* If we just stopped the last running service... */
+        if (lpService->lpImage->dwImageRunCount == 0)
+        {
+            /* Stop the dispatcher thread */
+            ScmControlService(lpService->lpImage->hControlPipe,
+                              L"",
+                              (SERVICE_STATUS_HANDLE)lpService,
+                              SERVICE_CONTROL_STOP);
+
+            /* Remove the service image */
+            ScmRemoveServiceImage(lpService->lpImage);
+            lpService->lpImage = NULL;
+        }
+    }
+
     /* Unlock the service database */
     ScmUnlockDatabase();
 
@@ -1733,7 +1777,8 @@ RSetServiceStatus(
         (lpServiceStatus->dwWin32ExitCode != ERROR_SUCCESS))
     {
         /* Log a failed service stop */
-        swprintf(szLogBuffer, L"%lu", lpServiceStatus->dwWin32ExitCode);
+        StringCchPrintfW(szLogBuffer, ARRAYSIZE(szLogBuffer),
+                         L"%lu", lpServiceStatus->dwWin32ExitCode);
         lpLogStrings[0] = lpService->lpDisplayName;
         lpLogStrings[1] = szLogBuffer;
 
@@ -1763,7 +1808,7 @@ RSetServiceStatus(
                 break;
         }
 
-        LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, 80);
+        LoadStringW(GetModuleHandle(NULL), uID, szLogBuffer, ARRAYSIZE(szLogBuffer));
         lpLogStrings[0] = lpService->lpDisplayName;
         lpLogStrings[1] = szLogBuffer;
 
@@ -1816,8 +1861,47 @@ RI_ScSetServiceBitsW(
     int bUpdateImmediately,
     wchar_t *lpString)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    PSERVICE pService;
+
+    DPRINT("RI_ScSetServiceBitsW(%p %lx %d %d %S)\n",
+           hServiceStatus, dwServiceBits, bSetBitsOn,
+           bUpdateImmediately, lpString);
+
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    if (lpString != NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    if (hServiceStatus == 0)
+    {
+        DPRINT("hServiceStatus == NULL!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    // FIXME: Validate the status handle
+    pService = (PSERVICE)hServiceStatus;
+
+    if (bSetBitsOn)
+    {
+        DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+        DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+        pService->dwServiceBits |= dwServiceBits;
+        g_dwServiceBits |= dwServiceBits;
+        DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+        DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+    }
+    else
+    {
+        DPRINT("Old service bits: %08lx\n", pService->dwServiceBits);
+        DPRINT("Old global service bits: %08lx\n", g_dwServiceBits);
+        pService->dwServiceBits &= ~dwServiceBits;
+        g_dwServiceBits &= ~dwServiceBits;
+        DPRINT("New service bits: %08lx\n", pService->dwServiceBits);
+        DPRINT("New global service bits: %08lx\n", g_dwServiceBits);
+    }
+
+    return ERROR_SUCCESS;
 }
 
 
@@ -2463,7 +2547,6 @@ RCreateServiceW(
                 goto done;
         }
 
-DPRINT1("\n");
         /* Write the security descriptor */
         dwError = ScmWriteSecurityDescriptor(hServiceKey,
                                              lpService->pSecurityDescriptor);
@@ -3291,8 +3374,17 @@ RI_ScSetServiceBitsA(
     int bUpdateImmediately,
     char *lpString)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    if (lpString != NULL)
+        return ERROR_INVALID_PARAMETER;
+
+    return RI_ScSetServiceBitsW(hServiceStatus,
+                                dwServiceBits,
+                                bSetBitsOn,
+                                bUpdateImmediately,
+                                NULL);
 }
 
 
@@ -5011,13 +5103,17 @@ RChangeServiceConfig2A(
     SC_RPC_HANDLE hService,
     SC_RPC_CONFIG_INFOA Info)
 {
-    SC_RPC_CONFIG_INFOW InfoW;
+    SC_RPC_CONFIG_INFOW InfoW = { 0 };
     DWORD dwRet, dwLength;
     PVOID ptr = NULL;
 
     DPRINT("RChangeServiceConfig2A() called\n");
     DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
 
+    if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+        (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+        return ERROR_INVALID_LEVEL;
+
     InfoW.dwInfoLevel = Info.dwInfoLevel;
 
     if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
@@ -5416,6 +5512,10 @@ RChangeServiceConfig2W(
     if (ScmShutdown)
         return ERROR_SHUTDOWN_IN_PROGRESS;
 
+    if ((Info.dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+        (Info.dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+        return ERROR_INVALID_LEVEL;
+
     hSvc = ScmGetServiceFromHandle(hService);
     if (hSvc == NULL)
     {
@@ -5552,6 +5652,10 @@ RQueryServiceConfig2A(
     if (ScmShutdown)
         return ERROR_SHUTDOWN_IN_PROGRESS;
 
+    if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+        (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+        return ERROR_INVALID_LEVEL;
+
     hSvc = ScmGetServiceFromHandle(hService);
     if (hSvc == NULL)
     {
@@ -5790,6 +5894,10 @@ RQueryServiceConfig2W(
     if (ScmShutdown)
         return ERROR_SHUTDOWN_IN_PROGRESS;
 
+    if ((dwInfoLevel < SERVICE_CONFIG_DESCRIPTION) ||
+        (dwInfoLevel > SERVICE_CONFIG_FAILURE_ACTIONS))
+        return ERROR_INVALID_LEVEL;
+
     hSvc = ScmGetServiceFromHandle(hService);
     if (hSvc == NULL)
     {