/* INCLUDES *****************************************************************/
#include "services.h"
+#include <ntsecapi.h>
#define NDEBUG
#include <debug.h>
+
/* FUNCTIONS *****************************************************************/
DWORD dwDependenciesLength)
{
DWORD dwError = ERROR_SUCCESS;
- DWORD dwGroupLength = 0;
- DWORD dwServiceLength = 0;
- DWORD dwLength;
+ SIZE_T cchGroupLength = 0;
+ SIZE_T cchServiceLength = 0;
+ SIZE_T cchLength;
LPWSTR lpGroupDeps;
LPWSTR lpServiceDeps;
LPCWSTR lpSrc;
lpDst = lpGroupDeps;
while (*lpSrc != 0)
{
- dwLength = wcslen(lpSrc) + 1;
+ cchLength = wcslen(lpSrc) + 1;
if (*lpSrc == SC_GROUP_IDENTIFIERW)
{
lpSrc++;
- dwGroupLength += dwLength;
+ cchLength--;
+ cchGroupLength += cchLength;
wcscpy(lpDst, lpSrc);
- lpDst = lpDst + dwLength;
+ lpDst = lpDst + cchLength;
}
- lpSrc = lpSrc + dwLength;
+ lpSrc = lpSrc + cchLength;
}
*lpDst = 0;
lpDst++;
- dwGroupLength++;
+ cchGroupLength++;
lpSrc = lpDependencies;
lpServiceDeps = lpDst;
while (*lpSrc != 0)
{
- dwLength = wcslen(lpSrc) + 1;
+ cchLength = wcslen(lpSrc) + 1;
if (*lpSrc != SC_GROUP_IDENTIFIERW)
{
- dwServiceLength += dwLength;
+ cchServiceLength += cchLength;
wcscpy(lpDst, lpSrc);
- lpDst = lpDst + dwLength;
+ lpDst = lpDst + cchLength;
}
- lpSrc = lpSrc + dwLength;
+ lpSrc = lpSrc + cchLength;
}
*lpDst = 0;
- dwServiceLength++;
+ cchServiceLength++;
- if (dwGroupLength > 1)
+ if (cchGroupLength > 1)
{
dwError = RegSetValueExW(hServiceKey,
L"DependOnGroup",
0,
REG_MULTI_SZ,
(LPBYTE)lpGroupDeps,
- dwGroupLength * sizeof(WCHAR));
+ (DWORD)(cchGroupLength * sizeof(WCHAR)));
}
else
{
if (dwError == ERROR_SUCCESS)
{
- if (dwServiceLength > 1)
+ if (cchServiceLength > 1)
{
dwError = RegSetValueExW(hServiceKey,
L"DependOnService",
0,
REG_MULTI_SZ,
(LPBYTE)lpServiceDeps,
- dwServiceLength * sizeof(WCHAR));
+ (DWORD)(cchServiceLength * sizeof(WCHAR)));
}
else
{
DWORD
ScmReadString(HKEY hServiceKey,
- LPWSTR lpValueName,
+ LPCWSTR lpValueName,
LPWSTR *lpValue)
{
- DWORD dwError;
- DWORD dwSize;
- DWORD dwType;
- DWORD dwSizeNeeded;
- LPWSTR expanded = NULL;
+ DWORD dwError = 0;
+ DWORD dwSize = 0;
+ DWORD dwType = 0;
LPWSTR ptr = NULL;
+ LPWSTR expanded = NULL;
*lpValue = NULL;
- dwSize = 0;
dwError = RegQueryValueExW(hServiceKey,
lpValueName,
0,
if (dwError != ERROR_SUCCESS)
return dwError;
- ptr = HeapAlloc(GetProcessHeap(), 0, dwSize);
+ ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (ptr == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
(LPBYTE)ptr,
&dwSize);
if (dwError != ERROR_SUCCESS)
- goto done;
+ {
+ HeapFree(GetProcessHeap(), 0, ptr);
+ return dwError;
+ }
if (dwType == REG_EXPAND_SZ)
{
/* Expand the value... */
- dwSizeNeeded = ExpandEnvironmentStringsW((LPCWSTR)ptr, NULL, 0);
- if (dwSizeNeeded == 0)
+ dwSize = ExpandEnvironmentStringsW(ptr, NULL, 0);
+ if (dwSize > 0)
{
- dwError = GetLastError();
- goto done;
+ 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;
+ }
}
- expanded = HeapAlloc(GetProcessHeap(), 0, dwSizeNeeded * sizeof(WCHAR));
- if (dwSizeNeeded < ExpandEnvironmentStringsW((LPCWSTR)ptr, expanded, dwSizeNeeded))
+ else
{
dwError = GetLastError();
- goto done;
}
- *lpValue = expanded;
+
HeapFree(GetProcessHeap(), 0, ptr);
- dwError = ERROR_SUCCESS;
}
else
{
*lpValue = ptr;
}
-done:
- if (dwError != ERROR_SUCCESS)
- {
- HeapFree(GetProcessHeap(), 0, ptr);
- if (expanded)
- HeapFree(GetProcessHeap(), 0, expanded);
- }
-
return dwError;
}
{
LPWSTR lpGroups = NULL;
LPWSTR lpServices = NULL;
- DWORD dwGroupsLength = 0;
- DWORD dwServicesLength = 0;
+ SIZE_T cchGroupsLength = 0;
+ SIZE_T cchServicesLength = 0;
LPWSTR lpSrc;
LPWSTR lpDest;
- DWORD len;
- DWORD dwTotalLength;
+ SIZE_T cchLength;
+ SIZE_T cchTotalLength;
*lpDependencies = NULL;
*lpdwDependenciesLength = 0;
{
DPRINT(" %S\n", lpSrc);
- len = wcslen(lpSrc) + 1;
- dwGroupsLength += len + 1;
+ cchLength = wcslen(lpSrc) + 1;
+ cchGroupsLength += cchLength + 1;
- lpSrc = lpSrc + len;
+ lpSrc = lpSrc + cchLength;
}
}
{
DPRINT(" %S\n", lpSrc);
- len = wcslen(lpSrc) + 1;
- dwServicesLength += len;
+ cchLength = wcslen(lpSrc) + 1;
+ cchServicesLength += cchLength;
- lpSrc = lpSrc + len;
+ lpSrc = lpSrc + cchLength;
}
}
- dwTotalLength = dwGroupsLength + dwServicesLength + 1;
- DPRINT("dwTotalLength: %lu\n", dwTotalLength);
+ cchTotalLength = cchGroupsLength + cchServicesLength + 1;
+ DPRINT("cchTotalLength: %lu\n", cchTotalLength);
/* Allocate the common buffer for the dependencies */
- *lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalLength * sizeof(WCHAR));
+ *lpDependencies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cchTotalLength * sizeof(WCHAR));
if (*lpDependencies == NULL)
{
if (lpGroups)
}
/* Return the allocated buffer length in characters */
- *lpdwDependenciesLength = dwTotalLength;
+ *lpdwDependenciesLength = (DWORD)cchTotalLength;
/* Copy the service dependencies into the common buffer */
lpDest = *lpDependencies;
{
memcpy(lpDest,
lpServices,
- dwServicesLength * sizeof(WCHAR));
+ cchServicesLength * sizeof(WCHAR));
- lpDest = lpDest + dwServicesLength;
+ lpDest = lpDest + cchServicesLength;
}
/* Copy the group dependencies into the common buffer */
lpSrc = lpGroups;
while (*lpSrc != 0)
{
- len = wcslen(lpSrc) + 1;
+ cchLength = wcslen(lpSrc) + 1;
*lpDest = SC_GROUP_IDENTIFIERW;
lpDest++;
wcscpy(lpDest, lpSrc);
- lpDest = lpDest + len;
- lpSrc = lpSrc + len;
+ lpDest = lpDest + cchLength;
+ lpSrc = lpSrc + cchLength;
}
}
return ERROR_SUCCESS;
}
+
+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;
+
+ RtlZeroMemory(&ObjectAttributes, sizeof(OBJECT_ATTRIBUTES));
+
+ Status = LsaOpenPolicy(NULL,
+ &ObjectAttributes,
+ POLICY_CREATE_SECRET,
+ &PolicyHandle);
+ if (!NT_SUCCESS(Status))
+ return RtlNtStatusToDosError(Status);
+
+ ServiceName.Length = (wcslen(pszServiceName) + 4) * sizeof(WCHAR);
+ 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,
+ pszPassword ? &Password : NULL);
+ 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;
+}
+
+
+DWORD
+ScmWriteSecurityDescriptor(
+ _In_ HKEY hServiceKey,
+ _In_ PSECURITY_DESCRIPTOR pSecurityDescriptor)
+{
+ HKEY hSecurityKey = NULL;
+ DWORD dwDisposition;
+ DWORD dwError;
+
+ DPRINT("ScmWriteSecurityDescriptor(%p %p)\n", hServiceKey, pSecurityDescriptor);
+
+ dwError = RegCreateKeyExW(hServiceKey,
+ L"Security",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_SET_VALUE,
+ NULL,
+ &hSecurityKey,
+ &dwDisposition);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ dwError = RegSetValueExW(hSecurityKey,
+ L"Security",
+ 0,
+ REG_BINARY,
+ (LPBYTE)pSecurityDescriptor,
+ RtlLengthSecurityDescriptor(pSecurityDescriptor));
+
+ RegCloseKey(hSecurityKey);
+
+ 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;
+
+ DPRINT("ScmReadSecurityDescriptor(%p %p)\n", hServiceKey, ppSecurityDescriptor);
+
+ *ppSecurityDescriptor = NULL;
+
+ dwError = RegOpenKeyExW(hServiceKey,
+ L"Security",
+ 0,
+ KEY_QUERY_VALUE,
+ &hSecurityKey);
+ if (dwError != ERROR_SUCCESS)
+ {
+ 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;
+ goto done;
+ }
+
+ dwError = RegQueryValueExW(hSecurityKey,
+ L"Security",
+ 0,
+ &dwType,
+ NULL,
+ &dwBufferLength);
+ if (dwError != ERROR_SUCCESS)
+ {
+ 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;
+ goto done;
+ }
+
+ DPRINT("dwBufferLength: %lu\n", dwBufferLength);
+ pRelativeSD = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ dwBufferLength);
+ if (pRelativeSD == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ DPRINT("pRelativeSD: %lu\n", pRelativeSD);
+ dwError = RegQueryValueExW(hSecurityKey,
+ L"Security",
+ 0,
+ &dwType,
+ (LPBYTE)pRelativeSD,
+ &dwBufferLength);
+ if (dwError != ERROR_SUCCESS)
+ {
+ goto done;
+ }
+
+ *ppSecurityDescriptor = pRelativeSD;
+
+done:
+ if (dwError != ERROR_SUCCESS && pRelativeSD != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, pRelativeSD);
+
+ if (hSecurityKey != NULL)
+ RegCloseKey(hSecurityKey);
+
+ return dwError;
+}
+
+
+DWORD
+ScmDeleteRegKey(
+ _In_ HKEY hKey,
+ _In_ PCWSTR pszSubKey)
+{
+ DWORD dwMaxSubkeyLen, dwMaxValueLen;
+ DWORD dwMaxLen, dwSize;
+ PWSTR pszName = NULL;
+ HKEY hSubKey;
+ DWORD dwError;
+
+ dwError = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
+ if (dwError != ERROR_SUCCESS)
+ return dwError;
+
+ /* Get maximum length of key and value names */
+ dwError = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
+ &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;
+ if (RegEnumKeyExW(hSubKey, 0, pszName, &dwSize,
+ NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ dwError = ScmDeleteRegKey(hSubKey, pszName);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+ }
+
+done:
+ if (pszName != NULL)
+ HeapFree(GetProcessHeap(), 0, pszName);
+
+ RegCloseKey(hSubKey);
+
+ /* Finally delete the key */
+ if (dwError == ERROR_SUCCESS)
+ dwError = RegDeleteKeyW(hKey, pszSubKey);
+
+ return dwError;
+}
+
+
+DWORD
+ScmDecryptPassword(
+ _In_ PBYTE pPassword,
+ _In_ DWORD dwPasswordSize,
+ _Out_ PWSTR *pClearTextPassword)
+{
+ PWSTR pBuffer;
+
+ /* Allocate a buffer for the decrypted password */
+ pBuffer = HeapAlloc(GetProcessHeap(), 0, dwPasswordSize);
+ if (pBuffer == NULL)
+ return ERROR_OUTOFMEMORY;
+
+ /* Decrypt the password */
+ CopyMemory(pBuffer,
+ pPassword,
+ dwPasswordSize);
+
+ *pClearTextPassword = pBuffer;
+
+ return ERROR_SUCCESS;
+}
+
/* EOF */