- GetServiceDisplayNameA/W and GetServiceKeyNameA/W: Fix returned name size.
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
index f4cc051..44df545 100644 (file)
@@ -78,6 +78,26 @@ HandleUnbind(VOID)
 #endif
 
 
+static DWORD
+ScmRpcStatusToWinError(RPC_STATUS Status)
+{
+    switch (Status)
+    {
+        case RPC_X_SS_IN_NULL_CONTEXT:
+            return ERROR_INVALID_HANDLE;
+
+        case RPC_X_NULL_REF_POINTER:
+            return ERROR_INVALID_PARAMETER;
+
+        case STATUS_ACCESS_VIOLATION:
+            return ERROR_INVALID_ADDRESS;
+
+        default:
+            return (DWORD)Status;
+    }
+}
+
+
 /**********************************************************************
  *  ChangeServiceConfig2A
  *
@@ -116,9 +136,18 @@ ChangeServiceConfig2A(SC_HANDLE hService,
 
     HandleBind();
 
-    dwError = RChangeServiceConfig2A(BindingHandle,
-                                     (SC_RPC_HANDLE)hService,
-                                     Info);
+    _SEH_TRY
+    {
+        dwError = RChangeServiceConfig2A(BindingHandle,
+                                         (SC_RPC_HANDLE)hService,
+                                         Info);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RChangeServiceConfig2A() failed (Error %lu)\n", dwError);
@@ -170,9 +199,18 @@ ChangeServiceConfig2W(SC_HANDLE hService,
 
     HandleBind();
 
-    dwError = RChangeServiceConfig2W(BindingHandle,
-                                     (SC_RPC_HANDLE)hService,
-                                     Info);
+    _SEH_TRY
+    {
+        dwError = RChangeServiceConfig2W(BindingHandle,
+                                         (SC_RPC_HANDLE)hService,
+                                         Info);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RChangeServiceConfig2W() failed (Error %lu)\n", dwError);
@@ -226,21 +264,30 @@ ChangeServiceConfigA(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RChangeServiceConfigA(BindingHandle,
-                                    (SC_RPC_HANDLE)hService,
-                                    dwServiceType,
-                                    dwStartType,
-                                    dwErrorControl,
-                                    (LPSTR)lpBinaryPathName,
-                                    (LPSTR)lpLoadOrderGroup,
-                                    lpdwTagId,
-                                    (LPSTR)lpDependencies,
-                                    dwDependenciesLength,
-                                    (LPSTR)lpServiceStartName,
-                                    NULL,              /* FIXME: lpPassword */
-                                    0,                 /* FIXME: dwPasswordLength */
-                                    (LPSTR)lpDisplayName);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RChangeServiceConfigA(BindingHandle,
+                                        (SC_RPC_HANDLE)hService,
+                                        dwServiceType,
+                                        dwStartType,
+                                        dwErrorControl,
+                                        (LPSTR)lpBinaryPathName,
+                                        (LPSTR)lpLoadOrderGroup,
+                                        lpdwTagId,
+                                        (LPSTR)lpDependencies,
+                                        dwDependenciesLength,
+                                        (LPSTR)lpServiceStartName,
+                                        NULL,              /* FIXME: lpPassword */
+                                        0,                 /* FIXME: dwPasswordLength */
+                                        (LPSTR)lpDisplayName);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
@@ -294,21 +341,30 @@ ChangeServiceConfigW(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RChangeServiceConfigW(BindingHandle,
-                                    (SC_RPC_HANDLE)hService,
-                                    dwServiceType,
-                                    dwStartType,
-                                    dwErrorControl,
-                                    (LPWSTR)lpBinaryPathName,
-                                    (LPWSTR)lpLoadOrderGroup,
-                                    lpdwTagId,
-                                    (LPBYTE)lpDependencies,
-                                    dwDependenciesLength,
-                                    (LPWSTR)lpServiceStartName,
-                                    NULL,              /* FIXME: lpPassword */
-                                    0,                 /* FIXME: dwPasswordLength */
-                                    (LPWSTR)lpDisplayName);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RChangeServiceConfigW(BindingHandle,
+                                        (SC_RPC_HANDLE)hService,
+                                        dwServiceType,
+                                        dwStartType,
+                                        dwErrorControl,
+                                        (LPWSTR)lpBinaryPathName,
+                                        (LPWSTR)lpLoadOrderGroup,
+                                        lpdwTagId,
+                                        (LPBYTE)lpDependencies,
+                                        dwDependenciesLength,
+                                        (LPWSTR)lpServiceStartName,
+                                        NULL,              /* FIXME: lpPassword */
+                                        0,                 /* FIXME: dwPasswordLength */
+                                        (LPWSTR)lpDisplayName);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
@@ -334,9 +390,18 @@ CloseServiceHandle(SC_HANDLE hSCObject)
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RCloseServiceHandle(BindingHandle,
-                                  (LPSC_RPC_HANDLE)&hSCObject);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RCloseServiceHandle(BindingHandle,
+                                      (LPSC_RPC_HANDLE)&hSCObject);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError)
     {
         ERR("RCloseServiceHandle() failed (Error %lu)\n", dwError);
@@ -367,11 +432,20 @@ ControlService(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RControlService(BindingHandle,
-                              (SC_RPC_HANDLE)hService,
-                              dwControl,
-                              lpServiceStatus);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RControlService(BindingHandle,
+                                  (SC_RPC_HANDLE)hService,
+                                  dwControl,
+                                  lpServiceStatus);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RControlService() failed (Error %lu)\n", dwError);
@@ -403,7 +477,6 @@ ControlServiceEx(IN SC_HANDLE hService,
 }
 
 
-
 /**********************************************************************
  *  CreateServiceA
  *
@@ -502,13 +575,13 @@ CreateServiceA(SC_HANDLE hSCManager,
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
             goto cleanup;
         }
-        MultiByteToWideChar(CP_ACP, 0, lpDependencies, -1, lpDependenciesW, dwDependenciesLength);
+        MultiByteToWideChar(CP_ACP, 0, lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
     }
 
     if (lpServiceStartName)
     {
         len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
-        lpServiceStartName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
         if (!lpServiceStartNameW)
         {
             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@@ -608,30 +681,41 @@ CreateServiceW(SC_HANDLE hSCManager,
             lpStr = lpStr + dwLength;
         }
         dwDependenciesLength++;
+
+        dwDependenciesLength *= sizeof(WCHAR);
     }
 
     /* FIXME: Encrypt the password */
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RCreateServiceW(BindingHandle,
-                              (SC_RPC_HANDLE)hSCManager,
-                              (LPWSTR)lpServiceName,
-                              (LPWSTR)lpDisplayName,
-                              dwDesiredAccess,
-                              dwServiceType,
-                              dwStartType,
-                              dwErrorControl,
-                              (LPWSTR)lpBinaryPathName,
-                              (LPWSTR)lpLoadOrderGroup,
-                              lpdwTagId,
-                              (LPBYTE)lpDependencies,
-                              dwDependenciesLength,
-                              (LPWSTR)lpServiceStartName,
-                              NULL,              /* FIXME: lpPassword */
-                              0,                 /* FIXME: dwPasswordLength */
-                              (SC_RPC_HANDLE *)&hService);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RCreateServiceW(BindingHandle,
+                                  (SC_RPC_HANDLE)hSCManager,
+                                  (LPWSTR)lpServiceName,
+                                  (LPWSTR)lpDisplayName,
+                                  dwDesiredAccess,
+                                  dwServiceType,
+                                  dwStartType,
+                                  dwErrorControl,
+                                  (LPWSTR)lpBinaryPathName,
+                                  (LPWSTR)lpLoadOrderGroup,
+                                  lpdwTagId,
+                                  (LPBYTE)lpDependencies,
+                                  dwDependenciesLength,
+                                  (LPWSTR)lpServiceStartName,
+                                  NULL,              /* FIXME: lpPassword */
+                                  0,                 /* FIXME: dwPasswordLength */
+                                  (SC_RPC_HANDLE *)&hService);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RCreateServiceW() failed (Error %lu)\n", dwError);
@@ -657,9 +741,18 @@ DeleteService(SC_HANDLE hService)
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RDeleteService(BindingHandle,
-                             (SC_RPC_HANDLE)hService);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RDeleteService(BindingHandle,
+                                 (SC_RPC_HANDLE)hService);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RDeleteService() failed (Error %lu)\n", dwError);
@@ -685,20 +778,28 @@ EnumDependentServicesA(SC_HANDLE hService,
                        LPDWORD lpServicesReturned)
 {
     LPENUM_SERVICE_STATUSA lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusA() called\n");
 
     HandleBind();
 
-    dwError = REnumDependentServicesA(BindingHandle,
-                                      (SC_RPC_HANDLE)hService,
-                                      dwServiceState,
-                                      (LPBYTE)lpServices,
-                                      cbBufSize,
-                                      pcbBytesNeeded,
-                                      lpServicesReturned);
+    _SEH_TRY
+    {
+        dwError = REnumDependentServicesA(BindingHandle,
+                                          (SC_RPC_HANDLE)hService,
+                                          dwServiceState,
+                                          (LPBYTE)lpServices,
+                                          cbBufSize,
+                                          pcbBytesNeeded,
+                                          lpServicesReturned);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
     for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
@@ -741,20 +842,28 @@ EnumDependentServicesW(SC_HANDLE hService,
                        LPDWORD lpServicesReturned)
 {
     LPENUM_SERVICE_STATUSW lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusW() called\n");
 
     HandleBind();
 
-    dwError = REnumDependentServicesW(BindingHandle,
-                                      (SC_RPC_HANDLE)hService,
-                                      dwServiceState,
-                                      (LPBYTE)lpServices,
-                                      cbBufSize,
-                                      pcbBytesNeeded,
-                                      lpServicesReturned);
+    _SEH_TRY
+    {
+        dwError = REnumDependentServicesW(BindingHandle,
+                                          (SC_RPC_HANDLE)hService,
+                                          dwServiceState,
+                                          (LPBYTE)lpServices,
+                                          cbBufSize,
+                                          pcbBytesNeeded,
+                                          lpServicesReturned);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
     for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
@@ -823,22 +932,30 @@ EnumServicesStatusA(SC_HANDLE hSCManager,
                     LPDWORD lpResumeHandle)
 {
     LPENUM_SERVICE_STATUSA lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusA() called\n");
 
     HandleBind();
 
-    dwError = REnumServicesStatusA(BindingHandle,
-                                   (SC_RPC_HANDLE)hSCManager,
-                                   dwServiceType,
-                                   dwServiceState,
-                                   (LPBYTE)lpServices,
-                                   cbBufSize,
-                                   pcbBytesNeeded,
-                                   lpServicesReturned,
-                                   lpResumeHandle);
+    _SEH_TRY
+    {
+        dwError = REnumServicesStatusA(BindingHandle,
+                                       (SC_RPC_HANDLE)hSCManager,
+                                       dwServiceType,
+                                       dwServiceState,
+                                       (LPBYTE)lpServices,
+                                       cbBufSize,
+                                       pcbBytesNeeded,
+                                       lpServicesReturned,
+                                       lpResumeHandle);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
     for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
@@ -883,22 +1000,30 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
                     LPDWORD lpResumeHandle)
 {
     LPENUM_SERVICE_STATUSW lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusW() called\n");
 
     HandleBind();
 
-    dwError = REnumServicesStatusW(BindingHandle,
-                                   (SC_RPC_HANDLE)hSCManager,
-                                   dwServiceType,
-                                   dwServiceState,
-                                   (LPBYTE)lpServices,
-                                   cbBufSize,
-                                   pcbBytesNeeded,
-                                   lpServicesReturned,
-                                   lpResumeHandle);
+    _SEH_TRY
+    {
+        dwError = REnumServicesStatusW(BindingHandle,
+                                       (SC_RPC_HANDLE)hSCManager,
+                                       dwServiceType,
+                                       dwServiceState,
+                                       (LPBYTE)lpServices,
+                                       cbBufSize,
+                                       pcbBytesNeeded,
+                                       lpServicesReturned,
+                                       lpResumeHandle);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
     for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
@@ -945,24 +1070,32 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
                       LPCSTR pszGroupName)
 {
     LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusExA() called\n");
 
     HandleBind();
 
-    dwError = REnumServicesStatusExA(BindingHandle,
-                                     (SC_RPC_HANDLE)hSCManager,
-                                     InfoLevel,
-                                     dwServiceType,
-                                     dwServiceState,
-                                     (LPBYTE)lpServices,
-                                     cbBufSize,
-                                     pcbBytesNeeded,
-                                     lpServicesReturned,
-                                     lpResumeHandle,
-                                     (LPSTR)pszGroupName);
+    _SEH_TRY
+    {
+        dwError = REnumServicesStatusExA(BindingHandle,
+                                         (SC_RPC_HANDLE)hSCManager,
+                                         InfoLevel,
+                                         dwServiceType,
+                                         dwServiceState,
+                                         (LPBYTE)lpServices,
+                                         cbBufSize,
+                                         pcbBytesNeeded,
+                                         lpServicesReturned,
+                                         lpResumeHandle,
+                                         (LPSTR)pszGroupName);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     if (dwError == ERROR_MORE_DATA)
     {
@@ -1017,24 +1150,32 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
                       LPCWSTR pszGroupName)
 {
     LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
-    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwError;
     DWORD dwCount;
 
     TRACE("EnumServicesStatusExW() called\n");
 
     HandleBind();
 
-    dwError = REnumServicesStatusExW(BindingHandle,
-                                     (SC_RPC_HANDLE)hSCManager,
-                                     InfoLevel,
-                                     dwServiceType,
-                                     dwServiceState,
-                                     (LPBYTE)lpServices,
-                                     cbBufSize,
-                                     pcbBytesNeeded,
-                                     lpServicesReturned,
-                                     lpResumeHandle,
-                                     (LPWSTR)pszGroupName);
+    _SEH_TRY
+    {
+        dwError = REnumServicesStatusExW(BindingHandle,
+                                         (SC_RPC_HANDLE)hSCManager,
+                                         InfoLevel,
+                                         dwServiceType,
+                                         dwServiceState,
+                                         (LPBYTE)lpServices,
+                                         cbBufSize,
+                                         pcbBytesNeeded,
+                                         lpServicesReturned,
+                                         lpResumeHandle,
+                                         (LPWSTR)pszGroupName);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     if (dwError == ERROR_MORE_DATA)
     {
@@ -1086,13 +1227,28 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
 
     TRACE("GetServiceDisplayNameA() called\n");
 
+    if (!lpDisplayName)
+        *lpcchBuffer = 0;
+
     HandleBind();
 
-    dwError = RGetServiceDisplayNameA(BindingHandle,
-                                      (SC_RPC_HANDLE)hSCManager,
-                                      (LPSTR)lpServiceName,
-                                      lpDisplayName,
-                                      lpcchBuffer);
+    _SEH_TRY
+    {
+        dwError = RGetServiceDisplayNameA(BindingHandle,
+                                          (SC_RPC_HANDLE)hSCManager,
+                                          (LPSTR)lpServiceName,
+                                          lpDisplayName,
+                                          lpcchBuffer);
+    }
+    _SEH_HANDLE
+    {
+        /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+
+
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
@@ -1100,8 +1256,6 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    (*lpcchBuffer)--;
-
     return TRUE;
 }
 
@@ -1121,13 +1275,25 @@ GetServiceDisplayNameW(SC_HANDLE hSCManager,
 
     TRACE("GetServiceDisplayNameW() called\n");
 
+    if (!lpDisplayName)
+        *lpcchBuffer = 0;
+
     HandleBind();
 
-    dwError = RGetServiceDisplayNameW(BindingHandle,
-                                      (SC_RPC_HANDLE)hSCManager,
-                                      (LPWSTR)lpServiceName,
-                                      lpDisplayName,
-                                      lpcchBuffer);
+    _SEH_TRY
+    {
+        dwError = RGetServiceDisplayNameW(BindingHandle,
+                                          (SC_RPC_HANDLE)hSCManager,
+                                          (LPWSTR)lpServiceName,
+                                          lpDisplayName,
+                                          lpcchBuffer);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
@@ -1135,8 +1301,6 @@ GetServiceDisplayNameW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    (*lpcchBuffer)--;
-
     return TRUE;
 }
 
@@ -1156,13 +1320,25 @@ GetServiceKeyNameA(SC_HANDLE hSCManager,
 
     TRACE("GetServiceKeyNameA() called\n");
 
+    if (!lpServiceName)
+        *lpcchBuffer = 0;
+
     HandleBind();
 
-    dwError = RGetServiceKeyNameA(BindingHandle,
-                                  (SC_RPC_HANDLE)hSCManager,
-                                  (LPSTR)lpDisplayName,
-                                  lpServiceName,
-                                  lpcchBuffer);
+    _SEH_TRY
+    {
+        dwError = RGetServiceKeyNameA(BindingHandle,
+                                      (SC_RPC_HANDLE)hSCManager,
+                                      (LPSTR)lpDisplayName,
+                                      lpServiceName,
+                                      lpcchBuffer);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
@@ -1170,8 +1346,6 @@ GetServiceKeyNameA(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    (*lpcchBuffer)--;
-
     return TRUE;
 }
 
@@ -1191,13 +1365,25 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
 
     TRACE("GetServiceKeyNameW() called\n");
 
+    if (!lpDisplayName)
+        *lpcchBuffer = 0;
+
     HandleBind();
 
-    dwError = RGetServiceKeyNameW(BindingHandle,
-                                  (SC_RPC_HANDLE)hSCManager,
-                                  (LPWSTR)lpDisplayName,
-                                  lpServiceName,
-                                  lpcchBuffer);
+    _SEH_TRY
+    {
+        dwError = RGetServiceKeyNameW(BindingHandle,
+                                      (SC_RPC_HANDLE)hSCManager,
+                                      (LPWSTR)lpDisplayName,
+                                      lpServiceName,
+                                      lpcchBuffer);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
@@ -1205,8 +1391,6 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    (*lpcchBuffer)--;
-
     return TRUE;
 }
 
@@ -1226,10 +1410,19 @@ LockServiceDatabase(SC_HANDLE hSCManager)
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RLockServiceDatabase(BindingHandle,
-                                   (SC_RPC_HANDLE)hSCManager,
-                                   (SC_RPC_LOCK *)&hLock);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RLockServiceDatabase(BindingHandle,
+                                       (SC_RPC_HANDLE)hSCManager,
+                                       (SC_RPC_LOCK *)&hLock);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RLockServiceDatabase() failed (Error %lu)\n", dwError);
@@ -1303,12 +1496,21 @@ OpenSCManagerA(LPCSTR lpMachineName,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = ROpenSCManagerA(BindingHandle,
-                              (LPSTR)lpMachineName,
-                              (LPSTR)lpDatabaseName,
-                              dwDesiredAccess,
-                              (SC_RPC_HANDLE *)&hScm);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = ROpenSCManagerA(BindingHandle,
+                                  (LPSTR)lpMachineName,
+                                  (LPSTR)lpDatabaseName,
+                                  dwDesiredAccess,
+                                  (SC_RPC_HANDLE *)&hScm);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("ROpenSCManagerA() failed (Error %lu)\n", dwError);
@@ -1342,12 +1544,21 @@ OpenSCManagerW(LPCWSTR lpMachineName,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = ROpenSCManagerW(BindingHandle,
-                              (LPWSTR)lpMachineName,
-                              (LPWSTR)lpDatabaseName,
-                              dwDesiredAccess,
-                              (SC_RPC_HANDLE *)&hScm);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = ROpenSCManagerW(BindingHandle,
+                                  (LPWSTR)lpMachineName,
+                                  (LPWSTR)lpDatabaseName,
+                                  dwDesiredAccess,
+                                  (SC_RPC_HANDLE *)&hScm);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("ROpenSCManagerW() failed (Error %lu)\n", dwError);
@@ -1379,12 +1590,21 @@ OpenServiceA(SC_HANDLE hSCManager,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = ROpenServiceA(BindingHandle,
-                            (SC_RPC_HANDLE)hSCManager,
-                            (LPSTR)lpServiceName,
-                            dwDesiredAccess,
-                            (SC_RPC_HANDLE *)&hService);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = ROpenServiceA(BindingHandle,
+                                (SC_RPC_HANDLE)hSCManager,
+                                (LPSTR)lpServiceName,
+                                dwDesiredAccess,
+                                (SC_RPC_HANDLE *)&hService);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("ROpenServiceA() failed (Error %lu)\n", dwError);
@@ -1416,15 +1636,27 @@ OpenServiceW(SC_HANDLE hSCManager,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = ROpenServiceW(BindingHandle,
-                            (SC_RPC_HANDLE)hSCManager,
-                            (LPWSTR)lpServiceName,
-                            dwDesiredAccess,
-                            (SC_RPC_HANDLE *)&hService);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = ROpenServiceW(BindingHandle,
+                                (SC_RPC_HANDLE)hSCManager,
+                                (LPWSTR)lpServiceName,
+                                dwDesiredAccess,
+                                (SC_RPC_HANDLE *)&hService);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
-        ERR("ROpenServiceW() failed (Error %lu)\n", dwError);
+        if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
+            WARN("ROpenServiceW() failed (Error %lu)\n", dwError);
+        else
+            ERR("ROpenServiceW() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return NULL;
     }
@@ -1453,12 +1685,21 @@ QueryServiceConfigA(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceConfigA(BindingHandle,
-                                   (SC_RPC_HANDLE)hService,
-                                   lpServiceConfig,
-                                   cbBufSize,
-                                   pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceConfigA(BindingHandle,
+                                       (SC_RPC_HANDLE)hService,
+                                       (LPBYTE)lpServiceConfig,
+                                       cbBufSize,
+                                       pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
@@ -1516,15 +1757,27 @@ QueryServiceConfigW(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceConfigW(BindingHandle,
-                                   (SC_RPC_HANDLE)hService,
-                                   (LPBYTE)lpServiceConfig,
-                                   cbBufSize,
-                                   pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceConfigW(BindingHandle,
+                                       (SC_RPC_HANDLE)hService,
+                                       (LPBYTE)lpServiceConfig,
+                                       cbBufSize,
+                                       pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
-        ERR("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
+        if (dwError == ERROR_INSUFFICIENT_BUFFER)
+            WARN("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
+        else
+            ERR("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return FALSE;
     }
@@ -1580,13 +1833,22 @@ QueryServiceConfig2A(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceConfig2A(BindingHandle,
-                                    (SC_RPC_HANDLE)hService,
-                                    dwInfoLevel,
-                                    lpBuffer,
-                                    cbBufSize,
-                                    pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceConfig2A(BindingHandle,
+                                        (SC_RPC_HANDLE)hService,
+                                        dwInfoLevel,
+                                        lpBuffer,
+                                        cbBufSize,
+                                        pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
@@ -1655,13 +1917,22 @@ QueryServiceConfig2W(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceConfig2W(BindingHandle,
-                                    (SC_RPC_HANDLE)hService,
-                                    dwInfoLevel,
-                                    lpBuffer,
-                                    cbBufSize,
-                                    pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceConfig2W(BindingHandle,
+                                        (SC_RPC_HANDLE)hService,
+                                        dwInfoLevel,
+                                        lpBuffer,
+                                        cbBufSize,
+                                        pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
@@ -1728,12 +1999,21 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceLockStatusA(BindingHandle,
-                                       (SC_RPC_HANDLE)hSCManager,
-                                       lpLockStatus,
-                                       cbBufSize,
-                                       pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceLockStatusA(BindingHandle,
+                                           (SC_RPC_HANDLE)hSCManager,
+                                           lpLockStatus,
+                                           cbBufSize,
+                                           pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
@@ -1770,12 +2050,21 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceLockStatusW(BindingHandle,
-                                       (SC_RPC_HANDLE)hSCManager,
-                                       lpLockStatus,
-                                       cbBufSize,
-                                       pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceLockStatusW(BindingHandle,
+                                           (SC_RPC_HANDLE)hSCManager,
+                                           lpLockStatus,
+                                           cbBufSize,
+                                           pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
@@ -1814,13 +2103,22 @@ QueryServiceObjectSecurity(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceObjectSecurity(BindingHandle,
-                                          (SC_RPC_HANDLE)hService,
-                                          dwSecurityInformation,
-                                          (LPBYTE)lpSecurityDescriptor,
-                                          cbBufSize,
-                                          pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceObjectSecurity(BindingHandle,
+                                              (SC_RPC_HANDLE)hService,
+                                              dwSecurityInformation,
+                                              (LPBYTE)lpSecurityDescriptor,
+                                              cbBufSize,
+                                              pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
@@ -1875,12 +2173,20 @@ SetServiceObjectSecurity(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RSetServiceObjectSecurity(BindingHandle,
-                                        (SC_RPC_HANDLE)hService,
-                                        dwSecurityInformation,
-                                        (LPBYTE)SelfRelativeSD,
-                                        Length);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RSetServiceObjectSecurity(BindingHandle,
+                                            (SC_RPC_HANDLE)hService,
+                                            dwSecurityInformation,
+                                            (LPBYTE)SelfRelativeSD,
+                                            Length);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
 
@@ -1911,10 +2217,19 @@ QueryServiceStatus(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceStatus(BindingHandle,
-                                  (SC_RPC_HANDLE)hService,
-                                  lpServiceStatus);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceStatus(BindingHandle,
+                                      (SC_RPC_HANDLE)hService,
+                                      lpServiceStatus);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceStatus() failed (Error %lu)\n", dwError);
@@ -1944,13 +2259,22 @@ QueryServiceStatusEx(SC_HANDLE hService,
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RQueryServiceStatusEx(BindingHandle,
-                                    (SC_RPC_HANDLE)hService,
-                                    InfoLevel,
-                                    lpBuffer,
-                                    cbBufSize,
-                                    pcbBytesNeeded);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RQueryServiceStatusEx(BindingHandle,
+                                        (SC_RPC_HANDLE)hService,
+                                        InfoLevel,
+                                        lpBuffer,
+                                        cbBufSize,
+                                        pcbBytesNeeded);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
@@ -1974,11 +2298,18 @@ StartServiceA(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    dwError = RStartServiceA(BindingHandle,
-                             (SC_RPC_HANDLE)hService,
-                             dwNumServiceArgs,
-                             (LPSTRING_PTRSA)lpServiceArgVectors);
-
+    _SEH_TRY
+    {
+        dwError = RStartServiceA(BindingHandle,
+                                 (SC_RPC_HANDLE)hService,
+                                 dwNumServiceArgs,
+                                 (LPSTRING_PTRSA)lpServiceArgVectors);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     if (dwError != ERROR_SUCCESS)
     {
@@ -2003,10 +2334,18 @@ StartServiceW(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    dwError = RStartServiceW(BindingHandle,
-                             (SC_RPC_HANDLE)hService,
-                             dwNumServiceArgs,
-                             (LPSTRING_PTRSW)lpServiceArgVectors);
+    _SEH_TRY
+    {
+        dwError = RStartServiceW(BindingHandle,
+                                 (SC_RPC_HANDLE)hService,
+                                 dwNumServiceArgs,
+                                 (LPSTRING_PTRSW)lpServiceArgVectors);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
 
     if (dwError != ERROR_SUCCESS)
     {
@@ -2033,9 +2372,18 @@ UnlockServiceDatabase(SC_LOCK ScLock)
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RUnlockServiceDatabase(BindingHandle,
-                                     (SC_RPC_LOCK)ScLock);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RUnlockServiceDatabase(BindingHandle,
+                                         (SC_RPC_LOCK)ScLock);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
@@ -2061,10 +2409,19 @@ NotifyBootConfigStatus(BOOL BootAcceptable)
 
     HandleBind();
 
-    /* Call to services.exe using RPC */
-    dwError = RNotifyBootConfigStatus(BindingHandle,
-                                      NULL,
-                                      BootAcceptable);
+    _SEH_TRY
+    {
+        /* Call to services.exe using RPC */
+        dwError = RNotifyBootConfigStatus(BindingHandle,
+                                          NULL,
+                                          BootAcceptable);
+    }
+    _SEH_HANDLE
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    _SEH_END;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);