Move group-list related code to a separate file and keep the group name in the group...
[reactos.git] / reactos / subsys / system / services / database.c
index 48fba08..34bf1eb 100644 (file)
 #include <debug.h>
 
 
-/* TYPES *********************************************************************/
-
-typedef struct _SERVICE_GROUP
-{
-  LIST_ENTRY GroupListEntry;
-  UNICODE_STRING GroupName;
-
-  BOOLEAN ServicesRunning;
-  ULONG TagCount;
-  PULONG TagArray;
-
-} SERVICE_GROUP, *PSERVICE_GROUP;
-
-
 /* GLOBALS *******************************************************************/
 
-LIST_ENTRY GroupListHead;
 LIST_ENTRY ServiceListHead;
 
 static RTL_RESOURCE DatabaseLock;
+static DWORD dwResumeCount = 1;
 
 
 /* FUNCTIONS *****************************************************************/
@@ -113,101 +99,32 @@ ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName)
 }
 
 
-static NTSTATUS STDCALL
-CreateGroupOrderListRoutine(PWSTR ValueName,
-                            ULONG ValueType,
-                            PVOID ValueData,
-                            ULONG ValueLength,
-                            PVOID Context,
-                            PVOID EntryContext)
+PSERVICE
+ScmGetServiceEntryByResumeCount(DWORD dwResumeCount)
 {
-    PSERVICE_GROUP Group;
-
-    DPRINT("CreateGroupOrderListRoutine(%S, %x, %x, %x, %x, %x)\n",
-           ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
-
-    if (ValueType == REG_BINARY &&
-        ValueData != NULL &&
-        ValueLength >= sizeof(DWORD) &&
-        ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
-    {
-        Group = (PSERVICE_GROUP)Context;
-        Group->TagCount = ((PULONG)ValueData)[0];
-        if (Group->TagCount > 0)
-        {
-            if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
-            {
-                Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
-                                                    HEAP_ZERO_MEMORY,
-                                                    Group->TagCount * sizeof(DWORD));
-                if (Group->TagArray == NULL)
-                {
-                    Group->TagCount = 0;
-                    return STATUS_INSUFFICIENT_RESOURCES;
-                }
-
-                RtlCopyMemory(Group->TagArray,
-                              (PULONG)ValueData + 1,
-                              Group->TagCount * sizeof(DWORD));
-            }
-            else
-            {
-                Group->TagCount = 0;
-                return STATUS_UNSUCCESSFUL;
-            }
-        }
-    }
-
-    return STATUS_SUCCESS;
-}
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
 
+    DPRINT("ScmGetServiceEntryByResumeCount() called\n");
 
-static NTSTATUS STDCALL
-CreateGroupListRoutine(PWSTR ValueName,
-                       ULONG ValueType,
-                       PVOID ValueData,
-                       ULONG ValueLength,
-                       PVOID Context,
-                       PVOID EntryContext)
-{
-    PSERVICE_GROUP Group;
-    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-    NTSTATUS Status;
-
-    if (ValueType == REG_SZ)
+    ServiceEntry = ServiceListHead.Flink;
+    while (ServiceEntry != &ServiceListHead)
     {
-        DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
-
-        Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
-                                          HEAP_ZERO_MEMORY,
-                                          sizeof(SERVICE_GROUP));
-        if (Group == NULL)
-        {
-            return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        if (!RtlCreateUnicodeString(&Group->GroupName,
-                                    (PWSTR)ValueData))
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+        if (CurrentService->dwResumeCount > dwResumeCount)
         {
-            return STATUS_INSUFFICIENT_RESOURCES;
+            DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName);
+            return CurrentService;
         }
 
-        RtlZeroMemory(&QueryTable, sizeof(QueryTable));
-        QueryTable[0].Name = (PWSTR)ValueData;
-        QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
-
-        Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
-                                        L"GroupOrderList",
-                                        QueryTable,
-                                        (PVOID)Group,
-                                        NULL);
-        DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData);
-
-        InsertTailList(&GroupListHead,
-                       &Group->GroupListEntry);
+        ServiceEntry = ServiceEntry->Flink;
     }
 
-    return STATUS_SUCCESS;
+    DPRINT("Couldn't find a matching service\n");
+
+    return NULL;
 }
 
 
@@ -233,6 +150,9 @@ ScmCreateNewServiceRecord(LPWSTR lpServiceName,
     lpService->lpServiceName = lpService->szServiceName;
     lpService->lpDisplayName = lpService->lpServiceName;
 
+    /* Set the resume count */
+    lpService->dwResumeCount = dwResumeCount++;
+
     /* Append service entry */
     InsertTailList(&ServiceListHead,
                    &lpService->ServiceListEntry);
@@ -379,28 +299,29 @@ done:;
 }
 
 
-DWORD
-ScmReadGroupList(VOID)
+VOID
+ScmDeleteMarkedServices(VOID)
 {
-    RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-    NTSTATUS Status;
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
 
-    InitializeListHead(&GroupListHead);
+    ServiceEntry = ServiceListHead.Flink;
+    while (ServiceEntry != &ServiceListHead)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
 
-    /* Build group order list */
-    RtlZeroMemory(&QueryTable,
-                  sizeof(QueryTable));
+        ServiceEntry = ServiceEntry->Flink;
 
-    QueryTable[0].Name = L"List";
-    QueryTable[0].QueryRoutine = CreateGroupListRoutine;
+        if (CurrentService->bDeleted == TRUE)
+        {
+            DPRINT1("Delete service: %S\n", CurrentService->lpServiceName);
 
-    Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
-                                    L"ServiceGroupOrder",
-                                    QueryTable,
-                                    NULL,
-                                    NULL);
+            /* FIXME: Delete the registry keys */
+
+            /* FIXME: Delete the service record from the list */
 
-    return RtlNtStatusToDosError(Status);
+        }
+    }
 }
 
 
@@ -417,7 +338,7 @@ ScmCreateServiceDatabase(VOID)
 
     DPRINT("ScmCreateServiceDatabase() called\n");
 
-    dwError = ScmReadGroupList();
+    dwError = ScmCreateGroupList();
     if (dwError != ERROR_SUCCESS)
         return dwError;
 
@@ -474,7 +395,8 @@ ScmCreateServiceDatabase(VOID)
 
     RegCloseKey(hServicesKey);
 
-    /* FIXME: Delete services that are marked for delete */
+    /* Delete services that are marked for delete */
+    ScmDeleteMarkedServices();
 
     DPRINT("ScmCreateServiceDatabase() done\n");
 
@@ -567,9 +489,9 @@ ScmCheckDriver(PSERVICE Service)
                 {
                     CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
 
-                    DPRINT("Checking group '%wZ'\n", &CurrentGroup->GroupName);
+                    DPRINT("Checking group '%S'\n", &CurrentGroup->lpGroupName);
                     if (Service->lpServiceGroup != NULL &&
-                        _wcsicmp(Service->lpServiceGroup, CurrentGroup->GroupName.Buffer) == 0)
+                        _wcsicmp(Service->lpServiceGroup, CurrentGroup->lpGroupName) == 0)
                     {
                         CurrentGroup->ServicesRunning = TRUE;
                     }
@@ -836,8 +758,6 @@ static NTSTATUS
 ScmStartService(PSERVICE Service,
                 PSERVICE_GROUP Group)
 {
-    WCHAR szDriverPath[MAX_PATH];
-    UNICODE_STRING DriverPath;
     NTSTATUS Status;
 
     DPRINT("ScmStartService() called\n");
@@ -845,21 +765,12 @@ ScmStartService(PSERVICE Service,
     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
     {
@@ -935,7 +846,7 @@ ScmAutoStartServices(VOID)
     {
         CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
 
-        DPRINT("Group '%wZ'\n", &CurrentGroup->GroupName);
+        DPRINT("Group '%S'\n", CurrentGroup->lpGroupName);
 
         /* Start all services witch have a valid tag */
         for (i = 0; i < CurrentGroup->TagCount; i++)
@@ -946,7 +857,7 @@ ScmAutoStartServices(VOID)
                 CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
 
                 if ((CurrentService->lpServiceGroup != NULL) &&
-                    (_wcsicmp(CurrentGroup->GroupName.Buffer, CurrentService->lpServiceGroup) == 0) &&
+                    (_wcsicmp(CurrentGroup->lpGroupName, CurrentService->lpServiceGroup) == 0) &&
                     (CurrentService->dwStartType == SERVICE_AUTO_START) &&
                     (CurrentService->ServiceVisited == FALSE) &&
                     (CurrentService->dwTag == CurrentGroup->TagArray[i]))
@@ -967,7 +878,7 @@ ScmAutoStartServices(VOID)
             CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
 
             if ((CurrentService->lpServiceGroup != NULL) &&
-                (_wcsicmp(CurrentGroup->GroupName.Buffer, CurrentService->lpServiceGroup) == 0) &&
+                (_wcsicmp(CurrentGroup->lpGroupName, CurrentService->lpServiceGroup) == 0) &&
                 (CurrentService->dwStartType == SERVICE_AUTO_START) &&
                 (CurrentService->ServiceVisited == FALSE))
             {