Sync with trunk r63283
[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 DWORD
26 ScmSetServiceGroup(PSERVICE lpService,
27 LPCWSTR lpGroupName)
28 {
29 PLIST_ENTRY GroupEntry;
30 PSERVICE_GROUP lpGroup;
31
32 DPRINT("ScmSetServiceGroup(%S)\n", lpGroupName);
33
34 if (lpService->lpGroup != NULL)
35 {
36 lpService->lpGroup->dwRefCount--;
37
38 /* FIXME: What do we have to do when dwRefCount is 0? */
39 }
40
41 GroupEntry = GroupListHead.Flink;
42 while (GroupEntry != &GroupListHead)
43 {
44 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
45
46 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
47 {
48 lpService->lpGroup = lpGroup;
49 return ERROR_SUCCESS;
50 }
51
52 GroupEntry = GroupEntry->Flink;
53 }
54
55 GroupEntry = UnknownGroupListHead.Flink;
56 while (GroupEntry != &UnknownGroupListHead)
57 {
58 lpGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
59
60 if (!_wcsicmp(lpGroup->lpGroupName, lpGroupName))
61 {
62 lpGroup->dwRefCount++;
63 lpService->lpGroup = lpGroup;
64 return ERROR_SUCCESS;
65 }
66
67 GroupEntry = GroupEntry->Flink;
68 }
69
70 lpGroup = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
71 HEAP_ZERO_MEMORY,
72 sizeof(SERVICE_GROUP) + ((wcslen(lpGroupName) + 1)* sizeof(WCHAR)));
73 if (lpGroup == NULL)
74 return ERROR_NOT_ENOUGH_MEMORY;
75
76 wcscpy(lpGroup->szGroupName, lpGroupName);
77 lpGroup->lpGroupName = lpGroup->szGroupName;
78 lpGroup->dwRefCount = 1;
79 lpService->lpGroup = lpGroup;
80
81 InsertTailList(&UnknownGroupListHead,
82 &lpGroup->GroupListEntry);
83
84 return ERROR_SUCCESS;
85 }
86
87
88 static NTSTATUS WINAPI
89 CreateGroupOrderListRoutine(PWSTR ValueName,
90 ULONG ValueType,
91 PVOID ValueData,
92 ULONG ValueLength,
93 PVOID Context,
94 PVOID EntryContext)
95 {
96 PSERVICE_GROUP Group;
97
98 DPRINT("CreateGroupOrderListRoutine(%S, %x, %p, %x, %p, %p)\n",
99 ValueName, ValueType, ValueData, ValueLength, Context, EntryContext);
100
101 if (ValueType == REG_BINARY &&
102 ValueData != NULL &&
103 ValueLength >= sizeof(DWORD) &&
104 ValueLength >= (*(PULONG)ValueData + 1) * sizeof(DWORD))
105 {
106 Group = (PSERVICE_GROUP)Context;
107 Group->TagCount = ((PULONG)ValueData)[0];
108 if (Group->TagCount > 0)
109 {
110 if (ValueLength >= (Group->TagCount + 1) * sizeof(DWORD))
111 {
112 Group->TagArray = (PULONG)HeapAlloc(GetProcessHeap(),
113 HEAP_ZERO_MEMORY,
114 Group->TagCount * sizeof(DWORD));
115 if (Group->TagArray == NULL)
116 {
117 Group->TagCount = 0;
118 return STATUS_INSUFFICIENT_RESOURCES;
119 }
120
121 RtlCopyMemory(Group->TagArray,
122 (PULONG)ValueData + 1,
123 Group->TagCount * sizeof(DWORD));
124 }
125 else
126 {
127 Group->TagCount = 0;
128 return STATUS_UNSUCCESSFUL;
129 }
130 }
131 }
132
133 return STATUS_SUCCESS;
134 }
135
136
137 static NTSTATUS WINAPI
138 CreateGroupListRoutine(PWSTR ValueName,
139 ULONG ValueType,
140 PVOID ValueData,
141 ULONG ValueLength,
142 PVOID Context,
143 PVOID EntryContext)
144 {
145 PSERVICE_GROUP Group;
146 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
147 NTSTATUS Status;
148
149 if (ValueType == REG_SZ)
150 {
151 DPRINT("Data: '%S'\n", (PWCHAR)ValueData);
152
153 Group = (PSERVICE_GROUP)HeapAlloc(GetProcessHeap(),
154 HEAP_ZERO_MEMORY,
155 sizeof(SERVICE_GROUP) + ((wcslen((const wchar_t*) ValueData) + 1) * sizeof(WCHAR)));
156 if (Group == NULL)
157 {
158 return STATUS_INSUFFICIENT_RESOURCES;
159 }
160
161 wcscpy(Group->szGroupName, (const wchar_t*) ValueData);
162 Group->lpGroupName = Group->szGroupName;
163 Group->dwRefCount = (DWORD)-1;
164
165 RtlZeroMemory(&QueryTable, sizeof(QueryTable));
166 QueryTable[0].Name = (PWSTR)ValueData;
167 QueryTable[0].QueryRoutine = CreateGroupOrderListRoutine;
168
169 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
170 L"GroupOrderList",
171 QueryTable,
172 (PVOID)Group,
173 NULL);
174 DPRINT("%x %lu %S\n", Status, Group->TagCount, (PWSTR)ValueData);
175
176 InsertTailList(&GroupListHead,
177 &Group->GroupListEntry);
178 }
179
180 return STATUS_SUCCESS;
181 }
182
183
184 DWORD
185 ScmCreateGroupList(VOID)
186 {
187 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
188 NTSTATUS Status;
189
190 InitializeListHead(&GroupListHead);
191 InitializeListHead(&UnknownGroupListHead);
192
193 /* Build group order list */
194 RtlZeroMemory(&QueryTable,
195 sizeof(QueryTable));
196
197 QueryTable[0].Name = L"List";
198 QueryTable[0].QueryRoutine = CreateGroupListRoutine;
199
200 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
201 L"ServiceGroupOrder",
202 QueryTable,
203 NULL,
204 NULL);
205
206 return RtlNtStatusToDosError(Status);
207 }
208
209 /* EOF */