CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Jun 2001
    Location
    Switzerland
    Posts
    4,443

    Detect the locally logged on user from a service

    Hi there.

    This is a bit complicated, so stick with me.

    I have following scenario: I have a service that needs to detect whether a user is locally logged on (Win2k). Normally, it is no problem to hook up a Dll to the Notify section of Winlogon and to call ControlService() on Startup/Logon/StartShell/Logoff and ShutDown. However, this works only if the service is already running before a user loggs on locally. Which I cannot assume. Thus the dilemma: given that the service gets started at some point (can be started remotely, for example), is there any reliable way to detect whether a user is logged on locally, and if so, what's the username?

    Comments/thoughts/flames ( ) are welcome.

    Cheers,
    Gabriel, CodeGuru moderator

    Forever trusting who we are
    And nothing else matters
    - Metallica

    Learn about the advantages of std::vector.

  2. #2
    Join Date
    Apr 2005
    Location
    Norway
    Posts
    3,934

    Re: Detect the locally logged on user from a service

    Maybe you can use WTSEnumerateSessions and WTSQuerySessionInfromation to get the information you need (they should be available on W2K Professional/Server, XP, Vista ...)

    Code:
    #include <windows.h>
    #include <vector>
    #include <string>
    
    #include <WtsApi32.h>
    #pragma comment(lib, "WtsApi32.lib")
    
    // 
    typedef std::basic_string<TCHAR> tstring;
    
    // Get current sessions
    bool EnumSessionIds(std::vector<DWORD>& list)
    {
        list.clear();
    
        WTS_SESSION_INFO *pSI = NULL;
        DWORD dwSICount;
    
        BOOL bRes = WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSI, &dwSICount);
        if (bRes == 0)
            return false;
    
        for (unsigned int i = 0; i < dwSICount; ++i)
            list.push_back(pSI[i].SessionId);
    
        WTSFreeMemory(pSI);
    
        return true;
    }
    
    // Get username from session id
    bool GetSessionUserName(DWORD dwSessionId, tstring& username)
    {
        LPTSTR	pBuffer = NULL;
        DWORD	dwBufferLen;
    
        BOOL bRes = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSUserName, &pBuffer, &dwBufferLen);
    
        if (bRes == FALSE)
            return false;
    
        username = pBuffer;
        WTSFreeMemory(pBuffer);
    
        return true;
    }
    
    // Get domain name from session id
    bool GetSessionDomain(DWORD dwSessionId, tstring& domain)
    {
        LPTSTR	pBuffer = NULL;
        DWORD	dwBufferLen;
    
        BOOL bRes = WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionId, WTSDomainName, &pBuffer, &dwBufferLen);
    
        if (bRes == FALSE)
            return false;
    
        domain = pBuffer;
        WTSFreeMemory(pBuffer);
    
        return true;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        std::vector<DWORD> sessionIds;
        bool bRes = EnumSessionIds(sessionIds);
        if (!bRes)
        {
            // error
            return 0;
        }
    
        // enum sessions
        std::vector<DWORD>::iterator iter;
        for (iter = sessionIds.begin(); iter != sessionIds.end(); iter++)
        {
            // print session domain
            tstring domain;
            GetSessionDomain(*iter, domain);
            _tprintf(_T("Session Domain = %s\n"), domain.c_str());
    
            // print session username
            tstring username;
            GetSessionUserName(*iter, username);
            _tprintf(_T("Session UserName = %s\n"), username.c_str());
        }
    
        return 0;
    }
    - petter

  3. #3
    Join Date
    Aug 2004
    Posts
    294

    Re: Detect the locally logged on user from a service

    Or you may want to have a look at SysInternals' PsLoggedOn - source code is available.

    From a quick glance at DisplayLocalLogons it seems that they are just enumerating the immediate children of HKEY_USERS, skipping those that are named ".default" or contain "Classes", convert the key name to SID and then the SID to username. The assumption is that user registry hive is loaded only for users that are logged on locally.
    Boris Karadjov
    Brainbench MVP for Visual C++
    http://www.brainbench.com/

  4. #4
    Join Date
    Jun 2001
    Location
    Switzerland
    Posts
    4,443

    Re: Detect the locally logged on user from a service

    Boris, Petter,

    Thanks you guys. You saved me a lot of time skimming thru MSDN.
    Gabriel, CodeGuru moderator

    Forever trusting who we are
    And nothing else matters
    - Metallica

    Learn about the advantages of std::vector.

  5. #5
    Join Date
    Jun 2001
    Location
    Switzerland
    Posts
    4,443

    Re: Detect the locally logged on user from a service

    Petter,

    I've tested your code on WinXP Pro, and it works. However, on Win2k Pro it doesn't, WTSEnumerateSessions() constantly returns error 1151 (The specified program is not a Windows or MS-DOS program. )

    To be honest, I don't really know what to make out of that error in the given context...

    Unfortunately, I have to stick with Win2k, as that's what our customer uses.

    Greets,
    Gabriel, CodeGuru moderator

    Forever trusting who we are
    And nothing else matters
    - Metallica

    Learn about the advantages of std::vector.

  6. #6
    Join Date
    Mar 2006
    Location
    Bangalore, India
    Posts
    18

    Re: Detect the locally logged on user from a service

    Check,

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon

    "DefualtUserName" is the current username

    You can get it easily with Registry functions.


    Cheers.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured