WTSQueryUserToken always throws "An attempt was made to reference a token that does not exist" on Windows 7 in C#

StackOverflow https://stackoverflow.com/questions/16621448

Question

I'm trying to launch a process from a Windows Service on Windows 7.

This is my code to obtain the user token.

uint sessionId = Kernel32.WTSGetActiveConsoleSessionId();
var userTokenPtr = new IntPtr();
if (!WtsApi32.WTSQueryUserToken(sessionId, out userTokenPtr))
{
    int lastError = Marshal.GetLastWin32Error();
    throw new Win32Exception(lastError);
}

These are the DllImport statements :

public class Kernel32
{
    [DllImport("kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionId")]
    public static extern uint WTSGetActiveConsoleSessionId();
}

public class WtsApi32
{
    [DllImport("Wtsapi32.dll", EntryPoint = "WTSQueryUserToken")]
    public static extern bool WTSQueryUserToken(UInt32 sessionId, out IntPtr phToken);
}

I took the code from this answer and copied it as is : https://stackoverflow.com/a/11266955/410075

It always throws a Win32Exception with the message "An attempt was made to reference a token that does not exist". This is the data : sessionId = 1 and lastError = 1008.

I have tried to run this as :

  • A debug process (with the Visual Studio hosting process)
  • A debug process (without the Visual Studio hosting process)
  • An admin user
  • An elevated admin user
  • A Windows service.
  • A Windows service logged in as an admin user.
  • As I was praying to God, Satan, Buddah and Rael.

I also created a manifest for the executable to require admin elevation.

Nothing works and it always throws exactly the same exception. I am out of ideas...

Was it helpful?

Solution

You must add SetLastError = true to the DllImport attribute for WTSQueryUserToken otherwise, GetLastWin32Error is not meaningful.

Also, you must be running this code in the context of the LocalSystem account as stipulated in the documentation (not just "an admin user"):

Obtains the primary access token of the logged-on user specified by the session ID. To call this function successfully, the calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top