Starting an Interactive Client Process in C++

简介:

The following example uses the  LogonUser  function to start a new  logon session  for a client. The example gets the  logon SID  from the client's  access token , and uses it to add  access control entries  (ACEs) to the  discretionary access control list  (DACL) of the interactive window station and desktop. The ACEs allow the client access to the interactive desktop for the duration of the logon session. Next, the example calls the ImpersonateLoggedOnUserfunction to ensure that it has access to the client's executable file. A call to the  CreateProcessAsUser  function creates the client's  process , specifying that it run in the interactive desktop. Note that your process must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges for successful execution of CreateProcessAsUser. Before the function returns, it calls the RevertToSelf function to end the caller's impersonation of the client.

This example calls the GetLogonSID and FreeLogonSID functions described in Getting the Logon SID in C++.

  #define  DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \ 
DESKTOP_CREATEMENU  |  DESKTOP_HOOKCONTROL  |  DESKTOP_JOURNALRECORD  |  \
DESKTOP_JOURNALPLAYBACK  |  DESKTOP_ENUMERATE  |  DESKTOP_WRITEOBJECTS  |  \
DESKTOP_SWITCHDESKTOP  |  STANDARD_RIGHTS_REQUIRED)

  #define  WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \ 
WINSTA_ACCESSCLIPBOARD  |  WINSTA_CREATEDESKTOP  |  WINSTA_WRITEATTRIBUTES  |  \
WINSTA_ACCESSGLOBALATOMS  |  WINSTA_EXITWINDOWS  |  WINSTA_ENUMERATE  |  \
WINSTA_READSCREEN  |  STANDARD_RIGHTS_REQUIRED)

  #define  GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | \ 
GENERIC_ALL)

BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid);

BOOL AddAceToDesktop(HDESK hdesk, PSID psid);

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(
        " 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(
       " 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;
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess  =  FALSE;
   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 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   =   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;
   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;
目录
相关文章
|
9月前
|
传感器 人工智能 机器人
具身智能9大开源工具全景解析:人形机器人开发必备指南
本文旨在对具身智能、人形机器人、协作机器人、AI机器人、端到端AI系统、AI Agent、AI Agentic、空间智能或世界模型等前沿领域中具有重要影响力的开源软件产品或工具进行深入分析,重点聚焦于支持这些先进AI能力实现的工具、平台和框架。
3338 8
|
人工智能 编解码 内存技术
手把手教你生成一幅好看的AI图片
想要生成一幅好看的AI图片,但是却不知道如何下手?只会1girl的你现在是不是很烦恼?别急,看这篇文章就够了。
手把手教你生成一幅好看的AI图片
|
存储 监控 安全
SaaS业务架构:业务能力分析
【9月更文挑战第20天】在数字化时代,软件即服务(SaaS)模式逐渐成为企业软件解决方案的首选。SaaS 业务架构设计对于提供高效、可靠的服务至关重要。其核心业务能力包括:用户管理(注册登录、角色权限)、数据管理(存储备份、安全共享)、业务流程管理(设计定制、工作流自动化)、应用集成(第三方应用、移动应用)及客户服务(支持培训、反馈改进)。通过优化这些能力,可为企业提供更高效、可靠的 SaaS 服务。
423 11
|
应用服务中间件 Apache Windows
免安装版的Tomcat注册为windows服务
免安装版的Tomcat注册为windows服务
605 3
|
前端开发 测试技术 程序员
在工作中会涉及到的几个环境(概念补充) 办公环境、开发环境、测试环境、线下环境、线上环境/生产环境都是什么,他们之间的关系?
本文解释了在职场中可能会接触到的不同环境,包括办公环境、开发环境、测试环境和生产环境(线上环境),以及它们之间的关系和重要性。
702 1
|
XML JavaScript Java
NekoHTML 是一个基于Java的HTML扫描器和标签补全器
**NekoHTML** 是一个基于Java的HTML扫描器和标签补全器(tag balancer),由J. Andrew Clark开发。它主要用于解析HTML文档,并能够“修正”许多在编写HTML文档过程中常犯的错误,如增补缺失的父元素、自动用结束标签关闭相应的元素,以及处理不匹配的内嵌元素标签等。这使得程序能够以标准的XML接口来访问HTML文档中的信息。 ### NekoHTML的主要特点包括: 1. **错误修正**:能够自动修正HTML中的常见错误,如未闭合的标签等。 2. **DOM树生成**:将HTML源代码转化为DOM(Document Object Model)结构,便
388 1
|
JSON API 数据格式
App Inventor 2 天气预报App开发 - 第三方API接入的通用方法
通过调用第三方天气api,填入必要的参数,通过Web客户端请求url。返回json格式的数据结果,使用AppInventor2解析json结果,显示到App上即可。
703 5
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的校园综合服务平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的校园综合服务平台的详细设计和实现(源码+lw+部署文档+讲解等)
356 5
|
存储 算法 Java
分布式自增ID算法---雪花算法(SnowFlake)Java实现
分布式自增ID算法---雪花算法(SnowFlake)Java实现
1818 0
|
开发者 Windows Android开发
跨平台开发新选择:揭秘Uno Platform与.NET MAUI优劣对比,帮你找到最适合的框架,告别选择困难症!
【8月更文挑战第31天】本文对比了备受关注的跨平台开发框架Uno Platform与.NET MAUI的特点、优势及适用场景。Uno Platform基于WebAssembly和WebGL技术,支持Windows、iOS、Android及Web平台,而.NET MAUI由微软推出,旨在统一多种UI框架,支持Windows、iOS和Android。两者均采用C#和XAML进行开发,但在性能、平台支持及社区生态方面存在差异。Uno Platform在Web应用方面表现出色,但性能略逊于原生应用;.NET MAUI则接近原生性能,但不支持Web平台。开发者应根据具体需求选择合适的框架。
860 0