Fragensteller
Windows 8: Interaktiven Prozess von Windows Service aus starten

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.
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. -
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.