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"
|
2016-05-23 15:02:37 +00:00
|
|
|
#include <ntsecapi.h>
|
2005-12-31 19:02:48 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2018-09-18 19:33:29 +00:00
|
|
|
struct ustring
|
|
|
|
{
|
|
|
|
DWORD Length;
|
|
|
|
DWORD MaximumLength;
|
|
|
|
unsigned char *Buffer;
|
|
|
|
};
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
WINAPI
|
|
|
|
SystemFunction005(
|
|
|
|
const struct ustring *in,
|
|
|
|
const struct ustring *key,
|
|
|
|
struct ustring *out);
|
|
|
|
|
2018-09-19 10:28:58 +00:00
|
|
|
NTSTATUS
|
|
|
|
WINAPI
|
|
|
|
SystemFunction028(
|
|
|
|
IN PVOID ContextHandle,
|
|
|
|
OUT LPBYTE SessionKey);
|
2016-06-26 15:02:48 +00:00
|
|
|
|
2005-12-31 19:02:48 +00:00
|
|
|
/* 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++;
|
2015-08-30 09:52:57 +00:00
|
|
|
cchLength--;
|
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;
|
|
|
|
}
|
|
|
|
|
2016-05-23 15:02:37 +00:00
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmSetServicePassword(
|
|
|
|
IN PCWSTR pszServiceName,
|
|
|
|
IN PCWSTR pszPassword)
|
|
|
|
{
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
LSA_HANDLE PolicyHandle = NULL;
|
|
|
|
UNICODE_STRING ServiceName = {0, 0, NULL};
|
|
|
|
UNICODE_STRING Password;
|
|
|
|
NTSTATUS Status;
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
2021-06-29 16:50:15 +00:00
|
|
|
SIZE_T ServiceNameLength;
|
2016-05-23 15:02:37 +00:00
|
|
|
|
|
|
|
RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
|
|
|
|
|
2021-06-29 16:50:15 +00:00
|
|
|
ServiceNameLength = wcslen(pszServiceName);
|
|
|
|
if (ServiceNameLength > (UNICODE_STRING_MAX_CHARS - 4))
|
|
|
|
{
|
|
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-05-23 15:02:37 +00:00
|
|
|
Status = LsaOpenPolicy(NULL,
|
|
|
|
&ObjectAttributes,
|
|
|
|
POLICY_CREATE_SECRET,
|
|
|
|
&PolicyHandle);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return RtlNtStatusToDosError(Status);
|
|
|
|
|
2021-06-29 16:50:15 +00:00
|
|
|
ServiceName.Length = ((USHORT)ServiceNameLength + 4) * sizeof(WCHAR);
|
2016-05-23 15:02:37 +00:00
|
|
|
ServiceName.MaximumLength = ServiceName.Length + sizeof(WCHAR);
|
|
|
|
ServiceName.Buffer = HeapAlloc(GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
ServiceName.MaximumLength);
|
|
|
|
if (ServiceName.Buffer == NULL)
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
|
|
|
|
wcscpy(ServiceName.Buffer, L"_SC_");
|
|
|
|
wcscat(ServiceName.Buffer, pszServiceName);
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&Password, pszPassword);
|
|
|
|
|
|
|
|
Status = LsaStorePrivateData(PolicyHandle,
|
|
|
|
&ServiceName,
|
2016-05-23 21:48:32 +00:00
|
|
|
pszPassword ? &Password : NULL);
|
2016-05-23 15:02:37 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
dwError = RtlNtStatusToDosError(Status);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (ServiceName.Buffer != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, ServiceName.Buffer);
|
|
|
|
|
|
|
|
if (PolicyHandle != NULL)
|
|
|
|
LsaClose(PolicyHandle);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmWriteSecurityDescriptor(
|
|
|
|
_In_ HKEY hServiceKey,
|
|
|
|
_In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
|
|
|
|
{
|
|
|
|
HKEY hSecurityKey = NULL;
|
|
|
|
DWORD dwDisposition;
|
|
|
|
DWORD dwError;
|
|
|
|
|
2016-06-26 20:09:37 +00:00
|
|
|
DPRINT("ScmWriteSecurityDescriptor(%p %p)\n", hServiceKey, pSecurityDescriptor);
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
dwError = RegCreateKeyExW(hServiceKey,
|
|
|
|
L"Security",
|
|
|
|
0,
|
|
|
|
NULL,
|
|
|
|
REG_OPTION_NON_VOLATILE,
|
|
|
|
KEY_SET_VALUE,
|
|
|
|
NULL,
|
|
|
|
&hSecurityKey,
|
|
|
|
&dwDisposition);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
2016-06-26 20:09:37 +00:00
|
|
|
return dwError;
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
dwError = RegSetValueExW(hSecurityKey,
|
|
|
|
L"Security",
|
|
|
|
0,
|
|
|
|
REG_BINARY,
|
2016-06-26 15:02:48 +00:00
|
|
|
(LPBYTE)pSecurityDescriptor,
|
|
|
|
RtlLengthSecurityDescriptor(pSecurityDescriptor));
|
2016-06-09 21:30:48 +00:00
|
|
|
|
2016-06-26 20:09:37 +00:00
|
|
|
RegCloseKey(hSecurityKey);
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmReadSecurityDescriptor(
|
|
|
|
_In_ HKEY hServiceKey,
|
|
|
|
_Out_ PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
|
|
|
|
{
|
|
|
|
PSECURITY_DESCRIPTOR pRelativeSD = NULL;
|
|
|
|
HKEY hSecurityKey = NULL;
|
|
|
|
DWORD dwBufferLength = 0;
|
|
|
|
DWORD dwType;
|
|
|
|
DWORD dwError;
|
2016-06-11 09:41:05 +00:00
|
|
|
|
2016-06-26 20:09:37 +00:00
|
|
|
DPRINT("ScmReadSecurityDescriptor(%p %p)\n", hServiceKey, ppSecurityDescriptor);
|
2016-06-11 09:41:05 +00:00
|
|
|
|
|
|
|
*ppSecurityDescriptor = NULL;
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
dwError = RegOpenKeyExW(hServiceKey,
|
|
|
|
L"Security",
|
|
|
|
0,
|
|
|
|
KEY_QUERY_VALUE,
|
|
|
|
&hSecurityKey);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
2016-06-11 09:41:05 +00:00
|
|
|
DPRINT("RegOpenKeyExW() failed (Error %lu)\n", dwError);
|
|
|
|
|
|
|
|
/* Do not fail if the Security key does not exist */
|
|
|
|
if (dwError == ERROR_FILE_NOT_FOUND)
|
|
|
|
dwError = ERROR_SUCCESS;
|
2016-06-09 21:30:48 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwError = RegQueryValueExW(hSecurityKey,
|
|
|
|
L"Security",
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
NULL,
|
|
|
|
&dwBufferLength);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
2016-06-11 09:41:05 +00:00
|
|
|
DPRINT("RegQueryValueExW() failed (Error %lu)\n", dwError);
|
|
|
|
|
|
|
|
/* Do not fail if the Security value does not exist */
|
|
|
|
if (dwError == ERROR_FILE_NOT_FOUND)
|
|
|
|
dwError = ERROR_SUCCESS;
|
2016-06-09 21:30:48 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2016-06-11 09:41:05 +00:00
|
|
|
DPRINT("dwBufferLength: %lu\n", dwBufferLength);
|
2016-06-09 21:30:48 +00:00
|
|
|
pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwBufferLength);
|
|
|
|
if (pRelativeSD == NULL)
|
|
|
|
{
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
}
|
|
|
|
|
2016-06-11 09:41:05 +00:00
|
|
|
DPRINT("pRelativeSD: %lu\n", pRelativeSD);
|
2016-06-09 21:30:48 +00:00
|
|
|
dwError = RegQueryValueExW(hSecurityKey,
|
|
|
|
L"Security",
|
|
|
|
0,
|
|
|
|
&dwType,
|
|
|
|
(LPBYTE)pRelativeSD,
|
|
|
|
&dwBufferLength);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2016-06-11 09:41:05 +00:00
|
|
|
*ppSecurityDescriptor = pRelativeSD;
|
2016-06-09 21:30:48 +00:00
|
|
|
|
|
|
|
done:
|
2016-06-11 09:41:05 +00:00
|
|
|
if (dwError != ERROR_SUCCESS && pRelativeSD != NULL)
|
2016-06-09 21:30:48 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
|
|
|
|
|
|
|
|
if (hSecurityKey != NULL)
|
|
|
|
RegCloseKey(hSecurityKey);
|
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
2016-11-27 20:12:39 +00:00
|
|
|
|
|
|
|
DWORD
|
2016-11-27 20:39:10 +00:00
|
|
|
ScmDeleteRegKey(
|
|
|
|
_In_ HKEY hKey,
|
|
|
|
_In_ PCWSTR pszSubKey)
|
2016-11-27 20:12:39 +00:00
|
|
|
{
|
|
|
|
DWORD dwMaxSubkeyLen, dwMaxValueLen;
|
|
|
|
DWORD dwMaxLen, dwSize;
|
|
|
|
PWSTR pszName = NULL;
|
2016-11-27 20:39:10 +00:00
|
|
|
HKEY hSubKey;
|
2016-11-27 20:12:39 +00:00
|
|
|
DWORD dwError;
|
|
|
|
|
2016-11-27 20:39:10 +00:00
|
|
|
dwError = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
|
2016-11-27 20:12:39 +00:00
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
return dwError;
|
|
|
|
|
|
|
|
/* Get maximum length of key and value names */
|
2016-11-27 20:39:10 +00:00
|
|
|
dwError = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
|
2016-11-27 20:12:39 +00:00
|
|
|
&dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
|
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
dwMaxSubkeyLen++;
|
|
|
|
dwMaxValueLen++;
|
|
|
|
dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
|
|
|
|
|
|
|
|
/* Allocate the name buffer */
|
|
|
|
pszName = HeapAlloc(GetProcessHeap(), 0, dwMaxLen * sizeof(WCHAR));
|
|
|
|
if (pszName == NULL)
|
|
|
|
{
|
|
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Recursively delete all the subkeys */
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
dwSize = dwMaxLen;
|
2016-11-27 20:39:10 +00:00
|
|
|
if (RegEnumKeyExW(hSubKey, 0, pszName, &dwSize,
|
|
|
|
NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
|
|
{
|
2016-11-27 20:12:39 +00:00
|
|
|
break;
|
2016-11-27 20:39:10 +00:00
|
|
|
}
|
2016-11-27 20:12:39 +00:00
|
|
|
|
2016-11-27 20:44:09 +00:00
|
|
|
dwError = ScmDeleteRegKey(hSubKey, pszName);
|
2016-11-27 20:12:39 +00:00
|
|
|
if (dwError != ERROR_SUCCESS)
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (pszName != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, pszName);
|
|
|
|
|
2016-11-27 20:39:10 +00:00
|
|
|
RegCloseKey(hSubKey);
|
|
|
|
|
|
|
|
/* Finally delete the key */
|
|
|
|
if (dwError == ERROR_SUCCESS)
|
|
|
|
dwError = RegDeleteKeyW(hKey, pszSubKey);
|
2016-11-27 20:12:39 +00:00
|
|
|
|
|
|
|
return dwError;
|
|
|
|
}
|
|
|
|
|
2018-09-17 14:34:48 +00:00
|
|
|
|
|
|
|
DWORD
|
|
|
|
ScmDecryptPassword(
|
2021-07-17 14:26:16 +00:00
|
|
|
_In_ PVOID ContextHandle,
|
2018-09-17 14:34:48 +00:00
|
|
|
_In_ PBYTE pPassword,
|
|
|
|
_In_ DWORD dwPasswordSize,
|
|
|
|
_Out_ PWSTR *pClearTextPassword)
|
|
|
|
{
|
2018-09-18 19:33:29 +00:00
|
|
|
struct ustring inData, keyData, outData;
|
2018-09-19 10:28:58 +00:00
|
|
|
BYTE SessionKey[16];
|
2018-09-17 14:34:48 +00:00
|
|
|
PWSTR pBuffer;
|
2018-09-18 19:33:29 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2018-09-19 10:28:58 +00:00
|
|
|
/* Get the session key */
|
2021-07-17 14:26:16 +00:00
|
|
|
Status = SystemFunction028(ContextHandle,
|
2018-09-19 10:28:58 +00:00
|
|
|
SessionKey);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SystemFunction028 failed (Status 0x%08lx)\n", Status);
|
|
|
|
return RtlNtStatusToDosError(Status);
|
|
|
|
}
|
|
|
|
|
2018-09-18 19:33:29 +00:00
|
|
|
inData.Length = dwPasswordSize;
|
|
|
|
inData.MaximumLength = inData.Length;
|
|
|
|
inData.Buffer = pPassword;
|
|
|
|
|
2018-09-19 10:28:58 +00:00
|
|
|
keyData.Length = sizeof(SessionKey);
|
2018-09-18 19:33:29 +00:00
|
|
|
keyData.MaximumLength = keyData.Length;
|
2018-09-19 10:28:58 +00:00
|
|
|
keyData.Buffer = SessionKey;
|
2018-09-18 19:33:29 +00:00
|
|
|
|
|
|
|
outData.Length = 0;
|
|
|
|
outData.MaximumLength = 0;
|
|
|
|
outData.Buffer = NULL;
|
|
|
|
|
|
|
|
/* Get the required buffer size */
|
|
|
|
Status = SystemFunction005(&inData,
|
|
|
|
&keyData,
|
|
|
|
&outData);
|
|
|
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
|
|
{
|
|
|
|
DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status);
|
|
|
|
return RtlNtStatusToDosError(Status);
|
|
|
|
}
|
2018-09-17 14:34:48 +00:00
|
|
|
|
2018-09-18 19:33:29 +00:00
|
|
|
/* Allocate a buffer for the clear text password */
|
|
|
|
pBuffer = HeapAlloc(GetProcessHeap(), 0, outData.Length);
|
2018-09-17 14:34:48 +00:00
|
|
|
if (pBuffer == NULL)
|
|
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
|
2018-09-18 19:33:29 +00:00
|
|
|
outData.MaximumLength = outData.Length;
|
|
|
|
outData.Buffer = (unsigned char *)pBuffer;
|
|
|
|
|
2018-09-17 14:34:48 +00:00
|
|
|
/* Decrypt the password */
|
2018-09-18 19:33:29 +00:00
|
|
|
Status = SystemFunction005(&inData,
|
|
|
|
&keyData,
|
|
|
|
&outData);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT1("SystemFunction005 failed (Status 0x%08lx)\n", Status);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pBuffer);
|
|
|
|
return RtlNtStatusToDosError(Status);
|
|
|
|
}
|
2018-09-17 14:34:48 +00:00
|
|
|
|
|
|
|
*pClearTextPassword = pBuffer;
|
|
|
|
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2009-12-25 15:08:03 +00:00
|
|
|
/* EOF */
|