If you want to obtain a user’s token in a Terminal Server or Citrix session (eg to launch a process in a session) you can call the WTSQueryUserToken function.

On the x64 versions of Windows XP and Server 2003 this function fails however and returns ERROR_INSUFFICIENT_BUFFER (“The data area passed to a system call is too small.”) when called from a 32 bit process.

Internally WTSQueryUserToken calls the undocumented function WinstationQueryInformationW with the WinStationUserToken class (14) and passing a WINSTATIONUSERTOKEN struct, filled with caller ProcessId and ThreadId.

But on x64 Windows the size of this structure is 24 bytes, while on 32 bit Windows the size of the structure is 12 bytes!

Ok, let’s try to call WinstationQueryInformationW function directly:

But this call returns ERROR_INSUFFICIENT_BUFFER again! Why?

The reason is that WinstationQueryInformationW does some buffer checks/adjustments, before calling the real function, RpcWinStationQueryInformation.

Unfortunately, in some cases the buffer size is (incorrectly) hardcoded while the receiver (termsrv.dll) in many cases allows any value greater then required.

The buffer check is done in an internal function called ValidUserBuffer:

So, as you can see, there is no way to succeed using the original winsta.dll!

The only workaround is to patch it (and possibly distribute it with your app) or use RpcWinStationQueryInformation directly.

The code below works fine:

However to use the RpcWinStationQueryInformation you need the MIDL compiler, which supports only C/C++, to generate the code.

Of course it can be done using Delphi but that is out of scope for this article.