[MSIEXEC] Sync with Wine Staging 2.16. CORE-13762
[reactos.git] / base / system / services / groupdb.c
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
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
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
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
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
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 */