xref: /reactos/base/system/services/config.c (revision 5d8e8348)
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