none
Windows 8: Interaktiven Prozess von Windows Service aus starten RRS feed

  • Frage

  • Hallo,

    ich haben einen Service der bisher in der Lage war einen Interaktiven Prozess zu starten. Leider funktioniert das ab Windows 8 nicht mehr. Der Prozess wird zwar gestartet jedoch nicht auf der sichtbaren Window Station/Desktop angezeigt. Ich habe diesbezüglich viele Artikel gelesen, diese bezogen sich jedoch immer nur auf Windows Vista oder Windows 7. Kann mir jemand sagen, ob sich in Windows 8 gegenüber Windows 7 etwas geändert hat und ob das überhaubt noch unter Windows 8 möglich ist.

    Vielen Dank im Voraus.

    Montag, 14. Januar 2013 13:18

Alle Antworten

  • Wie startest Du denn Deinen "interaktiven" Prozess aus dem Service?

    Best regards

    Bordon

    Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.

    Montag, 14. Januar 2013 13:45
  • Hallo Bordon,

    ich habe es zuletzt mit einem Beispielcode, den ich auf einer Seite im Internet gefunden habe probiert. Die Funktion StartInteractiveClientProcess ("MyUser","MyPassword","MyDomain","C:/Windows/notepad.exe") soll den Windows Editor anzeigen und wird ereignisgesteuert im Service aufgerufen. Der Service läuft unter dem "LocalSystem"-Acount.

    BOOL StartInteractiveClientProcess (
    	LPTSTR lpszUsername,    // client to log on
    	LPTSTR lpszDomain,      // domain of client's account
    	LPTSTR lpszPassword,    // client's password
    	LPTSTR lpCommandLine    // command line to execute
    	) 
    {
    	HANDLE      hToken;
    	HDESK       hdesk = NULL;
    	HWINSTA     hwinsta = NULL, hwinstaSave = NULL;
    	PROCESS_INFORMATION pi;
    	PSID pSid = NULL;
    	STARTUPINFO si;
    	BOOL bResult = FALSE;
    	// Log the client on to the local computer.
    	if (!LogonUser(
    		lpszUsername,
    		lpszDomain,
    		lpszPassword,
    		LOGON32_LOGON_INTERACTIVE,
    		LOGON32_PROVIDER_DEFAULT,
    		&hToken) ) 
    	{
    		goto Cleanup;
    	}
    	// Save a handle to the caller's current window station.
    	if ( (hwinstaSave = GetProcessWindowStation() ) == NULL)
    		goto Cleanup;
    	// Get a handle to the interactive window station.
    	hwinsta = OpenWindowStation(
    		_T("winsta0"),                   // the interactive window station 
    		FALSE,                       // handle is not inheritable
    		READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL
    	if (hwinsta == NULL) 
    		goto Cleanup;
    	// To get the correct default desktop, set the caller's 
    	// window station to the interactive window station.
    	if (!SetProcessWindowStation(hwinsta))
    		goto Cleanup;
    	// Get a handle to the interactive desktop.
    	hdesk = OpenDesktop(
    		_T("default"),     // the interactive window station 
    		0,             // no interaction with other desktop processes
    		FALSE,         // handle is not inheritable
    		READ_CONTROL | // request the rights to read and write the DACL
    		WRITE_DAC | 
    		DESKTOP_WRITEOBJECTS | 
    		DESKTOP_READOBJECTS);
    	// Restore the caller's window station.
    	if (!SetProcessWindowStation(hwinstaSave)) 
    		goto Cleanup;
    	if (hdesk == NULL) 
    		goto Cleanup;
    	// Get the SID for the client's logon session.
    	if (!GetLogonSID(hToken, &pSid)) 
    		goto Cleanup;
    	// Allow logon SID full access to interactive window station.
    	if (! AddAceToWindowStation(hwinsta, pSid) ) 
    		goto Cleanup;
    	// Allow logon SID full access to interactive desktop.
    	if (! AddAceToDesktop(hdesk, pSid) ) 
    		goto Cleanup;
    	// Impersonate client to ensure access to executable file.
    	if (! ImpersonateLoggedOnUser(hToken) ) 
    		goto Cleanup;
    	// Initialize the STARTUPINFO structure.
    	// Specify that the process runs in the interactive desktop.
    	ZeroMemory(&si, sizeof(STARTUPINFO));
    	si.cb= sizeof(STARTUPINFO);
    	si.lpDesktop = TEXT("winsta0\\default");
    	// Launch the process in the client's logon session.
    	bResult = CreateProcessAsUser(
    		hToken,            // client's access token
    		NULL,              // file to execute
    		lpCommandLine,     // command line
    		NULL,              // pointer to process SECURITY_ATTRIBUTES
    		NULL,              // pointer to thread SECURITY_ATTRIBUTES
    		FALSE,             // handles are not inheritable
    		NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,   // creation flags
    		NULL,              // pointer to new environment block 
    		NULL,              // name of current directory 
    		&si,               // pointer to STARTUPINFO structure
    		&pi                // receives information about new process
    		); 
    	// End impersonation of client.
    	RevertToSelf();
    	if (bResult && pi.hProcess != INVALID_HANDLE_VALUE) 
    	{ 
    		WaitForSingleObject(pi.hProcess, INFINITE); 
    		CloseHandle(pi.hProcess); 
    	} 
    	if (pi.hThread != INVALID_HANDLE_VALUE)
    		CloseHandle(pi.hThread);  
    Cleanup: 
    	if (hwinstaSave != NULL)
    		SetProcessWindowStation (hwinstaSave);
    	// Free the buffer for the logon SID.
    	if (pSid)
    		FreeLogonSID(&pSid);
    	// Close the handles to the interactive window station and desktop.
    	if (hwinsta)
    		CloseWindowStation(hwinsta);
    	if (hdesk)
    		CloseDesktop(hdesk);
    	// Close the handle to the client's access token.
    	if (hToken != INVALID_HANDLE_VALUE)
    		CloseHandle(hToken);  
    	return bResult;
    }
    BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid)
    {
    	ACCESS_ALLOWED_ACE   *pace = NULL;
    	ACL_SIZE_INFORMATION aclSizeInfo;
    	BOOL                 bDaclExist;
    	BOOL                 bDaclPresent;
    	BOOL                 bSuccess = FALSE;
    	DWORD                dwNewAclSize;
    	DWORD                dwSidSize = 0;
    	DWORD                dwSdSizeNeeded;
    	PACL                 pacl;
    	PACL                 pNewAcl = NULL;
    	PSECURITY_DESCRIPTOR psd = NULL;
    	PSECURITY_DESCRIPTOR psdNew = NULL;
    	PVOID                pTempAce;
    	SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
    	unsigned int         i;
    	__try
    	{
    		// Obtain the DACL for the window station.
    		if (!GetUserObjectSecurity(
    			hwinsta,
    			&si,
    			psd,
    			dwSidSize,
    			&dwSdSizeNeeded)
    			)
    			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    			{
    				psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
    					GetProcessHeap(),
    					HEAP_ZERO_MEMORY,
    					dwSdSizeNeeded);
    				if (psd == NULL)
    					__leave;
    				psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
    					GetProcessHeap(),
    					HEAP_ZERO_MEMORY,
    					dwSdSizeNeeded);
    				if (psdNew == NULL)
    					__leave;
    				dwSidSize = dwSdSizeNeeded;
    				if (!GetUserObjectSecurity(
    					hwinsta,
    					&si,
    					psd,
    					dwSidSize,
    					&dwSdSizeNeeded)
    					)
    					__leave;
    			}
    			else
    				__leave;
    		// Create a new DACL.
    		if (!InitializeSecurityDescriptor(
    			psdNew,
    			SECURITY_DESCRIPTOR_REVISION)
    			)
    			__leave;
    		// Get the DACL from the security descriptor.
    		if (!GetSecurityDescriptorDacl(
    			psd,
    			&bDaclPresent,
    			&pacl,
    			&bDaclExist)
    			)
    			__leave;
    		// Initialize the ACL.
    		ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
    		aclSizeInfo.AclBytesInUse = sizeof(ACL);
    		// Call only if the DACL is not NULL.
    		if (pacl != NULL)
    		{
    			// get the file ACL size info
    			if (!GetAclInformation(
    				pacl,
    				(LPVOID)&aclSizeInfo,
    				sizeof(ACL_SIZE_INFORMATION),
    				AclSizeInformation)
    				)
    				__leave;
    		}
    		// Compute the size of the new ACL.
    		dwNewAclSize = aclSizeInfo.AclBytesInUse +
    			(2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) -
    			(2*sizeof(DWORD));
    		// Allocate memory for the new ACL.
    		pNewAcl = (PACL)HeapAlloc(
    			GetProcessHeap(),
    			HEAP_ZERO_MEMORY,
    			dwNewAclSize);
    		if (pNewAcl == NULL)
    			__leave;
    		// Initialize the new DACL.
    		if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
    			__leave;
    		// If DACL is present, copy it to a new DACL.
    		if (bDaclPresent)
    		{
    			// Copy the ACEs to the new ACL.
    			if (aclSizeInfo.AceCount)
    			{
    				for (i=0; i < aclSizeInfo.AceCount; i++)
    				{
    					// Get an ACE.
    					if (!GetAce(pacl, i, &pTempAce))
    						__leave;
    					// Add the ACE to the new ACL.
    					if (!AddAce(
    						pNewAcl,
    						ACL_REVISION,
    						MAXDWORD,
    						pTempAce,
    						((PACE_HEADER)pTempAce)->AceSize)
    						)
    						__leave;
    				}
    			}
    		}
    		// Add the first ACE to the window station.
    		pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
    			GetProcessHeap(),
    			HEAP_ZERO_MEMORY,
    			sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
    			sizeof(DWORD));
    		if (pace == NULL)
    			__leave;
    		pace->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;
    		pace->Header.AceFlags = CONTAINER_INHERIT_ACE |
    			INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
    		pace->Header.AceSize  = LOWORD(sizeof(ACCESS_ALLOWED_ACE) +
    			GetLengthSid(psid) - sizeof(DWORD));
    		pace->Mask            = GENERIC_ACCESS;
    		if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
    			__leave;
    		if (!AddAce(
    			pNewAcl,
    			ACL_REVISION,
    			MAXDWORD,
    			(LPVOID)pace,
    			pace->Header.AceSize)
    			)
    			__leave;
    		// Add the second ACE to the window station.
    		pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
    		pace->Mask            = WINSTA_ALL;
    		if (!AddAce(
    			pNewAcl,
    			ACL_REVISION,
    			MAXDWORD,
    			(LPVOID)pace,
    			pace->Header.AceSize)
    			)
    			__leave;
    		// Set a new DACL for the security descriptor.
    		if (!SetSecurityDescriptorDacl(
    			psdNew,
    			TRUE,
    			pNewAcl,
    			FALSE)
    			)
    			__leave;
    		// Set the new security descriptor for the window station.
    		if (!SetUserObjectSecurity(hwinsta, &si, psdNew))
    			__leave;
    		// Indicate success.
    		bSuccess = TRUE;
    	}
    	__finally
    	{
    		// Free the allocated buffers.
    		if (pace != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)pace);
    		if (pNewAcl != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
    		if (psd != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
    		if (psdNew != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
    	}
    	return bSuccess;
    }
    BOOL AddAceToDesktop(HDESK hdesk, PSID psid)
    {
    	ACL_SIZE_INFORMATION aclSizeInfo;
    	BOOL                 bDaclExist;
    	BOOL                 bDaclPresent;
    	BOOL                 bSuccess = FALSE;
    	DWORD                dwNewAclSize;
    	DWORD                dwSidSize = 0;
    	DWORD                dwSdSizeNeeded;
    	PACL                 pacl;
    	PACL                 pNewAcl = NULL;
    	PSECURITY_DESCRIPTOR psd = NULL;
    	PSECURITY_DESCRIPTOR psdNew = NULL;
    	PVOID                pTempAce;
    	SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
    	unsigned int         i;
    	__try
    	{
    		// Obtain the security descriptor for the desktop object.
    		if (!GetUserObjectSecurity(
    			hdesk,
    			&si,
    			psd,
    			dwSidSize,
    			&dwSdSizeNeeded))
    		{
    			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    			{
    				psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
    					GetProcessHeap(),
    					HEAP_ZERO_MEMORY,
    					dwSdSizeNeeded );
    				if (psd == NULL)
    					__leave;
    				psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
    					GetProcessHeap(),
    					HEAP_ZERO_MEMORY,
    					dwSdSizeNeeded);
    				if (psdNew == NULL)
    					__leave;
    				dwSidSize = dwSdSizeNeeded;
    				if (!GetUserObjectSecurity(
    					hdesk,
    					&si,
    					psd,
    					dwSidSize,
    					&dwSdSizeNeeded)
    					)
    					__leave;
    			}
    			else
    				__leave;
    		}
    		// Create a new security descriptor.
    		if (!InitializeSecurityDescriptor(
    			psdNew,
    			SECURITY_DESCRIPTOR_REVISION)
    			)
    			__leave;
    		// Obtain the DACL from the security descriptor.
    		if (!GetSecurityDescriptorDacl(
    			psd,
    			&bDaclPresent,
    			&pacl,
    			&bDaclExist)
    			)
    			__leave;
    		// Initialize.
    		ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
    		aclSizeInfo.AclBytesInUse = sizeof(ACL);
    		// Call only if NULL DACL.
    		if (pacl != NULL)
    		{
    			// Determine the size of the ACL information.
    			if (!GetAclInformation(
    				pacl,
    				(LPVOID)&aclSizeInfo,
    				sizeof(ACL_SIZE_INFORMATION),
    				AclSizeInformation)
    				)
    				__leave;
    		}
    		// Compute the size of the new ACL.
    		dwNewAclSize = aclSizeInfo.AclBytesInUse +
    			sizeof(ACCESS_ALLOWED_ACE) +
    			GetLengthSid(psid) - sizeof(DWORD);
    		// Allocate buffer for the new ACL.
    		pNewAcl = (PACL)HeapAlloc(
    			GetProcessHeap(),
    			HEAP_ZERO_MEMORY,
    			dwNewAclSize);
    		if (pNewAcl == NULL)
    			__leave;
    		// Initialize the new ACL.
    		if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
    			__leave;
    		// If DACL is present, copy it to a new DACL.
    		if (bDaclPresent)
    		{
    			// Copy the ACEs to the new ACL.
    			if (aclSizeInfo.AceCount)
    			{
    				for (i=0; i < aclSizeInfo.AceCount; i++)
    				{
    					// Get an ACE.
    					if (!GetAce(pacl, i, &pTempAce))
    						__leave;
    					// Add the ACE to the new ACL.
    					if (!AddAce(
    						pNewAcl,
    						ACL_REVISION,
    						MAXDWORD,
    						pTempAce,
    						((PACE_HEADER)pTempAce)->AceSize)
    						)
    						__leave;
    				}
    			}
    		}
    		// Add ACE to the DACL.
    		if (!AddAccessAllowedAce(
    			pNewAcl,
    			ACL_REVISION,
    			DESKTOP_ALL,
    			psid)
    			)
    			__leave;
    		// Set new DACL to the new security descriptor.
    		if (!SetSecurityDescriptorDacl(
    			psdNew,
    			TRUE,
    			pNewAcl,
    			FALSE)
    			)
    			__leave;
    		// Set the new security descriptor for the desktop object.
    		if (!SetUserObjectSecurity(hdesk, &si, psdNew))
    			__leave;
    		// Indicate success.
    		bSuccess = TRUE;
    	}
    	__finally
    	{
    		// Free buffers.
    		if (pNewAcl != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
    		if (psd != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
    		if (psdNew != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
    	}
    	return bSuccess;
    }
    BOOL GetLogonSID (HANDLE hToken, PSID *ppsid) 
    {
    	BOOL bSuccess = FALSE;
    	DWORD dwIndex;
    	DWORD dwLength = 0;
    	PTOKEN_GROUPS ptg = NULL;
    	// Verify the parameter passed in is not NULL.
    	if (NULL == ppsid)
    		goto Cleanup;
    	// Get required buffer size and allocate the TOKEN_GROUPS buffer.
    	if (!GetTokenInformation(
    		hToken,         // handle to the access token
    		TokenGroups,    // get information about the token's groups 
    		(LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer
    		0,              // size of buffer
    		&dwLength       // receives required buffer size
    		)) 
    	{
    		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 
    			goto Cleanup;
    		ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),
    			HEAP_ZERO_MEMORY, dwLength);
    		if (ptg == NULL)
    			goto Cleanup;
    	}
    	// Get the token group information from the access token.
    	if (!GetTokenInformation(
    		hToken,         // handle to the access token
    		TokenGroups,    // get information about the token's groups 
    		(LPVOID) ptg,   // pointer to TOKEN_GROUPS buffer
    		dwLength,       // size of buffer
    		&dwLength       // receives required buffer size
    		)) 
    	{
    		goto Cleanup;
    	}
    	// Loop through the groups to find the logon SID.
    	for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) 
    		if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)
    			==  SE_GROUP_LOGON_ID) 
    		{
    			// Found the logon SID; make a copy of it.
    			dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid);
    			*ppsid = (PSID) HeapAlloc(GetProcessHeap(),
    				HEAP_ZERO_MEMORY, dwLength);
    			if (*ppsid == NULL)
    				goto Cleanup;
    			if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid)) 
    			{
    				HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
    				goto Cleanup;
    			}
    			break;
    		}
    		bSuccess = TRUE;
    Cleanup: 
    		// Free the buffer for the token groups.
    		if (ptg != NULL)
    			HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
    		return bSuccess;
    }
    VOID FreeLogonSID (PSID *ppsid) 
    {
    	HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);
    }

    Unter Windows 7 oder früher funktioniert der Code und unter Windows 8 sehe leider nur im TaskManager, dass die Anwendung gestartet wurde.

    Montag, 14. Januar 2013 15:05