[SERVICES]
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
index d3117e1..64fa02c 100644 (file)
@@ -229,11 +229,11 @@ ChangeServiceConfig2W(SC_HANDLE hService,
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
-            Info.psd = (LPSERVICE_DESCRIPTIONW)&lpInfo;
+            Info.psd = (LPSERVICE_DESCRIPTIONW)lpInfo;
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
-            Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)&lpInfo;
+            Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)lpInfo;
             break;
 
         default:
@@ -288,14 +288,14 @@ ChangeServiceConfigA(SC_HANDLE hService,
     DWORD dwError;
     DWORD dwDependenciesLength = 0;
     DWORD dwLength;
-    LPSTR lpStr;
+    LPCSTR lpStr;
 
     TRACE("ChangeServiceConfigA() called\n");
 
     /* Calculate the Dependencies length*/
     if (lpDependencies != NULL)
     {
-        lpStr = (LPSTR)lpDependencies;
+        lpStr = lpDependencies;
         while (*lpStr)
         {
             dwLength = strlen(lpStr) + 1;
@@ -362,14 +362,14 @@ ChangeServiceConfigW(SC_HANDLE hService,
     DWORD dwError;
     DWORD dwDependenciesLength = 0;
     DWORD dwLength;
-    LPWSTR lpStr;
+    LPCWSTR lpStr;
 
     TRACE("ChangeServiceConfigW() called\n");
 
     /* Calculate the Dependencies length*/
     if (lpDependencies != NULL)
     {
-        lpStr = (LPWSTR)lpDependencies;
+        lpStr = lpDependencies;
         while (*lpStr)
         {
             dwLength = wcslen(lpStr) + 1;
@@ -540,10 +540,10 @@ CreateServiceA(SC_HANDLE hSCManager,
     DWORD dwDependenciesLength = 0;
     DWORD dwError;
     DWORD dwLength;
-    LPSTR lpStr;
+    LPCSTR lpStr;
 
     TRACE("CreateServiceA() called\n");
-    TRACE("%p %s %s\n", hSCManager, 
+    TRACE("%p %s %s\n", hSCManager,
           lpServiceName, lpDisplayName);
 
     if (!hSCManager)
@@ -552,10 +552,10 @@ CreateServiceA(SC_HANDLE hSCManager,
         return NULL;
     }
 
-    /* Calculate the Dependencies length*/
+    /* Calculate the Dependencies length */
     if (lpDependencies != NULL)
     {
-        lpStr = (LPSTR)lpDependencies;
+        lpStr = lpDependencies;
         while (*lpStr)
         {
             dwLength = strlen(lpStr) + 1;
@@ -628,10 +628,10 @@ CreateServiceW(SC_HANDLE hSCManager,
     DWORD dwDependenciesLength = 0;
     DWORD dwError;
     DWORD dwLength;
-    LPWSTR lpStr;
+    LPCWSTR lpStr;
 
     TRACE("CreateServiceW() called\n");
-    TRACE("%p %S %S\n", hSCManager, 
+    TRACE("%p %S %S\n", hSCManager,
           lpServiceName, lpDisplayName);
 
     if (!hSCManager)
@@ -640,10 +640,10 @@ CreateServiceW(SC_HANDLE hSCManager,
         return NULL;
     }
 
-    /* Calculate the Dependencies length*/
+    /* Calculate the Dependencies length */
     if (lpDependencies != NULL)
     {
-        lpStr = (LPWSTR)lpDependencies;
+        lpStr = lpDependencies;
         while (*lpStr)
         {
             dwLength = wcslen(lpStr) + 1;
@@ -2076,23 +2076,43 @@ QueryServiceConfig2A(SC_HANDLE hService,
                      DWORD cbBufSize,
                      LPDWORD pcbBytesNeeded)
 {
+    SERVICE_DESCRIPTIONA ServiceDescription;
+    SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
+    LPBYTE lpTempBuffer;
+    BOOL bUseTempBuffer = FALSE;
+    DWORD dwBufferSize;
     DWORD dwError;
 
     TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
-    if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
-        dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
-    {
-        SetLastError(ERROR_INVALID_LEVEL);
-        return FALSE;
-    }
+    lpTempBuffer = lpBuffer;
+    dwBufferSize = cbBufSize;
 
-    if ((lpBuffer == NULL && cbBufSize != 0) ||
-        pcbBytesNeeded == NULL)
+    switch (dwInfoLevel)
     {
-        SetLastError(ERROR_INVALID_ADDRESS);
-        return FALSE;
+        case SERVICE_CONFIG_DESCRIPTION:
+            if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA)))
+            {
+                lpTempBuffer = (LPBYTE)&ServiceDescription;
+                dwBufferSize = sizeof(SERVICE_DESCRIPTIONA);
+                bUseTempBuffer = TRUE;
+            }
+            break;
+
+        case SERVICE_CONFIG_FAILURE_ACTIONS:
+            if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA)))
+            {
+                lpTempBuffer = (LPBYTE)&ServiceFailureActions;
+                dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA);
+                bUseTempBuffer = TRUE;
+            }
+            break;
+
+        default:
+            WARN("Unknown info level 0x%lx\n", dwInfoLevel);
+            SetLastError(ERROR_INVALID_LEVEL);
+            return FALSE;
     }
 
     RpcTryExcept
@@ -2100,8 +2120,8 @@ QueryServiceConfig2A(SC_HANDLE hService,
         /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
-                                        lpBuffer,
-                                        cbBufSize,
+                                        lpTempBuffer,
+                                        dwBufferSize,
                                         pcbBytesNeeded);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2117,40 +2137,42 @@ QueryServiceConfig2A(SC_HANDLE hService,
         return FALSE;
     }
 
+    if (bUseTempBuffer == TRUE)
+    {
+        TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return FALSE;
+    }
+
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
             {
-                LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
+                LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
 
                 if (lpPtr->lpDescription != NULL)
                     lpPtr->lpDescription =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
             }
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
             {
-                LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
+                LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
 
                 if (lpPtr->lpRebootMsg != NULL)
                     lpPtr->lpRebootMsg =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
 
                 if (lpPtr->lpCommand != NULL)
                     lpPtr->lpCommand =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
 
                 if (lpPtr->lpsaActions != NULL)
                     lpPtr->lpsaActions =
-                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+                        (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
             }
             break;
-
-        default:
-            ERR("Unknown info level 0x%lx\n", dwInfoLevel);
-            SetLastError(ERROR_INVALID_PARAMETER);
-            return FALSE;
     }
 
     TRACE("QueryServiceConfig2A() done\n");
@@ -2171,23 +2193,43 @@ QueryServiceConfig2W(SC_HANDLE hService,
                      DWORD cbBufSize,
                      LPDWORD pcbBytesNeeded)
 {
+    SERVICE_DESCRIPTIONW ServiceDescription;
+    SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
+    LPBYTE lpTempBuffer;
+    BOOL bUseTempBuffer = FALSE;
+    DWORD dwBufferSize;
     DWORD dwError;
 
     TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
            hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
-    if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
-        dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
-    {
-        SetLastError(ERROR_INVALID_LEVEL);
-        return FALSE;
-    }
+    lpTempBuffer = lpBuffer;
+    dwBufferSize = cbBufSize;
 
-    if ((lpBuffer == NULL && cbBufSize != 0) ||
-        pcbBytesNeeded == NULL)
+    switch (dwInfoLevel)
     {
-        SetLastError(ERROR_INVALID_ADDRESS);
-        return FALSE;
+        case SERVICE_CONFIG_DESCRIPTION:
+            if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)))
+            {
+                lpTempBuffer = (LPBYTE)&ServiceDescription;
+                dwBufferSize = sizeof(SERVICE_DESCRIPTIONW);
+                bUseTempBuffer = TRUE;
+            }
+            break;
+
+        case SERVICE_CONFIG_FAILURE_ACTIONS:
+            if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)))
+            {
+                lpTempBuffer = (LPBYTE)&ServiceFailureActions;
+                dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+                bUseTempBuffer = TRUE;
+            }
+            break;
+
+        default:
+            WARN("Unknown info level 0x%lx\n", dwInfoLevel);
+            SetLastError(ERROR_INVALID_LEVEL);
+            return FALSE;
     }
 
     RpcTryExcept
@@ -2195,8 +2237,8 @@ QueryServiceConfig2W(SC_HANDLE hService,
         /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
-                                        lpBuffer,
-                                        cbBufSize,
+                                        lpTempBuffer,
+                                        dwBufferSize,
                                         pcbBytesNeeded);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2212,40 +2254,42 @@ QueryServiceConfig2W(SC_HANDLE hService,
         return FALSE;
     }
 
+    if (bUseTempBuffer == TRUE)
+    {
+        TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return FALSE;
+    }
+
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
             {
-                LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
+                LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
 
                 if (lpPtr->lpDescription != NULL)
                     lpPtr->lpDescription =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
             }
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
             {
-                LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
+                LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
 
                 if (lpPtr->lpRebootMsg != NULL)
                     lpPtr->lpRebootMsg =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
 
                 if (lpPtr->lpCommand != NULL)
                     lpPtr->lpCommand =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
 
                 if (lpPtr->lpsaActions != NULL)
                     lpPtr->lpsaActions =
-                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+                        (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
             }
             break;
-
-        default:
-            WARN("Unknown info level 0x%lx\n", dwInfoLevel);
-            SetLastError(ERROR_INVALID_PARAMETER);
-            return FALSE;
     }
 
     TRACE("QueryServiceConfig2W() done\n");
@@ -2265,16 +2309,30 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
                         DWORD cbBufSize,
                         LPDWORD pcbBytesNeeded)
 {
+    QUERY_SERVICE_LOCK_STATUSA LockStatus;
+    LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
+    DWORD dwBufferSize;
     DWORD dwError;
 
     TRACE("QueryServiceLockStatusA() called\n");
 
+    if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
+    {
+        lpStatusPtr = &LockStatus;
+        dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
+    }
+    else
+    {
+        lpStatusPtr = lpLockStatus;
+        dwBufferSize = cbBufSize;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
-                                           lpLockStatus,
-                                           cbBufSize,
+                                           lpStatusPtr,
+                                           dwBufferSize,
                                            pcbBytesNeeded);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2290,10 +2348,10 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    if (lpLockStatus->lpLockOwner != NULL)
+    if (lpStatusPtr->lpLockOwner != NULL)
     {
-        lpLockStatus->lpLockOwner =
-            (LPSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
+        lpStatusPtr->lpLockOwner =
+            (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
     }
 
     TRACE("QueryServiceLockStatusA() done\n");
@@ -2313,16 +2371,30 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
                         DWORD cbBufSize,
                         LPDWORD pcbBytesNeeded)
 {
+    QUERY_SERVICE_LOCK_STATUSW LockStatus;
+    LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
+    DWORD dwBufferSize;
     DWORD dwError;
 
     TRACE("QueryServiceLockStatusW() called\n");
 
+    if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
+    {
+        lpStatusPtr = &LockStatus;
+        dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
+    }
+    else
+    {
+        lpStatusPtr = lpLockStatus;
+        dwBufferSize = cbBufSize;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
-                                           lpLockStatus,
-                                           cbBufSize,
+                                           lpStatusPtr,
+                                           dwBufferSize,
                                            pcbBytesNeeded);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2338,10 +2410,10 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    if (lpLockStatus->lpLockOwner != NULL)
+    if (lpStatusPtr->lpLockOwner != NULL)
     {
-        lpLockStatus->lpLockOwner =
-            (LPWSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
+        lpStatusPtr->lpLockOwner =
+            (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
     }
 
     TRACE("QueryServiceLockStatusW() done\n");
@@ -2526,6 +2598,13 @@ QueryServiceStatusEx(SC_HANDLE hService,
         return FALSE;
     }
 
+    if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
+    {
+        *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */