-
March 31st, 2006, 02:24 PM
#1
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,
-
March 31st, 2006, 08:37 PM
#2
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
-
April 1st, 2006, 05:13 AM
#3
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/
-
April 1st, 2006, 07:07 AM
#4
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.
-
April 1st, 2006, 09:42 AM
#5
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,
-
April 3rd, 2006, 06:00 AM
#6
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|