#include <userenv.h>
#include <strsafe.h>
+#include <reactos/undocuser.h>
+
#define NDEBUG
#include <debug.h>
static RTL_RESOURCE DatabaseLock;
static DWORD ResumeCount = 1;
static DWORD NoInteractiveServices = 0;
+static DWORD ServiceTag = 0;
/* The critical section synchronizes service control requests */
static CRITICAL_SECTION ControlServiceCriticalSection;
}
+DWORD
+ScmGetServiceNameFromTag(PTAG_INFO_NAME_FROM_TAG_IN_PARAMS InParams, PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS *OutParams)
+{
+ PLIST_ENTRY ServiceEntry;
+ PSERVICE CurrentService;
+ PSERVICE_IMAGE CurrentImage;
+ PTAG_INFO_NAME_FROM_TAG_OUT_PARAMS OutBuffer = NULL;
+ DWORD dwError;
+
+ /* Lock the database */
+ ScmLockDatabaseExclusive();
+
+ /* Find the matching service */
+ ServiceEntry = ServiceListHead.Flink;
+ while (ServiceEntry != &ServiceListHead)
+ {
+ CurrentService = CONTAINING_RECORD(ServiceEntry,
+ SERVICE,
+ ServiceListEntry);
+
+ /* We must match the tag */
+ if (CurrentService->dwTag == InParams->dwTag &&
+ CurrentService->lpImage != NULL)
+ {
+ CurrentImage = CurrentService->lpImage;
+ /* And matching the PID */
+ if (CurrentImage->hProcess == (HANDLE)InParams->dwPid)
+ {
+ break;
+ }
+ }
+
+ ServiceEntry = ServiceEntry->Flink;
+ }
+
+ /* No match! */
+ if (ServiceEntry == &ServiceListHead)
+ {
+ dwError = ERROR_RETRY;
+ goto Cleanup;
+ }
+
+ /* Allocate the output buffer */
+ OutBuffer = MIDL_user_allocate(sizeof(TAG_INFO_NAME_FROM_TAG_OUT_PARAMS));
+ if (OutBuffer == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ /* And the buffer for the name */
+ OutBuffer->pszName = MIDL_user_allocate(wcslen(CurrentService->lpServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
+ if (OutBuffer->pszName == NULL)
+ {
+ dwError = ERROR_NOT_ENOUGH_MEMORY;
+ goto Cleanup;
+ }
+
+ /* Fill in output data */
+ wcscpy(OutBuffer->pszName, CurrentService->lpServiceName);
+ OutBuffer->TagType = TagTypeService;
+
+ /* And return */
+ *OutParams = OutBuffer;
+ dwError = ERROR_SUCCESS;
+
+Cleanup:
+
+ /* Unlock database */
+ ScmUnlockDatabase();
+
+ /* If failure, free allocated memory */
+ if (dwError != ERROR_SUCCESS)
+ {
+ MIDL_user_free(OutBuffer);
+ }
+
+ /* Return error/success */
+ return dwError;
+}
+
+
static
BOOL
ScmIsSameServiceAccount(
_In_ PCWSTR pszAccountName1,
_In_ PCWSTR pszAccountName2)
{
- if (pszAccountName1 == NULL && pszAccountName2 == NULL)
+ if (pszAccountName1 == NULL &&
+ pszAccountName2 == NULL)
return TRUE;
- if (pszAccountName1 == NULL && pszAccountName2 && wcscmp(pszAccountName2, L"LocalSystem") == 0)
+ if (pszAccountName1 == NULL &&
+ pszAccountName2 != NULL &&
+ _wcsicmp(pszAccountName2, L"LocalSystem") == 0)
return TRUE;
- if (pszAccountName2 == NULL && pszAccountName1 && wcscmp(pszAccountName1, L"LocalSystem") == 0)
+ if (pszAccountName1 != NULL &&
+ pszAccountName2 == NULL &&
+ _wcsicmp(pszAccountName1, L"LocalSystem") == 0)
return TRUE;
- if (pszAccountName1 && pszAccountName2 && wcscmp(pszAccountName1, pszAccountName2) == 0)
+ if (pszAccountName1 != NULL &&
+ pszAccountName2 != NULL &&
+ _wcsicmp(pszAccountName1, pszAccountName2) == 0)
return TRUE;
return FALSE;
_In_ PCWSTR pszAccountName)
{
if (pszAccountName == NULL ||
- wcscmp(pszAccountName, L"LocalSystem") == 0)
+ _wcsicmp(pszAccountName, L"LocalSystem") == 0)
return TRUE;
return FALSE;
IN PSERVICE pService,
IN PSERVICE_IMAGE pImage)
{
-#if 0
+ DWORD dwError = ERROR_SUCCESS;
PROFILEINFOW ProfileInfo;
PWSTR pszUserName = NULL;
PWSTR pszDomainName = NULL;
PWSTR pszPassword = NULL;
PWSTR ptr;
- DWORD dwError = ERROR_SUCCESS;
-#endif
DPRINT("ScmLogonService(%p %p)\n", pService, pImage);
-
DPRINT("Service %S\n", pService->lpServiceName);
if (ScmIsLocalSystemAccount(pImage->pszAccountName))
return ERROR_SUCCESS;
- // FIXME: Always assume LocalSystem
- return ERROR_SUCCESS;
-
-#if 0
/* Get the user and domain names */
ptr = wcschr(pImage->pszAccountName, L'\\');
if (ptr != NULL)
{
*ptr = L'\0';
-
pszUserName = ptr + 1;
pszDomainName = pImage->pszAccountName;
}
else
{
+ // ERROR_INVALID_SERVICE_ACCOUNT
pszUserName = pImage->pszAccountName;
pszDomainName = NULL;
}
DPRINT("Domain: %S User: %S Password: %S\n", pszDomainName, pszUserName, pszPassword);
- /* Service logon */
+ /* Do the service logon */
if (!LogonUserW(pszUserName,
pszDomainName,
pszPassword,
{
dwError = GetLastError();
DPRINT1("LogonUserW() failed (Error %lu)\n", dwError);
+
+ /* Normalize the returned error */
+ dwError = ERROR_SERVICE_LOGON_FAILED;
goto done;
}
- // FIXME: Call LoadUserProfileW to be able to initialize a per-user
- // environment block, with user-specific environment variables as
- // %USERNAME%, %USERPROFILE%, and %ALLUSERSPROFILE% correctly initialized!!
-
- /* Load the user profile, so that the per-user environment variables can be initialized */
+ /* Load the user profile; the per-user environment variables are thus correctly initialized */
ZeroMemory(&ProfileInfo, sizeof(ProfileInfo));
ProfileInfo.dwSize = sizeof(ProfileInfo);
ProfileInfo.dwFlags = PI_NOUI;
*ptr = L'\\';
return dwError;
-#endif
}
}
+DWORD
+ScmGenerateServiceTag(PSERVICE lpServiceRecord)
+{
+ /* Check for an overflow */
+ if (ServiceTag == -1)
+ {
+ return ERROR_INVALID_DATA;
+ }
+
+ /* This is only valid for Win32 services */
+ if (!(lpServiceRecord->Status.dwServiceType & SERVICE_WIN32))
+ {
+ return ERROR_INVALID_PARAMETER;
+ }
+
+ /* Increment the tag counter and set it */
+ ServiceTag = ServiceTag % 0xFFFFFFFF + 1;
+ lpServiceRecord->dwTag = ServiceTag;
+
+ return ERROR_SUCCESS;
+}
+
+
DWORD
ScmCreateNewServiceRecord(LPCWSTR lpServiceName,
PSERVICE *lpServiceRecord,
if (ScmIsDeleteFlagSet(hServiceKey))
lpService->bDeleted = TRUE;
+ else
+ ScmGenerateServiceTag(lpService);
if (lpService->Status.dwServiceType & SERVICE_WIN32)
{
? SERVICE_CONTROL_START_OWN
: SERVICE_CONTROL_START_SHARE;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
+ ControlPacket->dwServiceTag = Service->dwTag;
/* Copy the start command line */
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
- /* Use the interactive desktop if the service is interactive */
- if ((NoInteractiveServices == 0) &&
- (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
- StartupInfo.lpDesktop = L"WinSta0\\Default";
-
if (Service->lpImage->hToken)
{
/* User token: Run the service under the user account */
lpEnvironment = NULL;
}
+ /* Use the interactive desktop if the service is interactive */
+ if ((NoInteractiveServices == 0) &&
+ (Service->Status.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
+ {
+ StartupInfo.dwFlags |= STARTF_INHERITDESKTOP;
+ StartupInfo.lpDesktop = L"WinSta0\\Default";
+ }
+
Result = CreateProcessW(NULL,
Service->lpImage->pszImagePath,
NULL,