Share via


WTSQueryUserToken() fails with error 1008 if team viewer [and perhaps remote desktop] is running at system boot

Question

Wednesday, February 27, 2019 6:48 AM

I have a windows service which is set to start automatically at system boot. As part of its startup routine, I need to create a process with the token of the interactive user. So I get the session id, either by enumerating all sessions and checking which one is active, or using the WTSGetActiveConsoleSessionId api. However, if team viewer [version 14] is running , I get the same session id using both methods, and both session ids fail when using WTSQueryUserToken with error 1008.

This happens ONLY at time of booting the system. Any other time, it works ok even if Team viewer is running. That is, there are no problems if I start the service manually after the system has booted. 

Please let me know how I can bypass this issue. Thanks.https://social.msdn.microsoft.com/Forums/ie/en-US/3fc2175b-ee6f-43e2-8fd8-c039680ca069/wtsqueryusertoken-failed-on-a-remote-desktop-session?forum=windowssecurity 

suggests the following 

"Again, WTSGetActiveConsoleSessionId returns the session id of the session bound to the physical machine.

If you're connecting using remote desktop, the session you're getting is remote (i.e. not bound to the physical machine).

And since there can be more than one remotely connected user in some configurations, there's no API that returns *the* remotely connected session id.

Assuming you're on a client SKU of Windows (where only one session can be active at a time), you can enumerate all sessions (using WTSEnumerateSessions) and look for the active one in the returned array. "

However, I found that both methods [enumerate sessions and WTSQueryUserToken return the same session id , which fails with error 1008]

The code I use is as below

HANDLE CProcessManager::GetImpersonationToken() {
    
    //The following api call fails to get a valid session id if remote desktop /team viewer is running at startup
    UINT dwSessionId = WTSGetActiveConsoleSessionId();
    Report(L"Session id from WTSGetActiveConsoleSessionId:%d", dwSessionId);

    
    HANDLE hImpersonationToken = NULL;
    if (!WTSQueryUserToken(dwSessionId, &hImpersonationToken))
        {
            //log error
            DWORD err = GetLastError();
            Report(L"Exception in WTSQueryUserToken:%d Proceeding to enumerate sessions!", err);
        }
        else 
        {
            Report(L"Returning Impersonation Token:%d", hImpersonationToken);
            WCHAR* pUserName;
            DWORD user_name_len = 0;

            if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE,dwSessionId, WTSUserName, &pUserName, &user_name_len))
            {
                Report(L"UserName from sessionId is %s:", pUserName);
                if (pUserName) WTSFreeMemory(pUserName);
                return hImpersonationToken;
                //LocalFree(lpszUserName);
            }
            else
            {
                DWORD err = GetLastError();
                Report(L"Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", err);
                return NULL;
            }

            
        }
    DWORD session_id = -1;
    DWORD session_count = 0;

    WTS_SESSION_INFOA *pSession = NULL;

    try {
        if (WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
        {
            //log success
        }
        else
        {
            //log error
            return NULL;
        }
    }
    catch (...) {}
    Report(L"Session Count :%d", session_count);
    Report(L"Begin Enumerating Sesions");
    for (int i = 0; i < session_count; i++)
    {
        {
            session_id = pSession[i].SessionId;
            Report(L"SessionId:%d", session_id);

            WTS_CONNECTSTATE_CLASS wts_connect_state = WTSDisconnected;
            WTS_CONNECTSTATE_CLASS* ptr_wts_connect_state = NULL;

            DWORD bytes_returned = 0;
            if (::WTSQuerySessionInformation(
                WTS_CURRENT_SERVER_HANDLE,
                session_id,
                WTSConnectState,
                reinterpret_cast<LPTSTR*>(&ptr_wts_connect_state),
                &bytes_returned))
            {
                wts_connect_state = *ptr_wts_connect_state;
                ::WTSFreeMemory(ptr_wts_connect_state);
                if (wts_connect_state != WTSActive)
                {
                    Report(L"wts_connect_state != WTSActive! Continuing ###");
                    continue;
                }
            }
            else
            {
                Report(L"Error in WTSQuerySessionInformation:%d: Continuing ###", GetLastError());
                continue;
            }
        }
        //catch (...) {}
        Report(L"End Enumerating Sesions");
        Report(L"Selected Session Id:%d", session_id);
    }
    
    Report(L"session_id from enumerating sessions: %d", session_id);
    Report(L"Session id from WTSGetActiveConsoleSessionId:%d", dwSessionId);
    if (session_id == -1) {
        Report(L"Fatal Error: Failed to get session_id by both methods");
        return NULL;
    }
    if (!WTSQueryUserToken(session_id, &hImpersonationToken))
    {
        //log error
        DWORD err = GetLastError();
        Report(L"Fatal Error: Failed WTSQueryUserToken on enumerated sessionid: %d", err);
        return NULL;
    }


    // Get user name of this process
    //LPTSTR pUserName = NULL;
    WCHAR* pUserName;
    DWORD user_name_len = 0;

    if (WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, session_id, WTSUserName, &pUserName, &user_name_len))
    {
        //log username contained in pUserName WCHAR string
        // char * lpszUserName = WideCharToChar(pUserName);
        Report(L"UserName from session_id [after enumeration] is %s:",pUserName);
        //LocalFree(lpszUserName);
    }
    else
    {
        DWORD err = GetLastError();
        Report(L"Exception in WTSQuerySessionInformation:%d! Returning Null Impersonation Token", err);
        return NULL;
    }

    //Free memory
    if (pUserName) WTSFreeMemory(pUserName);

    Report(L"Returning Impersonation Token:%d", hImpersonationToken);

    return hImpersonationToken;
}

All replies (1)

Wednesday, February 27, 2019 7:13 AM âś…Answered

Setting the windows service to delayed start automatic resolved the issue. Thanks.