Window Stations and Desktops 6

 

 

Starting an Interactive Client Process in C++ Working Program Example

 

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 ImpersonateLoggedOnUser() function 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.

 

 

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

Then, add the source file and give it a suitable name.

Next, add the following source code.

 

#include <windows.h>

#include <stdio.h>

 

// Constants

#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)

 

// Prototypes

BOOL GetLogonSID(HANDLE hToken, PSID *ppsid);

VOID FreeLogonSID (PSID *ppsid);

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

      );

BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid);

BOOL AddAceToDesktop(HDESK hdesk, PSID psid);

BOOL RemoveAceFromWindowStation(HWINSTA hwinsta, PSID psid);

BOOL RemoveAceFromDesktop(HDESK hdesk, PSID psid);

 

int wmain(int argc, WCHAR **argv)

{

    // The user is a valid account on the local computer

    WCHAR lpszUsername[] = LJohnny;   // Valid username

    WCHAR lpszDomain[] = L.;    // Using local user account database

    WCHAR lpszPassword[] = L123;      // Johnny's password

    WCHAR lpCommandLine[] = LC:\\Windows\\System32\\calc.exe;

    BOOL RetVal;

 

    // Call StartInteractiveClientProcess()

    RetVal = StartInteractiveClientProcess (

    lpszUsername,    // client to log on

    lpszDomain,      // domain of client's account

    lpszPassword,    // client's password

    lpCommandLine    // command line to execute

);

      wprintf(LStartInteractiveClientProcess() returns %d\n, RetVal);

      return 0;

}

 

BOOL GetLogonSID(HANDLE hToken, PSID *ppsid)

{

      BOOL bSuccess = FALSE;

      DWORD dwIndex;

      DWORD dwLength = 0;

      PTOKEN_GROUPS ptg = NULL;

     

      wprintf(L\nGetting the Logon SID...\n);

 

    // Verify the parameter passed in is not NULL

    if (ppsid == NULL)

        goto Cleanup;

      else

            wprintf(Lppsid is not NULL!\n);

     

      // 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)

            {

                  wprintf(LGetTokenInformation() 1 failed, error %d\n, GetLastError());

                  goto Cleanup;

            }

            else

                  wprintf(LWell, we have ample buffer...\n);

 

            ptg = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwLength);

           

            if (ptg == NULL)

                  goto Cleanup;

            else

                  wprintf(LHeap allocated for ptg!\n);

      }

     

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

            ))

      {

            wprintf(LGetTokenInformation() 2 failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

      {

            wprintf(LGetTokenInformation() is pretty fine!\n);

            wprintf(Lptg->GroupCount is %d\n, ptg->GroupCount);

            wprintf(Lptg->Groups->Attributes is %d\n, ptg->Groups->Attributes);

      }

     

      // 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;

                  else

                        wprintf(LHeap allocated for *ppsid!\n);

                 

                  if (!CopySid(dwLength, *ppsid, ptg->Groups[dwIndex].Sid))

                  {

                        wprintf(LCopySid() failed, error %d\n, GetLastError());

                        HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);

                        goto Cleanup;

                  }

                  else

                        wprintf(LCopySid() is fine!\n);

                  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)

{

      wprintf(L\nFreeing up the Logon SID...\n\n);

      HeapFree(GetProcessHeap(), 0, (LPVOID)*ppsid);

}

 

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;

     

      wprintf(LStarting the interactive client process...\n);

      // Log the client on to the local computer.

      if (!LogonUser(lpszUsername,lpszDomain,lpszPassword,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hToken))

      {

            wprintf(LLogonUser() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LLogonUser() is working!\n);     

      // Save a handle to the caller's current window station.

      if ((hwinstaSave = GetProcessWindowStation()) == NULL)

            goto Cleanup;

      else

            wprintf(LGetProcessWindowStation() should be fine!\n);     

      // Get a handle to the interactive window station.

      hwinsta = OpenWindowStation(

            Lwinsta0,                  // the interactive window station

            FALSE,                       // handle is not inheritable

            READ_CONTROL | WRITE_DAC);   // rights to read/write the DACL

     

      if (hwinsta == NULL)

            goto Cleanup;

      else

            wprintf(LOpenWindowStation() is working!\n);

     

      // To get the correct default desktop, set the caller's

      // window station to the interactive window station.

      if (!SetProcessWindowStation(hwinsta))

            goto Cleanup;

      else

            wprintf(LSetProcessWindowStation() 1 is working!\n);

     

      // Get a handle to the interactive desktop.

      hdesk = OpenDesktop(

            Ldefault,    // 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))

      {

            wprintf(LSetProcessWindowStation() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LSetProcessWindowStation() 2 is working!\n);

     

      if (hdesk == NULL)

            goto Cleanup;

      else

            wprintf(LOpenDesktop() is working!\n);

     

      // Get the SID for the client's logon session.

      if (!GetLogonSID(hToken, &pSid))

      {

            wprintf(LGetLogonSID() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LGetLogonSID() is working!\n);

     

      // Allow logon SID full access to interactive window station.

      if (!AddAceToWindowStation(hwinsta, pSid))

      {

            wprintf(LAddAceToWindowStation() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LAddAceToWindowStation() is working!\n);

     

      // Allow logon SID full access to interactive desktop.

      if (!AddAceToDesktop(hdesk, pSid))

      {

            wprintf(LAddAceToDesktop() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LAddAceToDesktop() is working!\n);

     

      // Impersonate client to ensure access to executable file.

      if (!ImpersonateLoggedOnUser(hToken))

      {

            wprintf(LImpersonateLoggedOnUser() failed, error %d\n, GetLastError());

            goto Cleanup;

      }

      else

            wprintf(LImpersonateLoggedOnUser() is working!\n);

     

      // Initialize the STARTUPINFO structure.

      // Specify that the process runs in the interactive desktop.

      ZeroMemory(&si, sizeof(STARTUPINFO));

      si.cb= sizeof(STARTUPINFO);

      si.lpDesktop = Lwinsta0\\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

            );

     

      // When running many times, it will keeps adding more ACLs to the Windows station until you hit some limit

      // https://support.microsoft.com/kb/185292/

      // Then SetUserObjectSecurity() will fails with ERROR_NOT_ENOUGH_QUOTA.

      // Undone any changes that were made to the Windows station and desktop.

      wprintf(LRemoving the ACE from Window station and desktop...\n);

      RemoveAceFromWindowStation(hwinsta, pSid);

      RemoveAceFromDesktop(hdesk, pSid);

     

      // End impersonation of client

      if(RevertToSelf() != 0)

            wprintf(LRevertToSelf() is OK!\n);

      else

            wprintf(LRevertToSelf() failed, error %d\n, GetLastError());

     

      if (bResult && pi.hProcess != INVALID_HANDLE_VALUE)

      {

            WaitForSingleObject(pi.hProcess, INFINITE);

 

            if(CloseHandle(pi.hProcess) != 0)

                  wprintf(Lpi.hProcess handle was closed successfully!\n);

            else

                  wprintf(LFailed to close pi.hProcess handle, error %d\n, GetLastError());

      }

     

      if (pi.hThread != INVALID_HANDLE_VALUE)

      {

            if(CloseHandle(pi.hThread) != 0)

                  wprintf(Lpi.hThread handle was closed successfully!\n);

            else

                  wprintf(LFailed to close pi.hThread handle, error %d\n, GetLastError());

      }

      else

            wprintf(Lpi.hThread handle already invalid!\n);

 

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;

     

      wprintf(L\nAdding ACE to WindowStation...\n);

 

      __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;

                        else

                              wprintf(LHeap allocated for psd!\n);

                       

                        psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,dwSdSizeNeeded);

                        if (psdNew == NULL)

                              __leave;

                        else

                              wprintf(LHeap allocated for psdNew!\n);

                       

                        dwSidSize = dwSdSizeNeeded;

                        if (!GetUserObjectSecurity(hwinsta,&si,psd,dwSidSize,&dwSdSizeNeeded))

                        {

                              wprintf(LGetUserObjectSecurity() failed, error %d\n, GetLastError());

                              __leave;

                        }

                        else

                              wprintf(LGetUserObjectSecurity() is working!\n);

                  }

                  else

                        __leave;

           

            // Create a new DACL.

            if (!InitializeSecurityDescriptor(psdNew,SECURITY_DESCRIPTOR_REVISION))

            {

                  wprintf(LInitializeSecurityDescriptor() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LInitializeSecurityDescriptor() is working!\n);

           

            // Get the DACL from the security descriptor.

            if (!GetSecurityDescriptorDacl(psd,&bDaclPresent,&pacl,&bDaclExist))

            {

                  wprintf(LGetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LGetSecurityDescriptorDacl() is working!\n);

           

            // Initialize the ACL

            SecureZeroMemory(&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))

                  {

                        wprintf(LGetAclInformation() failed, error %d\n, GetLastError());

                        __leave;

                  }

                  else

                        wprintf(LGetAclInformation() is working!\n);

            }

           

            // 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;

            else

                  wprintf(LHeap allocated for pNewAcl!\n);

           

            // Initialize the new DACL

            if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))

            {

                  wprintf(LInitializeAcl() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LInitializeAcl() is working!\n);

 

            // 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))

                              {

                                    wprintf(LGetAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                              else

                                    wprintf(LGetAce() is working!\n);

 

                              // Add the ACE to the new ACL.

                              if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,pTempAce,((PACE_HEADER)pTempAce)->AceSize))

                              {

                                    wprintf(LAddAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                              else

                                    wprintf(LAddAce() is working!\n);

                        }

                  }

            }

           

            // 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;

            else

                  wprintf(LHeap allocated for pace!\n);

           

            pace->Header.AceType  = ACCESS_ALLOWED_ACE_TYPE;

            pace->Header.AceFlags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;

            pace->Header.AceSize  = (WORD)(sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD));

            pace->Mask            = GENERIC_ACCESS;

           

            if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))

            {

                  wprintf(LCopySid() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LCopySid() is working!\n);

           

            if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,(LPVOID)pace,pace->Header.AceSize))

            {

                  wprintf(LAddAce() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LAddAce() 1 is working!\n);

           

            // 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))

            {

                  wprintf(LAddAce() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LAddAce() 2 is working!\n);

           

            // Set a new DACL for the security descriptor

            if (!SetSecurityDescriptorDacl(psdNew,TRUE,pNewAcl,FALSE))

            {

                  wprintf(LSetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LSetSecurityDescriptorDacl() is working!\n);

 

            // Set the new security descriptor for the window station

            if (!SetUserObjectSecurity(hwinsta, &si, psdNew))

            {

                  wprintf(LSetUserObjectSecurity() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LSetUserObjectSecurity() is working!\n);

 

            // 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;

     

      wprintf(L\nAdding ACE to Desktop...\n);

 

      __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))

                        {

                              wprintf(LGetUserObjectSecurity() failed, error %d\n, GetLastError());

                              __leave;

                        }

                  }

                  else

                        __leave;

            }

           

            // Create a new security descriptor

            if (!InitializeSecurityDescriptor(psdNew,SECURITY_DESCRIPTOR_REVISION))

            {

                  wprintf(LInitializeSecurityDescriptor() failed, error %d\n, GetLastError());

                  __leave;

            }           

            // Obtain the DACL from the security descriptor

            if (!GetSecurityDescriptorDacl(psd,&bDaclPresent,&pacl,&bDaclExist))

            {

                  wprintf(LGetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __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))

                  {

                        wprintf(LGetAclInformation() failed, error %d\n, GetLastError());

                        __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))

            {

                  wprintf(LInitializeAcl() failed, error %d\n, GetLastError());

                  __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))

                              {

                                    wprintf(LGetAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                              // Add the ACE to the new ACL.

                              if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,pTempAce,((PACE_HEADER)pTempAce)->AceSize))

                              {

                                    wprintf(LAddAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                        }

                  }

            }

           

            // Add ACE to the DACL

            if (!AddAccessAllowedAce(pNewAcl,ACL_REVISION,DESKTOP_ALL,psid))

            {

                  wprintf(LAddAccessAllowedAce() failed, error %d\n, GetLastError());

                  __leave;

            }

            // Set new DACL to the new security descriptor

            if (!SetSecurityDescriptorDacl(psdNew,TRUE,pNewAcl,FALSE))

            {

                  wprintf(LSetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __leave;

            }

            // Set the new security descriptor for the desktop object

            if (!SetUserObjectSecurity(hdesk, &si, psdNew))

            {

                  wprintf(LSetUserObjectSecurity() failed, error %d\n, GetLastError());

                  __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 RemoveAceFromWindowStation(HWINSTA hwinsta, 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;

      ACCESS_ALLOWED_ACE*  pTempAce;

      SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;

      unsigned int         i;

     

      wprintf(L\nRemoving ACE from Window Station...\n);

      __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))

                        {

                              wprintf(LGetUserObjectSecurity() failed, error %d\n, GetLastError());

                              __leave;

                        }

                  }

                  else

                        __leave;

           

            // Create a new DACL

            if (!InitializeSecurityDescriptor(psdNew,SECURITY_DESCRIPTOR_REVISION))

            {

                  wprintf(LInitializeSecurityDescriptor() failed, error %d\n, GetLastError());

                  __leave;

            }

           

            // Get the DACL from the security descriptor

            if (!GetSecurityDescriptorDacl(psd,&bDaclPresent,&pacl,&bDaclExist))

            {

                  wprintf(LGetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __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))

                  {

                        wprintf(LGetAclInformation() failed, error %d\n, GetLastError());

                        __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))

            {

                  wprintf(LInitializeAcl() failed, error %d\n, GetLastError());

                  __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, reinterpret_cast<void**>(&pTempAce)))

                              {

                                    wprintf(LGetAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                              else

                                    wprintf(LGetAce() looks OK!\n);

 

                              if (!EqualSid(psid, &pTempAce->SidStart))

                              {

                                    // Add the ACE to the new ACL.

                                    if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,pTempAce,((PACE_HEADER)pTempAce)->AceSize))

                                    {

                                          wprintf(LAddAce() failed, error %d\n, GetLastError());

                                          __leave;

                                    }

                                    else

                                          wprintf(LAddAce() looks OK!\n);

                              }

                              else

                                    wprintf(LEqualSid() is pretty fine!\n);

                        }

                  }

            }

           

            if(pacl != NULL)

                  HeapFree(GetProcessHeap(), 0, (LPVOID)pacl);

            // Set a new DACL for the security descriptor

            if (!SetSecurityDescriptorDacl(psdNew,TRUE,pNewAcl,FALSE))

            {

                  wprintf(LSetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __leave;

            }

            // Set the new security descriptor for the window station

            if (!SetUserObjectSecurity(hwinsta, &si, psdNew))

            {

                  wprintf(LSetUserObjectSecurity() failed, error %d\n, GetLastError());

                  __leave;

            }

            // Indicate success

            bSuccess = TRUE;

      }

      __finally

      {

            // Free the allocated buffers

            if(pacl != NULL)

                  HeapFree(GetProcessHeap(), 0, (LPVOID)pacl);

            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 RemoveAceFromDesktop(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;

      ACCESS_ALLOWED_ACE*  pTempAce;

      SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;

      unsigned int         i;

     

      wprintf(L\nRemoving ACE from Desktop...\n);

 

      __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))

                        {

                              wprintf(LGetUserObjectSecurity() failed, error %d\n, GetLastError());

                              __leave;

                        }

                  }

                  else

                        __leave;

            }

            else

                  wprintf(LGetUserObjectSecurity() should be OK!\n);

           

            // Create a new security descriptor

            if (!InitializeSecurityDescriptor(psdNew,SECURITY_DESCRIPTOR_REVISION))

            {

                  wprintf(LInitializeSecurityDescriptor() failed, error %d\n, GetLastError());

                  __leave;

            }

           

            // Obtain the DACL from the security descriptor

            if (!GetSecurityDescriptorDacl(psd,&bDaclPresent,&pacl,&bDaclExist))

            {

                  wprintf(LGetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __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))

                  {

                        wprintf(LGetAclInformation() failed, error %d\n, GetLastError());

                        __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))

            {

                  wprintf(LInitializeAcl() failed, error %d\n, GetLastError());

                  __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, reinterpret_cast<void**>(&pTempAce)))

                              {

                                    wprintf(LGetAce() failed, error %d\n, GetLastError());

                                    __leave;

                              }

                              else

                                    wprintf(LGetAce() should be fine!\n);

 

                              if (!EqualSid( psid, &pTempAce->SidStart))

                              {

                                    // Add the ACE to the new ACL.

                                    if (!AddAce(pNewAcl,ACL_REVISION,MAXDWORD,pTempAce,((PACE_HEADER)pTempAce)->AceSize))

                                    {

                                          wprintf(LAddAce() failed, error %d\n, GetLastError());

                                          __leave;

                                    }

                                    else

                                          wprintf(LAddAce() should be fine!\n);

                              }

                              else

                                    wprintf(LEqualSid() should be fine!\n);

                        }

                  }

            }

           

            // Set new DACL to the new security descriptor

            if (!SetSecurityDescriptorDacl(psdNew,TRUE,pNewAcl,FALSE))

            {

                  wprintf(LSetSecurityDescriptorDacl() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LSetSecurityDescriptorDacl() is pretty fine!\n);

 

            // Set the new security descriptor for the desktop object

            if (!SetUserObjectSecurity(hdesk, &si, psdNew))

            {

                  wprintf(LSetUserObjectSecurity() failed, error %d\n, GetLastError());

                  __leave;

            }

            else

                  wprintf(LSetUserObjectSecurity() is pretty fine!\n);

 

            // Indicate success

            bSuccess = TRUE;

      }

      __finally

      {

            // Free buffers

            if(pacl != NULL)

                  HeapFree(GetProcessHeap(), 0, (LPVOID)pacl);

            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;

}

 

 

Build and run the project. The following screenshot is a sample output.

 

Starting an Interactive Client Process in C++ Working Program Example: A sample program output in action

 

Starting an Interactive Client Process in C++ Working Program Example: Another program sample output

 

 

< Window Station and Desktop 5 | Window Station and Desktop | Win32 Programming | Windows Socket 2 (Winssock2) >