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
10 /* INCLUDES *****************************************************************/
20 RtlLengthSecurityDescriptor(
21 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor
);
23 /* FUNCTIONS *****************************************************************/
27 ScmOpenServiceKey(LPWSTR lpServiceName
,
31 HKEY hServicesKey
= NULL
;
36 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
37 L
"System\\CurrentControlSet\\Services",
41 if (dwError
!= ERROR_SUCCESS
)
44 dwError
= RegOpenKeyExW(hServicesKey
,
50 RegCloseKey(hServicesKey
);
57 ScmCreateServiceKey(LPCWSTR lpServiceName
,
61 HKEY hServicesKey
= NULL
;
67 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
68 L
"System\\CurrentControlSet\\Services",
70 KEY_READ
| KEY_CREATE_SUB_KEY
,
72 if (dwError
!= ERROR_SUCCESS
)
75 dwError
= RegCreateKeyExW(hServicesKey
,
79 REG_OPTION_NON_VOLATILE
,
85 if ((dwError
== ERROR_SUCCESS
) &&
86 (dwDisposition
== REG_OPENED_EXISTING_KEY
))
90 dwError
= ERROR_SERVICE_EXISTS
;
94 RegCloseKey(hServicesKey
);
102 ScmWriteDependencies(HKEY hServiceKey
,
103 LPCWSTR lpDependencies
,
104 DWORD dwDependenciesLength
)
106 DWORD dwError
= ERROR_SUCCESS
;
107 SIZE_T cchGroupLength
= 0;
108 SIZE_T cchServiceLength
= 0;
111 LPWSTR lpServiceDeps
;
115 if (*lpDependencies
== 0)
117 RegDeleteValueW(hServiceKey
,
119 RegDeleteValueW(hServiceKey
,
124 lpGroupDeps
= HeapAlloc(GetProcessHeap(),
126 (dwDependenciesLength
+ 2) * sizeof(WCHAR
));
127 if (lpGroupDeps
== NULL
)
128 return ERROR_NOT_ENOUGH_MEMORY
;
130 lpSrc
= lpDependencies
;
134 cchLength
= wcslen(lpSrc
) + 1;
135 if (*lpSrc
== SC_GROUP_IDENTIFIERW
)
139 cchGroupLength
+= cchLength
;
140 wcscpy(lpDst
, lpSrc
);
141 lpDst
= lpDst
+ cchLength
;
144 lpSrc
= lpSrc
+ cchLength
;
150 lpSrc
= lpDependencies
;
151 lpServiceDeps
= lpDst
;
154 cchLength
= wcslen(lpSrc
) + 1;
155 if (*lpSrc
!= SC_GROUP_IDENTIFIERW
)
157 cchServiceLength
+= cchLength
;
158 wcscpy(lpDst
, lpSrc
);
159 lpDst
= lpDst
+ cchLength
;
162 lpSrc
= lpSrc
+ cchLength
;
167 if (cchGroupLength
> 1)
169 dwError
= RegSetValueExW(hServiceKey
,
174 (DWORD
)(cchGroupLength
* sizeof(WCHAR
)));
178 RegDeleteValueW(hServiceKey
,
182 if (dwError
== ERROR_SUCCESS
)
184 if (cchServiceLength
> 1)
186 dwError
= RegSetValueExW(hServiceKey
,
190 (LPBYTE
)lpServiceDeps
,
191 (DWORD
)(cchServiceLength
* sizeof(WCHAR
)));
195 RegDeleteValueW(hServiceKey
,
200 HeapFree(GetProcessHeap(), 0, lpGroupDeps
);
208 ScmMarkServiceForDelete(PSERVICE pService
)
210 HKEY hServiceKey
= NULL
;
214 DPRINT("ScmMarkServiceForDelete() called\n");
216 dwError
= ScmOpenServiceKey(pService
->lpServiceName
,
219 if (dwError
!= ERROR_SUCCESS
)
222 dwError
= RegSetValueExW(hServiceKey
,
229 RegCloseKey(hServiceKey
);
236 ScmIsDeleteFlagSet(HKEY hServiceKey
)
241 DWORD dwSize
= sizeof(DWORD
);
243 dwError
= RegQueryValueExW(hServiceKey
,
250 return (dwError
== ERROR_SUCCESS
);
255 ScmReadString(HKEY hServiceKey
,
263 LPWSTR expanded
= NULL
;
267 dwError
= RegQueryValueExW(hServiceKey
,
273 if (dwError
!= ERROR_SUCCESS
)
276 ptr
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
);
278 return ERROR_NOT_ENOUGH_MEMORY
;
280 dwError
= RegQueryValueExW(hServiceKey
,
286 if (dwError
!= ERROR_SUCCESS
)
288 HeapFree(GetProcessHeap(), 0, ptr
);
292 if (dwType
== REG_EXPAND_SZ
)
294 /* Expand the value... */
295 dwSize
= ExpandEnvironmentStringsW(ptr
, NULL
, 0);
298 expanded
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwSize
* sizeof(WCHAR
));
301 if (dwSize
== ExpandEnvironmentStringsW(ptr
, expanded
, dwSize
))
304 dwError
= ERROR_SUCCESS
;
308 dwError
= GetLastError();
309 HeapFree(GetProcessHeap(), 0, expanded
);
314 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
319 dwError
= GetLastError();
322 HeapFree(GetProcessHeap(), 0, ptr
);
334 ScmReadDependencies(HKEY hServiceKey
,
335 LPWSTR
*lpDependencies
,
336 DWORD
*lpdwDependenciesLength
)
338 LPWSTR lpGroups
= NULL
;
339 LPWSTR lpServices
= NULL
;
340 SIZE_T cchGroupsLength
= 0;
341 SIZE_T cchServicesLength
= 0;
345 SIZE_T cchTotalLength
;
347 *lpDependencies
= NULL
;
348 *lpdwDependenciesLength
= 0;
350 /* Read the dependency values */
351 ScmReadString(hServiceKey
,
355 ScmReadString(hServiceKey
,
359 /* Leave, if there are no dependencies */
360 if (lpGroups
== NULL
&& lpServices
== NULL
)
361 return ERROR_SUCCESS
;
363 /* Determine the total buffer size for the dependencies */
370 DPRINT(" %S\n", lpSrc
);
372 cchLength
= wcslen(lpSrc
) + 1;
373 cchGroupsLength
+= cchLength
+ 1;
375 lpSrc
= lpSrc
+ cchLength
;
381 DPRINT("Services:\n");
385 DPRINT(" %S\n", lpSrc
);
387 cchLength
= wcslen(lpSrc
) + 1;
388 cchServicesLength
+= cchLength
;
390 lpSrc
= lpSrc
+ cchLength
;
394 cchTotalLength
= cchGroupsLength
+ cchServicesLength
+ 1;
395 DPRINT("cchTotalLength: %lu\n", cchTotalLength
);
397 /* Allocate the common buffer for the dependencies */
398 *lpDependencies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cchTotalLength
* sizeof(WCHAR
));
399 if (*lpDependencies
== NULL
)
402 HeapFree(GetProcessHeap(), 0, lpGroups
);
405 HeapFree(GetProcessHeap(), 0, lpServices
);
407 return ERROR_NOT_ENOUGH_MEMORY
;
410 /* Return the allocated buffer length in characters */
411 *lpdwDependenciesLength
= (DWORD
)cchTotalLength
;
413 /* Copy the service dependencies into the common buffer */
414 lpDest
= *lpDependencies
;
419 cchServicesLength
* sizeof(WCHAR
));
421 lpDest
= lpDest
+ cchServicesLength
;
424 /* Copy the group dependencies into the common buffer */
430 cchLength
= wcslen(lpSrc
) + 1;
432 *lpDest
= SC_GROUP_IDENTIFIERW
;
435 wcscpy(lpDest
, lpSrc
);
437 lpDest
= lpDest
+ cchLength
;
438 lpSrc
= lpSrc
+ cchLength
;
442 /* Free the temporary buffers */
444 HeapFree(GetProcessHeap(), 0, lpGroups
);
447 HeapFree(GetProcessHeap(), 0, lpServices
);
449 return ERROR_SUCCESS
;
454 ScmSetServicePassword(
455 IN PCWSTR pszServiceName
,
456 IN PCWSTR pszPassword
)
458 OBJECT_ATTRIBUTES ObjectAttributes
;
459 LSA_HANDLE PolicyHandle
= NULL
;
460 UNICODE_STRING ServiceName
= {0, 0, NULL
};
461 UNICODE_STRING Password
;
463 DWORD dwError
= ERROR_SUCCESS
;
465 RtlZeroMemory(&ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
));
467 Status
= LsaOpenPolicy(NULL
,
469 POLICY_CREATE_SECRET
,
471 if (!NT_SUCCESS(Status
))
472 return RtlNtStatusToDosError(Status
);
474 ServiceName
.Length
= (wcslen(pszServiceName
) + 4) * sizeof(WCHAR
);
475 ServiceName
.MaximumLength
= ServiceName
.Length
+ sizeof(WCHAR
);
476 ServiceName
.Buffer
= HeapAlloc(GetProcessHeap(),
478 ServiceName
.MaximumLength
);
479 if (ServiceName
.Buffer
== NULL
)
480 return ERROR_NOT_ENOUGH_MEMORY
;
482 wcscpy(ServiceName
.Buffer
, L
"_SC_");
483 wcscat(ServiceName
.Buffer
, pszServiceName
);
485 RtlInitUnicodeString(&Password
, pszPassword
);
487 Status
= LsaStorePrivateData(PolicyHandle
,
489 pszPassword
? &Password
: NULL
);
490 if (!NT_SUCCESS(Status
))
492 dwError
= RtlNtStatusToDosError(Status
);
497 if (ServiceName
.Buffer
!= NULL
)
498 HeapFree(GetProcessHeap(), 0, ServiceName
.Buffer
);
500 if (PolicyHandle
!= NULL
)
501 LsaClose(PolicyHandle
);
508 ScmWriteSecurityDescriptor(
509 _In_ HKEY hServiceKey
,
510 _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor
)
512 HKEY hSecurityKey
= NULL
;
516 DPRINT("ScmWriteSecurityDescriptor(%p %p)\n", hServiceKey
, pSecurityDescriptor
);
518 dwError
= RegCreateKeyExW(hServiceKey
,
522 REG_OPTION_NON_VOLATILE
,
527 if (dwError
!= ERROR_SUCCESS
)
530 dwError
= RegSetValueExW(hSecurityKey
,
534 (LPBYTE
)pSecurityDescriptor
,
535 RtlLengthSecurityDescriptor(pSecurityDescriptor
));
537 RegCloseKey(hSecurityKey
);
544 ScmReadSecurityDescriptor(
545 _In_ HKEY hServiceKey
,
546 _Out_ PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
548 PSECURITY_DESCRIPTOR pRelativeSD
= NULL
;
549 HKEY hSecurityKey
= NULL
;
550 DWORD dwBufferLength
= 0;
554 DPRINT("ScmReadSecurityDescriptor(%p %p)\n", hServiceKey
, ppSecurityDescriptor
);
556 *ppSecurityDescriptor
= NULL
;
558 dwError
= RegOpenKeyExW(hServiceKey
,
563 if (dwError
!= ERROR_SUCCESS
)
565 DPRINT("RegOpenKeyExW() failed (Error %lu)\n", dwError
);
567 /* Do not fail if the Security key does not exist */
568 if (dwError
== ERROR_FILE_NOT_FOUND
)
569 dwError
= ERROR_SUCCESS
;
573 dwError
= RegQueryValueExW(hSecurityKey
,
579 if (dwError
!= ERROR_SUCCESS
)
581 DPRINT("RegQueryValueExW() failed (Error %lu)\n", dwError
);
583 /* Do not fail if the Security value does not exist */
584 if (dwError
== ERROR_FILE_NOT_FOUND
)
585 dwError
= ERROR_SUCCESS
;
589 DPRINT("dwBufferLength: %lu\n", dwBufferLength
);
590 pRelativeSD
= RtlAllocateHeap(RtlGetProcessHeap(),
593 if (pRelativeSD
== NULL
)
595 return ERROR_OUTOFMEMORY
;
598 DPRINT("pRelativeSD: %lu\n", pRelativeSD
);
599 dwError
= RegQueryValueExW(hSecurityKey
,
605 if (dwError
!= ERROR_SUCCESS
)
610 *ppSecurityDescriptor
= pRelativeSD
;
613 if (dwError
!= ERROR_SUCCESS
&& pRelativeSD
!= NULL
)
614 RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD
);
616 if (hSecurityKey
!= NULL
)
617 RegCloseKey(hSecurityKey
);