2005-12-31 19:02:48 +00:00
|
|
|
/*
|
2007-09-06 14:51:38 +00:00
|
|
|
* PROJECT: ReactOS Service Control Manager
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
|
|
* FILE: base/system/services/config.c
|
|
|
|
* PURPOSE: Service configuration interface
|
|
|
|
* COPYRIGHT: Copyright 2005 Eric Kohl
|
|
|
|
*
|
2005-12-31 19:02:48 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
|
|
|
#include "services.h"
|
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmOpenServiceKey(LPWSTR lpServiceName,
|
|
|
|
REGSAM samDesired,
|
|
|
|
PHKEY phKey)
|
|
|
|
{
|
|
|
|
HKEY hServicesKey = NULL;
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
|
|
*phKey = NULL;
|
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"System\\CurrentControlSet\\Services",
|
|
|
|
0,
|
|
|
|
KEY_READ,
|
|
|
|
&hServicesKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return dwError;
|
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(hServicesKey,
|
|
|
|
lpServiceName,
|
|
|
|
0,
|
|
|
|
samDesired,
|
|
|
|
phKey);
|
|
|
|
|
|
|
|
RegCloseKey(hServicesKey);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
2009-01-06 07:53:04 +00:00
|
|
|
ScmCreateServiceKey(LPCWSTR lpServiceName,
|
2005-12-31 19:02:48 +00:00
|
|
|
REGSAM samDesired,
|
|
|
|
PHKEY phKey)
|
|
|
|
{
|
|
|
|
HKEY hServicesKey = NULL;
|
|
|
|
DWORD dwDisposition;
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
|
|
*phKey = NULL;
|
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
|
|
L"System\\CurrentControlSet\\Services",
|
|
|
|
0,
|
|
|
|
KEY_READ | KEY_CREATE_SUB_KEY,
|
|
|
|
&hServicesKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return dwError;
|
|
|
|
|
|
|
|
dwError = RegCreateKeyExW(hServicesKey,
|
|
|
|
lpServiceName,
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_NON_VOLATILE,
|
|
|
|
samDesired,
|
|
|
|
NULL,
|
|
|
|
phKey,
|
|
|
|
&dwDisposition);
|
|
|
|
#if 0
|
|
|
|
if ((dwError == ERROR_SUCCESS) &&
|
|
|
|
(dwDisposition == REG_OPENED_EXISTING_KEY))
|
|
|
|
{
|
|
|
|
RegCloseKey(*phKey);
|
|
|
|
*phKey = NULL;
|
|
|
|
dwError = ERROR_SERVICE_EXISTS;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RegCloseKey(hServicesKey);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmWriteDependencies(HKEY hServiceKey,
|
2011-11-06 13:33:29 +00:00
|
|
|
LPCWSTR lpDependencies,
|
2005-12-31 19:02:48 +00:00
|
|
|
DWORD dwDependenciesLength)
|
|
|
|
{
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2012-08-19 10:01:05 +00:00
|
|
|
SIZE_T cchGroupLength = 0;
|
|
|
|
SIZE_T cchServiceLength = 0;
|
|
|
|
SIZE_T cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
LPWSTR lpGroupDeps;
|
|
|
|
LPWSTR lpServiceDeps;
|
2011-11-06 13:33:29 +00:00
|
|
|
LPCWSTR lpSrc;
|
2005-12-31 19:02:48 +00:00
|
|
|
LPWSTR lpDst;
|
|
|
|
|
|
|
|
if (*lpDependencies == 0)
|
|
|
|
{
|
2009-01-31 13:44:48 +00:00
|
|
|
RegDeleteValueW(hServiceKey,
|
2005-12-31 19:02:48 +00:00
|
|
|
L"DependOnService");
|
2009-01-31 13:44:48 +00:00
|
|
|
RegDeleteValueW(hServiceKey,
|
2005-12-31 19:02:48 +00:00
|
|
|
L"DependOnGroup");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lpGroupDeps = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(dwDependenciesLength + 2) * sizeof(WCHAR));
|
|
|
|
if (lpGroupDeps == NULL)
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
lpSrc = lpDependencies;
|
|
|
|
lpDst = lpGroupDeps;
|
|
|
|
while (*lpSrc != 0)
|
|
|
|
{
|
2012-08-19 10:01:05 +00:00
|
|
|
cchLength = wcslen(lpSrc) + 1;
|
2005-12-31 19:02:48 +00:00
|
|
|
if (*lpSrc == SC_GROUP_IDENTIFIERW)
|
|
|
|
{
|
|
|
|
lpSrc++;
|
2012-08-19 10:01:05 +00:00
|
|
|
cchGroupLength += cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
wcscpy(lpDst, lpSrc);
|
2012-08-19 10:01:05 +00:00
|
|
|
lpDst = lpDst + cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpSrc = lpSrc + cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
|
|
|
*lpDst = 0;
|
|
|
|
lpDst++;
|
2012-08-19 10:01:05 +00:00
|
|
|
cchGroupLength++;
|
2005-12-31 19:02:48 +00:00
|
|
|
|
|
|
|
lpSrc = lpDependencies;
|
|
|
|
lpServiceDeps = lpDst;
|
|
|
|
while (*lpSrc != 0)
|
|
|
|
{
|
2012-08-19 10:01:05 +00:00
|
|
|
cchLength = wcslen(lpSrc) + 1;
|
2005-12-31 19:02:48 +00:00
|
|
|
if (*lpSrc != SC_GROUP_IDENTIFIERW)
|
|
|
|
{
|
2012-08-19 10:01:05 +00:00
|
|
|
cchServiceLength += cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
wcscpy(lpDst, lpSrc);
|
2012-08-19 10:01:05 +00:00
|
|
|
lpDst = lpDst + cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpSrc = lpSrc + cchLength;
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
|
|
|
*lpDst = 0;
|
2012-08-19 10:01:05 +00:00
|
|
|
cchServiceLength++;
|
2005-12-31 19:02:48 +00:00
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
if (cchGroupLength > 1)
|
2005-12-31 19:02:48 +00:00
|
|
|
{
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
2011-03-27 13:12:12 +00:00
|
|
|
L"DependOnGroup",
|
2005-12-31 19:02:48 +00:00
|
|
|
0,
|
|
|
|
REG_MULTI_SZ,
|
2011-03-27 13:12:12 +00:00
|
|
|
(LPBYTE)lpGroupDeps,
|
2012-08-19 10:01:05 +00:00
|
|
|
(DWORD)(cchGroupLength * sizeof(WCHAR)));
|
2011-03-27 13:12:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RegDeleteValueW(hServiceKey,
|
|
|
|
L"DependOnGroup");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
|
|
{
|
2012-08-19 10:01:05 +00:00
|
|
|
if (cchServiceLength > 1)
|
2011-03-27 13:12:12 +00:00
|
|
|
{
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
L"DependOnService",
|
|
|
|
0,
|
|
|
|
REG_MULTI_SZ,
|
|
|
|
(LPBYTE)lpServiceDeps,
|
2012-08-19 10:01:05 +00:00
|
|
|
(DWORD)(cchServiceLength * sizeof(WCHAR)));
|
2011-03-27 13:12:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RegDeleteValueW(hServiceKey,
|
|
|
|
L"DependOnService");
|
|
|
|
}
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpGroupDeps);
|
|
|
|
}
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmMarkServiceForDelete(PSERVICE pService)
|
|
|
|
{
|
|
|
|
HKEY hServiceKey = NULL;
|
|
|
|
DWORD dwValue = 1;
|
|
|
|
DWORD dwError;
|
|
|
|
|
|
|
|
DPRINT("ScmMarkServiceForDelete() called\n");
|
|
|
|
|
|
|
|
dwError = ScmOpenServiceKey(pService->lpServiceName,
|
|
|
|
KEY_WRITE,
|
|
|
|
&hServiceKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return dwError;
|
|
|
|
|
|
|
|
dwError = RegSetValueExW(hServiceKey,
|
|
|
|
L"DeleteFlag",
|
|
|
|
0,
|
|
|
|
REG_DWORD,
|
|
|
|
(LPBYTE)&dwValue,
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
|
|
|
RegCloseKey(hServiceKey);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
ScmIsDeleteFlagSet(HKEY hServiceKey)
|
|
|
|
{
|
|
|
|
DWORD dwError;
|
|
|
|
DWORD dwType;
|
|
|
|
DWORD dwFlag;
|
|
|
|
DWORD dwSize = sizeof(DWORD);
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hServiceKey,
|
|
|
|
L"DeleteFlag",
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
(LPBYTE)&dwFlag,
|
|
|
|
&dwSize);
|
|
|
|
|
|
|
|
return (dwError == ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmReadString(HKEY hServiceKey,
|
2012-09-18 21:54:43 +00:00
|
|
|
LPCWSTR lpValueName,
|
2005-12-31 19:02:48 +00:00
|
|
|
LPWSTR *lpValue)
|
|
|
|
{
|
2012-09-18 21:54:43 +00:00
|
|
|
DWORD dwError = 0;
|
|
|
|
DWORD dwSize = 0;
|
|
|
|
DWORD dwType = 0;
|
2005-12-31 19:02:48 +00:00
|
|
|
LPWSTR ptr = NULL;
|
2012-09-18 21:54:43 +00:00
|
|
|
LPWSTR expanded = NULL;
|
2005-12-31 19:02:48 +00:00
|
|
|
|
|
|
|
*lpValue = NULL;
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hServiceKey,
|
|
|
|
lpValueName,
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
NULL,
|
|
|
|
&dwSize);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return dwError;
|
|
|
|
|
2012-09-18 21:54:43 +00:00
|
|
|
ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
|
2005-12-31 19:02:48 +00:00
|
|
|
if (ptr == NULL)
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hServiceKey,
|
|
|
|
lpValueName,
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
(LPBYTE)ptr,
|
|
|
|
&dwSize);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2012-09-18 21:54:43 +00:00
|
|
|
{
|
|
|
|
HeapFree(GetProcessHeap(), 0, ptr);
|
|
|
|
return dwError;
|
|
|
|
}
|
2005-12-31 19:02:48 +00:00
|
|
|
|
|
|
|
if (dwType == REG_EXPAND_SZ)
|
|
|
|
{
|
|
|
|
/* Expand the value... */
|
2012-09-18 21:54:43 +00:00
|
|
|
dwSize = ExpandEnvironmentStringsW(ptr, NULL, 0);
|
|
|
|
if (dwSize > 0)
|
2005-12-31 19:02:48 +00:00
|
|
|
{
|
2012-09-18 21:54:43 +00:00
|
|
|
expanded = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize * sizeof(WCHAR));
|
|
|
|
if (expanded)
|
|
|
|
{
|
|
|
|
if (dwSize == ExpandEnvironmentStringsW(ptr, expanded, dwSize))
|
|
|
|
{
|
|
|
|
*lpValue = expanded;
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
HeapFree(GetProcessHeap(), 0, expanded);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
2005-12-31 19:02:48 +00:00
|
|
|
}
|
2012-09-18 21:54:43 +00:00
|
|
|
else
|
2005-12-31 19:02:48 +00:00
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
}
|
2012-09-18 21:54:43 +00:00
|
|
|
|
2005-12-31 19:02:48 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, ptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*lpValue = ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-25 15:08:03 +00:00
|
|
|
DWORD
|
|
|
|
ScmReadDependencies(HKEY hServiceKey,
|
|
|
|
LPWSTR *lpDependencies,
|
|
|
|
DWORD *lpdwDependenciesLength)
|
|
|
|
{
|
|
|
|
LPWSTR lpGroups = NULL;
|
|
|
|
LPWSTR lpServices = NULL;
|
2012-08-19 10:01:05 +00:00
|
|
|
SIZE_T cchGroupsLength = 0;
|
|
|
|
SIZE_T cchServicesLength = 0;
|
2009-12-25 15:08:03 +00:00
|
|
|
LPWSTR lpSrc;
|
|
|
|
LPWSTR lpDest;
|
2012-08-19 10:01:05 +00:00
|
|
|
SIZE_T cchLength;
|
|
|
|
SIZE_T cchTotalLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
|
|
|
|
*lpDependencies = NULL;
|
|
|
|
*lpdwDependenciesLength = 0;
|
|
|
|
|
|
|
|
/* Read the dependency values */
|
|
|
|
ScmReadString(hServiceKey,
|
|
|
|
L"DependOnGroup",
|
|
|
|
&lpGroups);
|
|
|
|
|
|
|
|
ScmReadString(hServiceKey,
|
|
|
|
L"DependOnService",
|
|
|
|
&lpServices);
|
|
|
|
|
|
|
|
/* Leave, if there are no dependencies */
|
|
|
|
if (lpGroups == NULL && lpServices == NULL)
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
|
|
|
|
/* Determine the total buffer size for the dependencies */
|
|
|
|
if (lpGroups)
|
|
|
|
{
|
|
|
|
DPRINT("Groups:\n");
|
|
|
|
lpSrc = lpGroups;
|
|
|
|
while (*lpSrc != 0)
|
|
|
|
{
|
|
|
|
DPRINT(" %S\n", lpSrc);
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
cchLength = wcslen(lpSrc) + 1;
|
|
|
|
cchGroupsLength += cchLength + 1;
|
2009-12-25 15:08:03 +00:00
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpSrc = lpSrc + cchLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lpServices)
|
|
|
|
{
|
|
|
|
DPRINT("Services:\n");
|
|
|
|
lpSrc = lpServices;
|
|
|
|
while (*lpSrc != 0)
|
|
|
|
{
|
|
|
|
DPRINT(" %S\n", lpSrc);
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
cchLength = wcslen(lpSrc) + 1;
|
|
|
|
cchServicesLength += cchLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpSrc = lpSrc + cchLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
cchTotalLength = cchGroupsLength + cchServicesLength + 1;
|
|
|
|
DPRINT("cchTotalLength: %lu\n", cchTotalLength);
|
2009-12-25 15:08:03 +00:00
|
|
|
|
|
|
|
/* Allocate the common buffer for the dependencies */
|
2012-08-19 10:01:05 +00:00
|
|
|
*lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cchTotalLength * sizeof(WCHAR));
|
2009-12-25 15:08:03 +00:00
|
|
|
if (*lpDependencies == NULL)
|
|
|
|
{
|
|
|
|
if (lpGroups)
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpGroups);
|
|
|
|
|
|
|
|
if (lpServices)
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpServices);
|
|
|
|
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return the allocated buffer length in characters */
|
2012-08-19 10:01:05 +00:00
|
|
|
*lpdwDependenciesLength = (DWORD)cchTotalLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
|
|
|
|
/* Copy the service dependencies into the common buffer */
|
|
|
|
lpDest = *lpDependencies;
|
|
|
|
if (lpServices)
|
|
|
|
{
|
|
|
|
memcpy(lpDest,
|
|
|
|
lpServices,
|
2012-08-19 10:01:05 +00:00
|
|
|
cchServicesLength * sizeof(WCHAR));
|
2009-12-25 15:08:03 +00:00
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpDest = lpDest + cchServicesLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy the group dependencies into the common buffer */
|
|
|
|
if (lpGroups)
|
|
|
|
{
|
|
|
|
lpSrc = lpGroups;
|
|
|
|
while (*lpSrc != 0)
|
|
|
|
{
|
2012-08-19 10:01:05 +00:00
|
|
|
cchLength = wcslen(lpSrc) + 1;
|
2009-12-25 15:08:03 +00:00
|
|
|
|
|
|
|
*lpDest = SC_GROUP_IDENTIFIERW;
|
|
|
|
lpDest++;
|
|
|
|
|
|
|
|
wcscpy(lpDest, lpSrc);
|
|
|
|
|
2012-08-19 10:01:05 +00:00
|
|
|
lpDest = lpDest + cchLength;
|
|
|
|
lpSrc = lpSrc + cchLength;
|
2009-12-25 15:08:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the temporary buffers */
|
|
|
|
if (lpGroups)
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpGroups);
|
|
|
|
|
|
|
|
if (lpServices)
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpServices);
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|