GetServiceDisplayNameA/W and GetServiceKeyNameA/W must return an empty String if...
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
index 4976381..2e3c79f 100644 (file)
@@ -191,15 +191,15 @@ ScmRpcStatusToWinError(RPC_STATUS Status)
 {
     switch (Status)
     {
+        case RPC_S_INVALID_BINDING:
         case RPC_X_SS_IN_NULL_CONTEXT:
             return ERROR_INVALID_HANDLE;
 
-        case RPC_X_NULL_REF_POINTER:
         case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
         case RPC_X_BYTE_COUNT_TOO_SMALL:
             return ERROR_INVALID_PARAMETER;
 
-        case STATUS_ACCESS_VIOLATION:
+        case RPC_X_NULL_REF_POINTER:
             return ERROR_INVALID_ADDRESS;
 
         default:
@@ -229,10 +229,11 @@ ChangeServiceConfig2A(SC_HANDLE hService,
     {
         case SERVICE_CONFIG_DESCRIPTION:
             Info.psd = (LPSERVICE_DESCRIPTIONA)&lpInfo;
+            Info.lpDescription = ((LPSERVICE_DESCRIPTIONA)lpInfo)->lpDescription; //HACK
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
-            Info.psfa = (LPSERVICE_FAILURE_ACTIONSA)&lpInfo;
+            Info.psfa = (LPSERVICE_FAILURE_ACTIONSA)lpInfo;
             break;
 
         default:
@@ -286,10 +287,8 @@ ChangeServiceConfig2W(SC_HANDLE hService,
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
-        {
             Info.psd = (LPSERVICE_DESCRIPTIONW)&lpInfo;
             break;
-        }
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
             Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)&lpInfo;
@@ -486,6 +485,12 @@ CloseServiceHandle(SC_HANDLE hSCObject)
 
     TRACE("CloseServiceHandle() called\n");
 
+    if (!hSCObject)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
@@ -589,68 +594,24 @@ CreateServiceA(SC_HANDLE hSCManager,
                LPCSTR lpServiceStartName,
                LPCSTR lpPassword)
 {
-    SC_HANDLE RetVal = NULL;
-    LPWSTR lpServiceNameW = NULL;
-    LPWSTR lpDisplayNameW = NULL;
-    LPWSTR lpBinaryPathNameW = NULL;
-    LPWSTR lpLoadOrderGroupW = NULL;
-    LPWSTR lpDependenciesW = NULL;
-    LPWSTR lpServiceStartNameW = NULL;
-    LPWSTR lpPasswordW = NULL;
+    SC_HANDLE hService = NULL;
     DWORD dwDependenciesLength = 0;
+    DWORD dwError;
     DWORD dwLength;
-    int len;
     LPSTR lpStr;
 
-    if (lpServiceName)
-    {
-        len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
-        lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpServiceNameW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
-    }
-
-    if (lpDisplayName)
-    {
-        len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
-        lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpDisplayNameW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
-    }
-
-    if (lpBinaryPathName)
-    {
-        len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
-        lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpBinaryPathNameW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
-    }
+    TRACE("CreateServiceA() called\n");
+    TRACE("%p %s %s\n", hSCManager, 
+          lpServiceName, lpDisplayName);
 
-    if (lpLoadOrderGroup)
+    if (!hSCManager)
     {
-        len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
-        lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpLoadOrderGroupW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
+        SetLastError(ERROR_INVALID_HANDLE);
+        return NULL;
     }
 
-    if (lpDependencies)
+    /* Calculate the Dependencies length*/
+    if (lpDependencies != NULL)
     {
         lpStr = (LPSTR)lpDependencies;
         while (*lpStr)
@@ -660,77 +621,44 @@ CreateServiceA(SC_HANDLE hSCManager,
             lpStr = lpStr + dwLength;
         }
         dwDependenciesLength++;
-
-        lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
-        if (!lpDependenciesW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
     }
 
-    if (lpServiceStartName)
+    /* FIXME: Encrypt the password */
+
+    RpcTryExcept
     {
-        len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
-        lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpServiceStartNameW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
+        /* Call to services.exe using RPC */
+        dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager,
+                                  (LPSTR)lpServiceName,
+                                  (LPSTR)lpDisplayName,
+                                  dwDesiredAccess,
+                                  dwServiceType,
+                                  dwStartType,
+                                  dwErrorControl,
+                                  (LPSTR)lpBinaryPathName,
+                                  (LPSTR)lpLoadOrderGroup,
+                                  lpdwTagId,
+                                  (LPBYTE)lpDependencies,
+                                  dwDependenciesLength,
+                                  (LPSTR)lpServiceStartName,
+                                  NULL,              /* FIXME: lpPassword */
+                                  0,                 /* FIXME: dwPasswordLength */
+                                  (SC_RPC_HANDLE *)&hService);
     }
-
-    if (lpPassword)
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
     {
-        len = MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, NULL, 0);
-        lpPasswordW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        if (!lpPasswordW)
-        {
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto cleanup;
-        }
-        MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, lpPasswordW, len);
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
     }
+    RpcEndExcept;
 
-    RetVal = CreateServiceW(hSCManager,
-                            lpServiceNameW,
-                            lpDisplayNameW,
-                            dwDesiredAccess,
-                            dwServiceType,
-                            dwStartType,
-                            dwErrorControl,
-                            lpBinaryPathNameW,
-                            lpLoadOrderGroupW,
-                            lpdwTagId,
-                            lpDependenciesW,
-                            lpServiceStartNameW,
-                            lpPasswordW);
-
-cleanup:
-    if (lpServiceNameW !=NULL)
-        HeapFree(GetProcessHeap(), 0, lpServiceNameW);
-
-    if (lpDisplayNameW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
-
-    if (lpBinaryPathNameW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
-
-    if (lpLoadOrderGroupW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
-
-    if (lpDependenciesW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpDependenciesW);
-
-    if (lpServiceStartNameW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
-
-    if (lpPasswordW != NULL)
-        HeapFree(GetProcessHeap(), 0, lpPasswordW);
+    if (dwError != ERROR_SUCCESS)
+    {
+        ERR("RCreateServiceA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return NULL;
+    }
 
-    return RetVal;
+    return hService;
 }
 
 
@@ -764,6 +692,12 @@ CreateServiceW(SC_HANDLE hSCManager,
     TRACE("%p %S %S\n", hSCManager, 
           lpServiceName, lpDisplayName);
 
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return NULL;
+    }
+
     /* Calculate the Dependencies length*/
     if (lpDependencies != NULL)
     {
@@ -1019,6 +953,48 @@ EnumServicesStatusA(SC_HANDLE hSCManager,
 
     TRACE("EnumServicesStatusA() called\n");
 
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (dwServiceType != SERVICE_DRIVER && dwServiceType != SERVICE_WIN32)
+    {
+        if (pcbBytesNeeded && lpServicesReturned)
+        {
+            *pcbBytesNeeded = 0;
+            *lpServicesReturned = 0;
+        }
+
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (dwServiceState != SERVICE_ACTIVE && dwServiceState != SERVICE_INACTIVE && dwServiceState != SERVICE_STATE_ALL)
+    {
+            if (pcbBytesNeeded)
+                *pcbBytesNeeded = 0;
+
+            if (lpServicesReturned)
+                *lpServicesReturned = 0;
+
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    if (!pcbBytesNeeded || !lpServicesReturned)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
+    if (!lpServices && cbBufSize != 0)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         dwError = REnumServicesStatusA((SC_RPC_HANDLE)hSCManager,
@@ -1084,6 +1060,12 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
 
     TRACE("EnumServicesStatusW() called\n");
 
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
@@ -1151,6 +1133,19 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
 
     TRACE("EnumServicesStatusExA() called\n");
 
+    if (InfoLevel != SC_ENUM_PROCESS_INFO)
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+
     RpcTryExcept
     {
         dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager,
@@ -1294,19 +1289,34 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
                        LPDWORD lpcchBuffer)
 {
     DWORD dwError;
+    LPSTR lpNameBuffer;
+    CHAR szEmptyName[] = "";
 
     TRACE("GetServiceDisplayNameA() called\n");
     TRACE("%p %s %p %p\n", hSCManager,
           debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
 
-    if (!lpDisplayName)
-        *lpcchBuffer = 0;
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!lpDisplayName || *lpcchBuffer < sizeof(CHAR))
+    {
+        lpNameBuffer = szEmptyName;
+        *lpcchBuffer = sizeof(CHAR);
+    }
+    else
+    {
+        lpNameBuffer = lpDisplayName;
+    }
 
     RpcTryExcept
     {
         dwError = RGetServiceDisplayNameA((SC_RPC_HANDLE)hSCManager,
                                           lpServiceName,
-                                          lpDisplayName,
+                                          lpNameBuffer,
                                           lpcchBuffer);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -1314,8 +1324,6 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
         /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
         dwError = ScmRpcStatusToWinError(RpcExceptionCode());
     }
-
-
     RpcEndExcept;
 
     if (dwError != ERROR_SUCCESS)
@@ -1341,17 +1349,32 @@ GetServiceDisplayNameW(SC_HANDLE hSCManager,
                        LPDWORD lpcchBuffer)
 {
     DWORD dwError;
+    LPWSTR lpNameBuffer;
+    WCHAR szEmptyName[] = L"";
 
     TRACE("GetServiceDisplayNameW() called\n");
 
-    if (!lpDisplayName)
-        *lpcchBuffer = 0;
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!lpDisplayName || *lpcchBuffer < sizeof(WCHAR))
+    {
+        lpNameBuffer = szEmptyName;
+        *lpcchBuffer = sizeof(WCHAR);
+    }
+    else
+    {
+        lpNameBuffer = lpDisplayName;
+    }
 
     RpcTryExcept
     {
         dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager,
                                           lpServiceName,
-                                          lpDisplayName,
+                                          lpNameBuffer,
                                           lpcchBuffer);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -1383,17 +1406,32 @@ GetServiceKeyNameA(SC_HANDLE hSCManager,
                    LPDWORD lpcchBuffer)
 {
     DWORD dwError;
+    LPSTR lpNameBuffer;
+    CHAR szEmptyName[] = "";
 
     TRACE("GetServiceKeyNameA() called\n");
 
-    if (!lpServiceName)
-        *lpcchBuffer = 0;
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!lpServiceName || *lpcchBuffer < sizeof(CHAR))
+    {
+        lpNameBuffer = szEmptyName;
+        *lpcchBuffer = sizeof(CHAR);
+    }
+    else
+    {
+        lpNameBuffer = lpServiceName;
+    }
 
     RpcTryExcept
     {
         dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager,
                                       lpDisplayName,
-                                      lpServiceName,
+                                      lpNameBuffer,
                                       lpcchBuffer);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -1425,17 +1463,32 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
                    LPDWORD lpcchBuffer)
 {
     DWORD dwError;
+    LPWSTR lpNameBuffer;
+    WCHAR szEmptyName[] = L"";
 
     TRACE("GetServiceKeyNameW() called\n");
 
-    if (!lpDisplayName)
-        *lpcchBuffer = 0;
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (!lpServiceName || *lpcchBuffer < sizeof(WCHAR))
+    {
+        lpNameBuffer = szEmptyName;
+        *lpcchBuffer = sizeof(WCHAR);
+    }
+    else
+    {
+        lpNameBuffer = lpServiceName;
+    }
 
     RpcTryExcept
     {
         dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager,
                                       lpDisplayName,
-                                      lpServiceName,
+                                      lpNameBuffer,
                                       lpcchBuffer);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -1639,6 +1692,12 @@ OpenServiceA(SC_HANDLE hSCManager,
     TRACE("OpenServiceA(%p, %s, %lx)\n",
            hSCManager, lpServiceName, dwDesiredAccess);
 
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return NULL;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
@@ -1682,6 +1741,12 @@ OpenServiceW(SC_HANDLE hSCManager,
     TRACE("OpenServiceW(%p, %S, %lx)\n",
            hSCManager, lpServiceName, dwDesiredAccess);
 
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return NULL;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
@@ -1867,7 +1932,7 @@ QueryServiceConfig2A(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    TRACE("QueryServiceConfig2A(%p, %lu, %p, %lu, %p)\n",
+    DbgPrint("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
            hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
     if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
@@ -2264,6 +2329,12 @@ QueryServiceStatus(SC_HANDLE hService,
     TRACE("QueryServiceStatus(%p, %p)\n",
            hService, lpServiceStatus);
 
+    if (!hService)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */
@@ -2303,6 +2374,12 @@ QueryServiceStatusEx(SC_HANDLE hService,
 
     TRACE("QueryServiceStatusEx() called\n");
 
+    if (InfoLevel != SC_STATUS_PROCESS_INFO)
+    {
+        SetLastError(ERROR_INVALID_LEVEL);
+        return FALSE;
+    }
+
     RpcTryExcept
     {
         /* Call to services.exe using RPC */