[SERVICES]
[reactos.git] / reactos / base / system / services / config.c
1 /*
2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/config.c
5 * PURPOSE: Service configuration 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 /* FUNCTIONS *****************************************************************/
18
19
20 DWORD
21 ScmOpenServiceKey(LPWSTR lpServiceName,
22 REGSAM samDesired,
23 PHKEY phKey)
24 {
25 HKEY hServicesKey = NULL;
26 DWORD dwError;
27
28 *phKey = NULL;
29
30 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
31 L"System\\CurrentControlSet\\Services",
32 0,
33 KEY_READ,
34 &hServicesKey);
35 if (dwError != ERROR_SUCCESS)
36 return dwError;
37
38 dwError = RegOpenKeyExW(hServicesKey,
39 lpServiceName,
40 0,
41 samDesired,
42 phKey);
43
44 RegCloseKey(hServicesKey);
45
46 return dwError;
47 }
48
49
50 DWORD
51 ScmCreateServiceKey(LPCWSTR lpServiceName,
52 REGSAM samDesired,
53 PHKEY phKey)
54 {
55 HKEY hServicesKey = NULL;
56 DWORD dwDisposition;
57 DWORD dwError;
58
59 *phKey = NULL;
60
61 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
62 L"System\\CurrentControlSet\\Services",
63 0,
64 KEY_READ | KEY_CREATE_SUB_KEY,
65 &hServicesKey);
66 if (dwError != ERROR_SUCCESS)
67 return dwError;
68
69 dwError = RegCreateKeyExW(hServicesKey,
70 lpServiceName,
71 0,
72 NULL,
73 REG_OPTION_NON_VOLATILE,
74 samDesired,
75 NULL,
76 phKey,
77 &dwDisposition);
78 #if 0
79 if ((dwError == ERROR_SUCCESS) &&
80 (dwDisposition == REG_OPENED_EXISTING_KEY))
81 {
82 RegCloseKey(*phKey);
83 *phKey = NULL;
84 dwError = ERROR_SERVICE_EXISTS;
85 }
86 #endif
87
88 RegCloseKey(hServicesKey);
89
90 return dwError;
91 }
92
93
94
95 DWORD
96 ScmWriteDependencies(HKEY hServiceKey,
97 LPCWSTR lpDependencies,
98 DWORD dwDependenciesLength)
99 {
100 DWORD dwError = ERROR_SUCCESS;
101 SIZE_T cchGroupLength = 0;
102 SIZE_T cchServiceLength = 0;
103 SIZE_T cchLength;
104 LPWSTR lpGroupDeps;
105 LPWSTR lpServiceDeps;
106 LPCWSTR lpSrc;
107 LPWSTR lpDst;
108
109 if (*lpDependencies == 0)
110 {
111 RegDeleteValueW(hServiceKey,
112 L"DependOnService");
113 RegDeleteValueW(hServiceKey,
114 L"DependOnGroup");
115 }
116 else
117 {
118 lpGroupDeps = HeapAlloc(GetProcessHeap(),
119 HEAP_ZERO_MEMORY,
120 (dwDependenciesLength + 2) * sizeof(WCHAR));
121 if (lpGroupDeps == NULL)
122 return ERROR_NOT_ENOUGH_MEMORY;
123
124 lpSrc = lpDependencies;
125 lpDst = lpGroupDeps;
126 while (*lpSrc != 0)
127 {
128 cchLength = wcslen(lpSrc) + 1;
129 if (*lpSrc == SC_GROUP_IDENTIFIERW)
130 {
131 lpSrc++;
132 cchLength--;
133 cchGroupLength += cchLength;
134 wcscpy(lpDst, lpSrc);
135 lpDst = lpDst + cchLength;
136 }
137
138 lpSrc = lpSrc + cchLength;
139 }
140 *lpDst = 0;
141 lpDst++;
142 cchGroupLength++;
143
144 lpSrc = lpDependencies;
145 lpServiceDeps = lpDst;
146 while (*lpSrc != 0)
147 {
148 cchLength = wcslen(lpSrc) + 1;
149 if (*lpSrc != SC_GROUP_IDENTIFIERW)
150 {
151 cchServiceLength += cchLength;
152 wcscpy(lpDst, lpSrc);
153 lpDst = lpDst + cchLength;
154 }
155
156 lpSrc = lpSrc + cchLength;
157 }
158 *lpDst = 0;
159 cchServiceLength++;
160
161 if (cchGroupLength > 1)
162 {
163 dwError = RegSetValueExW(hServiceKey,
164 L"DependOnGroup",
165 0,
166 REG_MULTI_SZ,
167 (LPBYTE)lpGroupDeps,
168 (DWORD)(cchGroupLength * sizeof(WCHAR)));
169 }
170 else
171 {
172 RegDeleteValueW(hServiceKey,
173 L"DependOnGroup");
174 }
175
176 if (dwError == ERROR_SUCCESS)
177 {
178 if (cchServiceLength > 1)
179 {
180 dwError = RegSetValueExW(hServiceKey,
181 L"DependOnService",
182 0,
183 REG_MULTI_SZ,
184 (LPBYTE)lpServiceDeps,
185 (DWORD)(cchServiceLength * sizeof(WCHAR)));
186 }
187 else
188 {
189 RegDeleteValueW(hServiceKey,
190 L"DependOnService");
191 }
192 }
193
194 HeapFree(GetProcessHeap(), 0, lpGroupDeps);
195 }
196
197 return dwError;
198 }
199
200
201 DWORD
202 ScmMarkServiceForDelete(PSERVICE pService)
203 {
204 HKEY hServiceKey = NULL;
205 DWORD dwValue = 1;
206 DWORD dwError;
207
208 DPRINT("ScmMarkServiceForDelete() called\n");
209
210 dwError = ScmOpenServiceKey(pService->lpServiceName,
211 KEY_WRITE,
212 &hServiceKey);
213 if (dwError != ERROR_SUCCESS)
214 return dwError;
215
216 dwError = RegSetValueExW(hServiceKey,
217 L"DeleteFlag",
218 0,
219 REG_DWORD,
220 (LPBYTE)&dwValue,
221 sizeof(DWORD));
222
223 RegCloseKey(hServiceKey);
224
225 return dwError;
226 }
227
228
229 BOOL
230 ScmIsDeleteFlagSet(HKEY hServiceKey)
231 {
232 DWORD dwError;
233 DWORD dwType;
234 DWORD dwFlag;
235 DWORD dwSize = sizeof(DWORD);
236
237 dwError = RegQueryValueExW(hServiceKey,
238 L"DeleteFlag",
239 0,
240 &dwType,
241 (LPBYTE)&dwFlag,
242 &dwSize);
243
244 return (dwError == ERROR_SUCCESS);
245 }
246
247
248 DWORD
249 ScmReadString(HKEY hServiceKey,
250 LPCWSTR lpValueName,
251 LPWSTR *lpValue)
252 {
253 DWORD dwError = 0;
254 DWORD dwSize = 0;
255 DWORD dwType = 0;
256 LPWSTR ptr = NULL;
257 LPWSTR expanded = NULL;
258
259 *lpValue = NULL;
260
261 dwError = RegQueryValueExW(hServiceKey,
262 lpValueName,
263 0,
264 &dwType,
265 NULL,
266 &dwSize);
267 if (dwError != ERROR_SUCCESS)
268 return dwError;
269
270 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
271 if (ptr == NULL)
272 return ERROR_NOT_ENOUGH_MEMORY;
273
274 dwError = RegQueryValueExW(hServiceKey,
275 lpValueName,
276 0,
277 &dwType,
278 (LPBYTE)ptr,
279 &dwSize);
280 if (dwError != ERROR_SUCCESS)
281 {
282 HeapFree(GetProcessHeap(), 0, ptr);
283 return dwError;
284 }
285
286 if (dwType == REG_EXPAND_SZ)
287 {
288 /* Expand the value... */
289 dwSize = ExpandEnvironmentStringsW(ptr, NULL, 0);
290 if (dwSize > 0)
291 {
292 expanded = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR));
293 if (expanded)
294 {
295 if (dwSize == ExpandEnvironmentStringsW(ptr, expanded, dwSize))
296 {
297 *lpValue = expanded;
298 dwError = ERROR_SUCCESS;
299 }
300 else
301 {
302 dwError = GetLastError();
303 HeapFree(GetProcessHeap(), 0, expanded);
304 }
305 }
306 else
307 {
308 dwError = ERROR_NOT_ENOUGH_MEMORY;
309 }
310 }
311 else
312 {
313 dwError = GetLastError();
314 }
315
316 HeapFree(GetProcessHeap(), 0, ptr);
317 }
318 else
319 {
320 *lpValue = ptr;
321 }
322
323 return dwError;
324 }
325
326
327 DWORD
328 ScmReadDependencies(HKEY hServiceKey,
329 LPWSTR *lpDependencies,
330 DWORD *lpdwDependenciesLength)
331 {
332 LPWSTR lpGroups = NULL;
333 LPWSTR lpServices = NULL;
334 SIZE_T cchGroupsLength = 0;
335 SIZE_T cchServicesLength = 0;
336 LPWSTR lpSrc;
337 LPWSTR lpDest;
338 SIZE_T cchLength;
339 SIZE_T cchTotalLength;
340
341 *lpDependencies = NULL;
342 *lpdwDependenciesLength = 0;
343
344 /* Read the dependency values */
345 ScmReadString(hServiceKey,
346 L"DependOnGroup",
347 &lpGroups);
348
349 ScmReadString(hServiceKey,
350 L"DependOnService",
351 &lpServices);
352
353 /* Leave, if there are no dependencies */
354 if (lpGroups == NULL && lpServices == NULL)
355 return ERROR_SUCCESS;
356
357 /* Determine the total buffer size for the dependencies */
358 if (lpGroups)
359 {
360 DPRINT("Groups:\n");
361 lpSrc = lpGroups;
362 while (*lpSrc != 0)
363 {
364 DPRINT(" %S\n", lpSrc);
365
366 cchLength = wcslen(lpSrc) + 1;
367 cchGroupsLength += cchLength + 1;
368
369 lpSrc = lpSrc + cchLength;
370 }
371 }
372
373 if (lpServices)
374 {
375 DPRINT("Services:\n");
376 lpSrc = lpServices;
377 while (*lpSrc != 0)
378 {
379 DPRINT(" %S\n", lpSrc);
380
381 cchLength = wcslen(lpSrc) + 1;
382 cchServicesLength += cchLength;
383
384 lpSrc = lpSrc + cchLength;
385 }
386 }
387
388 cchTotalLength = cchGroupsLength + cchServicesLength + 1;
389 DPRINT("cchTotalLength: %lu\n", cchTotalLength);
390
391 /* Allocate the common buffer for the dependencies */
392 *lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cchTotalLength * sizeof(WCHAR));
393 if (*lpDependencies == NULL)
394 {
395 if (lpGroups)
396 HeapFree(GetProcessHeap(), 0, lpGroups);
397
398 if (lpServices)
399 HeapFree(GetProcessHeap(), 0, lpServices);
400
401 return ERROR_NOT_ENOUGH_MEMORY;
402 }
403
404 /* Return the allocated buffer length in characters */
405 *lpdwDependenciesLength = (DWORD)cchTotalLength;
406
407 /* Copy the service dependencies into the common buffer */
408 lpDest = *lpDependencies;
409 if (lpServices)
410 {
411 memcpy(lpDest,
412 lpServices,
413 cchServicesLength * sizeof(WCHAR));
414
415 lpDest = lpDest + cchServicesLength;
416 }
417
418 /* Copy the group dependencies into the common buffer */
419 if (lpGroups)
420 {
421 lpSrc = lpGroups;
422 while (*lpSrc != 0)
423 {
424 cchLength = wcslen(lpSrc) + 1;
425
426 *lpDest = SC_GROUP_IDENTIFIERW;
427 lpDest++;
428
429 wcscpy(lpDest, lpSrc);
430
431 lpDest = lpDest + cchLength;
432 lpSrc = lpSrc + cchLength;
433 }
434 }
435
436 /* Free the temporary buffers */
437 if (lpGroups)
438 HeapFree(GetProcessHeap(), 0, lpGroups);
439
440 if (lpServices)
441 HeapFree(GetProcessHeap(), 0, lpServices);
442
443 return ERROR_SUCCESS;
444 }
445
446 /* EOF */