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