- Implement RCreateServiceA.
[reactos.git] / reactos / base / system / services / rpcserver.c
index 63d5dca..a5b7f9f 100644 (file)
@@ -151,12 +151,12 @@ ScmCreateManagerHandle(LPWSTR lpDatabaseName,
     if (lpDatabaseName == NULL)
         lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
 
-    if (wcsicmp(lpDatabaseName,SERVICES_FAILED_DATABASEW)==0)
+    if (_wcsicmp(lpDatabaseName,SERVICES_FAILED_DATABASEW)==0)
     {
         DPRINT1("Database %S, does not exist\n",lpDatabaseName);
         return ERROR_DATABASE_DOES_NOT_EXIST;
     }
-    else if (wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
+    else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
     {
         DPRINT1("Invalid Database name %S.\n",lpDatabaseName);
         return ERROR_INVALID_NAME;
@@ -332,7 +332,7 @@ Int_EnumDependentServicesW(HKEY hServicesKey,
             /* Can be more than one Dependencies in the DependOnService string */
             while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
             {
-                if (wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
+                if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
                 {
                     /* Get the current enumed service pointer */
                     lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
@@ -400,7 +400,6 @@ Int_EnumDependentServicesW(HKEY hServicesKey,
 
 /* Function 0 */
 DWORD RCloseServiceHandle(
-    handle_t BindingHandle,
     LPSC_RPC_HANDLE hSCObject)
 {
     PMANAGER_HANDLE hManager;
@@ -498,8 +497,8 @@ DWORD RCloseServiceHandle(
                    it is now safe to delete the service */
 
                 /* Delete the Service Key */
-                dwError = RegDeleteKey(hServicesKey,
-                                       lpService->lpServiceName);
+                dwError = RegDeleteKeyW(hServicesKey,
+                                        lpService->lpServiceName);
 
                 RegCloseKey(hServicesKey);
 
@@ -526,7 +525,6 @@ DWORD RCloseServiceHandle(
 
 /* Function 1 */
 DWORD RControlService(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwControl,
     LPSERVICE_STATUS lpServiceStatus)
@@ -657,7 +655,6 @@ DWORD RControlService(
 
 /* Function 2 */
 DWORD RDeleteService(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService)
 {
     PSERVICE_HANDLE hSvc;
@@ -707,7 +704,6 @@ DWORD RDeleteService(
 
 /* Function 3 */
 DWORD RLockServiceDatabase(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPSC_RPC_LOCK lpLock)
 {
@@ -736,14 +732,12 @@ DWORD RLockServiceDatabase(
 
 /* Function 4 */
 DWORD RQueryServiceObjectSecurity(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     SECURITY_INFORMATION dwSecurityInformation,
     LPBYTE lpSecurityDescriptor,
     DWORD cbBufSize,
     LPBOUNDED_DWORD_256K pcbBytesNeeded)
 {
-#if 0
     PSERVICE_HANDLE hSvc;
     PSERVICE lpService;
     ULONG DesiredAccess = 0;
@@ -751,6 +745,9 @@ DWORD RQueryServiceObjectSecurity(
     DWORD dwBytesNeeded;
     DWORD dwError;
 
+
+    SECURITY_DESCRIPTOR ObjectDescriptor;
+
     DPRINT("RQueryServiceObjectSecurity() called\n");
 
     hSvc = (PSERVICE_HANDLE)hService;
@@ -784,10 +781,13 @@ DWORD RQueryServiceObjectSecurity(
 
     /* FIXME: Lock the service list */
 
-    Status = RtlQuerySecurityObject(lpService->lpSecurityDescriptor,
+    /* hack */
+    Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION);
+
+    Status = RtlQuerySecurityObject(&ObjectDescriptor  /* lpService->lpSecurityDescriptor */,
                                     dwSecurityInformation,
                                     (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
-                                    dwSecuityDescriptorSize,
+                                    cbBufSize,
                                     &dwBytesNeeded);
 
     /* FIXME: Unlock the service list */
@@ -812,15 +812,11 @@ DWORD RQueryServiceObjectSecurity(
     }
 
     return dwError;
-#endif
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 5 */
 DWORD RSetServiceObjectSecurity(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwSecurityInformation,
     LPBYTE lpSecurityDescriptor,
@@ -829,9 +825,9 @@ DWORD RSetServiceObjectSecurity(
     PSERVICE_HANDLE hSvc;
     PSERVICE lpService;
     ULONG DesiredAccess = 0;
-    HANDLE hToken = NULL;
+    /* HANDLE hToken = NULL; */
     HKEY hServiceKey;
-    NTSTATUS Status;
+    /* NTSTATUS Status; */
     DWORD dwError;
 
     DPRINT1("RSetServiceObjectSecurity() called\n");
@@ -861,11 +857,11 @@ DWORD RSetServiceObjectSecurity(
         DesiredAccess |= WRITE_OWNER;
 
     if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
-        (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
+        (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
         return ERROR_INVALID_PARAMETER;
 
     if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
-        (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
+        (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
         return ERROR_INVALID_PARAMETER;
 
     if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
@@ -885,6 +881,7 @@ DWORD RSetServiceObjectSecurity(
     if (lpService->bDeleted)
         return ERROR_SERVICE_MARKED_FOR_DELETE;
 
+#if 0
     RpcImpersonateClient(NULL);
 
     Status = NtOpenThreadToken(NtCurrentThread(),
@@ -892,13 +889,12 @@ DWORD RSetServiceObjectSecurity(
                                TRUE,
                                &hToken);
     if (!NT_SUCCESS(Status))
-        return RtlNtStatusToDosError(Status);
+        return RtlNtStatusToDosError(Status); 
 
     RpcRevertToSelf();
 
     /* FIXME: Lock service database */
 
-#if 0
     Status = RtlSetSecurityObject(dwSecurityInformation,
                                   (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
                                   &lpService->lpSecurityDescriptor,
@@ -927,8 +923,10 @@ DWORD RSetServiceObjectSecurity(
 
 Done:
 
+#if 0
     if (hToken != NULL)
         NtClose(hToken);
+#endif
 
     /* FIXME: Unlock service database */
 
@@ -940,7 +938,6 @@ Done:
 
 /* Function 6 */
 DWORD RQueryServiceStatus(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     LPSERVICE_STATUS lpServiceStatus)
 {
@@ -1004,8 +1001,7 @@ ScmIsValidServiceState(DWORD dwCurrentState)
 
 /* Function 7 */
 DWORD RSetServiceStatus(
-    handle_t BindingHandle,
-    SC_RPC_HANDLE hServiceStatus,
+    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
     LPSERVICE_STATUS lpServiceStatus)
 {
     PSERVICE lpService;
@@ -1026,7 +1022,7 @@ DWORD RSetServiceStatus(
         return ERROR_INVALID_HANDLE;
     }
 
-    lpService = ScmGetServiceEntryByClientHandle((ULONG)hServiceStatus);
+    lpService = ScmGetServiceEntryByClientHandle((HANDLE)hServiceStatus);
     if (lpService == NULL)
     {
         DPRINT1("lpService == NULL!\n");
@@ -1049,8 +1045,7 @@ DWORD RSetServiceStatus(
     }
 
     /* Check accepted controls */
-    if (lpServiceStatus->dwControlsAccepted == 0 ||
-        lpServiceStatus->dwControlsAccepted & ~0xFF)
+    if (lpServiceStatus->dwControlsAccepted & ~0xFF)
     {
         DPRINT1("Invalid controls accepted!\n");
         return ERROR_INVALID_DATA;
@@ -1070,7 +1065,6 @@ DWORD RSetServiceStatus(
 
 /* Function 8 */
 DWORD RUnlockServiceDatabase(
-    handle_t BindingHandle,
     LPSC_RPC_LOCK Lock)
 {
     UNIMPLEMENTED;
@@ -1080,7 +1074,6 @@ DWORD RUnlockServiceDatabase(
 
 /* Function 9 */
 DWORD RNotifyBootConfigStatus(
-    handle_t BindingHandle,
     SVCCTL_HANDLEW lpMachineName,
     DWORD BootAcceptable)
 {
@@ -1091,8 +1084,7 @@ DWORD RNotifyBootConfigStatus(
 
 /* Function 10 */
 DWORD RI_ScSetServiceBitsW(
-    handle_t BindingHandle,
-    SC_RPC_HANDLE hServiceStatus,
+    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
     DWORD dwServiceBits,
     int bSetBitsOn,
     int bUpdateImmediately,
@@ -1105,7 +1097,6 @@ DWORD RI_ScSetServiceBitsW(
 
 /* Function 11 */
 DWORD RChangeServiceConfigW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwServiceType,
     DWORD dwStartType,
@@ -1291,7 +1282,11 @@ DWORD RChangeServiceConfigW(
                                  (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
         if (dwError != ERROR_SUCCESS)
             goto done;
-        /* FIXME: Update lpService->lpServiceGroup */
+
+        dwError = ScmSetServiceGroup(lpService,
+                                     lpLoadOrderGroup);
+        if (dwError != ERROR_SUCCESS)
+            goto done;
     }
 
     if (lpdwTagId != NULL)
@@ -1357,7 +1352,7 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
 
     /* First check, if it's already good */
     if (ServiceNameLen > 12 &&
-        !wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
+        !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
     {
         *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
         if (*RelativeName == NULL)
@@ -1375,7 +1370,7 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
 
     /* If it has %SystemRoot% prefix, substitute it to \System*/
     if (ServiceNameLen > 13 &&
-        !wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
+        !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
     {
         /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
         *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR));
@@ -1445,7 +1440,7 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
     Expanded[ExpandedLen] = 0;
 
     if (ServiceNameLen > ExpandedLen &&
-        !wcsnicmp(Expanded, CanonName, ExpandedLen))
+        !_wcsnicmp(Expanded, CanonName, ExpandedLen))
     {
         /* Only \SystemRoot\ is missing */
         *RelativeName = LocalAlloc(LMEM_ZEROINIT,
@@ -1517,7 +1512,7 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
 
                 ExpandedLen = LinkTarget.Length / sizeof(WCHAR);
                 if ((ServiceNameLen > ExpandedLen) &&
-                    !wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
+                    !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
                 {
                     *RelativeName = LocalAlloc(LMEM_ZEROINIT,
                        (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
@@ -1584,20 +1579,20 @@ ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
 
 DWORD
 ScmCanonDriverImagePath(DWORD dwStartType,
-                        wchar_t *lpServiceName,
+                        const wchar_t *lpServiceName,
                         wchar_t **lpCanonName)
 {
     DWORD ServiceNameLen, Result;
     UNICODE_STRING NtServiceName;
     WCHAR *RelativeName;
-    WCHAR *SourceName = lpServiceName;
+    const WCHAR *SourceName = lpServiceName;
 
     /* Calculate the length of the service's name */
     ServiceNameLen = wcslen(lpServiceName);
 
     /* 12 is wcslen(L"\\SystemRoot\\") */
     if (ServiceNameLen > 12 &&
-        !wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
+        !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
     {
         /* SystemRoot prefix is already included */
 
@@ -1622,7 +1617,7 @@ ScmCanonDriverImagePath(DWORD dwStartType,
 
     /* Check if it has %SystemRoot% (len=13) */
     if (ServiceNameLen > 13 &&
-        !wcsnicmp(L"%%SystemRoot%%\\", lpServiceName, 13))
+        !_wcsnicmp(L"%%SystemRoot%%\\", lpServiceName, 13))
     {
         /* Substitute %SystemRoot% with \\SystemRoot\\ */
         *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
@@ -1715,20 +1710,19 @@ ScmCanonDriverImagePath(DWORD dwStartType,
 
 /* Function 12 */
 DWORD RCreateServiceW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
-    LPWSTR lpServiceName,
-    LPWSTR lpDisplayName,
+    LPCWSTR lpServiceName,
+    LPCWSTR lpDisplayName,
     DWORD dwDesiredAccess,
     DWORD dwServiceType,
     DWORD dwStartType,
     DWORD dwErrorControl,
-    LPWSTR lpBinaryPathName,
-    LPWSTR lpLoadOrderGroup,
+    LPCWSTR lpBinaryPathName,
+    LPCWSTR lpLoadOrderGroup,
     LPDWORD lpdwTagId,
     LPBYTE lpDependencies,
     DWORD dwDependSize,
-    LPWSTR lpServiceStartName,
+    LPCWSTR lpServiceStartName,
     LPBYTE lpPassword,
     DWORD dwPwSize,
     LPSC_RPC_HANDLE lpServiceHandle)
@@ -1739,6 +1733,7 @@ DWORD RCreateServiceW(
     SC_HANDLE hServiceHandle = NULL;
     LPWSTR lpImagePath = NULL;
     HKEY hServiceKey = NULL;
+    LPWSTR lpObjectName;
 
     DPRINT("RCreateServiceW() called\n");
     DPRINT("lpServiceName = %S\n", lpServiceName);
@@ -1842,7 +1837,7 @@ DWORD RCreateServiceW(
     /* Fill the display name */
     if (lpDisplayName != NULL &&
         *lpDisplayName != 0 &&
-        wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
+        _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
     {
         lpService->lpDisplayName = (WCHAR*) HeapAlloc(GetProcessHeap(), 0,
                                              (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
@@ -1979,15 +1974,16 @@ DWORD RCreateServiceW(
             goto done;
     }
 
-    /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
-    if ((dwServiceType & SERVICE_WIN32) && (!lpServiceName))
+    /* Write service start name */
+    if (dwServiceType & SERVICE_WIN32)
     {
+        lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
         dwError = RegSetValueExW(hServiceKey,
                                  L"ObjectName",
                                  0,
                                  REG_SZ,
-                                 (LPBYTE)L"LocalSystem",
-                                 24);
+                                 (LPBYTE)lpObjectName,
+                                 (wcslen(lpObjectName) + 1) * sizeof(WCHAR));
         if (dwError != ERROR_SUCCESS)
             goto done;
     }
@@ -2051,7 +2047,6 @@ done:;
 
 /* Function 13 */
 DWORD REnumDependentServicesW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwServiceState,
     LPBYTE lpServices,
@@ -2181,7 +2176,6 @@ Done:
 
 /* Function 14 */
 DWORD REnumServicesStatusW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     DWORD dwServiceType,
     DWORD dwServiceState,
@@ -2200,7 +2194,7 @@ DWORD REnumServicesStatusW(
     DWORD dwRequiredSize;
     DWORD dwServiceCount;
     DWORD dwSize;
-    DWORD dwLastResumeCount;
+    DWORD dwLastResumeCount = 0;
     LPENUM_SERVICE_STATUSW lpStatusPtr;
     LPWSTR lpStringPtr;
 
@@ -2216,6 +2210,21 @@ DWORD REnumServicesStatusW(
         return ERROR_INVALID_HANDLE;
     }
 
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+
+    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+    {
+        DPRINT("Not a valid Service Type!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+    {
+        DPRINT("Not a valid Service State!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
     /* Check access rights */
     if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
                                   SC_MANAGER_ENUMERATE_SERVICE))
@@ -2225,10 +2234,8 @@ DWORD REnumServicesStatusW(
         return ERROR_ACCESS_DENIED;
     }
 
-    *pcbBytesNeeded = 0;
-    *lpServicesReturned = 0;
-
-    dwLastResumeCount = *lpResumeHandle;
+    if (lpResumeHandle)
+        dwLastResumeCount = *lpResumeHandle;
 
     /* FIXME: Lock the service list shared */
 
@@ -2306,7 +2313,9 @@ DWORD REnumServicesStatusW(
 
     DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
 
-    *lpResumeHandle = dwLastResumeCount;
+    if (lpResumeHandle)
+        *lpResumeHandle = dwLastResumeCount;
+
     *lpServicesReturned = dwServiceCount;
     *pcbBytesNeeded = dwRequiredSize;
 
@@ -2359,6 +2368,12 @@ DWORD REnumServicesStatusW(
         dwRequiredSize += dwSize;
     }
 
+    if (dwError == 0) 
+    {
+        *pcbBytesNeeded = 0;
+        if (lpResumeHandle) *lpResumeHandle = 0;
+    }
+
 Done:;
     /* FIXME: Unlock the service list */
 
@@ -2370,7 +2385,6 @@ Done:;
 
 /* Function 15 */
 DWORD ROpenSCManagerW(
-    handle_t BindingHandle,
     LPWSTR lpMachineName,
     LPWSTR lpDatabaseName,
     DWORD dwDesiredAccess,
@@ -2421,7 +2435,6 @@ DWORD ROpenSCManagerW(
 
 /* Function 16 */
 DWORD ROpenServiceW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPWSTR lpServiceName,
     DWORD dwDesiredAccess,
@@ -2441,12 +2454,6 @@ DWORD ROpenServiceW(
     if (ScmShutdown)
         return ERROR_SHUTDOWN_IN_PROGRESS;
 
-    if (!lpServiceHandle)
-        return ERROR_INVALID_PARAMETER;
-
-    if (!lpServiceName)
-        return ERROR_INVALID_ADDRESS;
-
     hManager = (PMANAGER_HANDLE)hSCManager;
     if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
     {
@@ -2454,6 +2461,12 @@ DWORD ROpenServiceW(
         return ERROR_INVALID_HANDLE;
     }
 
+    if (!lpServiceHandle)
+        return ERROR_INVALID_PARAMETER;
+
+    if (!lpServiceName)
+        return ERROR_INVALID_ADDRESS;
+
     /* FIXME: Lock the service list */
 
     /* Get service database entry */
@@ -2497,7 +2510,6 @@ DWORD ROpenServiceW(
 
 /* Function 17 */
 DWORD RQueryServiceConfigW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
     DWORD cbBufSize,
@@ -2510,6 +2522,8 @@ DWORD RQueryServiceConfigW(
     HKEY hServiceKey = NULL;
     LPWSTR lpImagePath = NULL;
     LPWSTR lpServiceStartName = NULL;
+    LPWSTR lpDependencies = NULL;
+    DWORD dwDependenciesLength = 0;
     DWORD dwRequiredSize;
     LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
     WCHAR lpEmptyString[] = {0,0};
@@ -2549,16 +2563,23 @@ DWORD RQueryServiceConfigW(
     if (dwError != ERROR_SUCCESS)
         goto Done;
 
+    /* Read the image path */
     dwError = ScmReadString(hServiceKey,
                             L"ImagePath",
                             &lpImagePath);
     if (dwError != ERROR_SUCCESS)
         goto Done;
 
+    /* Read the service start name */
     ScmReadString(hServiceKey,
                   L"ObjectName",
                   &lpServiceStartName);
 
+    /* Read the dependencies */
+    ScmReadDependencies(hServiceKey,
+                        &lpDependencies,
+                        &dwDependenciesLength);
+
     dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
 
     if (lpImagePath != NULL)
@@ -2571,7 +2592,10 @@ DWORD RQueryServiceConfigW(
     else
         dwRequiredSize += 2 * sizeof(WCHAR);
 
-    /* FIXME: Add Dependencies length*/
+    if (lpDependencies != NULL)
+        dwRequiredSize += dwDependenciesLength * sizeof(WCHAR);
+    else
+        dwRequiredSize += 2 * sizeof(WCHAR);
 
     if (lpServiceStartName != NULL)
         dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
@@ -2597,6 +2621,7 @@ DWORD RQueryServiceConfigW(
 
         lpStr = (LPWSTR)(lpConfig + 1);
 
+        /* Append the image path */
         if (lpImagePath != NULL)
         {
             wcscpy(lpStr, lpImagePath);
@@ -2609,6 +2634,7 @@ DWORD RQueryServiceConfigW(
         lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
         lpStr += (wcslen(lpStr) + 1);
 
+        /* Append the group name */
         if (lpService->lpGroup != NULL)
         {
             wcscpy(lpStr, lpService->lpGroup->lpGroupName);
@@ -2621,12 +2647,25 @@ DWORD RQueryServiceConfigW(
         lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
         lpStr += (wcslen(lpStr) + 1);
 
-        /* FIXME: Append Dependencies */
-        wcscpy(lpStr, lpEmptyString);
+        /* Append Dependencies */
+        if (lpDependencies != NULL)
+        {
+            memcpy(lpStr,
+                   lpDependencies,
+                   dwDependenciesLength * sizeof(WCHAR));
+        }
+        else
+        {
+            wcscpy(lpStr, lpEmptyString);
+        }
 
-        lpStr += (wcslen(lpStr) + 1);
         lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
+        if (lpDependencies != NULL)
+            lpStr += dwDependenciesLength * sizeof(WCHAR);
+        else
+            lpStr += (wcslen(lpStr) + 1);
 
+        /* Append the service start name */
         if (lpServiceStartName != NULL)
         {
             wcscpy(lpStr, lpServiceStartName);
@@ -2639,6 +2678,7 @@ DWORD RQueryServiceConfigW(
         lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
         lpStr += (wcslen(lpStr) + 1);
 
+        /* Append the display name */
         if (lpService->lpDisplayName != NULL)
         {
             wcscpy(lpStr, lpService->lpDisplayName);
@@ -2661,6 +2701,9 @@ Done:;
     if (lpServiceStartName != NULL)
         HeapFree(GetProcessHeap(), 0, lpServiceStartName);
 
+    if (lpDependencies != NULL)
+        HeapFree(GetProcessHeap(), 0, lpDependencies);
+
     if (hServiceKey != NULL)
         RegCloseKey(hServiceKey);
 
@@ -2674,7 +2717,6 @@ Done:;
 
 /* Function 18 */
 DWORD RQueryServiceLockStatusW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
     DWORD cbBufSize,
@@ -2687,7 +2729,6 @@ DWORD RQueryServiceLockStatusW(
 
 /* Function 19 */
 DWORD RStartServiceW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD argc,
     LPSTRING_PTRSW argv)
@@ -2742,9 +2783,8 @@ DWORD RStartServiceW(
 
 /* Function 20 */
 DWORD RGetServiceDisplayNameW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
-    LPWSTR lpServiceName,
+    LPCWSTR lpServiceName,
     LPWSTR lpDisplayName,
     DWORD *lpcchBuffer)
 {
@@ -2772,12 +2812,15 @@ DWORD RGetServiceDisplayNameW(
     {
         DPRINT1("Could not find a service!\n");
 
-        /* If the service could not be found and lpcchBuffer is 0, windows
-           puts null in lpDisplayName and puts 1 in lpcchBuffer */
-        if (*lpcchBuffer == 0)
+        /* If the service could not be found and lpcchBuffer is less than 2, windows
+           puts null in lpDisplayName and puts 2 in lpcchBuffer */
+        if (*lpcchBuffer < 2)
         {
-            *lpcchBuffer = 1;
-            *lpDisplayName = '\0';
+            *lpcchBuffer = 2;
+            if (lpDisplayName != NULL)
+            {
+                *lpDisplayName = '\0';
+            }
         }
 
         return ERROR_SERVICE_DOES_NOT_EXIST;
@@ -2787,7 +2830,7 @@ DWORD RGetServiceDisplayNameW(
     {
         dwLength = wcslen(lpService->lpServiceName);
 
-        if (lpServiceName != NULL &&
+        if (lpDisplayName != NULL &&
             *lpcchBuffer > dwLength)
         {
             wcscpy(lpDisplayName, lpService->lpServiceName);
@@ -2814,9 +2857,8 @@ DWORD RGetServiceDisplayNameW(
 
 /* Function 21 */
 DWORD RGetServiceKeyNameW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
-    LPWSTR lpDisplayName,
+    LPCWSTR lpDisplayName,
     LPWSTR lpServiceName,
     DWORD *lpcchBuffer)
 {
@@ -2844,12 +2886,15 @@ DWORD RGetServiceKeyNameW(
     {
         DPRINT1("Could not find a service!\n");
 
-        /* If the service could not be found and lpcchBuffer is 0, windows
+        /* If the service could not be found and lpcchBuffer is less than 2, windows
            puts null in lpDisplayName and puts 2 in lpcchBuffer */
-        if (*lpcchBuffer == 0)
+        if (*lpcchBuffer < 2)
         {
             *lpcchBuffer = 2;
-            *lpServiceName = '\0';
+            if (lpServiceName != NULL)
+            {
+                *lpServiceName = '\0';
+            }
         }
 
         return ERROR_SERVICE_DOES_NOT_EXIST;
@@ -2867,7 +2912,7 @@ DWORD RGetServiceKeyNameW(
 
     dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
 
-    *lpcchBuffer = dwLength * 2;
+    *lpcchBuffer = dwLength;
 
     return dwError;
 }
@@ -2875,8 +2920,7 @@ DWORD RGetServiceKeyNameW(
 
 /* Function 22 */
 DWORD RI_ScSetServiceBitsA(
-    handle_t BindingHandle,
-    SC_RPC_HANDLE hServiceStatus,
+    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
     DWORD dwServiceBits,
     int bSetBitsOn,
     int bUpdateImmediately,
@@ -2889,7 +2933,6 @@ DWORD RI_ScSetServiceBitsA(
 
 /* Function 23 */
 DWORD RChangeServiceConfigA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwServiceType,
     DWORD dwStartType,
@@ -2981,7 +3024,7 @@ DWORD RChangeServiceConfigA(
                             lpDisplayName,
                             -1,
                             lpDisplayNameW,
-                            wcslen(lpDisplayNameW) + 1);
+                            strlen(lpDisplayName) + 1);
 
         RegSetValueExW(hServiceKey,
                        L"DisplayName",
@@ -3051,7 +3094,7 @@ DWORD RChangeServiceConfigA(
         if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
         {
             lpBinaryPathNameW=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName)+1) * sizeof(WCHAR));
-            MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, wcslen(lpBinaryPathNameW)+1);
+            MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, strlen(lpBinaryPathName)+1);
             dwError = RegSetValueExW(hServiceKey,
                                      L"ImagePath",
                                      0,
@@ -3083,7 +3126,7 @@ DWORD RChangeServiceConfigA(
     {
         lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(),
                                       0,
-                                      (strlen(lpLoadOrderGroup)+1) * sizeof(WCHAR));
+                                      (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
         if (lpLoadOrderGroupW == NULL)
         {
             dwError = ERROR_NOT_ENOUGH_MEMORY;
@@ -3095,7 +3138,7 @@ DWORD RChangeServiceConfigA(
                             lpLoadOrderGroup,
                             -1,
                             lpLoadOrderGroupW,
-                            wcslen(lpLoadOrderGroupW) + 1);
+                            strlen(lpLoadOrderGroup) + 1);
 
         dwError = RegSetValueExW(hServiceKey,
                                  L"Group",
@@ -3104,11 +3147,18 @@ DWORD RChangeServiceConfigA(
                                  (LPBYTE)lpLoadOrderGroupW,
                                  (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR));
         if (dwError != ERROR_SUCCESS)
+        {
+            HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
             goto done;
+        }
 
-        /* FIXME: Update lpService->lpServiceGroup */
+        dwError = ScmSetServiceGroup(lpService,
+                                     lpLoadOrderGroupW);
 
         HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
+
+        if (dwError != ERROR_SUCCESS)
+            goto done;
     }
 
     if (lpdwTagId != NULL)
@@ -3134,7 +3184,7 @@ DWORD RChangeServiceConfigA(
     {
         lpDependenciesW = HeapAlloc(GetProcessHeap(),
                                     0,
-                                    (strlen(lpDependencies)+1) * sizeof(WCHAR));
+                                    (strlen(lpDependencies) + 1) * sizeof(WCHAR));
         if (lpDependenciesW == NULL)
         {
             dwError = ERROR_NOT_ENOUGH_MEMORY;
@@ -3146,7 +3196,7 @@ DWORD RChangeServiceConfigA(
                             lpDependencies,
                             dwDependSize,
                             lpDependenciesW,
-                            wcslen(lpDependenciesW)+1);
+                            strlen(lpDependencies) + 1);
 
         dwError = ScmWriteDependencies(hServiceKey,
                                        (LPWSTR)lpDependenciesW,
@@ -3174,7 +3224,6 @@ done:
 
 /* Function 24 */
 DWORD RCreateServiceA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPSTR lpServiceName,
     LPSTR lpDisplayName,
@@ -3192,14 +3241,140 @@ DWORD RCreateServiceA(
     DWORD dwPwSize,
     LPSC_RPC_HANDLE lpServiceHandle)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    DWORD dwError = ERROR_SUCCESS;
+    LPWSTR lpServiceNameW = NULL;
+    LPWSTR lpDisplayNameW = NULL;
+    LPWSTR lpBinaryPathNameW = NULL;
+    LPWSTR lpLoadOrderGroupW = NULL;
+    LPWSTR lpDependenciesW = NULL;
+    LPWSTR lpServiceStartNameW = NULL;
+    DWORD dwDependenciesLength = 0;
+    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);
+    }
+
+    if (lpLoadOrderGroup)
+    {
+        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);
+    }
+
+    if (lpDependencies)
+    {
+        lpStr = (LPSTR)lpDependencies;
+        while (*lpStr)
+        {
+            dwLength = strlen(lpStr) + 1;
+            dwDependenciesLength += dwLength;
+            lpStr = lpStr + dwLength;
+        }
+        dwDependenciesLength++;
+
+        lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
+        if (!lpDependenciesW)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto cleanup;
+        }
+        MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
+    }
+
+    if (lpServiceStartName)
+    {
+        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);
+    }
+
+    dwError = RCreateServiceW(hSCManager,
+                              lpServiceNameW,
+                              lpDisplayNameW,
+                              dwDesiredAccess,
+                              dwServiceType,
+                              dwStartType,
+                              dwErrorControl,
+                              lpBinaryPathNameW,
+                              lpLoadOrderGroupW,
+                              lpdwTagId,
+                              (LPBYTE)lpDependenciesW,
+                              dwDependenciesLength,
+                              lpServiceStartNameW,
+                              lpPassword,
+                              dwPwSize,
+                              lpServiceHandle);
+
+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);
+
+    return dwError;
 }
 
 
 /* Function 25 */
 DWORD REnumDependentServicesA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwServiceState,
     LPBYTE lpServices,
@@ -3243,7 +3418,8 @@ DWORD REnumDependentServicesA(
                             KEY_READ,
                             &hServicesKey);
 
-    if (dwError != ERROR_SUCCESS) return dwError;
+    if (dwError != ERROR_SUCCESS)
+        return dwError;
 
     /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
              both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
@@ -3347,7 +3523,6 @@ Done:
 
 /* Function 26 */
 DWORD REnumServicesStatusA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     DWORD dwServiceType,
     DWORD dwServiceState,
@@ -3357,14 +3532,94 @@ DWORD REnumServicesStatusA(
     LPBOUNDED_DWORD_256K lpServicesReturned,
     LPBOUNDED_DWORD_256K lpResumeHandle)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
+    LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
+    LPWSTR lpStringPtrW;
+    LPSTR lpStringPtrA;
+    DWORD dwError;
+    DWORD dwServiceCount;
+
+    DPRINT("REnumServicesStatusA() called\n");
+
+    if ((dwBufSize > 0) && (lpBuffer))
+    {
+        lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
+        if (!lpStatusPtrW)
+        {
+            DPRINT1("Failed to allocate buffer!\n");
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+
+    dwError = REnumServicesStatusW(hSCManager,
+                                   dwServiceType,
+                                   dwServiceState,
+                                   (LPBYTE)lpStatusPtrW,
+                                   dwBufSize,
+                                   pcbBytesNeeded,
+                                   lpServicesReturned,
+                                   lpResumeHandle);
+
+    /* if no services were returned then we are Done */
+    if (*lpServicesReturned == 0)
+        goto Done;
+
+    lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
+    lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
+                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
+    lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 
+                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW));
+
+    for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
+    {
+        /* Copy the service name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            lpStringPtrW,
+                            -1,
+                            lpStringPtrA,
+                            wcslen(lpStringPtrW),
+                            0,
+                            0);
+
+        lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+        lpStringPtrA += wcslen(lpStringPtrW) + 1;
+        lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+        /* Copy the display name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            lpStringPtrW,
+                            -1,
+                            lpStringPtrA,
+                            wcslen(lpStringPtrW),
+                            0,
+                            0);
+
+        lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+        lpStringPtrA += wcslen(lpStringPtrW) + 1;
+        lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+        /* Copy the status information */
+        memcpy(&lpStatusPtrA->ServiceStatus,
+               &lpStatusPtrW->ServiceStatus,
+               sizeof(SERVICE_STATUS));
+
+        lpStatusPtrA++;
+    }
+
+Done:;
+    if (lpStatusPtrW)
+        HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
+
+    DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
+
+    return dwError;
 }
 
 
 /* Function 27 */
 DWORD ROpenSCManagerA(
-    handle_t BindingHandle,
     LPSTR lpMachineName,
     LPSTR lpDatabaseName,
     DWORD dwDesiredAccess,
@@ -3384,8 +3639,7 @@ DWORD ROpenSCManagerA(
         RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
                                          lpDatabaseName);
 
-    dwError = ROpenSCManagerW(BindingHandle,
-                              lpMachineName ? MachineName.Buffer : NULL,
+    dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL,
                               lpDatabaseName ? DatabaseName.Buffer : NULL,
                               dwDesiredAccess,
                               lpScHandle);
@@ -3402,7 +3656,6 @@ DWORD ROpenSCManagerA(
 
 /* Function 28 */
 DWORD ROpenServiceA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPSTR lpServiceName,
     DWORD dwDesiredAccess,
@@ -3417,8 +3670,7 @@ DWORD ROpenServiceA(
         RtlCreateUnicodeStringFromAsciiz(&ServiceName,
                                          lpServiceName);
 
-    dwError = ROpenServiceW(BindingHandle,
-                            hSCManager,
+    dwError = ROpenServiceW(hSCManager,
                             lpServiceName ? ServiceName.Buffer : NULL,
                             dwDesiredAccess,
                             lpServiceHandle);
@@ -3432,7 +3684,6 @@ DWORD ROpenServiceA(
 
 /* Function 29 */
 DWORD RQueryServiceConfigA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     LPBYTE lpBuf, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
     DWORD cbBufSize,
@@ -3445,6 +3696,8 @@ DWORD RQueryServiceConfigA(
     HKEY hServiceKey = NULL;
     LPWSTR lpImagePath = NULL;
     LPWSTR lpServiceStartName = NULL;
+    LPWSTR lpDependencies = NULL;
+    DWORD dwDependenciesLength = 0;
     DWORD dwRequiredSize;
     LPQUERY_SERVICE_CONFIGA lpConfig = NULL;
     CHAR lpEmptyString[]={0,0};
@@ -3484,16 +3737,23 @@ DWORD RQueryServiceConfigA(
     if (dwError != ERROR_SUCCESS)
         goto Done;
 
+    /* Read the image path */
     dwError = ScmReadString(hServiceKey,
                             L"ImagePath",
                             &lpImagePath);
     if (dwError != ERROR_SUCCESS)
         goto Done;
 
+    /* Read the service start name */
     ScmReadString(hServiceKey,
                   L"ObjectName",
                   &lpServiceStartName);
 
+    /* Read the dependencies */
+    ScmReadDependencies(hServiceKey,
+                        &lpDependencies,
+                        &dwDependenciesLength);
+
     dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
 
     if (lpImagePath != NULL)
@@ -3501,13 +3761,16 @@ DWORD RQueryServiceConfigA(
     else
         dwRequiredSize += 2;
 
-    if (lpService->lpGroup != NULL)
+    if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
         dwRequiredSize += wcslen(lpService->lpGroup->lpGroupName) + 1;
     else
         dwRequiredSize += 2;
 
-    /* FIXME: Add Dependencies length*/
-    dwRequiredSize += 2;
+    /* Add Dependencies length */
+    if (lpDependencies != NULL)
+        dwRequiredSize += dwDependenciesLength;
+    else
+        dwRequiredSize += 2;
 
     if (lpServiceStartName != NULL)
         dwRequiredSize += wcslen(lpServiceStartName) + 1;
@@ -3543,7 +3806,7 @@ DWORD RQueryServiceConfigA(
                                 lpImagePath,
                                 -1,
                                 lpStr,
-                                wcslen(lpImagePath),
+                                wcslen(lpImagePath) + 1,
                                 0,
                                 0);
         }
@@ -3555,14 +3818,14 @@ DWORD RQueryServiceConfigA(
         lpConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
         lpStr += (strlen((LPSTR)lpStr) + 1);
 
-        if (lpService->lpGroup)
+        if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
         {
             WideCharToMultiByte(CP_ACP,
                                 0,
                                 lpService->lpGroup->lpGroupName,
                                 -1,
                                 lpStr,
-                                wcslen(lpService->lpGroup->lpGroupName),
+                                wcslen(lpService->lpGroup->lpGroupName) + 1,
                                 0,
                                 0);
         }
@@ -3574,11 +3837,28 @@ DWORD RQueryServiceConfigA(
         lpConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
         lpStr += (strlen(lpStr) + 1);
 
-        /* FIXME: Append Dependencies */
-        strcpy(lpStr, lpEmptyString);
+        /* Append Dependencies */
+        if (lpDependencies)
+        {
+            WideCharToMultiByte(CP_ACP,
+                                0,
+                                lpDependencies,
+                                dwDependenciesLength,
+                                lpStr,
+                                dwDependenciesLength,
+                                0,
+                                0);
+        }
+        else
+        {
+            strcpy(lpStr, lpEmptyString);
+        }
 
         lpConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
-        lpStr += (strlen(lpStr) + 1);
+        if (lpDependencies)
+            lpStr += dwDependenciesLength;
+        else
+            lpStr += (strlen(lpStr) + 1);
 
         if (lpServiceStartName)
         {
@@ -3587,7 +3867,7 @@ DWORD RQueryServiceConfigA(
                                 lpServiceStartName,
                                 -1,
                                 lpStr,
-                                wcslen(lpServiceStartName),
+                                wcslen(lpServiceStartName) + 1,
                                 0,
                                 0);
         }
@@ -3606,7 +3886,7 @@ DWORD RQueryServiceConfigA(
                                 lpService->lpDisplayName,
                                 -1,
                                 lpStr,
-                                wcslen(lpService->lpDisplayName),
+                                wcslen(lpService->lpDisplayName) + 1,
                                 0,
                                 0);
         }
@@ -3628,6 +3908,9 @@ Done:;
     if (lpServiceStartName != NULL)
         HeapFree(GetProcessHeap(), 0, lpServiceStartName);
 
+    if (lpDependencies != NULL)
+        HeapFree(GetProcessHeap(), 0, lpDependencies);
+
     if (hServiceKey != NULL)
         RegCloseKey(hServiceKey);
 
@@ -3641,7 +3924,6 @@ Done:;
 
 /* Function 30 */
 DWORD RQueryServiceLockStatusA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
     DWORD cbBufSize,
@@ -3654,7 +3936,6 @@ DWORD RQueryServiceLockStatusA(
 
 /* Function 31 */
 DWORD RStartServiceA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD argc,
     LPSTRING_PTRSA argv)
@@ -3708,14 +3989,13 @@ DWORD RStartServiceA(
 
 /* Function 32 */
 DWORD RGetServiceDisplayNameA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
-    LPSTR lpServiceName,
+    LPCSTR lpServiceName,
     LPSTR lpDisplayName,
     LPBOUNDED_DWORD_4K lpcchBuffer)
 {
 //    PMANAGER_HANDLE hManager;
-    PSERVICE lpService;
+    PSERVICE lpService = NULL;
     DWORD dwLength;
     DWORD dwError;
     LPWSTR lpServiceNameW;
@@ -3733,23 +4013,26 @@ DWORD RGetServiceDisplayNameA(
 //        return ERROR_INVALID_HANDLE;
 //    }
 
-    dwLength = strlen(lpServiceName) + 1;
-    lpServiceNameW = HeapAlloc(GetProcessHeap(),
-                               HEAP_ZERO_MEMORY,
-                               dwLength * sizeof(WCHAR));
-    if (!lpServiceNameW)
-        return ERROR_NOT_ENOUGH_MEMORY;
+    if (lpServiceName != NULL)
+    {
+        dwLength = strlen(lpServiceName) + 1;
+        lpServiceNameW = HeapAlloc(GetProcessHeap(),
+                                   HEAP_ZERO_MEMORY,
+                                   dwLength * sizeof(WCHAR));
+        if (!lpServiceNameW)
+            return ERROR_NOT_ENOUGH_MEMORY;
 
-    MultiByteToWideChar(CP_ACP,
-                        0,
-                        lpServiceName,
-                        strlen(lpServiceName),
-                        lpServiceNameW,
-                        dwLength);
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            lpServiceName,
+                            -1,
+                            lpServiceNameW,
+                            dwLength);
 
-    lpService = ScmGetServiceEntryByName(lpServiceNameW);
+        lpService = ScmGetServiceEntryByName(lpServiceNameW);
 
-    HeapFree(GetProcessHeap(), 0, lpServiceNameW);
+        HeapFree(GetProcessHeap(), 0, lpServiceNameW);
+    }
 
     if (lpService == NULL)
     {
@@ -3760,7 +4043,10 @@ DWORD RGetServiceDisplayNameA(
         if (*lpcchBuffer == 0)
         {
             *lpcchBuffer = 1;
-            *lpDisplayName = '\0';
+            if (lpDisplayName != NULL)
+            {
+                *lpDisplayName = '\0';
+            }
         }
         return ERROR_SERVICE_DOES_NOT_EXIST;
     }
@@ -3768,7 +4054,7 @@ DWORD RGetServiceDisplayNameA(
     if (!lpService->lpDisplayName)
     {
         dwLength = wcslen(lpService->lpServiceName);
-        if (lpServiceName != NULL &&
+        if (lpDisplayName != NULL &&
             *lpcchBuffer > dwLength)
         {
             WideCharToMultiByte(CP_ACP,
@@ -3776,7 +4062,7 @@ DWORD RGetServiceDisplayNameA(
                                 lpService->lpServiceName,
                                 wcslen(lpService->lpServiceName),
                                 lpDisplayName,
-                                *lpcchBuffer,
+                                dwLength + 1,
                                 NULL,
                                 NULL);
             return ERROR_SUCCESS;
@@ -3793,7 +4079,7 @@ DWORD RGetServiceDisplayNameA(
                                 lpService->lpDisplayName,
                                 wcslen(lpService->lpDisplayName),
                                 lpDisplayName,
-                                *lpcchBuffer,
+                                dwLength + 1,
                                 NULL,
                                 NULL);
             return ERROR_SUCCESS;
@@ -3810,9 +4096,8 @@ DWORD RGetServiceDisplayNameA(
 
 /* Function 33 */
 DWORD RGetServiceKeyNameA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
-    LPSTR lpDisplayName,
+    LPCSTR lpDisplayName,
     LPSTR lpServiceName,
     LPBOUNDED_DWORD_4K lpcchBuffer)
 {
@@ -3837,7 +4122,7 @@ DWORD RGetServiceKeyNameA(
     MultiByteToWideChar(CP_ACP,
                         0,
                         lpDisplayName,
-                        strlen(lpDisplayName),
+                        -1,
                         lpDisplayNameW,
                         dwLength);
 
@@ -3854,14 +4139,17 @@ DWORD RGetServiceKeyNameA(
         if (*lpcchBuffer == 0)
         {
             *lpcchBuffer = 1;
-            *lpServiceName = '\0';
+            if (lpServiceName != NULL)
+            {
+                *lpServiceName = '\0';
+            }
         }
 
         return ERROR_SERVICE_DOES_NOT_EXIST;
     }
 
     dwLength = wcslen(lpService->lpServiceName);
-    if (lpService != NULL &&
+    if (lpServiceName != NULL &&
         *lpcchBuffer > dwLength)
     {
         WideCharToMultiByte(CP_ACP,
@@ -3869,7 +4157,7 @@ DWORD RGetServiceKeyNameA(
                             lpService->lpServiceName,
                             wcslen(lpService->lpServiceName),
                             lpServiceName,
-                            dwLength,
+                            dwLength + 1,
                             NULL,
                             NULL);
         return ERROR_SUCCESS;
@@ -3885,7 +4173,6 @@ DWORD RGetServiceKeyNameA(
 
 /* Function 34 */
 DWORD RI_ScGetCurrentGroupStateW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     LPWSTR lpLoadOrderGroup,
     LPDWORD lpState)
@@ -3897,7 +4184,6 @@ DWORD RI_ScGetCurrentGroupStateW(
 
 /* Function 35 */
 DWORD REnumServiceGroupW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     DWORD dwServiceType,
     DWORD dwServiceState,
@@ -3913,20 +4199,123 @@ DWORD REnumServiceGroupW(
 }
 
 
+//
+// WARNING: This function is untested
+//
 /* Function 36 */
 DWORD RChangeServiceConfig2A(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     SC_RPC_CONFIG_INFOA Info)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    SC_RPC_CONFIG_INFOW InfoW;
+    DWORD dwRet, dwLength;
+    PVOID ptr = NULL;
+
+    DPRINT("RChangeServiceConfig2A() called\n");
+    DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
+
+    InfoW.dwInfoLevel = Info.dwInfoLevel;
+
+    if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
+    {
+        LPSERVICE_DESCRIPTIONW lpServiceDescriptonW;
+        LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
+
+        lpServiceDescriptonA = Info.psd;
+
+        ///if (lpServiceDescriptonA &&
+        ///lpServiceDescriptonA->lpDescription)
+        ///{
+            dwLength = (strlen(Info.lpDescription) + 1) * sizeof(WCHAR);
+
+            lpServiceDescriptonW = HeapAlloc(GetProcessHeap(),
+                                            0,
+                                            dwLength + sizeof(SERVICE_DESCRIPTIONW));
+            if (!lpServiceDescriptonW)
+            {
+                return ERROR_NOT_ENOUGH_MEMORY;
+            }
+
+            lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1);
+
+            MultiByteToWideChar(CP_ACP,
+                                0,
+                                Info.lpDescription,
+                                -1,
+                                lpServiceDescriptonW->lpDescription,
+                                dwLength);
+
+            ptr = lpServiceDescriptonW;
+            InfoW.psd = lpServiceDescriptonW;
+        ///}
+    }
+    else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
+    {
+        LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
+        LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
+        DWORD dwRebootLen = 0;
+        DWORD dwCommandLen = 0;
+
+        lpServiceFailureActionsA = Info.psfa;
+
+        if (lpServiceFailureActionsA)
+        {
+            if (lpServiceFailureActionsA->lpRebootMsg)
+            {
+                dwRebootLen = (strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR);
+            }
+            if (lpServiceFailureActionsA->lpCommand)
+            {
+                dwCommandLen = (strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR);
+            }
+            dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW);
+
+            lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
+                                                 0,
+                                                 dwLength);
+            if (!lpServiceFailureActionsW)
+            {
+                return ERROR_NOT_ENOUGH_MEMORY;
+            }
+
+            lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
+            lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
+            CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION));
+
+            if (lpServiceFailureActionsA->lpRebootMsg)
+            {
+                MultiByteToWideChar(CP_ACP,
+                                    0,
+                                    lpServiceFailureActionsA->lpRebootMsg,
+                                    -1,
+                                    lpServiceFailureActionsW->lpRebootMsg,
+                                    dwRebootLen);
+            }
+
+            if (lpServiceFailureActionsA->lpCommand)
+            {
+                MultiByteToWideChar(CP_ACP,
+                                    0,
+                                    lpServiceFailureActionsA->lpCommand,
+                                    -1,
+                                    lpServiceFailureActionsW->lpCommand,
+                                    dwCommandLen);
+            }
+
+            ptr = lpServiceFailureActionsW;
+        }
+    }
+
+    dwRet = RChangeServiceConfig2W(hService, InfoW);
+
+    HeapFree(GetProcessHeap(), 0, ptr);
+
+    return dwRet;
 }
 
 
 /* Function 37 */
 DWORD RChangeServiceConfig2W(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     SC_RPC_CONFIG_INFOW Info)
 {
@@ -3978,16 +4367,17 @@ DWORD RChangeServiceConfig2W(
     if (dwError != ERROR_SUCCESS)
         goto done;
 
-    if (Info.dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
+    if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
     {
         LPSERVICE_DESCRIPTIONW lpServiceDescription;
 
-        lpServiceDescription = (LPSERVICE_DESCRIPTIONW)&Info;
-        lpServiceDescription->lpDescription = (LPWSTR)(&Info + sizeof(LPSERVICE_DESCRIPTIONW));
+        lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
+        lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpServiceDescription + sizeof(LPSERVICE_DESCRIPTIONW));
 
         if (lpServiceDescription != NULL &&
             lpServiceDescription->lpDescription != NULL)
         {
+            DPRINT1("Setting value %S\n", lpServiceDescription->lpDescription);
             RegSetValueExW(hServiceKey,
                            L"Description",
                            0,
@@ -3999,7 +4389,7 @@ DWORD RChangeServiceConfig2W(
                 goto done;
         }
     }
-    else if (Info.dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
+    else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
     {
         UNIMPLEMENTED;
         dwError = ERROR_CALL_NOT_IMPLEMENTED;
@@ -4019,7 +4409,6 @@ done:
 
 /* Function 38 */
 DWORD RQueryServiceConfig2A(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwInfoLevel,
     LPBYTE lpBuffer,
@@ -4030,11 +4419,11 @@ DWORD RQueryServiceConfig2A(
     PSERVICE_HANDLE hSvc;
     PSERVICE lpService = NULL;
     HKEY hServiceKey = NULL;
-    DWORD dwRequiredSize;
     LPWSTR lpDescriptionW = NULL;
     LPSTR lpDescription = NULL;
 
-    DPRINT("RQueryServiceConfig2W() called\n");
+    DPRINT1("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
+            hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
     if (!lpBuffer)
         return ERROR_INVALID_ADDRESS;
@@ -4071,37 +4460,49 @@ DWORD RQueryServiceConfig2A(
     if (dwError != ERROR_SUCCESS)
         goto done;
 
-    if (dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
+    if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
     {
         LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer;
         LPSTR lpStr;
 
+        *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA);
+
         dwError = ScmReadString(hServiceKey,
                                 L"Description",
                                 &lpDescriptionW);
-        if (dwError != ERROR_SUCCESS)
-            goto done;
+        if (dwError == ERROR_SUCCESS)
+        {
+            *pcbBytesNeeded += ((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
+        }
+
+        if (cbBufSize >= *pcbBytesNeeded)
+        {
 
-        dwRequiredSize = sizeof(SERVICE_DESCRIPTIONA) + ((wcslen(lpDescriptionW) + 1));
+            if (dwError == ERROR_SUCCESS)
+            {
+                lpStr = (LPSTR)(lpServiceDescription + 1);
 
-        if (cbBufSize < dwRequiredSize)
+                WideCharToMultiByte(CP_ACP,
+                                    0,
+                                    lpDescriptionW,
+                                    -1,
+                                    lpStr,
+                                    wcslen(lpDescriptionW),
+                                    NULL,
+                                    NULL);
+                lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
+            }
+            else
+            {
+                lpServiceDescription->lpDescription = NULL;
+                goto done;
+            }
+        }
+        else
         {
-            *pcbBytesNeeded = dwRequiredSize;
             dwError = ERROR_INSUFFICIENT_BUFFER;
             goto done;
         }
-
-        lpStr = (LPSTR)(lpServiceDescription + 1);
-
-        WideCharToMultiByte(CP_ACP,
-                            0,
-                            lpDescriptionW,
-                            -1,
-                            lpStr,
-                            wcslen(lpDescriptionW),
-                            NULL,
-                            NULL);
-        lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
     }
     else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
     {
@@ -4127,7 +4528,6 @@ done:
 
 /* Function 39 */
 DWORD RQueryServiceConfig2W(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwInfoLevel,
     LPBYTE lpBuffer,
@@ -4140,6 +4540,8 @@ DWORD RQueryServiceConfig2W(
     HKEY hServiceKey = NULL;
     DWORD dwRequiredSize;
     LPWSTR lpDescription = NULL;
+    LPWSTR lpFailureCommand = NULL;
+    LPWSTR lpRebootMessage = NULL;
 
     DPRINT("RQueryServiceConfig2W() called\n");
 
@@ -4178,7 +4580,7 @@ DWORD RQueryServiceConfig2W(
     if (dwError != ERROR_SUCCESS)
         goto done;
 
-    if (dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
+    if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
     {
         LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
         LPWSTR lpStr;
@@ -4202,10 +4604,57 @@ DWORD RQueryServiceConfig2W(
         wcscpy(lpStr, lpDescription);
         lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
     }
-    else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
+    else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
     {
+        LPWSTR lpStr;
+        LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
+
         UNIMPLEMENTED;
-        dwError = ERROR_CALL_NOT_IMPLEMENTED;
+
+        dwError = ScmReadString(hServiceKey,
+                                L"FailureCommand",
+                                &lpFailureCommand);
+
+        dwError = ScmReadString(hServiceKey,
+                                L"RebootMessage",
+                                &lpRebootMessage);
+
+        dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
+
+        if (lpFailureCommand)
+            dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
+
+        if (lpRebootMessage)
+            dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
+
+        if (cbBufSize < dwRequiredSize)
+        {
+            *pcbBytesNeeded = dwRequiredSize;
+            dwError = ERROR_INSUFFICIENT_BUFFER;
+            goto done;
+        }
+
+        lpFailureActions->cActions = 0; 
+        lpFailureActions->dwResetPeriod = 0;
+        lpFailureActions->lpCommand = NULL;
+        lpFailureActions->lpRebootMsg = NULL;
+        lpFailureActions->lpsaActions = NULL;
+
+        lpStr = (LPWSTR)(lpFailureActions + 1);
+        if (lpRebootMessage)
+        {
+            wcscpy(lpStr, lpRebootMessage);
+            lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage);
+            lpStr += wcslen(lpRebootMessage) + 1;
+        }
+
+        if (lpFailureCommand)
+        {
+            wcscpy(lpStr, lpFailureCommand);
+            lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand);
+            lpStr += wcslen(lpRebootMessage) + 1;
+        }
+        dwError = STATUS_SUCCESS;
         goto done;
     }
 
@@ -4213,6 +4662,12 @@ done:
     if (lpDescription != NULL)
         HeapFree(GetProcessHeap(), 0, lpDescription);
 
+    if (lpRebootMessage != NULL)
+        HeapFree(GetProcessHeap(), 0, lpRebootMessage);
+
+    if (lpFailureCommand != NULL)
+        HeapFree(GetProcessHeap(), 0, lpFailureCommand);
+
     if (hServiceKey != NULL)
         RegCloseKey(hServiceKey);
 
@@ -4226,7 +4681,6 @@ done:
 
 /* Function 40 */
 DWORD RQueryServiceStatusEx(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     SC_STATUS_TYPE InfoLevel,
     LPBYTE lpBuffer,
@@ -4287,7 +4741,6 @@ DWORD RQueryServiceStatusEx(
 
 /* Function 41 */
 DWORD REnumServicesStatusExA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     SC_ENUM_TYPE InfoLevel,
     DWORD dwServiceType,
@@ -4299,16 +4752,119 @@ DWORD REnumServicesStatusExA(
     LPBOUNDED_DWORD_256K lpResumeIndex,
     LPCSTR pszGroupName)
 {
-    UNIMPLEMENTED;
-    *pcbBytesNeeded = 0;
-    *lpServicesReturned = 0;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
+    LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
+    LPWSTR lpStringPtrW;
+    LPSTR lpStringPtrA;
+    LPWSTR pszGroupNameW = NULL;
+    DWORD dwError;
+    DWORD dwServiceCount;
+
+    DPRINT("REnumServicesStatusExA() called\n");
+
+    if (pszGroupName)
+    {
+        pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
+        if (!pszGroupNameW)
+        {
+             DPRINT1("Failed to allocate buffer!\n");
+             return ERROR_NOT_ENOUGH_MEMORY;
+        }
+
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            pszGroupName,
+                            -1,
+                            pszGroupNameW,
+                            strlen(pszGroupName) + 1);
+    }
+
+    if ((cbBufSize > 0) && (lpBuffer))
+    {
+        lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize);
+        if (!lpStatusPtrW)
+        {
+            DPRINT1("Failed to allocate buffer!\n");
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+    }
+
+    dwError = REnumServicesStatusExW(hSCManager,
+                                     InfoLevel,
+                                     dwServiceType,
+                                     dwServiceState,
+                                     (LPBYTE)lpStatusPtrW,
+                                     cbBufSize,
+                                     pcbBytesNeeded,
+                                     lpServicesReturned,
+                                     lpResumeIndex,
+                                     pszGroupNameW);
+
+    /* if no services were returned then we are Done */
+    if (*lpServicesReturned == 0)
+        goto Done;
+
+    lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
+    lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
+                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
+    lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 
+                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
+
+    for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
+    {
+        /* Copy the service name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            lpStringPtrW,
+                            -1,
+                            lpStringPtrA,
+                            wcslen(lpStringPtrW),
+                            0,
+                            0);
+
+        lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+        lpStringPtrA += wcslen(lpStringPtrW) + 1;
+        lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+        /* Copy the display name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            lpStringPtrW,
+                            -1,
+                            lpStringPtrA,
+                            wcslen(lpStringPtrW),
+                            0,
+                            0);
+
+        lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
+        lpStringPtrA += wcslen(lpStringPtrW) + 1;
+        lpStringPtrW += wcslen(lpStringPtrW) + 1;
+
+        /* Copy the status information */
+        memcpy(&lpStatusPtrA->ServiceStatusProcess,
+               &lpStatusPtrW->ServiceStatusProcess,
+               sizeof(SERVICE_STATUS));
+
+        lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrW->ServiceStatusProcess.dwProcessId; /* FIXME */
+        lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
+        lpStatusPtrA++;
+    }
+
+Done:;
+    if (pszGroupNameW)
+        HeapFree(GetProcessHeap(), 0, pszGroupNameW);
+
+    if (lpStatusPtrW)
+        HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
+
+    DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
+
+    return dwError;
 }
 
 
 /* Function 42 */
 DWORD REnumServicesStatusExW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hSCManager,
     SC_ENUM_TYPE InfoLevel,
     DWORD dwServiceType,
@@ -4329,7 +4885,7 @@ DWORD REnumServicesStatusExW(
     DWORD dwRequiredSize;
     DWORD dwServiceCount;
     DWORD dwSize;
-    DWORD dwLastResumeCount;
+    DWORD dwLastResumeCount = 0;
     LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
     LPWSTR lpStringPtr;
 
@@ -4348,6 +4904,21 @@ DWORD REnumServicesStatusExW(
         return ERROR_INVALID_HANDLE;
     }
 
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+
+    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+    {
+        DPRINT1("Not a valid Service Type!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+    {
+        DPRINT1("Not a valid Service State!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
     /* Check access rights */
     if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
                                   SC_MANAGER_ENUMERATE_SERVICE))
@@ -4357,10 +4928,7 @@ DWORD REnumServicesStatusExW(
         return ERROR_ACCESS_DENIED;
     }
 
-    *pcbBytesNeeded = 0;
-    *lpServicesReturned = 0;
-
-    dwLastResumeCount = *lpResumeIndex;
+    if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
 
     /* Lock the service list shared */
 
@@ -4471,10 +5039,19 @@ DWORD REnumServicesStatusExW(
 
     DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
 
-    *lpResumeIndex = dwLastResumeCount;
+    if (lpResumeIndex)
+        *lpResumeIndex = dwLastResumeCount;
+
     *lpServicesReturned = dwServiceCount;
     *pcbBytesNeeded = dwRequiredSize;
 
+    /* If there was no services that matched */
+    if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA))
+    {
+        dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+        goto Done;
+    }
+
     lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer;
     lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
                            dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
@@ -4545,7 +5122,13 @@ DWORD REnumServicesStatusExW(
         {
             break;
         }
+    }
 
+    if (dwError == 0) 
+    {
+        *pcbBytesNeeded = 0;
+        if (lpResumeIndex)
+            *lpResumeIndex = 0;
     }
 
 Done:;
@@ -4559,7 +5142,7 @@ Done:;
 
 /* Function 43 */
 DWORD RSendTSMessage(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
@@ -4616,7 +5199,7 @@ DWORD RCreateServiceWOW64W(
 
 /* Function 46 */
 DWORD RQueryServiceTagInfo(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
@@ -4625,7 +5208,6 @@ DWORD RQueryServiceTagInfo(
 
 /* Function 47 */
 DWORD RNotifyServiceStatusChange(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     SC_RPC_NOTIFY_PARAMS NotifyParams,
     GUID *pClientProcessGuid,
@@ -4640,7 +5222,6 @@ DWORD RNotifyServiceStatusChange(
 
 /* Function 48 */
 DWORD RGetNotifyResults(
-    handle_t BindingHandle,
     SC_NOTIFY_RPC_HANDLE hNotify,
     PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
 {
@@ -4651,7 +5232,6 @@ DWORD RGetNotifyResults(
 
 /* Function 49 */
 DWORD RCloseNotifyHandle(
-    handle_t BindingHandle,
     LPSC_NOTIFY_RPC_HANDLE phNotify,
     PBOOL pfApcFired)
 {
@@ -4662,7 +5242,6 @@ DWORD RCloseNotifyHandle(
 
 /* Function 50 */
 DWORD RControlServiceExA(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwControl,
     DWORD dwInfoLevel)
@@ -4674,7 +5253,6 @@ DWORD RControlServiceExA(
 
 /* Function 51 */
 DWORD RControlServiceExW(
-    handle_t BindingHandle,
     SC_RPC_HANDLE hService,
     DWORD dwControl,
     DWORD dwInfoLevel)
@@ -4686,7 +5264,7 @@ DWORD RControlServiceExW(
 
 /* Function 52 */
 DWORD RSendPnPMessage(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
@@ -4695,7 +5273,7 @@ DWORD RSendPnPMessage(
 
 /* Function 53 */
 DWORD RValidatePnPService(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
@@ -4704,7 +5282,7 @@ DWORD RValidatePnPService(
 
 /* Function 54 */
 DWORD ROpenServiceStatusHandle(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
@@ -4713,14 +5291,14 @@ DWORD ROpenServiceStatusHandle(
 
 /* Function 55 */
 DWORD RFunction55(
-    handle_t BindingHandle)
+    handle_t BindingHandle)  /* FIXME */
 {
     UNIMPLEMENTED;
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
-void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
+void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
 {
     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
 }
@@ -4746,5 +5324,4 @@ void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
 {
 }
 
-
 /* EOF */