- Merge from trunk up to r45543
[reactos.git] / 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 LPWSTR lpDependencies,
98 DWORD dwDependenciesLength)
99 {
100 DWORD dwError = ERROR_SUCCESS;
101 DWORD dwGroupLength = 0;
102 DWORD dwServiceLength = 0;
103 DWORD dwLength;
104 LPWSTR lpGroupDeps;
105 LPWSTR lpServiceDeps;
106 LPWSTR 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 dwLength = wcslen(lpSrc);
129 if (*lpSrc == SC_GROUP_IDENTIFIERW)
130 {
131 lpSrc++;
132 dwGroupLength += dwLength;
133 wcscpy(lpDst, lpSrc);
134 lpDst = lpDst + dwLength;
135 }
136
137 lpSrc = lpSrc + dwLength;
138 }
139 *lpDst = 0;
140 lpDst++;
141 dwGroupLength++;
142
143 lpSrc = lpDependencies;
144 lpServiceDeps = lpDst;
145 while (*lpSrc != 0)
146 {
147 dwLength = wcslen(lpSrc) + 1;
148 if (*lpSrc != SC_GROUP_IDENTIFIERW)
149 {
150 dwServiceLength += dwLength;
151 wcscpy(lpDst, lpSrc);
152 lpDst = lpDst + dwLength;
153 }
154
155 lpSrc = lpSrc + dwLength;
156 }
157 *lpDst = 0;
158 dwServiceLength++;
159
160 dwError = RegSetValueExW(hServiceKey,
161 L"DependOnGroup",
162 0,
163 REG_MULTI_SZ,
164 (LPBYTE)lpGroupDeps,
165 dwGroupLength * sizeof(WCHAR));
166
167 if (dwError == ERROR_SUCCESS)
168 {
169 dwError = RegSetValueExW(hServiceKey,
170 L"DependOnService",
171 0,
172 REG_MULTI_SZ,
173 (LPBYTE)lpServiceDeps,
174 dwServiceLength * sizeof(WCHAR));
175 }
176
177 HeapFree(GetProcessHeap(), 0, lpGroupDeps);
178 }
179
180 return dwError;
181 }
182
183
184 DWORD
185 ScmMarkServiceForDelete(PSERVICE pService)
186 {
187 HKEY hServiceKey = NULL;
188 DWORD dwValue = 1;
189 DWORD dwError;
190
191 DPRINT("ScmMarkServiceForDelete() called\n");
192
193 dwError = ScmOpenServiceKey(pService->lpServiceName,
194 KEY_WRITE,
195 &hServiceKey);
196 if (dwError != ERROR_SUCCESS)
197 return dwError;
198
199 dwError = RegSetValueExW(hServiceKey,
200 L"DeleteFlag",
201 0,
202 REG_DWORD,
203 (LPBYTE)&dwValue,
204 sizeof(DWORD));
205
206 RegCloseKey(hServiceKey);
207
208 return dwError;
209 }
210
211
212 BOOL
213 ScmIsDeleteFlagSet(HKEY hServiceKey)
214 {
215 DWORD dwError;
216 DWORD dwType;
217 DWORD dwFlag;
218 DWORD dwSize = sizeof(DWORD);
219
220 dwError = RegQueryValueExW(hServiceKey,
221 L"DeleteFlag",
222 0,
223 &dwType,
224 (LPBYTE)&dwFlag,
225 &dwSize);
226
227 return (dwError == ERROR_SUCCESS);
228 }
229
230
231 DWORD
232 ScmReadString(HKEY hServiceKey,
233 LPWSTR lpValueName,
234 LPWSTR *lpValue)
235 {
236 DWORD dwError;
237 DWORD dwSize;
238 DWORD dwType;
239 DWORD dwSizeNeeded;
240 LPWSTR expanded = NULL;
241 LPWSTR ptr = NULL;
242
243 *lpValue = NULL;
244
245 dwSize = 0;
246 dwError = RegQueryValueExW(hServiceKey,
247 lpValueName,
248 0,
249 &dwType,
250 NULL,
251 &dwSize);
252 if (dwError != ERROR_SUCCESS)
253 return dwError;
254
255 ptr = HeapAlloc(GetProcessHeap(), 0, dwSize);
256 if (ptr == NULL)
257 return ERROR_NOT_ENOUGH_MEMORY;
258
259 dwError = RegQueryValueExW(hServiceKey,
260 lpValueName,
261 0,
262 &dwType,
263 (LPBYTE)ptr,
264 &dwSize);
265 if (dwError != ERROR_SUCCESS)
266 goto done;
267
268 if (dwType == REG_EXPAND_SZ)
269 {
270 /* Expand the value... */
271 dwSizeNeeded = ExpandEnvironmentStringsW((LPCWSTR)ptr, NULL, 0);
272 if (dwSizeNeeded == 0)
273 {
274 dwError = GetLastError();
275 goto done;
276 }
277 expanded = HeapAlloc(GetProcessHeap(), 0, dwSizeNeeded * sizeof(WCHAR));
278 if (dwSizeNeeded < ExpandEnvironmentStringsW((LPCWSTR)ptr, expanded, dwSizeNeeded))
279 {
280 dwError = GetLastError();
281 goto done;
282 }
283 *lpValue = expanded;
284 HeapFree(GetProcessHeap(), 0, ptr);
285 dwError = ERROR_SUCCESS;
286 }
287 else
288 {
289 *lpValue = ptr;
290 }
291
292 done:
293 if (dwError != ERROR_SUCCESS)
294 {
295 HeapFree(GetProcessHeap(), 0, ptr);
296 if (expanded)
297 HeapFree(GetProcessHeap(), 0, expanded);
298 }
299
300 return dwError;
301 }
302
303
304 DWORD
305 ScmReadDependencies(HKEY hServiceKey,
306 LPWSTR *lpDependencies,
307 DWORD *lpdwDependenciesLength)
308 {
309 LPWSTR lpGroups = NULL;
310 LPWSTR lpServices = NULL;
311 DWORD dwGroupsLength = 0;
312 DWORD dwServicesLength = 0;
313 LPWSTR lpSrc;
314 LPWSTR lpDest;
315 DWORD len;
316 DWORD dwTotalLength;
317
318 *lpDependencies = NULL;
319 *lpdwDependenciesLength = 0;
320
321 /* Read the dependency values */
322 ScmReadString(hServiceKey,
323 L"DependOnGroup",
324 &lpGroups);
325
326 ScmReadString(hServiceKey,
327 L"DependOnService",
328 &lpServices);
329
330 /* Leave, if there are no dependencies */
331 if (lpGroups == NULL && lpServices == NULL)
332 return ERROR_SUCCESS;
333
334 /* Determine the total buffer size for the dependencies */
335 if (lpGroups)
336 {
337 DPRINT("Groups:\n");
338 lpSrc = lpGroups;
339 while (*lpSrc != 0)
340 {
341 DPRINT(" %S\n", lpSrc);
342
343 len = wcslen(lpSrc) + 1;
344 dwGroupsLength += len + 1;
345
346 lpSrc = lpSrc + len;
347 }
348 }
349
350 if (lpServices)
351 {
352 DPRINT("Services:\n");
353 lpSrc = lpServices;
354 while (*lpSrc != 0)
355 {
356 DPRINT(" %S\n", lpSrc);
357
358 len = wcslen(lpSrc) + 1;
359 dwServicesLength += len;
360
361 lpSrc = lpSrc + len;
362 }
363 }
364
365 dwTotalLength = dwGroupsLength + dwServicesLength + 1;
366 DPRINT("dwTotalLength: %lu\n", dwTotalLength);
367
368 /* Allocate the common buffer for the dependencies */
369 *lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalLength * sizeof(WCHAR));
370 if (*lpDependencies == NULL)
371 {
372 if (lpGroups)
373 HeapFree(GetProcessHeap(), 0, lpGroups);
374
375 if (lpServices)
376 HeapFree(GetProcessHeap(), 0, lpServices);
377
378 return ERROR_NOT_ENOUGH_MEMORY;
379 }
380
381 /* Return the allocated buffer length in characters */
382 *lpdwDependenciesLength = dwTotalLength;
383
384 /* Copy the service dependencies into the common buffer */
385 lpDest = *lpDependencies;
386 if (lpServices)
387 {
388 memcpy(lpDest,
389 lpServices,
390 dwServicesLength * sizeof(WCHAR));
391
392 lpDest = lpDest + dwServicesLength;
393 }
394
395 /* Copy the group dependencies into the common buffer */
396 if (lpGroups)
397 {
398 lpSrc = lpGroups;
399 while (*lpSrc != 0)
400 {
401 len = wcslen(lpSrc) + 1;
402
403 *lpDest = SC_GROUP_IDENTIFIERW;
404 lpDest++;
405
406 wcscpy(lpDest, lpSrc);
407
408 lpDest = lpDest + len;
409 lpSrc = lpSrc + len;
410 }
411 }
412
413 /* Free the temporary buffers */
414 if (lpGroups)
415 HeapFree(GetProcessHeap(), 0, lpGroups);
416
417 if (lpServices)
418 HeapFree(GetProcessHeap(), 0, lpServices);
419
420 return ERROR_SUCCESS;
421 }
422
423 /* EOF */