KEY: CreateProcessAsUser, service GUI interactive, C++ 启动进程
用于xp,server 2003,不适用于vista以上(http://blog.csdn.net/zhyRzfirst/archive/2009/03/16/3994344.aspx,http://www.codeproject.com/KB/vista-security/VistaSessions.aspx,可遍历WTSEnumerateSessions获取活跃桌面后设置STARTUPINFO参数中的lpDesktop参数)
CreateProcessAsUser 1314错误解决:控制面板-管理工具-本地安全策略-本地策略-用户权限分配-替换一个进程级令牌-添加本用户
参考:
http://stackoverflow.com/questions/267838/how-can-a-windows-service-execute-a-gui-application
http://support.microsoft.com/kb/165194
#include "stdafx.h" #include <iostream> using namespace std; #define RTN_OK 0 #define RTN_ERROR 13 #define WINSTA_ALL (WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS |\ WINSTA_CREATEDESKTOP | WINSTA_ENUMDESKTOPS |\ WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |\ WINSTA_READATTRIBUTES | WINSTA_READSCREEN |\ WINSTA_WRITEATTRIBUTES | DELETE |\ READ_CONTROL | WRITE_DAC |\ WRITE_OWNER) #define DESKTOP_ALL (DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |\ DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |\ DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |\ DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP |\ DESKTOP_WRITEOBJECTS | DELETE |\ READ_CONTROL | WRITE_DAC |\ WRITE_OWNER) #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE |\ GENERIC_EXECUTE | GENERIC_ALL) #include <windows.h> #include <stdio.h> BOOL ObtainSid( HANDLE hToken, // Handle to an process access token. PSID *psid // ptr to the buffer of the logon sid ); void RemoveSid( PSID *psid // ptr to the buffer of the logon sid ); BOOL AddTheAceWindowStation( HWINSTA hwinsta, // handle to a windowstation PSID psid // logon sid of the process ); BOOL AddTheAceDesktop( HDESK hdesk, // handle to a desktop PSID psid // logon sid of the process ); int main(void) { HANDLE hToken; HDESK hdesk; HWINSTA hwinsta; PROCESS_INFORMATION pi; PSID psid; STARTUPINFO si; // // obtain an access token for the user fester // if (!LogonUser( "yangyh", NULL, "adobe", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken )) return RTN_ERROR; // // obtain a handle to the interactive windowstation // hwinsta = OpenWindowStation( "winsta0", FALSE, READ_CONTROL | WRITE_DAC ); if (hwinsta == NULL) return RTN_ERROR; HWINSTA hwinstaold = GetProcessWindowStation(); // // set the windowstation to winsta0 so that you obtain the // correct default desktop // if (!SetProcessWindowStation(hwinsta)) return RTN_ERROR; // // obtain a handle to the "default" desktop // hdesk = OpenDesktop( "default", 0, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS ); if (hdesk == NULL) return RTN_ERROR; // // obtain the logon sid of the user fester // if (!ObtainSid(hToken, &psid)) return RTN_ERROR; // // add the user to interactive windowstation // if (!AddTheAceWindowStation(hwinsta, psid)) return RTN_ERROR; // // add user to "default" desktop // if (!AddTheAceDesktop(hdesk, psid)) return RTN_ERROR; // // free the buffer for the logon sid // RemoveSid(&psid); // // close the handles to the interactive windowstation and desktop // CloseWindowStation(hwinsta); CloseDesktop(hdesk); // // initialize STARTUPINFO structure // ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.lpDesktop = "winsta0\\default"; // // start the process // char str[256]; string cmd="E:\\Program Files\\Tencent\\QQ\\Bin\\QQ.exe"; sprintf(str,"\"%s\"",cmd.c_str()); if (!CreateProcessAsUser( hToken, NULL, str, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi )) return RTN_ERROR; SetProcessWindowStation(hwinstaold); //set it back // // close the handles // CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return RTN_OK; } BOOL ObtainSid(HANDLE hToken, PSID *psid) { BOOL bSuccess = FALSE; // assume function will // fail DWORD dwIndex; DWORD dwLength = 0; TOKEN_INFORMATION_CLASS tic = TokenGroups; PTOKEN_GROUPS ptg = NULL; __try { // // determine the size of the buffer // if (!GetTokenInformation( hToken, tic, (LPVOID)ptg, 0, &dwLength )) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { ptg = (PTOKEN_GROUPS)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength ); if (ptg == NULL) __leave; } else __leave; } // // obtain the groups the access token belongs to // if (!GetTokenInformation( hToken, tic, (LPVOID)ptg, dwLength, &dwLength )) __leave; // // determine which group is the logon sid // for (dwIndex = 0; dwIndex < ptg->GroupCount; dwIndex++) { if ((ptg->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) { // // determine the length of the sid // dwLength = GetLengthSid(ptg->Groups[dwIndex].Sid); // // allocate a buffer for the logon sid // *psid = (PSID)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength ); if (*psid == NULL) __leave; // // obtain a copy of the logon sid // if (!CopySid(dwLength, *psid, ptg->Groups[dwIndex].Sid)) __leave; // // break out of the loop because the logon sid has been // found // break; } } // // indicate success // bSuccess = TRUE; } __finally { // // free the buffer for the token group // if (ptg != NULL) HeapFree(GetProcessHeap(), 0, (LPVOID)ptg); } return bSuccess; } void RemoveSid(PSID *psid) { HeapFree(GetProcessHeap(), 0, (LPVOID)*psid); } BOOL AddTheAceWindowStation(HWINSTA hwinsta, PSID psid) { ACCESS_ALLOWED_ACE *pace; ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; // assume function will //fail DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl; PACL pNewAcl; 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 windowstation // 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 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 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) // only copy if DACL was present { // copy the ACEs to our 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 windowstation // 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 = 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 windowstation // pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE; pace->Mask = WINSTA_ALL; if (!AddAce( pNewAcl, ACL_REVISION, MAXDWORD, (LPVOID)pace, pace->Header.AceSize )) __leave; // // set new dacl for the security descriptor // if (!SetSecurityDescriptorDacl( psdNew, TRUE, pNewAcl, FALSE )) __leave; // // set the new security descriptor for the windowstation // 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 AddTheAceDesktop(HDESK hdesk, PSID psid) { ACL_SIZE_INFORMATION aclSizeInfo; BOOL bDaclExist; BOOL bDaclPresent; BOOL bSuccess = FALSE; // assume function will // fail DWORD dwNewAclSize; DWORD dwSidSize = 0; DWORD dwSdSizeNeeded; PACL pacl; PACL pNewAcl; 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 info // 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) // only copy if DACL was present { // copy the ACEs to our 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; }