系统服务启动交互式程序(C++)

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;
   }
	
posted on 2010-12-28 23:12  yangyh  阅读(2348)  评论(2编辑  收藏  举报