This simple example shows how you can change the target session of a new process.

uses
  JwaWindows,
  JwsclToken,
  JwsclComUtils;

var
   NewToken,
   UserToken : TJwSecurityToken;

   S : TStartupInfo;
   P : TProcessInformation;
begin
  UserToken := TJwSecurityToken.CreateWTSQueryUserTokenEx(nil, 1); //for example: here SessionID = 1
  TJwAutoPointer.Wrap(UserToken); //automatic destroy

  NewToken := TJwSecurityToken.CreateDuplicateExistingToken(UserToken.TokenHandle, MAXIMUM_ALLOWED);
  TJwAutoPointer.Wrap(NewToken);  

  //needs TCB privilege -> Service
  JwEnablePrivilege(SE_TCB_NAME, pst_Enable);
  NewToken.TokenSessionId := 2; //e.g. set to session 2 – of course it must exist
 
  ZeroMemory(@S, Sizeof(S));
  S.cb := sizeof(S);
  //examplary, but working CPAU call – adapt for your need
  CreateProcessAsUser(NewToken.TokenHandle,‘C:\Windows\system32\cmd.exe’,nil,nil,nil,false, 0, nil, nil, S,P);

All the source is doing is to get a user’s token by calling CreateWTSQueryUserToken and then duplicate so it will become possible to change the Token SessionID. The session ID is changed by setting the property TokenSessionID which is only possible with the TCB privilege (we need it, but it needn’t to be active).
You can do the CreateProcess part a little better if you read this: “CreateProcess in full glory“.

Did you know?
1. You can test this example in your own Delphi environment without writing a service first.

2. It is not possible to change the session ID of a running process.