advapi32.dll: Implement QueryServiceStatus.
services.exe: Implement OpenSCManagerA, OpenServiceA, OpenServiceW and QueryServiceStatus.
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/database.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c
Modified: trunk/reactos/subsys/system/services/services.h

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-04-22 19:57:03 UTC (rev 14749)
+++ trunk/reactos/include/idl/svcctl.idl	2005-04-23 00:01:37 UTC (rev 14750)
@@ -54,16 +54,18 @@
                                 [out] SC_LOCK *hLock);
 
   /* Function 4 */
-//  DWORD ScmrQueryServiceObjectSecurity();
+  DWORD ScmrQueryServiceObjectSecurity([in] handle_t BindingHandle); /* FIXME */
 
   /* Function 5 */
-//  DWORD ScmrSetServiceObjectSecurity();
+  DWORD ScmrSetServiceObjectSecurity([in] handle_t BindingHandle); /* FIXME */
 
   /* Function 6 */
-//  DWORD ScmrQueryServiceStatus();
+  DWORD ScmrQueryServiceStatus([in] handle_t BindingHandle,
+                               [in] SC_HANDLE hSCManager,
+                               [out] LPSERVICE_STATUS lpServiceStatus);
 
   /* Function 7 */
-//  DWORD ScmrSetServiceStatus();
+  DWORD ScmrSetServiceStatus([in] handle_t BindingHandle); /* FIXME */
 
   /* Function 8 */
   DWORD ScmrUnlockServiceDatabase([in] handle_t BindingHandle,
@@ -75,20 +77,23 @@
 
 
   /* Function 12 */
-  DWORD ScmrCreateServiceW([in] handle_t BindingHandle,
-                           [in] SC_HANDLE hSCManager,
-                           [in, string, ref] LPCWSTR lpServiceName,
-                           [in, string, ref] LPCWSTR lpDisplayName,
-                           [in] DWORD dwDesiredAccess,
-                           [in] DWORD dwServiceType,
-                           [in] DWORD dwStartType,
-                           [in] DWORD dwErrorControl,
-                           [in, string, ref] LPCWSTR lpBinaryPathName,
-                           [in, string, unique] LPCWSTR lpLoadOrderGroup,
-                           [out] LPDWORD lpdwTagId,
-                           [in, string, unique] LPCWSTR lpDependencies,
-                           [in, string, unique] LPCWSTR lpServiceStartName,
-                           [in, string, unique] LPCWSTR lpPassword);
+//  DWORD ScmrCreateServiceW([in] handle_t BindingHandle,
+//                           [in] SC_HANDLE hSCManager,
+//                           [in, string, ref] LPCWSTR lpServiceName,
+//                           [in, string, ref] LPCWSTR lpDisplayName,
+//                           [in] DWORD dwDesiredAccess,
+//                           [in] DWORD dwServiceType,
+//                           [in] DWORD dwStartType,
+//                           [in] DWORD dwErrorControl,
+//                           [in, string, ref] LPCWSTR lpBinaryPathName,
+//                           [in, string, unique] LPCWSTR lpLoadOrderGroup,
+//                           [out] LPDWORD lpdwTagId,
+//                           [in, size_is(dwDepwndenciesLength), unique] LPCWSTR lpDependencies,
+//                           [in] DWORD dwDependenciesLength,
+//                           [in, string, unique] LPCWSTR lpServiceStartName,
+//                           [in, size_is(dwPasswordLength), unique] LPCWSTR lpPassword,
+//                           [in] DWORD dwPasswordLength,
+//                           [out] SC_HANDLE *hService);
 
 
   /* Function 15 */

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-04-22 19:57:03 UTC (rev 14749)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-04-23 00:01:37 UTC (rev 14750)
@@ -835,17 +835,31 @@
 /**********************************************************************
  *  QueryServiceStatus
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-QueryServiceStatus(
-    SC_HANDLE       hService,
-    LPSERVICE_STATUS    lpServiceStatus)
+BOOL STDCALL
+QueryServiceStatus(SC_HANDLE hService,
+                   LPSERVICE_STATUS lpServiceStatus)
 {
-    DPRINT1("QueryServiceStatus is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  DWORD dwError;
+
+  DPRINT("QueryServiceStatus(%p, %p)\n",
+         hService, lpServiceStatus);
+
+  HandleBind();
+
+  /* Call to services.exe using RPC */
+  dwError = ScmrQueryServiceStatus(BindingHandle,
+                                   (unsigned int)hService,
+                                   lpServiceStatus);
+  if (dwError != ERROR_SUCCESS)
+  {
+    DPRINT1("ScmrQueryServiceStatus() failed (Error %lu)\n", dwError);
+    SetLastError(dwError);
     return FALSE;
+  }
+
+  return TRUE;
 }
 
 
@@ -886,8 +900,6 @@
 }
 
 
-
-
 /**********************************************************************
  *  StartServiceW
  *

Modified: trunk/reactos/subsys/system/services/database.c
--- trunk/reactos/subsys/system/services/database.c	2005-04-22 19:57:03 UTC (rev 14749)
+++ trunk/reactos/subsys/system/services/database.c	2005-04-23 00:01:37 UTC (rev 14750)
@@ -1,4 +1,4 @@
-/* $Id$
+/*
  *
  * service control manager
  * 
@@ -53,27 +53,8 @@
 } SERVICE_GROUP, *PSERVICE_GROUP;
 
 
-typedef struct _SERVICE
-{
-  LIST_ENTRY ServiceListEntry;
-  UNICODE_STRING ServiceName;
-  UNICODE_STRING RegistryPath;
-  UNICODE_STRING ServiceGroup;
 
-  ULONG Start;
-  ULONG Type;
-  ULONG ErrorControl;
-  ULONG Tag;
 
-  BOOLEAN ServiceRunning;
-  BOOLEAN ServiceVisited;
-
-  HANDLE ControlPipeHandle;
-  ULONG ProcessId;
-  ULONG ThreadId;
-} SERVICE, *PSERVICE;
-
-
 /* GLOBALS *******************************************************************/
 
 LIST_ENTRY GroupListHead;
@@ -82,6 +63,35 @@
 
 /* FUNCTIONS *****************************************************************/
 
+PSERVICE
+ScmGetServiceEntryByName(PUNICODE_STRING ServiceName)
+{
+  PLIST_ENTRY ServiceEntry;
+  PSERVICE CurrentService;
+
+  DPRINT("ScmGetServiceEntryByName() called\n");
+
+  ServiceEntry = ServiceListHead.Flink;
+  while (ServiceEntry != &ServiceListHead)
+  {
+    CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                       SERVICE,
+                                       ServiceListEntry);
+    if (RtlEqualUnicodeString(&CurrentService->ServiceName, ServiceName, TRUE))
+    {
+      DPRINT("Found service: '%wZ'\n", &CurrentService->ServiceName);
+      return CurrentService;
+    }
+
+    ServiceEntry = ServiceEntry->Flink;
+  }
+
+  DPRINT("Couldn't find a matching service\n");
+
+  return NULL;
+}
+
+
 static NTSTATUS STDCALL
 CreateGroupOrderListRoutine(PWSTR ValueName,
 			    ULONG ValueType,
@@ -277,6 +287,13 @@
   InsertTailList(&ServiceListHead,
 		 &Service->ServiceListEntry);
 
+  Service->CurrentState = SERVICE_STOPPED;
+  Service->ControlsAccepted = 0;
+  Service->Win32ExitCode = 0;
+  Service->ServiceSpecificExitCode = 0;
+  Service->CheckPoint = 0;
+  Service->WaitHint = 2000; /* 2 seconds */
+
   return STATUS_SUCCESS;
 }
 
@@ -461,7 +478,7 @@
 	  DPRINT("Found: '%wZ'  '%wZ'\n", &Service->ServiceName, &DirInfo->ObjectName);
 
 	  /* Mark service as 'running' */
-	  Service->ServiceRunning = TRUE;
+	  Service->CurrentState = SERVICE_RUNNING;
 
 	  /* Find the driver's group and mark it as 'running' */
 	  if (Service->ServiceGroup.Buffer != NULL)
@@ -767,7 +784,7 @@
 	{
 	  Group->ServicesRunning = TRUE;
 	}
-      Service->ServiceRunning = TRUE;
+      Service->CurrentState = SERVICE_RUNNING;
     }
 #if 0
   else

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-04-22 19:57:03 UTC (rev 14749)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-04-23 00:01:37 UTC (rev 14750)
@@ -44,7 +44,7 @@
   SCMGR_HANDLE Handle;
 
   DWORD DesiredAccess;
-  PVOID DatabaseEntry; /* FIXME */
+  PSERVICE ServiceEntry;
 
   /* FIXME: Insert more data here */
 
@@ -167,10 +167,10 @@
 
 
 static DWORD
-ScmCreateServiceHandle(LPVOID lpDatabaseEntry,
+ScmCreateServiceHandle(PSERVICE lpServiceEntry,
                        SC_HANDLE *Handle)
 {
-  PMANAGER_HANDLE Ptr;
+  PSERVICE_HANDLE Ptr;
 
   Ptr = GlobalAlloc(GPTR,
                     sizeof(SERVICE_HANDLE));
@@ -181,7 +181,7 @@
   Ptr->Handle.RefCount = 1;
 
   /* FIXME: initialize more data here */
-  // Ptr->DatabaseEntry = lpDatabaseEntry;
+  Ptr->ServiceEntry = lpServiceEntry;
 
   *Handle = (SC_HANDLE)Ptr;
 
@@ -278,21 +278,42 @@
                    unsigned long dwControl,
                    LPSERVICE_STATUS lpServiceStatus)
 {
+  PSERVICE_HANDLE hSvc;
+  PSERVICE lpService;
+
   DPRINT1("ScmrControlService() called\n");
 
-  /* FIXME: return proper service information */
+  hSvc = (PSERVICE_HANDLE)hService;
+  if (hSvc->Handle.Tag != SERVICE_TAG)
+  {
+    DPRINT1("Invalid handle tag!\n");
+    return ERROR_INVALID_HANDLE;
+  }
 
-  /* test data */
-// #if 0
-  lpServiceStatus->dwServiceType = 0x12345678;
-  lpServiceStatus->dwCurrentState = 0x98765432;
-  lpServiceStatus->dwControlsAccepted = 0xdeadbabe;
-  lpServiceStatus->dwWin32ExitCode = 0xbaadf00d;
-  lpServiceStatus->dwServiceSpecificExitCode = 0xdeadf00d;
-  lpServiceStatus->dwCheckPoint = 0xbaadbabe;
-  lpServiceStatus->dwWaitHint = 0x2468ACE1;
-// #endif
 
+  /* FIXME: Check access rights */
+
+
+  lpService = hSvc->ServiceEntry;
+  if (lpService == NULL)
+  {
+    DPRINT1("lpService == NULL!\n");
+    return ERROR_INVALID_HANDLE;
+  }
+
+
+  /* FIXME: Send control code to the service */
+
+
+  /* Return service status information */
+  lpServiceStatus->dwServiceType = lpService->Type;
+  lpServiceStatus->dwCurrentState = lpService->CurrentState;
+  lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
+  lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
+  lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
+  lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
+  lpServiceStatus->dwWaitHint = lpService->WaitHint;
+
   return ERROR_SUCCESS;
 }
 
@@ -303,6 +324,7 @@
                   unsigned int hService)
 {
   PSERVICE_HANDLE hSvc;
+  PSERVICE lpService;
 
   DPRINT1("ScmrDeleteService() called\n");
 
@@ -314,8 +336,15 @@
                                 STANDARD_RIGHTS_REQUIRED))
     return ERROR_ACCESS_DENIED;
 
-  /* FIXME: Delete the service */
+  lpService = hSvc->ServiceEntry;
+  if (lpService == NULL)
+  {
+    DPRINT1("lpService == NULL!\n");
+    return ERROR_INVALID_HANDLE;
+  }
 
+  /* FIXME: Mark service for delete */
+
   return ERROR_SUCCESS;
 }
 
@@ -347,13 +376,86 @@
 }
 
 
+/* Function 4 */
+unsigned long
+ScmrQueryServiceObjectSecurity(handle_t BindingHandle)
+{
+  DPRINT1("ScmrQueryServiceSecurity() is unimplemented\n");
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
+
+/* Function 5 */
+unsigned long
+ScmrSetServiceObjectSecurity(handle_t BindingHandle)
+{
+  DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
+/* Function 6 */
+unsigned long
+ScmrQueryServiceStatus(handle_t BindingHandle,
+                       unsigned int hService,
+                       LPSERVICE_STATUS lpServiceStatus)
+{
+  PSERVICE_HANDLE hSvc;
+  PSERVICE lpService;
+
+  DPRINT("ScmrQueryServiceStatus() called\n");
+
+  hSvc = (PSERVICE_HANDLE)hService;
+  if (hSvc->Handle.Tag != SERVICE_TAG)
+  {
+    DPRINT1("Invalid handle tag!\n");
+    return ERROR_INVALID_HANDLE;
+  }
+
+  if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+                                SERVICE_QUERY_STATUS))
+  {
+    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;
+  }
+
+  /* Return service status information */
+  lpServiceStatus->dwServiceType = lpService->Type;
+  lpServiceStatus->dwCurrentState = lpService->CurrentState;
+  lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
+  lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
+  lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
+  lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
+  lpServiceStatus->dwWaitHint = lpService->WaitHint;
+
+  return ERROR_SUCCESS;
+}
+
+
+/* Function 7 */
+unsigned long
+ScmrSetServiceStatus(handle_t BindingHandle)
+{
+  DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
+ /* FIXME */
+  return ERROR_CALL_NOT_IMPLEMENTED;
+}
+
+
 /* Function 8 */
 unsigned long
 ScmrUnlockServiceDatabase(handle_t BindingHandle,
                           unsigned int hLock)
 {
   DPRINT1("ScmrUnlockServiceDatabase() called\n");
+  /* FIXME */
   return ERROR_SUCCESS;
 }
 
@@ -364,12 +466,14 @@
                            unsigned long BootAcceptable)
 {
   DPRINT1("ScmrNotifyBootConfigStatus() called\n");
+  /* FIXME */
   return ERROR_SUCCESS;
 }
 
 
 
 /* Function 12 */
+#if 0
 unsigned long
 ScmrCreateServiceW(handle_t BindingHandle,
                    unsigned int hSCManager,
@@ -391,9 +495,9 @@
     *lpdwTagId = 0;
   return ERROR_SUCCESS;
 }
+#endif
 
 
-
 /* Function 15 */
 unsigned long
 ScmrOpenSCManagerW(handle_t BindingHandle,
@@ -447,6 +551,8 @@
                  unsigned long dwDesiredAccess,
                  unsigned int *hService)
 {
+  UNICODE_STRING ServiceName;
+  PSERVICE lpService;
   PMANAGER_HANDLE hManager;
   SC_HANDLE hHandle;
   DWORD dwError;
@@ -464,12 +570,21 @@
     return ERROR_INVALID_HANDLE;
   }
 
-  /* FIXME: Check desired access */
+  /* FIXME: Lock the service list */
 
-  /* FIXME: Get service database entry */
+  /* Get service database entry */
+  RtlInitUnicodeString(&ServiceName,
+                       lpServiceName);
 
+  lpService = ScmGetServiceEntryByName(&ServiceName);
+  if (lpService == NULL)
+  {
+    DPRINT1("Could not find a service!\n");
+    return ERROR_SERVICE_DOES_NOT_EXIST;
+  }
+
   /* Create a service handle */
-  dwError = ScmCreateServiceHandle(NULL,
+  dwError = ScmCreateServiceHandle(lpService,
                                    &hHandle);
   if (dwError != ERROR_SUCCESS)
   {
@@ -505,8 +620,33 @@
                    unsigned long dwDesiredAccess,
                    unsigned int *hScm)
 {
+  UNICODE_STRING MachineName;
+  UNICODE_STRING DatabaseName;
+  DWORD dwError;
+
   DPRINT("ScmrOpenSCManagerA() called\n");
-  return ERROR_SUCCESS;
+
+  if (lpMachineName)
+    RtlCreateUnicodeStringFromAsciiz(&MachineName,
+                                     lpMachineName);
+
+  if (lpDatabaseName)
+    RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
+                                     lpDatabaseName);
+
+  dwError = ScmrOpenSCManagerW(BindingHandle,
+                               lpMachineName ? MachineName.Buffer : NULL,
+                               lpDatabaseName ? DatabaseName.Buffer : NULL,
+                               dwDesiredAccess,
+                               hScm);
+
+  if (lpMachineName)
+    RtlFreeUnicodeString(&MachineName);
+
+  if (lpDatabaseName)
+    RtlFreeUnicodeString(&DatabaseName);
+
+  return dwError;
 }
 
 
@@ -518,8 +658,23 @@
                  unsigned long dwDesiredAccess,
                  unsigned int *hService)
 {
+  UNICODE_STRING ServiceName;
+  DWORD dwError;
+
   DPRINT("ScmrOpenServiceA() called\n");
-  return 0;
+
+  RtlCreateUnicodeStringFromAsciiz(&ServiceName,
+                                   lpServiceName);
+
+  dwError = ScmrOpenServiceW(BindingHandle,
+                             hSCManager,
+                             ServiceName.Buffer,
+                             dwDesiredAccess,
+                             hService);
+
+  RtlFreeUnicodeString(&ServiceName);
+
+  return dwError;
 }
 
 

Modified: trunk/reactos/subsys/system/services/services.h
--- trunk/reactos/subsys/system/services/services.h	2005-04-22 19:57:03 UTC (rev 14749)
+++ trunk/reactos/subsys/system/services/services.h	2005-04-23 00:01:37 UTC (rev 14750)
@@ -2,8 +2,33 @@
  * services.h
  */
 
+typedef struct _SERVICE
+{
+  LIST_ENTRY ServiceListEntry;
+  UNICODE_STRING ServiceName;
+  UNICODE_STRING RegistryPath;
+  UNICODE_STRING ServiceGroup;
 
+  ULONG Start;
+  ULONG Type;
+  ULONG ErrorControl;
+  ULONG Tag;
 
+  ULONG CurrentState;
+  ULONG ControlsAccepted;
+  ULONG Win32ExitCode;
+  ULONG ServiceSpecificExitCode;
+  ULONG CheckPoint;
+  ULONG WaitHint;
+
+  BOOLEAN ServiceVisited;
+
+  HANDLE ControlPipeHandle;
+  ULONG ProcessId;
+  ULONG ThreadId;
+} SERVICE, *PSERVICE;
+
+
 /* services.c */
 
 VOID PrintString(LPCSTR fmt, ...);
@@ -15,7 +40,10 @@
 VOID ScmGetBootAndSystemDriverState(VOID);
 VOID ScmAutoStartServices(VOID);
 
+PSERVICE
+ScmGetServiceEntryByName(PUNICODE_STRING ServiceName);
 
+
 /* rpcserver.c */
 
 VOID ScmStartRpcServer(VOID);