Author: ekohl
Date: Sat May 28 21:56:56 2016
New Revision: 71449
URL:
http://svn.reactos.org/svn/reactos?rev=71449&view=rev
Log:
[SERVICES]
Prepare service logon.
Modified:
trunk/reactos/base/system/services/database.c
trunk/reactos/base/system/services/rpcserver.c
trunk/reactos/base/system/services/services.h
Modified: trunk/reactos/base/system/services/database.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/datab…
==============================================================================
--- trunk/reactos/base/system/services/database.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/database.c [iso-8859-1] Sat May 28 21:56:56 2016
@@ -140,9 +140,9 @@
CurrentImage = CONTAINING_RECORD(ImageEntry,
SERVICE_IMAGE,
ImageListEntry);
- if (_wcsicmp(CurrentImage->szImagePath, lpImagePath) == 0)
- {
- DPRINT("Found image: '%S'\n",
CurrentImage->szImagePath);
+ if (_wcsicmp(CurrentImage->pszImagePath, lpImagePath) == 0)
+ {
+ DPRINT("Found image: '%S'\n",
CurrentImage->pszImagePath);
return CurrentImage;
}
@@ -153,21 +153,114 @@
return NULL;
+}
+
+
+static
+BOOL
+ScmIsSameServiceAccount(
+ IN PWSTR pszAccountName1,
+ IN PWSTR pszAccountName2)
+{
+ if ((pszAccountName1 == NULL && pszAccountName2 == NULL) ||
+ (pszAccountName1 == NULL && wcscmp(pszAccountName2,
L"LocalSystem") == 0) ||
+ (pszAccountName2 == NULL && wcscmp(pszAccountName1,
L"LocalSystem") == 0) ||
+ (wcscmp(pszAccountName1, pszAccountName2) == 0))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static
+BOOL
+ScmIsLocalSystemAccount(
+ IN PWSTR pszAccountName)
+{
+ if (pszAccountName == NULL ||
+ wcscmp(pszAccountName, L"LocalSystem") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+static
+DWORD
+ScmLogonService(
+ IN PSERVICE pService,
+ IN PSERVICE_IMAGE pImage)
+{
+ PWSTR pUserName = NULL;
+ PWSTR pDomainName = NULL;
+ PWSTR ptr;
+ DWORD dwError = ERROR_SUCCESS;
+
+ DPRINT("ScmLogonService()\n");
+
+ DPRINT("Service %S\n", pService->lpServiceName);
+
+ if (ScmIsLocalSystemAccount(pImage->pszAccountName))
+ return ERROR_SUCCESS;
+
+ ptr = wcschr(pImage->pszAccountName, L'\\');
+ if (ptr != NULL)
+ {
+ *ptr = 0;
+
+ pUserName = ptr + 1;
+ pDomainName = pImage->pszAccountName;
+ }
+ else
+ {
+ pUserName = pImage->pszAccountName;
+ pDomainName = NULL;
+ }
+
+ if (pDomainName == NULL || wcscmp(pDomainName, L".") == 0)
+ {
+ // pDomainName = computer name
+ }
+
+ DPRINT("Domain: %S User: %S\n", pDomainName, pUserName);
+
+ /* FIXME */
+#if 0
+ if (!LogonUserW(pUserName,
+ pDomainName,
+ L"", // lpszPassword,
+ LOGON32_LOGON_SERVICE,
+ LOGON32_PROVIDER_DEFAULT,
+ &pImage->hToken))
+ {
+ dwError = GetLastError();
+ DPRINT1("LogonUserW() failed (Error %lu)\n", dwError);
+ }
+#endif
+
+ if (ptr != NULL)
+ *ptr = L'\\';
+
+ return dwError;
}
static DWORD
ScmCreateOrReferenceServiceImage(PSERVICE pService)
{
- RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ RTL_QUERY_REGISTRY_TABLE QueryTable[3];
UNICODE_STRING ImagePath;
+ UNICODE_STRING ObjectName;
PSERVICE_IMAGE pServiceImage = NULL;
NTSTATUS Status;
DWORD dwError = ERROR_SUCCESS;
+ DWORD dwRecordSize;
+ LPWSTR pString;
DPRINT("ScmCreateOrReferenceServiceImage(%p)\n", pService);
RtlInitUnicodeString(&ImagePath, NULL);
+ RtlInitUnicodeString(&ObjectName, NULL);
/* Get service data */
RtlZeroMemory(&QueryTable,
@@ -176,6 +269,9 @@
QueryTable[0].Name = L"ImagePath";
QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].EntryContext = &ImagePath;
+ QueryTable[1].Name = L"ObjectName";
+ QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[1].EntryContext = &ObjectName;
Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
pService->lpServiceName,
@@ -189,14 +285,19 @@
}
DPRINT("ImagePath: '%wZ'\n", &ImagePath);
+ DPRINT("ObjectName: '%wZ'\n", &ObjectName);
pServiceImage = ScmGetServiceImageByImagePath(ImagePath.Buffer);
if (pServiceImage == NULL)
{
+ dwRecordSize = sizeof(SERVICE_IMAGE) +
+ ImagePath.Length + sizeof(WCHAR) +
+ ((ObjectName.Length != 0) ? (ObjectName.Length + sizeof(WCHAR)) :
0);
+
/* Create a new service image */
pServiceImage = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
- FIELD_OFFSET(SERVICE_IMAGE,
szImagePath[ImagePath.Length / sizeof(WCHAR) + 1]));
+ dwRecordSize);
if (pServiceImage == NULL)
{
dwError = ERROR_NOT_ENOUGH_MEMORY;
@@ -206,11 +307,30 @@
pServiceImage->dwImageRunCount = 1;
pServiceImage->hControlPipe = INVALID_HANDLE_VALUE;
+ pString = (PWSTR)((INT_PTR)pServiceImage + sizeof(SERVICE_IMAGE));
+
/* Set the image path */
- wcscpy(pServiceImage->szImagePath,
+ pServiceImage->pszImagePath = pString;
+ wcscpy(pServiceImage->pszImagePath,
ImagePath.Buffer);
- RtlFreeUnicodeString(&ImagePath);
+ /* Set the account name */
+ if (ObjectName.Length > 0)
+ {
+ pString = pString + wcslen(pString) + 1;
+
+ pServiceImage->pszAccountName = pString;
+ wcscpy(pServiceImage->pszAccountName,
+ ObjectName.Buffer);
+ }
+
+ /* Service logon */
+ dwError = ScmLogonService(pService, pServiceImage);
+ if (dwError != ERROR_SUCCESS)
+ {
+ DPRINT1("ScmLogonService() failed (Error %lu)\n", dwError);
+ goto done;
+ }
/* Create the control pipe */
dwError = ScmCreateNewControlPipe(pServiceImage);
@@ -229,16 +349,28 @@
}
else
{
+// if ((lpService->Status.dwServiceType & SERVICE_WIN32_SHARE_PROCESS) ==
0)
+
+ /* Fail if services in an image use different accounts */
+ if (!ScmIsSameServiceAccount(pServiceImage->pszAccountName,
ObjectName.Buffer))
+ {
+ dwError = ERROR_DIFFERENT_SERVICE_ACCOUNT;
+ goto done;
+ }
+
/* Increment the run counter */
pServiceImage->dwImageRunCount++;
}
+ DPRINT("pServiceImage->pszImagePath: %S\n",
pServiceImage->pszImagePath);
+ DPRINT("pServiceImage->pszAccountName: %S\n",
pServiceImage->pszAccountName);
DPRINT("pServiceImage->dwImageRunCount: %lu\n",
pServiceImage->dwImageRunCount);
/* Link the service image to the service */
pService->lpImage = pServiceImage;
-done:;
+done:
+ RtlFreeUnicodeString(&ObjectName);
RtlFreeUnicodeString(&ImagePath);
DPRINT("ScmCreateOrReferenceServiceImage() done (Error: %lu)\n", dwError);
@@ -262,6 +394,10 @@
/* Remove the service image from the list */
RemoveEntryList(&pServiceImage->ImageListEntry);
+
+ /* Close the logon token */
+ if (pServiceImage->hToken != NULL)
+ CloseHandle(pServiceImage->hToken);
/* Close the control pipe */
if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
@@ -1566,16 +1702,17 @@
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
- Result = CreateProcessW(NULL,
- Service->lpImage->szImagePath,
- NULL,
- NULL,
- FALSE,
- DETACHED_PROCESS | CREATE_SUSPENDED,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation);
+ Result = CreateProcessAsUserW(Service->lpImage->hToken,
+ NULL,
+ Service->lpImage->pszImagePath,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS | CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
if (!Result)
{
dwError = GetLastError();
Modified: trunk/reactos/base/system/services/rpcserver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcse…
==============================================================================
--- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Sat May 28 21:56:56 2016
@@ -1992,6 +1992,7 @@
goto done;
}
+ /* Set the tag */
if (lpdwTagId != NULL)
{
dwError = ScmAssignNewTag(lpService);
Modified: trunk/reactos/base/system/services/services.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/servi…
==============================================================================
--- trunk/reactos/base/system/services/services.h [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/services.h [iso-8859-1] Sat May 28 21:56:56 2016
@@ -43,13 +43,14 @@
typedef struct _SERVICE_IMAGE
{
LIST_ENTRY ImageListEntry;
+ LPWSTR pszImagePath;
+ LPWSTR pszAccountName;
DWORD dwImageRunCount;
HANDLE hControlPipe;
HANDLE hProcess;
DWORD dwProcessId;
-
- WCHAR szImagePath[1];
+ HANDLE hToken;
} SERVICE_IMAGE, *PSERVICE_IMAGE;