系统服务启动交互式程序(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;

   }

	

你可能感兴趣的:(C++)