WTSQueryUserToken returns a user's primary token so you don't need to duplicate it. Just past the tokenhandle to CreateProcessAsUser and be sure to pass nil for the desktop param of the startupinfo structure. Something like this:
Delphi-Quellcode:
// Obtain the primary user token
WTSQueryUserToken(SessionId, hToken);
if hToken <> 0 then
begin
// Fill buffer with zeroes
ZeroMemory(@si, SizeOf(si));
si.cb := SizeOf(si);
si.lpDesktop := nil;
if CreateProcessAsUser(hToken, nil, Cmd, nil, nil, False, 0, nil, nil,
si, pi) then
...
Notes: WTSQueryUserToken needs Windows XP/2003 or higher, if you need windows 2000 compatibility check
Jwscl as it contains a WTSQueryUserTokenEx function that also works on Windows 2000.