- Implement EnumServicesStatusW.
authorEric Kohl <eric.kohl@reactos.org>
Sun, 25 Dec 2005 14:45:30 +0000 (14:45 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 25 Dec 2005 14:45:30 +0000 (14:45 +0000)
- Add server stubs for ChangeServiceConfigA, GetServiceDisplayNameA, GetServiceKeyNameA and QueryServiceStatusEx.

svn path=/trunk/; revision=20328

reactos/include/idl/svcctl.idl
reactos/lib/advapi32/service/scm.c
reactos/subsys/system/services/rpcserver.c
reactos/subsys/system/services/services.h

index 5aa5ad6..239fe64 100644 (file)
 #define SC_HANDLE unsigned int\r
 #define SC_LOCK unsigned int\r
 #define SERVICE_STATUS_HANDLE unsigned long\r
+#define SC_STATUS_TYPE unsigned long\r
 #define LPSTR char*\r
 #define LPCSTR char*\r
 #define LPWSTR wchar_t*\r
 #define LPCWSTR wchar_t*\r
+#define LPBYTE unsigned char*\r
 #define LPDWORD unsigned long*\r
 \r
 [\r
@@ -90,12 +92,12 @@ cpp_quote("#endif")
                                    [in] BOOL BootAcceptable);\r
 \r
   /* Function 10 */\r
-  DWORD ScmrI_ScSetServiceBitsW([in] handle_t BindingHandle,\r
-                                [in] SERVICE_STATUS_HANDLE hServiceStatus,\r
-                                [in] DWORD dwServiceBits,\r
-                                [in] BOOL bSetBitsOn,\r
-                                [in] BOOL bUpdateImmediately,\r
-                                [in, string, unique] LPWSTR lpString);\r
+  DWORD ScmrSetServiceBitsW([in] handle_t BindingHandle,\r
+                            [in] SERVICE_STATUS_HANDLE hServiceStatus,\r
+                            [in] DWORD dwServiceBits,\r
+                            [in] BOOL bSetBitsOn,\r
+                            [in] BOOL bUpdateImmediately,\r
+                            [in, string, unique] LPWSTR lpString);\r
 \r
   /* Function 11 */\r
   DWORD ScmrChangeServiceConfigW([in] handle_t BindingHandle,\r
@@ -136,7 +138,7 @@ cpp_quote("#endif")
   DWORD ScmrEnumDependentServicesW([in] handle_t BindingHandle,\r
                                    [in] SC_HANDLE hService,\r
                                    [in] DWORD dwServiceState,\r
-                                   [out, size_is(cbBufSize)] BYTE *lpServices,\r
+                                   [out, size_is(cbBufSize)] LPBYTE lpServices,\r
                                    [in] DWORD cbBufSize,\r
                                    [out] LPDWORD pcbBytesNeeded,\r
                                    [out] LPDWORD lpServicesReturned);\r
@@ -146,7 +148,7 @@ cpp_quote("#endif")
                                 [in] SC_HANDLE hSCManager,\r
                                 [in] DWORD dwServiceType,\r
                                 [in] DWORD dwServiceState,\r
-                                [out, size_is(dwBufSize)] BYTE *lpServices,\r
+                                [out, size_is(dwBufSize)] LPBYTE lpServices,\r
                                 [in] DWORD dwBufSize,\r
                                 [out] LPDWORD pcbBytesNeeded,\r
                                 [out] LPDWORD lpServicesReturned,\r
@@ -169,10 +171,22 @@ cpp_quote("#endif")
   /* Function 17 */\r
   DWORD ScmrQueryServiceConfigW([in] handle_t BindingHandle,\r
                                 [in] SC_HANDLE hService,\r
-                                [out, unique, size_is(cbBufSize)] BYTE *lpServiceConfig,\r
+                                [out, unique, size_is(cbBufSize)] LPBYTE lpServiceConfig,\r
                                 [in] DWORD cbBufSize,\r
-                                [out] DWORD *pcbBytesNeeded);\r
+                                [out] LPDWORD pcbBytesNeeded);\r
 \r
+  /* Function 18 */\r
+  DWORD ScmrQueryServiceLockStatusW([in] handle_t BindingHandle,\r
+                                    [in] SC_HANDLE hSCManager,\r
+                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,\r
+                                    [in] DWORD cbBufSize,\r
+                                    [out] LPDWORD pcbBytesNeeded);\r
+\r
+  /* Function 19 */\r
+//  DWORD ScmrStartServiceW([in] handle_t BindingHandle,\r
+//                          [in] SC_HANDLE hService,\r
+//                          [in] DWORD dwNumServiceArgs,\r
+//                          [in, string, size_is(dwNumServiceArgs, ), unique] LPWSTR *lpServiceArgVectors);\r
 \r
   /* Function 20 */\r
   DWORD ScmrGetServiceDisplayNameW([in] handle_t BindingHandle,\r
@@ -188,6 +202,68 @@ cpp_quote("#endif")
                                [out, size_is(*lpcchBuffer), unique] LPWSTR lpServiceName,\r
                                [in, out, ref] LPDWORD lpcchBuffer);\r
 \r
+  /* Function 22 */\r
+  DWORD ScmrSetServiceBitsA([in] handle_t BindingHandle,\r
+                            [in] SERVICE_STATUS_HANDLE hServiceStatus,\r
+                            [in] DWORD dwServiceBits,\r
+                            [in] BOOL bSetBitsOn,\r
+                            [in] BOOL bUpdateImmediately,\r
+                            [in, string, unique] LPSTR lpString);\r
+\r
+  /* Function 23 */\r
+  DWORD ScmrChangeServiceConfigA([in] handle_t BindingHandle,\r
+                                 [in] SC_HANDLE hSCManager,\r
+                                 [in] DWORD dwServiceType,\r
+                                 [in] DWORD dwStartType,\r
+                                 [in] DWORD dwErrorControl,\r
+                                 [in, string, unique] LPCSTR lpBinaryPathName,\r
+                                 [in, string, unique] LPCSTR lpLoadOrderGroup,\r
+                                 [in, out, unique] LPDWORD lpdwTagId,\r
+                                 [in, size_is(dwDependenciesLength), unique] LPCSTR lpDependencies,\r
+                                 [in] DWORD dwDependenciesLength,\r
+                                 [in, string, unique] LPCSTR lpServiceStartName,\r
+                                 [in, size_is(dwPasswordLength), unique] LPCSTR lpPassword,\r
+                                 [in] DWORD dwPasswordLength,\r
+                                 [in, string, unique] LPCSTR lpDisplayName);\r
+\r
+  /* Function 24 */\r
+  DWORD ScmrCreateServiceA([in] handle_t BindingHandle,\r
+                           [in] SC_HANDLE hSCManager,\r
+                           [in, string, ref] LPCSTR lpServiceName,\r
+                           [in, string, unique] LPCSTR lpDisplayName,\r
+                           [in] DWORD dwDesiredAccess,\r
+                           [in] DWORD dwServiceType,\r
+                           [in] DWORD dwStartType,\r
+                           [in] DWORD dwErrorControl,\r
+                           [in, string, ref] LPCSTR lpBinaryPathName,\r
+                           [in, string, unique] LPCSTR lpLoadOrderGroup,\r
+                           [in, out, unique] LPDWORD lpdwTagId,\r
+                           [in, size_is(dwDependenciesLength), unique] LPCSTR lpDependencies,\r
+                           [in] DWORD dwDependenciesLength,\r
+                           [in, string, unique] LPCSTR lpServiceStartName,\r
+                           [in, size_is(dwPasswordLength), unique] LPCSTR lpPassword,\r
+                           [in] DWORD dwPasswordLength,\r
+                           [out] SC_HANDLE *hService);\r
+\r
+  /* Function 25 */\r
+  DWORD ScmrEnumDependentServicesA([in] handle_t BindingHandle,\r
+                                   [in] SC_HANDLE hService,\r
+                                   [in] DWORD dwServiceState,\r
+                                   [out, size_is(cbBufSize)] LPBYTE lpServices,\r
+                                   [in] DWORD cbBufSize,\r
+                                   [out] LPDWORD pcbBytesNeeded,\r
+                                   [out] LPDWORD lpServicesReturned);\r
+\r
+  /* Function 26 */\r
+  DWORD ScmrEnumServicesStatusA([in] handle_t BindingHandle,\r
+                                [in] SC_HANDLE hSCManager,\r
+                                [in] DWORD dwServiceType,\r
+                                [in] DWORD dwServiceState,\r
+                                [out, size_is(dwBufSize)] LPBYTE lpServices,\r
+                                [in] DWORD dwBufSize,\r
+                                [out] LPDWORD pcbBytesNeeded,\r
+                                [out] LPDWORD lpServicesReturned,\r
+                                [in, out, unique] LPDWORD lpResumeHandle);\r
 \r
   /* Function 27 */\r
   DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle,\r
@@ -202,4 +278,73 @@ cpp_quote("#endif")
                              [in, string] LPCSTR lpServiceName,\r
                              [in] DWORD dwDesiredAccess,\r
                              [out] SC_HANDLE *hScm);\r
+\r
+  /* Function 29 */\r
+  DWORD ScmrQueryServiceConfigA([in] handle_t BindingHandle,\r
+                                [in] SC_HANDLE hService,\r
+                                [out, unique, size_is(cbBufSize)] LPBYTE lpServiceConfig,\r
+                                [in] DWORD cbBufSize,\r
+                                [out] LPDWORD pcbBytesNeeded);\r
+\r
+  /* Function 30 */\r
+//  DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle,\r
+//                                    [in] SC_HANDLE hSCManager,\r
+//                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,\r
+//                                    [in] DWORD cbBufSize,\r
+//                                    [out] LPDWORD pcbBytesNeeded);\r
+\r
+  /* Function 31 */\r
+//  DWORD ScmrStartServiceA([in] handle_t BindingHandle,\r
+//                          [in] SC_HANDLE hService,\r
+//                          [in] DWORD dwNumServiceArgs,\r
+//                          [in, string, size_is(dwNumServiceArgs, ), unique] LPSTR *lpServiceArgVectors);\r
+\r
+  /* Function 32 */\r
+  DWORD ScmrGetServiceDisplayNameA([in] handle_t BindingHandle,\r
+                                   [in] SC_HANDLE hSCManager,\r
+                                   [in, string, ref] LPCSTR lpServiceName,\r
+                                   [out, size_is(*lpcchBuffer), unique] LPSTR lpDisplayName,\r
+                                   [in, out, ref] LPDWORD lpcchBuffer);\r
+\r
+  /* Function 33 */\r
+  DWORD ScmrGetServiceKeyNameA([in] handle_t BindingHandle,\r
+                               [in] SC_HANDLE hSCManager,\r
+                               [in, string, ref] LPCSTR lpDisplayName,\r
+                               [out, size_is(*lpcchBuffer), unique] LPSTR lpServiceName,\r
+                               [in, out, ref] LPDWORD lpcchBuffer);\r
+\r
+  /* Function 35 */\r
+  /* ScmrGetCurrentGroupStateW */\r
+\r
+  /* Function 35 */\r
+  /* ScmrEnumServiceGroupW */\r
+\r
+  /* Function 36 */\r
+  /* ScmrChangeServiceConfig2A */\r
+\r
+  /* Function 37 */\r
+  /* ScmrChangeServiceConfig2W */\r
+\r
+  /* Function 38 */\r
+  /* ScmrQueryServiceConfig2A */\r
+\r
+  /* Function 39 */\r
+  /* ScmrQueryServiceConfig2W */\r
+\r
+  /* Function 40 */\r
+  DWORD ScmrQueryServiceStatusEx([in] handle_t BindingHandle,\r
+                                 [in] SC_HANDLE hService,\r
+                                 [in] SC_STATUS_TYPE InfoLevel,\r
+                                 [out, size_is(cbBufSize)] LPBYTE lpBuffer,\r
+                                 [in] DWORD cbBufSize,\r
+                                 [out] LPDWORD pcbBytesNeeded);\r
+\r
+  /* Function 41 */\r
+  /* ScmrEnumServicesStatusExA */\r
+\r
+  /* Function 42 */\r
+  /* ScmrEnumServicesStatusExW */\r
+\r
+  /* Function 43 */\r
+  /* ScmrSendTSMessage */\r
 }\r
index ed1bb9a..20befe2 100644 (file)
@@ -80,26 +80,68 @@ HandleUnbind(VOID)
 /**********************************************************************
  *  ChangeServiceConfigA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-ChangeServiceConfigA(
-    SC_HANDLE   hService,
-    DWORD       dwServiceType,
-    DWORD       dwStartType,
-    DWORD       dwErrorControl,
-    LPCSTR      lpBinaryPathName,
-    LPCSTR      lpLoadOrderGroup,
-    LPDWORD     lpdwTagId,
-    LPCSTR      lpDependencies,
-    LPCSTR      lpServiceStartName,
-    LPCSTR      lpPassword,
-    LPCSTR      lpDisplayName)
+BOOL STDCALL
+ChangeServiceConfigA(SC_HANDLE hService,
+                     DWORD dwServiceType,
+                     DWORD dwStartType,
+                     DWORD dwErrorControl,
+                     LPCSTR lpBinaryPathName,
+                     LPCSTR lpLoadOrderGroup,
+                     LPDWORD lpdwTagId,
+                     LPCSTR lpDependencies,
+                     LPCSTR lpServiceStartName,
+                     LPCSTR lpPassword,
+                     LPCSTR lpDisplayName)
 {
-    DPRINT1("ChangeServiceConfigA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+    DWORD dwDependenciesLength = 0;
+    DWORD dwLength;
+    LPSTR lpStr;
+
+    DPRINT("ChangeServiceConfigA() called\n");
+
+    /* Calculate the Dependencies length*/
+    if (lpDependencies != NULL)
+    {
+        lpStr = (LPSTR)lpDependencies;
+        while (*lpStr)
+        {
+            dwLength = strlen(lpStr) + 1;
+            dwDependenciesLength += dwLength;
+            lpStr = lpStr + dwLength;
+        }
+        dwDependenciesLength++;
+    }
+
+    /* FIXME: Encrypt the password */
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrChangeServiceConfigA(BindingHandle,
+                                       (unsigned int)hService,
+                                       dwServiceType,
+                                       dwStartType,
+                                       dwErrorControl,
+                                       (LPSTR)lpBinaryPathName,
+                                       (LPSTR)lpLoadOrderGroup,
+                                       lpdwTagId,
+                                       (LPSTR)lpDependencies,
+                                       dwDependenciesLength,
+                                       (LPSTR)lpServiceStartName,
+                                       NULL,              /* FIXME: lpPassword */
+                                       0,                 /* FIXME: dwPasswordLength */
+                                       (LPSTR)lpDisplayName);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrChangeServiceConfigA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
@@ -540,15 +582,15 @@ EnumDependentServicesW(SC_HANDLE hService,
 BOOL
 STDCALL
 EnumServiceGroupW(
-    DWORD   Unknown0,
-    DWORD   Unknown1,
-    DWORD   Unknown2,
-    DWORD   Unknown3,
-    DWORD   Unknown4,
-    DWORD   Unknown5,
-    DWORD   Unknown6,
-    DWORD   Unknown7,
-    DWORD   Unknown8)
+    SC_HANDLE               hSCManager,
+    DWORD                   dwServiceType,
+    DWORD                   dwServiceState,
+    LPENUM_SERVICE_STATUSA  lpServices,
+    DWORD                   cbBufSize,
+    LPDWORD                 pcbBytesNeeded,
+    LPDWORD                 lpServicesReturned,
+    LPDWORD                 lpResumeHandle,
+    LPCWSTR                 lpGroup)
 {
     DPRINT1("EnumServiceGroupW is unimplemented\n");
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
@@ -582,10 +624,9 @@ EnumServicesStatusA(
 /**********************************************************************
  *  EnumServicesStatusW
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
+BOOL STDCALL
 EnumServicesStatusW(SC_HANDLE hSCManager,
                     DWORD dwServiceType,
                     DWORD dwServiceState,
@@ -595,10 +636,11 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
                     LPDWORD lpServicesReturned,
                     LPDWORD lpResumeHandle)
 {
-#if 0
+    LPENUM_SERVICE_STATUSW lpStatusPtr;
     DWORD dwError = ERROR_SUCCESS;
+    DWORD dwCount;
 
-    DPRINT1("EnumServicesStatusW() called\n");
+    DPRINT("EnumServicesStatusW() called\n");
 
     HandleBind();
 
@@ -611,23 +653,31 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
                                       pcbBytesNeeded,
                                       lpServicesReturned,
                                       lpResumeHandle);
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
+    for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
+    {
+        if (lpStatusPtr->lpServiceName)
+            lpStatusPtr->lpServiceName =
+                (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+
+        if (lpStatusPtr->lpDisplayName)
+            lpStatusPtr->lpDisplayName =
+                (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+
+        lpStatusPtr++;
+    }
+
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("ScmrEnumServicesStatusW() failed (Error %lu)\n", dwError);
+        DPRINT("ScmrEnumServicesStatusW() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return FALSE;
     }
 
-
-
-    DPRINT1("ScmrEnumServicesStatusW() done\n");
+    DPRINT("ScmrEnumServicesStatusW() done\n");
 
     return TRUE;
-#endif
-
-    DPRINT1("EnumServicesStatusW is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
 }
 
 
@@ -682,19 +732,35 @@ EnumServicesStatusExW(SC_HANDLE  hSCManager,
 /**********************************************************************
  *  GetServiceDisplayNameA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-GetServiceDisplayNameA(
-    SC_HANDLE   hSCManager,
-    LPCSTR      lpServiceName,
-    LPSTR       lpDisplayName,
-    LPDWORD     lpcchBuffer)
+BOOL STDCALL
+GetServiceDisplayNameA(SC_HANDLE hSCManager,
+                       LPCSTR lpServiceName,
+                       LPSTR lpDisplayName,
+                       LPDWORD lpcchBuffer)
 {
-    DPRINT1("GetServiceDisplayNameA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("GetServiceDisplayNameA() called\n");
+
+    HandleBind();
+
+    dwError = ScmrGetServiceDisplayNameA(BindingHandle,
+                                         (unsigned int)hSCManager,
+                                         (LPSTR)lpServiceName,
+                                         lpDisplayName,
+                                         lpcchBuffer);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    (*lpcchBuffer)--;
+
+    return TRUE;
 }
 
 
@@ -736,19 +802,35 @@ GetServiceDisplayNameW(SC_HANDLE hSCManager,
 /**********************************************************************
  *  GetServiceKeyNameA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-GetServiceKeyNameA(
-    SC_HANDLE   hSCManager,
-    LPCSTR      lpDisplayName,
-    LPSTR       lpServiceName,
-    LPDWORD     lpcchBuffer)
+BOOL STDCALL
+GetServiceKeyNameA(SC_HANDLE hSCManager,
+                   LPCSTR lpDisplayName,
+                   LPSTR lpServiceName,
+                   LPDWORD lpcchBuffer)
 {
-    DPRINT1("GetServiceKeyNameA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("GetServiceKeyNameA() called\n");
+
+    HandleBind();
+
+    dwError = ScmrGetServiceKeyNameA(BindingHandle,
+                                     (unsigned int)hSCManager,
+                                     (LPSTR)lpDisplayName,
+                                     lpServiceName,
+                                     lpcchBuffer);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrGetServiceKeyNameA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    (*lpcchBuffer)--;
+
+    return TRUE;
 }
 
 
@@ -1014,19 +1096,63 @@ OpenServiceW(SC_HANDLE hSCManager,
 /**********************************************************************
  *  QueryServiceConfigA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-QueryServiceConfigA(
-    SC_HANDLE       hService,
-    LPQUERY_SERVICE_CONFIGA lpServiceConfig,
-    DWORD           cbBufSize,
-    LPDWORD         pcbBytesNeeded)
+BOOL STDCALL
+QueryServiceConfigA(SC_HANDLE hService,
+                    LPQUERY_SERVICE_CONFIGA lpServiceConfig,
+                    DWORD cbBufSize,
+                    LPDWORD pcbBytesNeeded)
 {
-    DPRINT1("QueryServiceConfigA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("QueryServiceConfigA(%p, %p, %lu, %p)\n",
+           hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrQueryServiceConfigA(BindingHandle,
+                                      (unsigned int)hService,
+                                      (unsigned char *)lpServiceConfig,
+                                      cbBufSize,
+                                      pcbBytesNeeded);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT("ScmrQueryServiceConfigA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    /* Adjust the pointers */
+    if (lpServiceConfig->lpBinaryPathName)
+        lpServiceConfig->lpBinaryPathName =
+            (LPSTR)((ULONG_PTR)lpServiceConfig +
+                    (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
+
+    if (lpServiceConfig->lpLoadOrderGroup)
+        lpServiceConfig->lpLoadOrderGroup =
+            (LPSTR)((ULONG_PTR)lpServiceConfig +
+                    (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
+
+    if (lpServiceConfig->lpDependencies)
+        lpServiceConfig->lpDependencies =
+            (LPSTR)((ULONG_PTR)lpServiceConfig +
+                    (ULONG_PTR)lpServiceConfig->lpDependencies);
+
+    if (lpServiceConfig->lpServiceStartName)
+        lpServiceConfig->lpServiceStartName =
+            (LPSTR)((ULONG_PTR)lpServiceConfig +
+                    (ULONG_PTR)lpServiceConfig->lpServiceStartName);
+
+    if (lpServiceConfig->lpDisplayName)
+        lpServiceConfig->lpDisplayName =
+           (LPSTR)((ULONG_PTR)lpServiceConfig +
+                   (ULONG_PTR)lpServiceConfig->lpDisplayName);
+
+    DPRINT("QueryServiceConfigA() done\n");
+
+    return TRUE;
 }
 
 
@@ -1240,19 +1366,36 @@ QueryServiceStatus(SC_HANDLE hService,
 /**********************************************************************
  *  QueryServiceStatusEx
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-QueryServiceStatusEx(SC_HANDLE  hService,
-  SC_STATUS_TYPE  InfoLevel,
-  LPBYTE  lpBuffer,
-  DWORD  cbBufSize,
-  LPDWORD  pcbBytesNeeded)
+BOOL STDCALL
+QueryServiceStatusEx(SC_HANDLE hService,
+                     SC_STATUS_TYPE InfoLevel,
+                     LPBYTE lpBuffer,
+                     DWORD cbBufSize,
+                     LPDWORD pcbBytesNeeded)
 {
-    DPRINT1("QueryServiceStatusEx is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("QueryServiceStatusEx() called\n");
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrQueryServiceStatusEx(BindingHandle,
+                                       (unsigned int)hService,
+                                       InfoLevel,
+                                       lpBuffer,
+                                       cbBufSize,
+                                       pcbBytesNeeded);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
@@ -1350,6 +1493,26 @@ StartServiceW(
     DWORD       dwNumServiceArgs,
     LPCWSTR     *lpServiceArgVectors)
 {
+#if 0
+    DWORD dwError;
+
+    DPRINT("StartServiceW()\n", ScLock);
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrStartServiceW(BindingHandle,
+                                dwNumServiceArgs,
+                                lpServiceArgVectors);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrStartServiceW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
+#endif
     DPRINT1("StartServiceW is unimplemented, but returns success...\n");
     //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     //return FALSE;
index 8198709..78d66c0 100644 (file)
@@ -444,6 +444,8 @@ ScmrLockServiceDatabase(handle_t BindingHandle,
                                   SC_MANAGER_LOCK))
         return ERROR_ACCESS_DENIED;
 
+//    return ScmLockDatabase(0, hMgr->0xC, hLock);
+
     /* FIXME: Lock the database */
     *hLock = 0x12345678; /* Dummy! */
 
@@ -460,6 +462,7 @@ ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
                                unsigned long dwSecuityDescriptorSize,
                                unsigned long *pcbBytesNeeded)
 {
+#if 0
     PSERVICE_HANDLE hSvc;
     PSERVICE lpService;
     ULONG DesiredAccess = 0;
@@ -467,7 +470,7 @@ ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
     DWORD dwBytesNeeded;
     DWORD dwError;
 
-    DPRINT("ScmrQueryServiceSecurity() called\n");
+    DPRINT("ScmrQueryServiceObjectSecurity() called\n");
 
     hSvc = (PSERVICE_HANDLE)hService;
     if (hSvc->Handle.Tag != SERVICE_TAG)
@@ -528,6 +531,9 @@ ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
     }
 
     return dwError;
+#endif
+    DPRINT1("ScmrQueryServiceObjectSecurity() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
@@ -539,7 +545,114 @@ ScmrSetServiceObjectSecurity(handle_t BindingHandle,
                              unsigned char *lpSecurityDescriptor,
                              unsigned long dwSecuityDescriptorSize)
 {
-    DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
+#if 0
+    PSERVICE_HANDLE hSvc;
+    PSERVICE lpService;
+    ULONG DesiredAccess = 0;
+    HANDLE hToken = NULL;
+    HKEY hServiceKey;
+    NTSTATUS Status;
+    DWORD dwError;
+
+    DPRINT1("ScmrSetServiceObjectSecurity() called\n");
+
+    hSvc = (PSERVICE_HANDLE)hService;
+    if (hSvc->Handle.Tag != SERVICE_TAG)
+    {
+        DPRINT1("Invalid handle tag!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    if (dwSecurityInformation == 0 ||
+        dwSecurityInformation & ~0xF)
+        return 0x57;
+
+    if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
+        return 0x57;
+
+    if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
+        DesiredAccess |= ACCESS_SYSTEM_SECURITY;
+
+    if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
+        DesiredAccess |= 0x40000;
+
+    if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
+        DesiredAccess |= 0x80000;
+
+    if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
+        (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
+        return 0x57;
+
+    if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
+        (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
+        return 0x57;
+
+    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+                                  DesiredAccess))
+    {
+        DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+        return ERROR_ACCESS_DENIED;
+    }
+
+    lpService = hSvc->ServiceEntry;
+    if (lpService == NULL)
+    {
+        DPRINT1("lpService == NULL!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    if (lpService->bDeleted)
+        return 0x430;
+
+//    RpcImpersonateClient(NULL);
+
+    Status = NtOpenThreadToken(NtCurrentThread(),
+                               8,
+                               1,
+                               &hToken);
+    if (!NT_SUCCESS(Status))
+        return RtlNtStatusToDosError(Status);
+
+//    RpcRevertToSelf();
+
+    /* FIXME: Lock service database */
+
+    Status = RtlSetSecurityObject(dwSecurityInformation,
+                                  (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
+                                  &lpService->lpSecurityDescriptor,
+                                  &ScmServiceMapping,
+                                  hToken);
+    if (!NT_SUCCESS(Status))
+    {
+        dwError = RtlNtStatusToDosError(Status);
+        goto Done;
+    }
+
+    dwError = ScmOpenServiceKey(lpService->lpServiceName,
+                                0x20006,
+                                &hServiceKey);
+    if (dwError != ERROR_SUCCESS)
+        goto Done;
+
+//    dwError = ScmWriteSecurityDescriptor(hServiceKey,
+//                                         lpService->lpSecurityDescriptor);
+
+    RegFlushKey(hServiceKey);
+    RegCloseKey(hServiceKey);
+
+Done:;
+
+    if (hToken != NULL)
+        NtClose(hToken);
+
+    /* FIXME: Unlock service database */
+
+    DPRINT1("ScmrSetServiceObjectSecurity() done (Error %lu)\n", dwError);
+
+    return dwError;
+#endif
+
+    DPRINT1("ScmrSetServiceObjectSecurity() is unimplemented\n");
     return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
@@ -617,22 +730,22 @@ ScmrNotifyBootConfigStatus(handle_t BindingHandle,
 {
     DPRINT1("ScmrNotifyBootConfigStatus() called\n");
     /* FIXME */
-    return ERROR_SUCCESS;
+    return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
 /* Function 10 */
 unsigned long
-ScmrI_ScSetServiceBitsW(handle_t BindingHandle,
-                        unsigned long hServiceStatus,
-                        unsigned long dwServiceBits,
-                        unsigned long bSetBitsOn,
-                        unsigned long bUpdateImmediately,
-                        wchar_t *lpString)
+ScmrSetServiceBitsW(handle_t BindingHandle,
+                    unsigned long hServiceStatus,
+                    unsigned long dwServiceBits,
+                    unsigned long bSetBitsOn,
+                    unsigned long bUpdateImmediately,
+                    wchar_t *lpString)
 {
-    DPRINT1("ScmrI_ScSetServiceBitsW() called\n");
+    DPRINT1("ScmrSetServiceBitsW() called\n");
     /* FIXME */
-    return ERROR_SUCCESS;
+    return ERROR_CALL_NOT_IMPLEMENTED;
 }
 
 
@@ -1161,8 +1274,17 @@ ScmrEnumServicesStatusW(handle_t BindingHandle,
     PMANAGER_HANDLE hManager;
     PSERVICE lpService;
     DWORD dwError = ERROR_SUCCESS;
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
+    DWORD dwState;
+    DWORD dwRequiredSize;
+    DWORD dwServiceCount;
+    DWORD dwSize;
+    DWORD dwLastResumeCount;
+    LPENUM_SERVICE_STATUSW lpStatusPtr;
+    LPWSTR lpStringPtr;
 
-    DPRINT1("ScmrEnumServicesStatusW() called\n");
+    DPRINT("ScmrEnumServicesStatusW() called\n");
 
     if (ScmShutdown)
         return ERROR_SHUTDOWN_IN_PROGRESS;
@@ -1186,27 +1308,151 @@ ScmrEnumServicesStatusW(handle_t BindingHandle,
     *pcbBytesNeeded = 0;
     *lpServicesReturned = 0;
 
+    dwLastResumeCount = *lpResumeHandle;
+
     /* Lock the service list shared */
 
-    lpService = ScmGetServiceEntryByResumeCount(*lpResumeHandle);
+    lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
     if (lpService == NULL)
     {
-        dwError = ERROR_MORE_DATA; /* Hack! */
-        goto done;
+        dwError = ERROR_SUCCESS;
+        goto Done;
     }
 
-    DPRINT1("Service name: %S\n", lpService->lpServiceName);
+    dwRequiredSize = 0;
+    dwServiceCount = 0;
 
-//    DPRINT1("Display name: %S\n", lpService->lpDisplayName);
+    for (ServiceEntry = &lpService->ServiceListEntry;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
 
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
 
-    *lpResumeHandle = lpService->dwResumeCount;
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
 
-done:;
-    /* Unlock the service list */
+        if ((dwState & dwServiceState) == 0)
+            continue;
+
+        dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+        if (dwRequiredSize + dwSize <= dwBufSize)
+        {
+            DPRINT("Service name: %S  fit\n", CurrentService->lpServiceName);
+            dwRequiredSize += dwSize;
+            dwServiceCount++;
+            dwLastResumeCount = CurrentService->dwResumeCount;
+        }
+        else
+        {
+            DPRINT("Service name: %S  no fit\n", CurrentService->lpServiceName);
+            break;
+        }
+
+    }
+
+    DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
+    DPRINT("dwServiceCount: %lu\n", dwServiceCount);
+
+    for (;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
+
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
+
+        if ((dwState & dwServiceState) == 0)
+            continue;
+
+        dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
+                           ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                           ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+        dwError = ERROR_MORE_DATA;
+    }
+
+    DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+    *lpResumeHandle = dwLastResumeCount;
+    *lpServicesReturned = dwServiceCount;
+    *pcbBytesNeeded = dwRequiredSize;
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUS)lpServices;
+    lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
+                           dwServiceCount * sizeof(ENUM_SERVICE_STATUS));
+
+    dwRequiredSize = 0;
+    for (ServiceEntry = &lpService->ServiceListEntry;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
+
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
+
+        if ((dwState & dwServiceState) == 0)
+            continue;
 
+        dwSize = sizeof(ENUM_SERVICE_STATUSW) +
+                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 
-    DPRINT1("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
+        if (dwRequiredSize + dwSize <= dwBufSize)
+        {
+            /* Copy the service name */
+            wcscpy(lpStringPtr,
+                   CurrentService->lpServiceName);
+            lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
+            lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+            /* Copy the display name */
+            wcscpy(lpStringPtr,
+                   CurrentService->lpDisplayName);
+            lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
+            lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+            /* Copy the status information */
+            memcpy(&lpStatusPtr->ServiceStatus,
+                   &CurrentService->Status,
+                   sizeof(SERVICE_STATUS));
+
+            lpStatusPtr++;
+            dwRequiredSize += dwSize;
+        }
+        else
+        {
+            break;
+        }
+
+    }
+
+Done:;
+    /* Unlock the service list */
+
+    DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
 
     return dwError;
 }
@@ -1331,9 +1577,9 @@ ScmrOpenServiceW(handle_t BindingHandle,
 unsigned long
 ScmrQueryServiceConfigW(handle_t BindingHandle,
                         unsigned int hService,
-                        unsigned char *lpServiceConfig, /* [out, unique, size_is(cbBufSize)] */
-                        unsigned long cbBufSize,        /* [in] */
-                        unsigned long *pcbBytesNeeded)  /* [out] */
+                        unsigned char *lpServiceConfig,
+                        unsigned long cbBufSize,
+                        unsigned long *pcbBytesNeeded)
 {
     DWORD dwError = ERROR_SUCCESS;
     PSERVICE_HANDLE hSvc;
@@ -1470,6 +1716,23 @@ Done:;
 }
 
 
+/* Function 18 */
+unsigned long
+ScmrQueryServiceLockStatusW(handle_t BindingHandle,
+                            unsigned int hSCManager,
+                            unsigned char *lpLockStatus,   /* [out, unique, size_is(cbBufSize)] */
+                            unsigned long cbBufSize,       /* [in] */
+                            unsigned long *pcbBytesNeeded) /* [out] */
+{
+    DPRINT1("ScmrQueryServiceLockStatusW() called\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 19 */
+/* ScmrStartServiceW */
+
+
 /* Function 20 */
 unsigned long
 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
@@ -1570,6 +1833,99 @@ ScmrGetServiceKeyNameW(handle_t BindingHandle,
 }
 
 
+/* Function 22 */
+unsigned long
+ScmrSetServiceBitsA(handle_t BindingHandle,
+                    unsigned long hServiceStatus,
+                    unsigned long dwServiceBits,
+                    unsigned long bSetBitsOn,
+                    unsigned long bUpdateImmediately,
+                    char *lpString)
+{
+    DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 23 */
+unsigned long
+ScmrChangeServiceConfigA(handle_t BiningHandle,
+                         unsigned int hService,
+                         unsigned long dwServiceType,
+                         unsigned long dwStartType,
+                         unsigned long dwErrorControl,
+                         char *lpBinaryPathName,
+                         char *lpLoadOrderGroup,
+                         unsigned long *lpdwTagId,
+                         char *lpDependencies,
+                         unsigned long dwDependenciesLength,
+                         char *lpServiceStartName,
+                         char *lpPassword,
+                         unsigned long dwPasswordLength,
+                         char *lpDisplayName)
+{
+    DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 24 */
+unsigned long
+ScmrCreateServiceA(handle_t BindingHandle,
+                   unsigned int hSCManager,
+                   char *lpServiceName,
+                   char *lpDisplayName,
+                   unsigned long dwDesiredAccess,
+                   unsigned long dwServiceType,
+                   unsigned long dwStartType,
+                   unsigned long dwErrorControl,
+                   char *lpBinaryPathName,
+                   char *lpLoadOrderGroup,
+                   unsigned long *lpdwTagId, /* in, out */
+                   char *lpDependencies,
+                   unsigned long dwDependenciesLength,
+                   char *lpServiceStartName,
+                   char *lpPassword,
+                   unsigned long dwPasswordLength,
+                   unsigned int *hService) /* out */
+{
+    DPRINT1("ScmrCreateServiceA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 25 */
+unsigned long
+ScmrEnumDependentServicesA(handle_t BindingHandle,
+                           unsigned int hService,
+                           unsigned long dwServiceState,
+                           unsigned char *lpServices,
+                           unsigned long cbBufSize,
+                           unsigned long *pcbBytesNeeded,
+                           unsigned long *lpServicesReturned)
+{
+    DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 26 */
+unsigned long
+ScmrEnumServicesStatusA(handle_t BindingHandle,
+                        unsigned int hSCManager,
+                        unsigned long dwServiceType,
+                        unsigned long dwServiceState,
+                        unsigned char *lpServices,
+                        unsigned long dwBufSize,
+                        unsigned long *pcbBytesNeeded,
+                        unsigned long *lpServicesReturned,
+                        unsigned long *lpResumeHandle)
+{
+    DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /* Function 27 */
 unsigned long
 ScmrOpenSCManagerA(handle_t BindingHandle,
@@ -1636,6 +1992,112 @@ ScmrOpenServiceA(handle_t BindingHandle,
 }
 
 
+/* Function 29 */
+unsigned long
+ScmrQueryServiceConfigA(handle_t BindingHandle,
+                        unsigned int hService,
+                        unsigned char *lpServiceConfig,
+                        unsigned long cbBufSize,
+                        unsigned long *pcbBytesNeeded)
+{
+    DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 30 */
+unsigned long
+ScmrQueryServiceLockStatusA(handle_t BindingHandle,
+                            unsigned int hSCManager,
+                            unsigned char *lpLockStatus,   /* [out, unique, size_is(cbBufSize)] */
+                            unsigned long cbBufSize,       /* [in] */
+                            unsigned long *pcbBytesNeeded) /* [out] */
+{
+    DPRINT1("ScmrQueryServiceLockStatusA() called\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 31 */
+/* ScmrStartServiceA */
+
+
+/* Function 32 */
+unsigned long
+ScmrGetServiceDisplayNameA(handle_t BindingHandle,
+                           unsigned int hSCManager,
+                           char *lpServiceName,
+                           char *lpDisplayName, /* [out, unique] */
+                           unsigned long *lpcchBuffer)
+{
+    DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 33 */
+unsigned long
+ScmrGetServiceKeyNameA(handle_t BindingHandle,
+                       unsigned int hSCManager,
+                       char *lpDisplayName,
+                       char *lpServiceName, /* [out, unique] */
+                       unsigned long *lpcchBuffer)
+{
+    DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 34 */
+/* ScmrGetCurrentGroupStateW */
+
+
+/* Function 35 */
+/* ScmrEnumServiceGroupW */
+
+
+/* Function 36 */
+/* ScmrChangeServiceConfig2A */
+
+
+/* Function 37 */
+/* ScmrChangeServiceConfig2W */
+
+
+/* Function 38 */
+/* ScmrQueryServiceConfig2A */
+
+
+/* Function 39 */
+/* ScmrQueryServiceConfig2W */
+
+
+/* Function 40 */
+unsigned long
+ScmrQueryServiceStatusEx(handle_t BindingHandle,
+                         unsigned int hService,
+                         unsigned long InfoLevel,
+                         unsigned char *lpBuffer, /* out */
+                         unsigned long cbBufSize,
+                         unsigned long *pcbBytesNeeded) /* out */
+{
+    DPRINT1("ScmrQueryServiceStatusEx() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 41 */
+/* ScmrEnumServicesStatusExA */
+
+
+/* Function 42 */
+/* ScmrEnumServicesStatusExW */
+
+
+/* Function 43 */
+/* ScmrSendTSMessage */
+
+
 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
 {
     return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
index 37d57e5..b3e4c14 100644 (file)
@@ -39,6 +39,7 @@ typedef struct _SERVICE
 
 /* VARIABLES ***************************************************************/
 
+extern LIST_ENTRY ServiceListHead;
 extern BOOL ScmShutdown;