How to get the active user when multiple users are logged on in Windows?

前端 未结 2 2073
耶瑟儿~
耶瑟儿~ 2020-12-18 11:17

Suppose there are multiples users currently logged on on Windows. Say, user1 logs on, then switch user and user2 logs on, (without ma

2条回答
  •  梦毁少年i
    2020-12-18 11:43

    WTSGetActiveConsoleSessionId() may actually return session 0 when run from a windows service. If you need to do this from a Windows service you will need to enumerate all sessions and find the connected session then get the user from that.

    The code below does much more than that, including impersonation of that user and running a process as that user all from a windows service, but if you are just interested in the user name please look for the second instance the WTSQuerySessionInformation() function is called.

    //Function to run a process as active user from windows service
    void ImpersonateActiveUserAndRun(WCHAR* path, WCHAR* args)
    {
        DWORD session_id = -1;
        DWORD session_count = 0;
    
        WTS_SESSION_INFOA *pSession = NULL;
    
    
        if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSession, &session_count))
        {
            //log success
        }
        else
        {
            //log error
            return;
        }
    
        for (int i = 0; i < session_count; i++)
        {
            session_id = pSession[i].SessionId;
    
            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(&ptr_wts_connect_state),
                &bytes_returned))
            {
                wts_connect_state = *ptr_wts_connect_state;
                ::WTSFreeMemory(ptr_wts_connect_state);
                if (wts_connect_state != WTSActive) continue;
            }
            else
            {
                //log error
                continue;
            }
    
            HANDLE hImpersonationToken;
    
            if (!WTSQueryUserToken(session_id, &hImpersonationToken))
            {
                //log error
                continue;
            }
    
    
            //Get real token from impersonation token
            DWORD neededSize1 = 0;
            HANDLE *realToken = new HANDLE;
            if (GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize1))
            {
                CloseHandle(hImpersonationToken);
                hImpersonationToken = *realToken;
            }
            else
            {
                //log error
                continue;
            }
    
    
            HANDLE hUserToken;
    
            if (!DuplicateTokenEx(hImpersonationToken,
                //0,
                //MAXIMUM_ALLOWED,
                TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | MAXIMUM_ALLOWED,
                NULL,
                SecurityImpersonation,
                TokenPrimary,
                &hUserToken))
            {
                //log error
                continue;
            }
    
            // 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
            }
    
            //Free memory                         
            if (pUserName) WTSFreeMemory(pUserName);
    
            ImpersonateLoggedOnUser(hUserToken);
    
            STARTUPINFOW StartupInfo;
            GetStartupInfoW(&StartupInfo);
            StartupInfo.cb = sizeof(STARTUPINFOW);
            //StartupInfo.lpDesktop = "winsta0\\default";
    
            PROCESS_INFORMATION processInfo;
    
            SECURITY_ATTRIBUTES Security1;
            Security1.nLength = sizeof SECURITY_ATTRIBUTES;
    
            SECURITY_ATTRIBUTES Security2;
            Security2.nLength = sizeof SECURITY_ATTRIBUTES;
    
            void* lpEnvironment = NULL;
    
            // Get all necessary environment variables of logged in user
            // to pass them to the new process
            BOOL resultEnv = CreateEnvironmentBlock(&lpEnvironment, hUserToken, FALSE);
            if (!resultEnv)
            {
                //log error
                continue;
            }
    
            WCHAR PP[1024]; //path and parameters
            ZeroMemory(PP, 1024 * sizeof WCHAR);
            wcscpy(PP, path);
            wcscat(PP, L" ");
            wcscat(PP, args);
    
            // Start the process on behalf of the current user 
            BOOL result = CreateProcessAsUserW(hUserToken, 
                NULL,
                PP,
                //&Security1,
                //&Security2,
                NULL,
                NULL,
                FALSE, 
                NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
                //lpEnvironment,
                NULL,
                //"C:\\ProgramData\\some_dir",
                NULL,
                &StartupInfo,
                &processInfo);
    
            if (!result)
            {
                //log error
            }
            else
            {
                //log success
            }
    
            DestroyEnvironmentBlock(lpEnvironment);
    
            CloseHandle(hImpersonationToken);
            CloseHandle(hUserToken);
            CloseHandle(realToken);
    
            RevertToSelf();
        }
    
        WTSFreeMemory(pSession);
    }
    

提交回复
热议问题