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/database.c?rev=71449&r1=71448&r2=71449&view=diff ============================================================================== --- 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/rpcserver.c?rev=71449&r1=71448&r2=71449&view=diff ============================================================================== --- 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/services.h?rev=71449&r1=71448&r2=71449&view=diff ============================================================================== --- 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;