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