The target thread is impersonating at the time of the call, so you're getting the wrong token. Using OpenProcessToken() instead of OpenThreadToken() should resolve the problem. If for some reason you only have the thread ID and not the process ID, GetProcessIdOfThread() will bridge the gap.
Alternatively, if you had some reason for wanting to use the impersonation token you would have to use DuplicateTokenEx() to convert it into a primary token. But this is unlikely to be what you want to do, because it introduces a race condition, since you would typically have no way to know when the target thread is impersonating the right user. Also, it will not work at all if the thread turns out to be impersonating at the anonymous level.
(This race condition is probably also why it seems to be working on some machines but not others, although it might also be that the impersonation takes place only on certain Windows versions.)