Question

I have used GetUserName() METHOD , but the username it returned is 'SYSTEM' in a SYSTEM process.How can I get the active username in a SYSTEM process? THIS IS MY CODE:

void getComputerUsername(char * username,char * domainname)
{
 HANDLE hp , htoken;
 char buff[1024];
 unsigned long size = 1024;

 TOKEN_USER *tuser;
 PSID sid;
 TCHAR * user = new TCHAR[256];
 TCHAR * domain=new TCHAR[256];
 SID_NAME_USE snu;

 hp = htoken = INVALID_HANDLE_VALUE;
 hp = GetCurrentProcess();
 if(OpenProcessToken(hp, TOKEN_QUERY, &htoken))
 {
     if(GetTokenInformation(htoken, TokenUser, (void*)buff, size, &size))
 {
     tuser = (TOKEN_USER*)buff;
     sid = tuser->User.Sid;
     size = 256;
     if(LookupAccountSid(NULL, sid, user, &size, domain, &size, &snu))
     {
    int iLength = WideCharToMultiByte(CP_ACP, 0, user, -1, NULL, 0, NULL, NULL);  
    WideCharToMultiByte(CP_ACP, 0, user, -1, username, iLength, NULL, NULL);   

    iLength = WideCharToMultiByte(CP_ACP, 0, domain, -1, NULL, 0, NULL, NULL);  
    WideCharToMultiByte(CP_ACP, 0, domain, -1, domainname, iLength, NULL, NULL);  
           //strcpy( user,username);
     }
 }
 }

}

Était-ce utile?

La solution 3

You need to enumerate through all the running processes using EnumProcesses

Then see this answer to get the username from the process:

https://stackoverflow.com/a/2686150/203244

Autres conseils

If you want to know who is logged onto the physical console, you can call WTSGetActiveConsoleSessionId to get the terminal services (aka "fast user switching" aka "remote desktop") session ID that is currently active.

You can then call WTSQuerySessionInformation with WTSUserName to get the username.

(If the user you're interested in might be logged on via Remote Desktop, this approach will not work.)

The approach below will work for both physical console and virtual (remote desktop) console sessions.

Enumerating all processes is a way to do it, regardless of whether user is on the physical console or logged in via remote session, but it has certain issues:

1) You can't enumerate both x86 and x64 processes in the same service process using documented Windows APIs. An x86 service can only enumerate x86 processes and an x64 service can only enumerate x64 processes. A way to circumvent that is to have an x86 service launch an x64 helper process (and vice versa) to do the rest of the enumeration task.

2) The only process that is always present for a logged on user across different Windows versions (e.g. Vista to Windows 10) is explorer.exe however that process is x64 on x64 OS platforms and x32 on x32 OS platforms and its presence does not mean that the user is actively logged in.

A better way is to enumerate sessions, find the active interactive session or sessions that is also connected and then get the user name of that session.

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<LPTSTR*>(&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);
}

Enumerate the desktops and find the "Default" desktop. Get the user SID from that desktop. Maybe you have to try to find the correct access rights; I tried the code from an interactive process only.

BOOL CALLBACK EnumDesktopProc(_In_  LPTSTR lpszDesktop, _In_  LPARAM lParam)
{
    // todo: check if desktop is "Default"
    char info[1000];
    auto hd = OpenDesktop(lpszDesktop, NULL, FALSE, DESKTOP_READOBJECTS);
    GetUserObjectInformation(hd, UOI_USER_SID, info, 1000, NULL);
    return TRUE;
}

BOOL CALLBACK EnumWindowStationProc(_In_  LPTSTR lpszWindowStation, _In_  LPARAM lParam)
{
    auto hs = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS);
    EnumDesktops(hs, &EnumDesktopProc, NULL);
    return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
    EnumWindowStations(&EnumWindowStationProc, NULL);
    return 0;
}

If you only want get avtive console user name, please call windows api WTSGetActiveConsoleSessionId() and WTSQuerySessionInformation():

DWORD SessionIdWanted = WTSGetActiveConsoleSessionId();

if(0xFFFFFFFF != SessionIdWanted)
{
    WCHAR* pUserName;
    DWORD dwNameLen = 0;

    if(WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, SessionIdWanted, 
    &pUserName, &dwNameLen))
    {
        wstring UserName(pUserName);
        wcout << L"Current active console user: " << UserName << endl;
    }
    else
        //...
}
else
    //Now no active console user here.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top