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