xref: /reactos/base/system/services/groupdb.c (revision c2c66aff)
1 /*
2  * PROJECT:     ReactOS Service Control Manager
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/system/services/groupdb.c
5  * PURPOSE:     Service group control interface
6  * COPYRIGHT:   Copyright 2005 Eric Kohl
7  *
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include "services.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS *******************************************************************/
18 
19 LIST_ENTRY GroupListHead;
20 LIST_ENTRY UnknownGroupListHead;
21 
22 
23 /* FUNCTIONS *****************************************************************/
24 
25 PSERVICE_GROUP
ScmGetServiceGroupByName(_In_ LPCWSTR lpGroupName)26 ScmGetServiceGroupByName(
27     _In_ LPCWSTR lpGroupName)
28 {
29     PLIST_ENTRY GroupEntry;
30     PSERVICE_GROUP lpGroup;
31 
32     DPRINT("ScmGetServiceGroupByName(%S)\n", lpGroupName);
33 
34     GroupEntry = GroupListHead.Flink;
35     while (GroupEntry != &GroupListHead)
36     {
37         lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
38 
39         if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
40             return lpGroup;
41 
42         GroupEntry = GroupEntry->Flink;
43     }
44 
45     GroupEntry = UnknownGroupListHead.Flink;
46     while (GroupEntry != &UnknownGroupListHead)
47     {
48         lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
49 
50         if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
51             return lpGroup;
52 
53         GroupEntry = GroupEntry->Flink;
54     }
55 
56     return NULL;
57 }
58 
59 
60 DWORD
ScmSetServiceGroup(PSERVICE lpService,LPCWSTR lpGroupName)61 ScmSetServiceGroup(PSERVICE lpService,
62                    LPCWSTR lpGroupName)
63 {
64     PLIST_ENTRY GroupEntry;
65     PSERVICE_GROUP lpGroup;
66 
67     DPRINT("ScmSetServiceGroup(%S)\n", lpGroupName);
68 
69     if (lpService->lpGroup != NULL)
70     {
71         ASSERT(lpService->lpGroup->dwRefCount != 0);
72         ASSERT(lpService->lpGroup->dwRefCount == (DWORD)-1 ||
73                lpService->lpGroup->dwRefCount < 10000);
74         if (lpService->lpGroup->dwRefCount != (DWORD)-1)
75         {
76             lpService->lpGroup->dwRefCount--;
77             if (lpService->lpGroup->dwRefCount == 0)
78             {
79                 ASSERT(lpService->lpGroup->TagCount == 0);
80                 ASSERT(lpService->lpGroup->TagArray == NULL);
81                 RemoveEntryList(&lpService->lpGroup->GroupListEntry);
82                 HeapFree(GetProcessHeap(), 0, lpService->lpGroup);
83                 lpService->lpGroup = NULL;
84             }
85         }
86     }
87 
88     if (lpGroupName == NULL)
89         return ERROR_SUCCESS;
90 
91     GroupEntry = GroupListHead.Flink;
92     while (GroupEntry != &GroupListHead)
93     {
94         lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
95 
96         if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
97         {
98             lpService->lpGroup = lpGroup;
99             return ERROR_SUCCESS;
100         }
101 
102         GroupEntry = GroupEntry->Flink;
103     }
104 
105     GroupEntry = UnknownGroupListHead.Flink;
106     while (GroupEntry != &UnknownGroupListHead)
107     {
108         lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
109 
110         if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
111         {
112             lpGroup->dwRefCount++;
113             lpService->lpGroup = lpGroup;
114             return ERROR_SUCCESS;
115         }
116 
117         GroupEntry = GroupEntry->Flink;
118     }
119 
120     lpGroup = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
121                                         HEAP_ZERO_MEMORY,
122                                         sizeof(SERVICE_GROUP) + ((wcslen(lpGroupName) + 1)* sizeof(WCHAR)));
123     if (lpGroup == NULL)
124         return ERROR_NOT_ENOUGH_MEMORY;
125 
126     wcscpy(lpGroup->szGroupName, lpGroupName);
127     lpGroup->lpGroupName = lpGroup->szGroupName;
128     lpGroup->dwRefCount = 1;
129     lpService->lpGroup = lpGroup;
130 
131     InsertTailList(&UnknownGroupListHead,
132                    &lpGroup->GroupListEntry);
133 
134     return ERROR_SUCCESS;
135 }
136 
137 
138 static NTSTATUS WINAPI
CreateGroupOrderListRoutine(PWSTR ValueName,ULONG ValueType,PVOID ValueData,ULONG ValueLength,PVOID Context,PVOID EntryContext)139 CreateGroupOrderListRoutine(PWSTR ValueName,
140                             ULONG ValueType,
141                             PVOID ValueData,
142                             ULONG ValueLength,
143                             PVOID Context,
144                             PVOID EntryContext)
145 {
146     PSERVICE_GROUP Group;
147 
148     DPRINT("CreateGroupOrderListRoutine(%S, %x, %p, %x, %p, %p)\n",
149            ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
150 
151     if (ValueType == REG_BINARY &&
152         ValueData != NULL &&
153         ValueLength >= sizeof(DWORD) &&
154         ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
155     {
156         Group = (PSERVICE_GROUP)Context;
157         Group->TagCount = ((PULONG)ValueData)[0];
158         if (Group->TagCount > 0)
159         {
160             if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
161             {
162                 Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
163                                                     HEAP_ZERO_MEMORY,
164                                                     Group->TagCount * sizeof(DWORD));
165                 if (Group->TagArray == NULL)
166                 {
167                     Group->TagCount = 0;
168                     return STATUS_INSUFFICIENT_RESOURCES;
169                 }
170 
171                 RtlCopyMemory(Group->TagArray,
172                               (PULONG)ValueData + 1,
173                               Group->TagCount * sizeof(DWORD));
174             }
175             else
176             {
177                 Group->TagCount = 0;
178                 return STATUS_UNSUCCESSFUL;
179             }
180         }
181     }
182 
183     return STATUS_SUCCESS;
184 }
185 
186 
187 static NTSTATUS WINAPI
CreateGroupListRoutine(PWSTR ValueName,ULONG ValueType,PVOID ValueData,ULONG ValueLength,PVOID Context,PVOID EntryContext)188 CreateGroupListRoutine(PWSTR ValueName,
189                        ULONG ValueType,
190                        PVOID ValueData,
191                        ULONG ValueLength,
192                        PVOID Context,
193                        PVOID EntryContext)
194 {
195     PSERVICE_GROUP Group;
196     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
197     NTSTATUS Status;
198 
199     if (ValueType == REG_SZ)
200     {
201         DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
202 
203         Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
204                                           HEAP_ZERO_MEMORY,
205                                           sizeof(SERVICE_GROUP) + ((wcslen((const wchar_t*) ValueData) + 1) * sizeof(WCHAR)));
206         if (Group == NULL)
207         {
208             return STATUS_INSUFFICIENT_RESOURCES;
209         }
210 
211         wcscpy(Group->szGroupName, (const wchar_t*) ValueData);
212         Group->lpGroupName = Group->szGroupName;
213         Group->dwRefCount = (DWORD)-1;
214 
215         RtlZeroMemory(&QueryTable, sizeof(QueryTable));
216         QueryTable[0].Name = (PWSTR)ValueData;
217         QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
218 
219         Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
220                                         L"GroupOrderList",
221                                         QueryTable,
222                                         (PVOID)Group,
223                                         NULL);
224         DPRINT("%x %lu %S\n", Status, Group->TagCount, (PWSTR)ValueData);
225 
226         InsertTailList(&GroupListHead,
227                        &Group->GroupListEntry);
228     }
229 
230     return STATUS_SUCCESS;
231 }
232 
233 
234 DWORD
ScmCreateGroupList(VOID)235 ScmCreateGroupList(VOID)
236 {
237     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
238     NTSTATUS Status;
239 
240     InitializeListHead(&GroupListHead);
241     InitializeListHead(&UnknownGroupListHead);
242 
243     /* Build group order list */
244     RtlZeroMemory(&QueryTable,
245                   sizeof(QueryTable));
246 
247     QueryTable[0].Name = L"List";
248     QueryTable[0].QueryRoutine = CreateGroupListRoutine;
249 
250     Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
251                                     L"ServiceGroupOrder",
252                                     QueryTable,
253                                     NULL,
254                                     NULL);
255 
256     return RtlNtStatusToDosError(Status);
257 }
258 
259 /* EOF */
260