1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Service Control Manager
3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: base/system/services/config.c
5c2c66affSColin Finck * PURPOSE: Service configuration interface
6c2c66affSColin Finck * COPYRIGHT: Copyright 2005 Eric Kohl
7c2c66affSColin Finck *
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck /* INCLUDES *****************************************************************/
11c2c66affSColin Finck
12c2c66affSColin Finck #include "services.h"
13c2c66affSColin Finck #include <ntsecapi.h>
14c2c66affSColin Finck
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck
18e5fcda92SEric Kohl struct ustring
19e5fcda92SEric Kohl {
20e5fcda92SEric Kohl DWORD Length;
21e5fcda92SEric Kohl DWORD MaximumLength;
22e5fcda92SEric Kohl unsigned char *Buffer;
23e5fcda92SEric Kohl };
24e5fcda92SEric Kohl
25e5fcda92SEric Kohl NTSTATUS
26e5fcda92SEric Kohl WINAPI
27e5fcda92SEric Kohl SystemFunction005(
28e5fcda92SEric Kohl const struct ustring *in,
29e5fcda92SEric Kohl const struct ustring *key,
30e5fcda92SEric Kohl struct ustring *out);
31e5fcda92SEric Kohl
3276588be0SEric Kohl NTSTATUS
3376588be0SEric Kohl WINAPI
3476588be0SEric Kohl SystemFunction028(
3576588be0SEric Kohl IN PVOID ContextHandle,
3676588be0SEric Kohl OUT LPBYTE SessionKey);
37c2c66affSColin Finck
38c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
39c2c66affSColin Finck
40c2c66affSColin Finck
41c2c66affSColin Finck DWORD
ScmOpenServiceKey(LPWSTR lpServiceName,REGSAM samDesired,PHKEY phKey)42c2c66affSColin Finck ScmOpenServiceKey(LPWSTR lpServiceName,
43c2c66affSColin Finck REGSAM samDesired,
44c2c66affSColin Finck PHKEY phKey)
45c2c66affSColin Finck {
46c2c66affSColin Finck HKEY hServicesKey = NULL;
47c2c66affSColin Finck DWORD dwError;
48c2c66affSColin Finck
49c2c66affSColin Finck *phKey = NULL;
50c2c66affSColin Finck
51c2c66affSColin Finck dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
52c2c66affSColin Finck L"System\\CurrentControlSet\\Services",
53c2c66affSColin Finck 0,
54c2c66affSColin Finck KEY_READ,
55c2c66affSColin Finck &hServicesKey);
56c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
57c2c66affSColin Finck return dwError;
58c2c66affSColin Finck
59c2c66affSColin Finck dwError = RegOpenKeyExW(hServicesKey,
60c2c66affSColin Finck lpServiceName,
61c2c66affSColin Finck 0,
62c2c66affSColin Finck samDesired,
63c2c66affSColin Finck phKey);
64c2c66affSColin Finck
65c2c66affSColin Finck RegCloseKey(hServicesKey);
66c2c66affSColin Finck
67c2c66affSColin Finck return dwError;
68c2c66affSColin Finck }
69c2c66affSColin Finck
70c2c66affSColin Finck
71c2c66affSColin Finck DWORD
ScmCreateServiceKey(LPCWSTR lpServiceName,REGSAM samDesired,PHKEY phKey)72c2c66affSColin Finck ScmCreateServiceKey(LPCWSTR lpServiceName,
73c2c66affSColin Finck REGSAM samDesired,
74c2c66affSColin Finck PHKEY phKey)
75c2c66affSColin Finck {
76c2c66affSColin Finck HKEY hServicesKey = NULL;
77c2c66affSColin Finck DWORD dwDisposition;
78c2c66affSColin Finck DWORD dwError;
79c2c66affSColin Finck
80c2c66affSColin Finck *phKey = NULL;
81c2c66affSColin Finck
82c2c66affSColin Finck dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
83c2c66affSColin Finck L"System\\CurrentControlSet\\Services",
84c2c66affSColin Finck 0,
85c2c66affSColin Finck KEY_READ | KEY_CREATE_SUB_KEY,
86c2c66affSColin Finck &hServicesKey);
87c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
88c2c66affSColin Finck return dwError;
89c2c66affSColin Finck
90c2c66affSColin Finck dwError = RegCreateKeyExW(hServicesKey,
91c2c66affSColin Finck lpServiceName,
92c2c66affSColin Finck 0,
93c2c66affSColin Finck NULL,
94c2c66affSColin Finck REG_OPTION_NON_VOLATILE,
95c2c66affSColin Finck samDesired,
96c2c66affSColin Finck NULL,
97c2c66affSColin Finck phKey,
98c2c66affSColin Finck &dwDisposition);
99c2c66affSColin Finck #if 0
100c2c66affSColin Finck if ((dwError == ERROR_SUCCESS) &&
101c2c66affSColin Finck (dwDisposition == REG_OPENED_EXISTING_KEY))
102c2c66affSColin Finck {
103c2c66affSColin Finck RegCloseKey(*phKey);
104c2c66affSColin Finck *phKey = NULL;
105c2c66affSColin Finck dwError = ERROR_SERVICE_EXISTS;
106c2c66affSColin Finck }
107c2c66affSColin Finck #endif
108c2c66affSColin Finck
109c2c66affSColin Finck RegCloseKey(hServicesKey);
110c2c66affSColin Finck
111c2c66affSColin Finck return dwError;
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck
115c2c66affSColin Finck
116c2c66affSColin Finck DWORD
ScmWriteDependencies(HKEY hServiceKey,LPCWSTR lpDependencies,DWORD dwDependenciesLength)117c2c66affSColin Finck ScmWriteDependencies(HKEY hServiceKey,
118c2c66affSColin Finck LPCWSTR lpDependencies,
119c2c66affSColin Finck DWORD dwDependenciesLength)
120c2c66affSColin Finck {
121c2c66affSColin Finck DWORD dwError = ERROR_SUCCESS;
122c2c66affSColin Finck SIZE_T cchGroupLength = 0;
123c2c66affSColin Finck SIZE_T cchServiceLength = 0;
124c2c66affSColin Finck SIZE_T cchLength;
125c2c66affSColin Finck LPWSTR lpGroupDeps;
126c2c66affSColin Finck LPWSTR lpServiceDeps;
127c2c66affSColin Finck LPCWSTR lpSrc;
128c2c66affSColin Finck LPWSTR lpDst;
129c2c66affSColin Finck
130c2c66affSColin Finck if (*lpDependencies == 0)
131c2c66affSColin Finck {
132c2c66affSColin Finck RegDeleteValueW(hServiceKey,
133c2c66affSColin Finck L"DependOnService");
134c2c66affSColin Finck RegDeleteValueW(hServiceKey,
135c2c66affSColin Finck L"DependOnGroup");
136c2c66affSColin Finck }
137c2c66affSColin Finck else
138c2c66affSColin Finck {
139c2c66affSColin Finck lpGroupDeps = HeapAlloc(GetProcessHeap(),
140c2c66affSColin Finck HEAP_ZERO_MEMORY,
141c2c66affSColin Finck (dwDependenciesLength + 2) * sizeof(WCHAR));
142c2c66affSColin Finck if (lpGroupDeps == NULL)
143c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY;
144c2c66affSColin Finck
145c2c66affSColin Finck lpSrc = lpDependencies;
146c2c66affSColin Finck lpDst = lpGroupDeps;
147c2c66affSColin Finck while (*lpSrc != 0)
148c2c66affSColin Finck {
149c2c66affSColin Finck cchLength = wcslen(lpSrc) + 1;
150c2c66affSColin Finck if (*lpSrc == SC_GROUP_IDENTIFIERW)
151c2c66affSColin Finck {
152c2c66affSColin Finck lpSrc++;
153c2c66affSColin Finck cchLength--;
154c2c66affSColin Finck cchGroupLength += cchLength;
155c2c66affSColin Finck wcscpy(lpDst, lpSrc);
156c2c66affSColin Finck lpDst = lpDst + cchLength;
157c2c66affSColin Finck }
158c2c66affSColin Finck
159c2c66affSColin Finck lpSrc = lpSrc + cchLength;
160c2c66affSColin Finck }
161c2c66affSColin Finck *lpDst = 0;
162c2c66affSColin Finck lpDst++;
163c2c66affSColin Finck cchGroupLength++;
164c2c66affSColin Finck
165c2c66affSColin Finck lpSrc = lpDependencies;
166c2c66affSColin Finck lpServiceDeps = lpDst;
167c2c66affSColin Finck while (*lpSrc != 0)
168c2c66affSColin Finck {
169c2c66affSColin Finck cchLength = wcslen(lpSrc) + 1;
170c2c66affSColin Finck if (*lpSrc != SC_GROUP_IDENTIFIERW)
171c2c66affSColin Finck {
172c2c66affSColin Finck cchServiceLength += cchLength;
173c2c66affSColin Finck wcscpy(lpDst, lpSrc);
174c2c66affSColin Finck lpDst = lpDst + cchLength;
175c2c66affSColin Finck }
176c2c66affSColin Finck
177c2c66affSColin Finck lpSrc = lpSrc + cchLength;
178c2c66affSColin Finck }
179c2c66affSColin Finck *lpDst = 0;
180c2c66affSColin Finck cchServiceLength++;
181c2c66affSColin Finck
182c2c66affSColin Finck if (cchGroupLength > 1)
183c2c66affSColin Finck {
184c2c66affSColin Finck dwError = RegSetValueExW(hServiceKey,
185c2c66affSColin Finck L"DependOnGroup",
186c2c66affSColin Finck 0,
187c2c66affSColin Finck REG_MULTI_SZ,
188c2c66affSColin Finck (LPBYTE)lpGroupDeps,
189c2c66affSColin Finck (DWORD)(cchGroupLength * sizeof(WCHAR)));
190c2c66affSColin Finck }
191c2c66affSColin Finck else
192c2c66affSColin Finck {
193c2c66affSColin Finck RegDeleteValueW(hServiceKey,
194c2c66affSColin Finck L"DependOnGroup");
195c2c66affSColin Finck }
196c2c66affSColin Finck
197c2c66affSColin Finck if (dwError == ERROR_SUCCESS)
198c2c66affSColin Finck {
199c2c66affSColin Finck if (cchServiceLength > 1)
200c2c66affSColin Finck {
201c2c66affSColin Finck dwError = RegSetValueExW(hServiceKey,
202c2c66affSColin Finck L"DependOnService",
203c2c66affSColin Finck 0,
204c2c66affSColin Finck REG_MULTI_SZ,
205c2c66affSColin Finck (LPBYTE)lpServiceDeps,
206c2c66affSColin Finck (DWORD)(cchServiceLength * sizeof(WCHAR)));
207c2c66affSColin Finck }
208c2c66affSColin Finck else
209c2c66affSColin Finck {
210c2c66affSColin Finck RegDeleteValueW(hServiceKey,
211c2c66affSColin Finck L"DependOnService");
212c2c66affSColin Finck }
213c2c66affSColin Finck }
214c2c66affSColin Finck
215c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpGroupDeps);
216c2c66affSColin Finck }
217c2c66affSColin Finck
218c2c66affSColin Finck return dwError;
219c2c66affSColin Finck }
220c2c66affSColin Finck
221c2c66affSColin Finck
222c2c66affSColin Finck DWORD
ScmMarkServiceForDelete(PSERVICE pService)223c2c66affSColin Finck ScmMarkServiceForDelete(PSERVICE pService)
224c2c66affSColin Finck {
225c2c66affSColin Finck HKEY hServiceKey = NULL;
226c2c66affSColin Finck DWORD dwValue = 1;
227c2c66affSColin Finck DWORD dwError;
228c2c66affSColin Finck
229c2c66affSColin Finck DPRINT("ScmMarkServiceForDelete() called\n");
230c2c66affSColin Finck
231c2c66affSColin Finck dwError = ScmOpenServiceKey(pService->lpServiceName,
232c2c66affSColin Finck KEY_WRITE,
233c2c66affSColin Finck &hServiceKey);
234c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
235c2c66affSColin Finck return dwError;
236c2c66affSColin Finck
237c2c66affSColin Finck dwError = RegSetValueExW(hServiceKey,
238c2c66affSColin Finck L"DeleteFlag",
239c2c66affSColin Finck 0,
240c2c66affSColin Finck REG_DWORD,
241c2c66affSColin Finck (LPBYTE)&dwValue,
242c2c66affSColin Finck sizeof(DWORD));
243c2c66affSColin Finck
244c2c66affSColin Finck RegCloseKey(hServiceKey);
245c2c66affSColin Finck
246c2c66affSColin Finck return dwError;
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck
250c2c66affSColin Finck BOOL
ScmIsDeleteFlagSet(HKEY hServiceKey)251c2c66affSColin Finck ScmIsDeleteFlagSet(HKEY hServiceKey)
252c2c66affSColin Finck {
253c2c66affSColin Finck DWORD dwError;
254c2c66affSColin Finck DWORD dwType;
255c2c66affSColin Finck DWORD dwFlag;
256c2c66affSColin Finck DWORD dwSize = sizeof(DWORD);
257c2c66affSColin Finck
258c2c66affSColin Finck dwError = RegQueryValueExW(hServiceKey,
259c2c66affSColin Finck L"DeleteFlag",
260c2c66affSColin Finck 0,
261c2c66affSColin Finck &dwType,
262c2c66affSColin Finck (LPBYTE)&dwFlag,
263c2c66affSColin Finck &dwSize);
264c2c66affSColin Finck
265c2c66affSColin Finck return (dwError == ERROR_SUCCESS);
266c2c66affSColin Finck }
267c2c66affSColin Finck
268c2c66affSColin Finck
269c2c66affSColin Finck DWORD
ScmReadString(HKEY hServiceKey,LPCWSTR lpValueName,LPWSTR * lpValue)270c2c66affSColin Finck ScmReadString(HKEY hServiceKey,
271c2c66affSColin Finck LPCWSTR lpValueName,
272c2c66affSColin Finck LPWSTR *lpValue)
273c2c66affSColin Finck {
274c2c66affSColin Finck DWORD dwError = 0;
275c2c66affSColin Finck DWORD dwSize = 0;
276c2c66affSColin Finck DWORD dwType = 0;
277c2c66affSColin Finck LPWSTR ptr = NULL;
278c2c66affSColin Finck LPWSTR expanded = NULL;
279c2c66affSColin Finck
280c2c66affSColin Finck *lpValue = NULL;
281c2c66affSColin Finck
282c2c66affSColin Finck dwError = RegQueryValueExW(hServiceKey,
283c2c66affSColin Finck lpValueName,
284c2c66affSColin Finck 0,
285c2c66affSColin Finck &dwType,
286c2c66affSColin Finck NULL,
287c2c66affSColin Finck &dwSize);
288c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
289c2c66affSColin Finck return dwError;
290c2c66affSColin Finck
291c2c66affSColin Finck ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
292c2c66affSColin Finck if (ptr == NULL)
293c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY;
294c2c66affSColin Finck
295c2c66affSColin Finck dwError = RegQueryValueExW(hServiceKey,
296c2c66affSColin Finck lpValueName,
297c2c66affSColin Finck 0,
298c2c66affSColin Finck &dwType,
299c2c66affSColin Finck (LPBYTE)ptr,
300c2c66affSColin Finck &dwSize);
301c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
302c2c66affSColin Finck {
303c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ptr);
304c2c66affSColin Finck return dwError;
305c2c66affSColin Finck }
306c2c66affSColin Finck
307c2c66affSColin Finck if (dwType == REG_EXPAND_SZ)
308c2c66affSColin Finck {
309c2c66affSColin Finck /* Expand the value... */
310c2c66affSColin Finck dwSize = ExpandEnvironmentStringsW(ptr, NULL, 0);
311c2c66affSColin Finck if (dwSize > 0)
312c2c66affSColin Finck {
313c2c66affSColin Finck expanded = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR));
314c2c66affSColin Finck if (expanded)
315c2c66affSColin Finck {
316c2c66affSColin Finck if (dwSize == ExpandEnvironmentStringsW(ptr, expanded, dwSize))
317c2c66affSColin Finck {
318c2c66affSColin Finck *lpValue = expanded;
319c2c66affSColin Finck dwError = ERROR_SUCCESS;
320c2c66affSColin Finck }
321c2c66affSColin Finck else
322c2c66affSColin Finck {
323c2c66affSColin Finck dwError = GetLastError();
324c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, expanded);
325c2c66affSColin Finck }
326c2c66affSColin Finck }
327c2c66affSColin Finck else
328c2c66affSColin Finck {
329c2c66affSColin Finck dwError = ERROR_NOT_ENOUGH_MEMORY;
330c2c66affSColin Finck }
331c2c66affSColin Finck }
332c2c66affSColin Finck else
333c2c66affSColin Finck {
334c2c66affSColin Finck dwError = GetLastError();
335c2c66affSColin Finck }
336c2c66affSColin Finck
337c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ptr);
338c2c66affSColin Finck }
339c2c66affSColin Finck else
340c2c66affSColin Finck {
341c2c66affSColin Finck *lpValue = ptr;
342c2c66affSColin Finck }
343c2c66affSColin Finck
344c2c66affSColin Finck return dwError;
345c2c66affSColin Finck }
346c2c66affSColin Finck
347c2c66affSColin Finck
348c2c66affSColin Finck DWORD
ScmReadDependencies(HKEY hServiceKey,LPWSTR * lpDependencies,DWORD * lpdwDependenciesLength)349c2c66affSColin Finck ScmReadDependencies(HKEY hServiceKey,
350c2c66affSColin Finck LPWSTR *lpDependencies,
351c2c66affSColin Finck DWORD *lpdwDependenciesLength)
352c2c66affSColin Finck {
353c2c66affSColin Finck LPWSTR lpGroups = NULL;
354c2c66affSColin Finck LPWSTR lpServices = NULL;
355c2c66affSColin Finck SIZE_T cchGroupsLength = 0;
356c2c66affSColin Finck SIZE_T cchServicesLength = 0;
357c2c66affSColin Finck LPWSTR lpSrc;
358c2c66affSColin Finck LPWSTR lpDest;
359c2c66affSColin Finck SIZE_T cchLength;
360c2c66affSColin Finck SIZE_T cchTotalLength;
361c2c66affSColin Finck
362c2c66affSColin Finck *lpDependencies = NULL;
363c2c66affSColin Finck *lpdwDependenciesLength = 0;
364c2c66affSColin Finck
365c2c66affSColin Finck /* Read the dependency values */
366c2c66affSColin Finck ScmReadString(hServiceKey,
367c2c66affSColin Finck L"DependOnGroup",
368c2c66affSColin Finck &lpGroups);
369c2c66affSColin Finck
370c2c66affSColin Finck ScmReadString(hServiceKey,
371c2c66affSColin Finck L"DependOnService",
372c2c66affSColin Finck &lpServices);
373c2c66affSColin Finck
374c2c66affSColin Finck /* Leave, if there are no dependencies */
375c2c66affSColin Finck if (lpGroups == NULL && lpServices == NULL)
376c2c66affSColin Finck return ERROR_SUCCESS;
377c2c66affSColin Finck
378c2c66affSColin Finck /* Determine the total buffer size for the dependencies */
379c2c66affSColin Finck if (lpGroups)
380c2c66affSColin Finck {
381c2c66affSColin Finck DPRINT("Groups:\n");
382c2c66affSColin Finck lpSrc = lpGroups;
383c2c66affSColin Finck while (*lpSrc != 0)
384c2c66affSColin Finck {
385c2c66affSColin Finck DPRINT(" %S\n", lpSrc);
386c2c66affSColin Finck
387c2c66affSColin Finck cchLength = wcslen(lpSrc) + 1;
388c2c66affSColin Finck cchGroupsLength += cchLength + 1;
389c2c66affSColin Finck
390c2c66affSColin Finck lpSrc = lpSrc + cchLength;
391c2c66affSColin Finck }
392c2c66affSColin Finck }
393c2c66affSColin Finck
394c2c66affSColin Finck if (lpServices)
395c2c66affSColin Finck {
396c2c66affSColin Finck DPRINT("Services:\n");
397c2c66affSColin Finck lpSrc = lpServices;
398c2c66affSColin Finck while (*lpSrc != 0)
399c2c66affSColin Finck {
400c2c66affSColin Finck DPRINT(" %S\n", lpSrc);
401c2c66affSColin Finck
402c2c66affSColin Finck cchLength = wcslen(lpSrc) + 1;
403c2c66affSColin Finck cchServicesLength += cchLength;
404c2c66affSColin Finck
405c2c66affSColin Finck lpSrc = lpSrc + cchLength;
406c2c66affSColin Finck }
407c2c66affSColin Finck }
408c2c66affSColin Finck
409c2c66affSColin Finck cchTotalLength = cchGroupsLength + cchServicesLength + 1;
410c2c66affSColin Finck DPRINT("cchTotalLength: %lu\n", cchTotalLength);
411c2c66affSColin Finck
412c2c66affSColin Finck /* Allocate the common buffer for the dependencies */
413c2c66affSColin Finck *lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cchTotalLength * sizeof(WCHAR));
414c2c66affSColin Finck if (*lpDependencies == NULL)
415c2c66affSColin Finck {
416c2c66affSColin Finck if (lpGroups)
417c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpGroups);
418c2c66affSColin Finck
419c2c66affSColin Finck if (lpServices)
420c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpServices);
421c2c66affSColin Finck
422c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY;
423c2c66affSColin Finck }
424c2c66affSColin Finck
425c2c66affSColin Finck /* Return the allocated buffer length in characters */
426c2c66affSColin Finck *lpdwDependenciesLength = (DWORD)cchTotalLength;
427c2c66affSColin Finck
428c2c66affSColin Finck /* Copy the service dependencies into the common buffer */
429c2c66affSColin Finck lpDest = *lpDependencies;
430c2c66affSColin Finck if (lpServices)
431c2c66affSColin Finck {
432c2c66affSColin Finck memcpy(lpDest,
433c2c66affSColin Finck lpServices,
434c2c66affSColin Finck cchServicesLength * sizeof(WCHAR));
435c2c66affSColin Finck
436c2c66affSColin Finck lpDest = lpDest + cchServicesLength;
437c2c66affSColin Finck }
438c2c66affSColin Finck
439c2c66affSColin Finck /* Copy the group dependencies into the common buffer */
440c2c66affSColin Finck if (lpGroups)
441c2c66affSColin Finck {
442c2c66affSColin Finck lpSrc = lpGroups;
443c2c66affSColin Finck while (*lpSrc != 0)
444c2c66affSColin Finck {
445c2c66affSColin Finck cchLength = wcslen(lpSrc) + 1;
446c2c66affSColin Finck
447c2c66affSColin Finck *lpDest = SC_GROUP_IDENTIFIERW;
448c2c66affSColin Finck lpDest++;
449c2c66affSColin Finck
450c2c66affSColin Finck wcscpy(lpDest, lpSrc);
451c2c66affSColin Finck
452c2c66affSColin Finck lpDest = lpDest + cchLength;
453c2c66affSColin Finck lpSrc = lpSrc + cchLength;
454c2c66affSColin Finck }
455c2c66affSColin Finck }
456c2c66affSColin Finck
457c2c66affSColin Finck /* Free the temporary buffers */
458c2c66affSColin Finck if (lpGroups)
459c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpGroups);
460c2c66affSColin Finck
461c2c66affSColin Finck if (lpServices)
462c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, lpServices);
463c2c66affSColin Finck
464c2c66affSColin Finck return ERROR_SUCCESS;
465c2c66affSColin Finck }
466c2c66affSColin Finck
467c2c66affSColin Finck
468c2c66affSColin Finck DWORD
ScmSetServicePassword(IN PCWSTR pszServiceName,IN PCWSTR pszPassword)469c2c66affSColin Finck ScmSetServicePassword(
470c2c66affSColin Finck IN PCWSTR pszServiceName,
471c2c66affSColin Finck IN PCWSTR pszPassword)
472c2c66affSColin Finck {
473c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
474c2c66affSColin Finck LSA_HANDLE PolicyHandle = NULL;
475c2c66affSColin Finck UNICODE_STRING ServiceName = {0, 0, NULL};
476c2c66affSColin Finck UNICODE_STRING Password;
477c2c66affSColin Finck NTSTATUS Status;
478c2c66affSColin Finck DWORD dwError = ERROR_SUCCESS;
479*5d8e8348STimo Kreuzer SIZE_T ServiceNameLength;
480c2c66affSColin Finck
481c2c66affSColin Finck RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
482c2c66affSColin Finck
483*5d8e8348STimo Kreuzer ServiceNameLength = wcslen(pszServiceName);
484*5d8e8348STimo Kreuzer if (ServiceNameLength > (UNICODE_STRING_MAX_CHARS - 4))
485*5d8e8348STimo Kreuzer {
486*5d8e8348STimo Kreuzer return ERROR_INVALID_PARAMETER;
487*5d8e8348STimo Kreuzer }
488*5d8e8348STimo Kreuzer
489c2c66affSColin Finck Status = LsaOpenPolicy(NULL,
490c2c66affSColin Finck &ObjectAttributes,
491c2c66affSColin Finck POLICY_CREATE_SECRET,
492c2c66affSColin Finck &PolicyHandle);
493c2c66affSColin Finck if (!NT_SUCCESS(Status))
494c2c66affSColin Finck return RtlNtStatusToDosError(Status);
495c2c66affSColin Finck
496*5d8e8348STimo Kreuzer ServiceName.Length = ((USHORT)ServiceNameLength + 4) * sizeof(WCHAR);
497c2c66affSColin Finck ServiceName.MaximumLength = ServiceName.Length + sizeof(WCHAR);
498c2c66affSColin Finck ServiceName.Buffer = HeapAlloc(GetProcessHeap(),
499c2c66affSColin Finck HEAP_ZERO_MEMORY,
500c2c66affSColin Finck ServiceName.MaximumLength);
501c2c66affSColin Finck if (ServiceName.Buffer == NULL)
502c2c66affSColin Finck return ERROR_NOT_ENOUGH_MEMORY;
503c2c66affSColin Finck
504c2c66affSColin Finck wcscpy(ServiceName.Buffer, L"_SC_");
505c2c66affSColin Finck wcscat(ServiceName.Buffer, pszServiceName);
506c2c66affSColin Finck
507c2c66affSColin Finck RtlInitUnicodeString(&Password, pszPassword);
508c2c66affSColin Finck
509c2c66affSColin Finck Status = LsaStorePrivateData(PolicyHandle,
510c2c66affSColin Finck &ServiceName,
511c2c66affSColin Finck pszPassword ? &Password : NULL);
512c2c66affSColin Finck if (!NT_SUCCESS(Status))
513c2c66affSColin Finck {
514c2c66affSColin Finck dwError = RtlNtStatusToDosError(Status);
515c2c66affSColin Finck goto done;
516c2c66affSColin Finck }
517c2c66affSColin Finck
518c2c66affSColin Finck done:
519c2c66affSColin Finck if (ServiceName.Buffer != NULL)
520c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, ServiceName.Buffer);
521c2c66affSColin Finck
522c2c66affSColin Finck if (PolicyHandle != NULL)
523c2c66affSColin Finck LsaClose(PolicyHandle);
524c2c66affSColin Finck
525c2c66affSColin Finck return dwError;
526c2c66affSColin Finck }
527c2c66affSColin Finck
528c2c66affSColin Finck
529c2c66affSColin Finck DWORD
ScmWriteSecurityDescriptor(_In_ HKEY hServiceKey,_In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)530c2c66affSColin Finck ScmWriteSecurityDescriptor(
531c2c66affSColin Finck _In_ HKEY hServiceKey,
532c2c66affSColin Finck _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
533c2c66affSColin Finck {
534c2c66affSColin Finck HKEY hSecurityKey = NULL;
535c2c66affSColin Finck DWORD dwDisposition;
536c2c66affSColin Finck DWORD dwError;
537c2c66affSColin Finck
538c2c66affSColin Finck DPRINT("ScmWriteSecurityDescriptor(%p %p)\n", hServiceKey, pSecurityDescriptor);
539c2c66affSColin Finck
540c2c66affSColin Finck dwError = RegCreateKeyExW(hServiceKey,
541c2c66affSColin Finck L"Security",
542c2c66affSColin Finck 0,
543c2c66affSColin Finck NULL,
544c2c66affSColin Finck REG_OPTION_NON_VOLATILE,
545c2c66affSColin Finck KEY_SET_VALUE,
546c2c66affSColin Finck NULL,
547c2c66affSColin Finck &hSecurityKey,
548c2c66affSColin Finck &dwDisposition);
549c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
550c2c66affSColin Finck return dwError;
551c2c66affSColin Finck
552c2c66affSColin Finck dwError = RegSetValueExW(hSecurityKey,
553c2c66affSColin Finck L"Security",
554c2c66affSColin Finck 0,
555c2c66affSColin Finck REG_BINARY,
556c2c66affSColin Finck (LPBYTE)pSecurityDescriptor,
557c2c66affSColin Finck RtlLengthSecurityDescriptor(pSecurityDescriptor));
558c2c66affSColin Finck
559c2c66affSColin Finck RegCloseKey(hSecurityKey);
560c2c66affSColin Finck
561c2c66affSColin Finck return dwError;
562c2c66affSColin Finck }
563c2c66affSColin Finck
564c2c66affSColin Finck
565c2c66affSColin Finck DWORD
ScmReadSecurityDescriptor(_In_ HKEY hServiceKey,_Out_ PSECURITY_DESCRIPTOR * ppSecurityDescriptor)566c2c66affSColin Finck ScmReadSecurityDescriptor(
567c2c66affSColin Finck _In_ HKEY hServiceKey,
568c2c66affSColin Finck _Out_ PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
569c2c66affSColin Finck {
570c2c66affSColin Finck PSECURITY_DESCRIPTOR pRelativeSD = NULL;
571c2c66affSColin Finck HKEY hSecurityKey = NULL;
572c2c66affSColin Finck DWORD dwBufferLength = 0;
573c2c66affSColin Finck DWORD dwType;
574c2c66affSColin Finck DWORD dwError;
575c2c66affSColin Finck
576c2c66affSColin Finck DPRINT("ScmReadSecurityDescriptor(%p %p)\n", hServiceKey, ppSecurityDescriptor);
577c2c66affSColin Finck
578c2c66affSColin Finck *ppSecurityDescriptor = NULL;
579c2c66affSColin Finck
580c2c66affSColin Finck dwError = RegOpenKeyExW(hServiceKey,
581c2c66affSColin Finck L"Security",
582c2c66affSColin Finck 0,
583c2c66affSColin Finck KEY_QUERY_VALUE,
584c2c66affSColin Finck &hSecurityKey);
585c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
586c2c66affSColin Finck {
587c2c66affSColin Finck DPRINT("RegOpenKeyExW() failed (Error %lu)\n", dwError);
588c2c66affSColin Finck
589c2c66affSColin Finck /* Do not fail if the Security key does not exist */
590c2c66affSColin Finck if (dwError == ERROR_FILE_NOT_FOUND)
591c2c66affSColin Finck dwError = ERROR_SUCCESS;
592c2c66affSColin Finck goto done;
593c2c66affSColin Finck }
594c2c66affSColin Finck
595c2c66affSColin Finck dwError = RegQueryValueExW(hSecurityKey,
596c2c66affSColin Finck L"Security",
597c2c66affSColin Finck 0,
598c2c66affSColin Finck &dwType,
599c2c66affSColin Finck NULL,
600c2c66affSColin Finck &dwBufferLength);
601c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
602c2c66affSColin Finck {
603c2c66affSColin Finck DPRINT("RegQueryValueExW() failed (Error %lu)\n", dwError);
604c2c66affSColin Finck
605c2c66affSColin Finck /* Do not fail if the Security value does not exist */
606c2c66affSColin Finck if (dwError == ERROR_FILE_NOT_FOUND)
607c2c66affSColin Finck dwError = ERROR_SUCCESS;
608c2c66affSColin Finck goto done;
609c2c66affSColin Finck }
610c2c66affSColin Finck
611c2c66affSColin Finck DPRINT("dwBufferLength: %lu\n", dwBufferLength);
612c2c66affSColin Finck pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
613c2c66affSColin Finck HEAP_ZERO_MEMORY,
614c2c66affSColin Finck dwBufferLength);
615c2c66affSColin Finck if (pRelativeSD == NULL)
616c2c66affSColin Finck {
617c2c66affSColin Finck return ERROR_OUTOFMEMORY;
618c2c66affSColin Finck }
619c2c66affSColin Finck
620c2c66affSColin Finck DPRINT("pRelativeSD: %lu\n", pRelativeSD);
621c2c66affSColin Finck dwError = RegQueryValueExW(hSecurityKey,
622c2c66affSColin Finck L"Security",
623c2c66affSColin Finck 0,
624c2c66affSColin Finck &dwType,
625c2c66affSColin Finck (LPBYTE)pRelativeSD,
626c2c66affSColin Finck &dwBufferLength);
627c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
628c2c66affSColin Finck {
629c2c66affSColin Finck goto done;
630c2c66affSColin Finck }
631c2c66affSColin Finck
632c2c66affSColin Finck *ppSecurityDescriptor = pRelativeSD;
633c2c66affSColin Finck
634c2c66affSColin Finck done:
635c2c66affSColin Finck if (dwError != ERROR_SUCCESS && pRelativeSD != NULL)
636c2c66affSColin Finck RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
637c2c66affSColin Finck
638c2c66affSColin Finck if (hSecurityKey != NULL)
639c2c66affSColin Finck RegCloseKey(hSecurityKey);
640c2c66affSColin Finck
641c2c66affSColin Finck return dwError;
642c2c66affSColin Finck }
643c2c66affSColin Finck
644c2c66affSColin Finck
645c2c66affSColin Finck DWORD
ScmDeleteRegKey(_In_ HKEY hKey,_In_ PCWSTR pszSubKey)646c2c66affSColin Finck ScmDeleteRegKey(
647c2c66affSColin Finck _In_ HKEY hKey,
648c2c66affSColin Finck _In_ PCWSTR pszSubKey)
649c2c66affSColin Finck {
650c2c66affSColin Finck DWORD dwMaxSubkeyLen, dwMaxValueLen;
651c2c66affSColin Finck DWORD dwMaxLen, dwSize;
652c2c66affSColin Finck PWSTR pszName = NULL;
653c2c66affSColin Finck HKEY hSubKey;
654c2c66affSColin Finck DWORD dwError;
655c2c66affSColin Finck
656c2c66affSColin Finck dwError = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
657c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
658c2c66affSColin Finck return dwError;
659c2c66affSColin Finck
660c2c66affSColin Finck /* Get maximum length of key and value names */
661c2c66affSColin Finck dwError = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
662c2c66affSColin Finck &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
663c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
664c2c66affSColin Finck goto done;
665c2c66affSColin Finck
666c2c66affSColin Finck dwMaxSubkeyLen++;
667c2c66affSColin Finck dwMaxValueLen++;
668c2c66affSColin Finck dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
669c2c66affSColin Finck
670c2c66affSColin Finck /* Allocate the name buffer */
671c2c66affSColin Finck pszName = HeapAlloc(GetProcessHeap(), 0, dwMaxLen * sizeof(WCHAR));
672c2c66affSColin Finck if (pszName == NULL)
673c2c66affSColin Finck {
674c2c66affSColin Finck dwError = ERROR_NOT_ENOUGH_MEMORY;
675c2c66affSColin Finck goto done;
676c2c66affSColin Finck }
677c2c66affSColin Finck
678c2c66affSColin Finck /* Recursively delete all the subkeys */
679c2c66affSColin Finck while (TRUE)
680c2c66affSColin Finck {
681c2c66affSColin Finck dwSize = dwMaxLen;
682c2c66affSColin Finck if (RegEnumKeyExW(hSubKey, 0, pszName, &dwSize,
683c2c66affSColin Finck NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
684c2c66affSColin Finck {
685c2c66affSColin Finck break;
686c2c66affSColin Finck }
687c2c66affSColin Finck
688c2c66affSColin Finck dwError = ScmDeleteRegKey(hSubKey, pszName);
689c2c66affSColin Finck if (dwError != ERROR_SUCCESS)
690c2c66affSColin Finck goto done;
691c2c66affSColin Finck }
692c2c66affSColin Finck
693c2c66affSColin Finck done:
694c2c66affSColin Finck if (pszName != NULL)
695c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, pszName);
696c2c66affSColin Finck
697c2c66affSColin Finck RegCloseKey(hSubKey);
698c2c66affSColin Finck
699c2c66affSColin Finck /* Finally delete the key */
700c2c66affSColin Finck if (dwError == ERROR_SUCCESS)
701c2c66affSColin Finck dwError = RegDeleteKeyW(hKey, pszSubKey);
702c2c66affSColin Finck
703c2c66affSColin Finck return dwError;
704c2c66affSColin Finck }
705c2c66affSColin Finck
7065e2c4657SEric Kohl
7075e2c4657SEric Kohl DWORD
ScmDecryptPassword(_In_ PVOID ContextHandle,_In_ PBYTE pPassword,_In_ DWORD dwPasswordSize,_Out_ PWSTR * pClearTextPassword)7085e2c4657SEric Kohl ScmDecryptPassword(
7094cae3498SEric Kohl _In_ PVOID ContextHandle,
7105e2c4657SEric Kohl _In_ PBYTE pPassword,
7115e2c4657SEric Kohl _In_ DWORD dwPasswordSize,
7125e2c4657SEric Kohl _Out_ PWSTR *pClearTextPassword)
7135e2c4657SEric Kohl {
714e5fcda92SEric Kohl struct ustring inData, keyData, outData;
71576588be0SEric Kohl BYTE SessionKey[16];
7165e2c4657SEric Kohl PWSTR pBuffer;
717e5fcda92SEric Kohl NTSTATUS Status;
7185e2c4657SEric Kohl
71976588be0SEric Kohl /* Get the session key */
7204cae3498SEric Kohl Status = SystemFunction028(ContextHandle,
72176588be0SEric Kohl SessionKey);
72276588be0SEric Kohl if (!NT_SUCCESS(Status))
72376588be0SEric Kohl {
72476588be0SEric Kohl DPRINT1("SystemFunction028 failed (Status 0x%08lx)\n", Status);
72576588be0SEric Kohl return RtlNtStatusToDosError(Status);
72676588be0SEric Kohl }
72776588be0SEric Kohl
728e5fcda92SEric Kohl inData.Length = dwPasswordSize;
729e5fcda92SEric Kohl inData.MaximumLength = inData.Length;
730e5fcda92SEric Kohl inData.Buffer = pPassword;
731e5fcda92SEric Kohl
73276588be0SEric Kohl keyData.Length = sizeof(SessionKey);
733e5fcda92SEric Kohl keyData.MaximumLength = keyData.Length;
73476588be0SEric Kohl keyData.Buffer = SessionKey;
735e5fcda92SEric Kohl
736e5fcda92SEric Kohl outData.Length = 0;
737e5fcda92SEric Kohl outData.MaximumLength = 0;
738e5fcda92SEric Kohl outData.Buffer = NULL;
739e5fcda92SEric Kohl
740e5fcda92SEric Kohl /* Get the required buffer size */
741e5fcda92SEric Kohl Status = SystemFunction005(&inData,
742e5fcda92SEric Kohl &keyData,
743e5fcda92SEric Kohl &outData);
744e5fcda92SEric Kohl if (Status != STATUS_BUFFER_TOO_SMALL)
745e5fcda92SEric Kohl {
746e5fcda92SEric Kohl DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status);
747e5fcda92SEric Kohl return RtlNtStatusToDosError(Status);
748e5fcda92SEric Kohl }
749e5fcda92SEric Kohl
750e5fcda92SEric Kohl /* Allocate a buffer for the clear text password */
751e5fcda92SEric Kohl pBuffer = HeapAlloc(GetProcessHeap(), 0, outData.Length);
7525e2c4657SEric Kohl if (pBuffer == NULL)
7535e2c4657SEric Kohl return ERROR_OUTOFMEMORY;
7545e2c4657SEric Kohl
755e5fcda92SEric Kohl outData.MaximumLength = outData.Length;
756e5fcda92SEric Kohl outData.Buffer = (unsigned char *)pBuffer;
757e5fcda92SEric Kohl
7585e2c4657SEric Kohl /* Decrypt the password */
759e5fcda92SEric Kohl Status = SystemFunction005(&inData,
760e5fcda92SEric Kohl &keyData,
761e5fcda92SEric Kohl &outData);
762e5fcda92SEric Kohl if (!NT_SUCCESS(Status))
763e5fcda92SEric Kohl {
764e5fcda92SEric Kohl DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status);
765e5fcda92SEric Kohl HeapFree(GetProcessHeap(), 0, pBuffer);
766e5fcda92SEric Kohl return RtlNtStatusToDosError(Status);
767e5fcda92SEric Kohl }
7685e2c4657SEric Kohl
7695e2c4657SEric Kohl *pClearTextPassword = pBuffer;
7705e2c4657SEric Kohl
7715e2c4657SEric Kohl return ERROR_SUCCESS;
7725e2c4657SEric Kohl }
7735e2c4657SEric Kohl
774c2c66affSColin Finck /* EOF */
775