- Prepare to delete marked services upon startup.
- ControlService: Implement unloading of drivers.
Modified: trunk/reactos/subsys/system/services/database.c
Added: trunk/reactos/subsys/system/services/driver.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c
Modified: trunk/reactos/subsys/system/services/services.h
Modified: trunk/reactos/subsys/system/services/services.xml

Modified: trunk/reactos/subsys/system/services/database.c
--- trunk/reactos/subsys/system/services/database.c	2005-11-20 19:31:49 UTC (rev 19384)
+++ trunk/reactos/subsys/system/services/database.c	2005-11-20 20:18:00 UTC (rev 19385)
@@ -404,6 +404,32 @@
 }
 
 
+VOID
+ScmDeleteMarkedServices(VOID)
+{
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
+
+    ServiceEntry = ServiceListHead.Flink;
+    while (ServiceEntry != &ServiceListHead)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+
+        ServiceEntry = ServiceEntry->Flink;
+
+        if (CurrentService->bDeleted == TRUE)
+        {
+            DPRINT1("Delete service: %S\n", CurrentService->lpServiceName);
+
+            /* FIXME: Delete the registry keys */
+
+            /* FIXME: Delete the service record from the list */
+
+        }
+    }
+}
+
+
 DWORD
 ScmCreateServiceDatabase(VOID)
 {
@@ -474,7 +500,8 @@
 
     RegCloseKey(hServicesKey);
 
-    /* FIXME: Delete services that are marked for delete */
+    /* Delete services that are marked for delete */
+    ScmDeleteMarkedServices();
 
     DPRINT("ScmCreateServiceDatabase() done\n");
 
@@ -836,8 +863,6 @@
 ScmStartService(PSERVICE Service,
                 PSERVICE_GROUP Group)
 {
-    WCHAR szDriverPath[MAX_PATH];
-    UNICODE_STRING DriverPath;
     NTSTATUS Status;
 
     DPRINT("ScmStartService() called\n");
@@ -845,21 +870,12 @@
     Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
     DPRINT("Service->Type: %lu\n", Service->Status.dwServiceType);
 
-    if (Service->Status.dwServiceType == SERVICE_KERNEL_DRIVER ||
-        Service->Status.dwServiceType == SERVICE_FILE_SYSTEM_DRIVER ||
-        Service->Status.dwServiceType == SERVICE_RECOGNIZER_DRIVER)
+    if (Service->Status.dwServiceType & SERVICE_DRIVER)
     {
         /* Load driver */
-        wcscpy(szDriverPath,
-               L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
-        wcscat(szDriverPath,
-               Service->lpServiceName);
-
-        RtlInitUnicodeString(&DriverPath,
-                             szDriverPath);
-
-        DPRINT("  Path: %wZ\n", &DriverPath);
-        Status = NtLoadDriver(&DriverPath);
+        Status = ScmLoadDriver(Service);
+        if (Status == STATUS_SUCCESS)
+            Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
     }
     else
     {

Added: trunk/reactos/subsys/system/services/driver.c
--- trunk/reactos/subsys/system/services/driver.c	2005-11-20 19:31:49 UTC (rev 19384)
+++ trunk/reactos/subsys/system/services/driver.c	2005-11-20 20:18:00 UTC (rev 19385)
@@ -0,0 +1,113 @@
+/*
+ * driver.c
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "services.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+ScmLoadDriver(PSERVICE lpService)
+{
+    WCHAR szDriverPath[MAX_PATH];
+    UNICODE_STRING DriverPath;
+    NTSTATUS Status;
+
+    /* Build the driver path */
+    wcscpy(szDriverPath,
+           L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+    wcscat(szDriverPath,
+           lpService->lpServiceName);
+
+    RtlInitUnicodeString(&DriverPath,
+                         szDriverPath);
+
+    /* FIXME: Acquire privilege */
+
+    DPRINT("  Path: %wZ\n", &DriverPath);
+    Status = NtLoadDriver(&DriverPath);
+
+    /* FIXME: Release privilege */
+
+    return Status;
+}
+
+
+DWORD
+ScmUnloadDriver(PSERVICE lpService)
+{
+    WCHAR szDriverPath[MAX_PATH];
+    UNICODE_STRING DriverPath;
+    NTSTATUS Status;
+    DWORD dwError = ERROR_SUCCESS;
+
+    /* Build the driver path */
+    wcscpy(szDriverPath,
+           L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+    wcscat(szDriverPath,
+           lpService->lpServiceName);
+
+    RtlInitUnicodeString(&DriverPath,
+                         szDriverPath);
+
+    /* FIXME: Acquire privilege */
+
+    Status = NtUnloadDriver(&DriverPath);
+
+    /* FIXME: Release privilege */
+
+    if (!NT_SUCCESS(Status))
+    {
+        dwError = RtlNtStatusToDosError(Status);
+    }
+
+    return dwError;
+}
+
+
+DWORD
+ScmControlDriver(PSERVICE lpService,
+                 DWORD dwControl,
+                 LPSERVICE_STATUS lpServiceStatus)
+{
+    DWORD dwError;
+
+    DPRINT("ScmControlDriver() called\n");
+
+    switch (dwControl)
+    {
+        case SERVICE_CONTROL_STOP:
+            if (lpService->Status.dwCurrentState != SERVICE_RUNNING)
+            {
+                dwError = ERROR_INVALID_SERVICE_CONTROL;
+                goto done;
+            }
+
+            dwError = ScmUnloadDriver(lpService);
+            if (dwError == ERROR_SUCCESS)
+            {
+                lpService->Status.dwControlsAccepted = 0;
+                lpService->Status.dwCurrentState = SERVICE_STOPPED;
+            }
+            break;
+
+        case SERVICE_CONTROL_INTERROGATE:
+            dwError = ERROR_INVALID_SERVICE_CONTROL;
+            break;
+
+        default:
+            dwError = ERROR_INVALID_SERVICE_CONTROL;
+    }
+
+done:;
+    DPRINT("ScmControlDriver() done (Erorr: %lu)\n", dwError);
+
+    return dwError;
+}
+
+/* EOF */

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-11-20 19:31:49 UTC (rev 19384)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-11-20 20:18:00 UTC (rev 19385)
@@ -281,6 +281,7 @@
     PSERVICE_HANDLE hSvc;
     PSERVICE lpService;
     ACCESS_MASK DesiredAccess;
+    DWORD dwError = ERROR_SUCCESS;
 
     DPRINT("ScmrControlService() called\n");
 
@@ -335,16 +336,30 @@
         return ERROR_INVALID_HANDLE;
     }
 
+    if (lpService->Status.dwServiceType & SERVICE_DRIVER)
+    {
+        /* Send control code to the driver */
+        dwError = ScmControlDriver(lpService,
+                                   dwControl,
+                                   lpServiceStatus);
+    }
+    else
+    {
+        /* FIXME: Send control code to the service */
+#if 0
+        dwError = ScmControlService(lpService,
+                                    dwControl,
+                                    lpServiceStatus);
+#endif
+        dwError = ERROR_INVALID_SERVICE_CONTROL;
+    }
 
-    /* FIXME: Send control code to the service */
-
-
     /* Return service status information */
     RtlCopyMemory(lpServiceStatus,
                   &lpService->Status,
                   sizeof(SERVICE_STATUS));
 
-    return ERROR_SUCCESS;
+    return dwError;
 }
 
 

Modified: trunk/reactos/subsys/system/services/services.h
--- trunk/reactos/subsys/system/services/services.h	2005-11-20 19:31:49 UTC (rev 19384)
+++ trunk/reactos/subsys/system/services/services.h	2005-11-20 20:18:00 UTC (rev 19385)
@@ -76,6 +76,15 @@
 DWORD ScmMarkServiceForDelete(PSERVICE pService);
 
 
+/* driver.c */
+
+NTSTATUS ScmLoadDriver(PSERVICE lpService);
+DWORD ScmUnloadDriver(PSERVICE lpService);
+DWORD ScmControlDriver(PSERVICE lpService,
+                       DWORD dwControl,
+                       LPSERVICE_STATUS lpServiceStatus);
+
+
 /* rpcserver.c */
 
 VOID ScmStartRpcServer(VOID);

Modified: trunk/reactos/subsys/system/services/services.xml
--- trunk/reactos/subsys/system/services/services.xml	2005-11-20 19:31:49 UTC (rev 19384)
+++ trunk/reactos/subsys/system/services/services.xml	2005-11-20 20:18:00 UTC (rev 19385)
@@ -12,6 +12,7 @@
 	<library>rpcrt4</library>
 	<file>config.c</file>
 	<file>database.c</file>
+	<file>driver.c</file>
 	<file>rpcserver.c</file>
 	<file>services.c</file>
 	<file>services.rc</file>