get current user and user profile path from window service
void
getCurrentUserName( char *szCurName, DWORD sessionID )
{
HANDLE hToken , hTokenthis;
TOKEN_USER oUser[16];
DWORD u32Needed;
TCHAR sUserName[256],domainName[256];
DWORD userNameSize, domainNameSize;
SID_NAME_USE sidType;
WTSQueryUserToken ( sessionID , &hTokenthis );
DuplicateTokenEx(hTokenthis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hToken);
GetTokenInformation(hToken,TokenUser,&oUser[0], sizeof(oUser), &u32Needed);
userNameSize = sizeof (sUserName) - 1;
domainNameSize = sizeof (domainName) - 1;
LookupAccountSid (NULL,
oUser[0].User.Sid,
szCurName,
&userNameSize,
domainName,
&domainNameSize,
&sidType);
CloseHandle(hToken);
}
BOOL
getPersonalPath( LPTSTR pszPath, DWORD sessionID )
{
HKEY usersKey;
HKEY curUserKey;
TCHAR subKeyName[MAX_PATH];
TCHAR szBuffer[MAX_PATH];
TCHAR userName[MAX_PATH] = {0};
TCHAR curUserName[MAX_PATH];
DWORD subKeyNameSize, index, dwLength;
FILETIME lastWriteTime;
BOOL bRet = FALSE;
if( RegOpenKey( HKEY_USERS, NULL, &usersKey ) != ERROR_SUCCESS )
{
return FALSE;
}
getCurrentUserName( curUserName, sessionID );
index = 0;
subKeyNameSize = sizeof( subKeyName );
LPCTSTR szProfileList =
_T("Software//Microsoft//Windows//CurrentVersion//Explorer//Shell Folders//");
LPCTSTR szLogonUser =
_T("Software//Microsoft//Windows//CurrentVersion//Explorer//");
LONG lRet ;
while( lRet = RegEnumKeyEx( usersKey, index , subKeyName, &subKeyNameSize,
NULL, NULL, NULL, &lastWriteTime ) == ERROR_SUCCESS )
{
index ++;
subKeyNameSize = sizeof( subKeyName );
if ( ( _tcsicmp( subKeyName, _T(".default") ) == 0 ) ||
_tcsstr( subKeyName, _T("Classes") ) != 0 )
{
continue;
}
_stprintf( szBuffer, _T("%s//%s"), subKeyName,szLogonUser);
if ( ::RegOpenKeyEx( usersKey , szBuffer, 0, KEY_READ, &curUserKey ) != ERROR_SUCCESS )
{
RegCloseKey( usersKey );
continue;
}
if ( ::RegQueryValueEx( curUserKey,
_T("Logon User Name"), 0, NULL,
( LPBYTE )userName,
&dwLength ) != ERROR_SUCCESS )
{
continue;
}
if ( _tcsicmp( userName, curUserName ) != 0 )
{
continue;
}
_stprintf( szBuffer, _T("%s//%s"), subKeyName, szProfileList);
RegCloseKey( curUserKey );
dwLength = 256;
if ( ::RegOpenKeyEx( usersKey , szBuffer, 0, KEY_READ, &curUserKey )
== ERROR_SUCCESS )
{
if ( ::RegQueryValueEx( curUserKey,
_T("AppData"), 0, NULL,
( LPBYTE )pszPath,
&dwLength ) == ERROR_SUCCESS )
{
bRet = TRUE;
break;
}
}
} //while
RegCloseKey( curUserKey );
RegCloseKey( usersKey );
return bRet;
}
16:33 | 评论 (2)
Title: Getting the current logged in Windows user name when running as an NT service
Hi,
If I am not mistaken you can get the name of the logged in user from the USERNAME environment variable. You can get the logged in domain using the USERDOMAIN environment variable. You can use the GetEnvironmentVariable API to retrieve the said environment variables.
Hope this helps,
Madz
Accepted Answer from jkr
Date: 11/05/2003 06:37AM PST
Grade: A
Accepted Answer
Use
//--------------------------------------------------------------------
//
// DisplayLocalLogons
//
// Scans the HKEY_USERS key of the specified computer to see who
// has their profile loaded. Returns true if someone is logged on.
//
//--------------------------------------------------------------------
BOOLEAN DisplayLocalLogons( LPWSTR ServerName, LPWSTR UserName )
{
BOOLEAN first = TRUE;
TCHAR errorMessage[1024];
TCHAR userName[MAX_NAME_STRING], domainName[MAX_NAME_STRING];
TCHAR subKeyName[MAX_PATH];
DWORD subKeyNameSize, index;
DWORD userNameSize, domainNameSize;
FILETIME lastWriteTime;
HKEY usersKey;
PSID sid;
SID_NAME_USE sidType;
SID_IDENTIFIER_AUTHORITY authority;
BYTE subAuthorityCount;
DWORD authorityVal, revision;
DWORD subAuthorityVal[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
//
// Use RegConnectRegistry so that we work with remote computers
//
if( ServerName ) {
wprintf(L"Connecting to Registry of %s...", ServerName );
fflush( stdout );
if( RegConnectRegistry( ServerName, HKEY_USERS, &usersKey ) != ERROR_SUCCESS) {
wprintf(L"/r /r");
wprintf( L"Error opening HKEY_USERS for %s/n", ServerName );
return FALSE;
}
wprintf(L"/r /r");
} else {
if( RegOpenKey( HKEY_USERS, NULL, &usersKey ) != ERROR_SUCCESS ) {
wprintf( errorMessage, L"Error opening HKEY_USERS" );
PrintWin32Error( errorMessage, GetLastError() );
return FALSE;
}
}
//
// Enumerate keys under HKEY_USERS
//
index = 0;
subKeyNameSize = sizeof( subKeyName );
while( RegEnumKeyEx( usersKey, index, subKeyName, &subKeyNameSize,
NULL, NULL, NULL, &lastWriteTime ) == ERROR_SUCCESS ) {
//
// Ignore the default subkey and win2K user class subkeys
//
if( wcsicmp( subKeyName, L".default" ) &&
!wcsstr( subKeyName, L"Classes")) {
//
// Convert the textual SID into a binary SID
//
subAuthorityCount= swscanf( subKeyName, L"S-%d-%x-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu",
&revision, &authorityVal,
&subAuthorityVal[0],
&subAuthorityVal[1],
&subAuthorityVal[2],
&subAuthorityVal[3],
&subAuthorityVal[4],
&subAuthorityVal[5],
&subAuthorityVal[6],
&subAuthorityVal[7] );
if( subAuthorityCount >= 3 ) {
subAuthorityCount -= 2;
//
// Note: we can only deal with authority values
// of 4 bytes in length
//
authority.Value[5] = *(PBYTE) &authorityVal;
authority.Value[4] = *((PBYTE) &authorityVal+1);
authority.Value[3] = *((PBYTE) &authorityVal+2);
authority.Value[2] = *((PBYTE) &authorityVal+3);
authority.Value[1] = 0;
authority.Value[0] = 0;
//
// Initialize variables for subsequent operations
//
sid = NULL;
userNameSize = MAX_NAME_STRING;
domainNameSize = MAX_NAME_STRING;
if( AllocateAndInitializeSid( &authority,
subAuthorityCount,
subAuthorityVal[0],
subAuthorityVal[1],
subAuthorityVal[2],
subAuthorityVal[3],
subAuthorityVal[4],
subAuthorityVal[5],
subAuthorityVal[6],
subAuthorityVal[7],
&sid )) {
//
// We can finally lookup the account name
//
if( LookupAccountSid( ServerName,
sid,
userName,
&userNameSize,
domainName,
&domainNameSize,
&sidType )) {
//
// We've successfully looked up the user name
//
if( first && !UserName ) {
wprintf(L"Users logged on locally:/n");
first = FALSE;
}
if( !UserName || !wcsicmp( UserName, userName )) {
first = FALSE;
if( UserName ) wprintf(RESETLINE L"%s//%s logged onto %s locally./n",
domainName, UserName, ServerName );
else wprintf( L" %s//%s/n", domainName, userName );
}
}
}
if( sid ) FreeSid( sid );
}
}
subKeyNameSize = sizeof( subKeyName );
index++;
}
RegCloseKey( usersKey );
if( first && !UserName ) wprintf(L"No one is logged on locally./n");
return !first;
}
Code taken from http://www.sysinternals.com/files/PsLoggedonSrc.zip
Comment from nicjansma
Date: 11/05/2003 01:06PM PST
Author Comment
Madz - Unfortunately, I tried this and it returns USERNAME="" when running as a service (it did work properly when not running as a service, so I know the code is OK).
jkr - I do not believe this would work with Fast User Switching in XP, correct? As several users would have their hives loaded?
My software works with FUS, so it needs to know the login name of the current session, not just all users who are logged in.
Any more ideas?
Comment from jkr
Date: 11/05/2003 01:22PM PST
Comment
>>I do not believe this would work with Fast User Switching in XP, correct?
It should (using 'RegEnumKeyEx()' for the hives) - that's why I posted it in the 1st place.
Comment from granslant
Date: 11/19/2003 11:10AM PST
Comment
>>>>I do not believe this would work with Fast User Switching in XP, correct?
>>
>>It should (using 'RegEnumKeyEx()' for the hives) - that's why I posted it in the 1st place.
Unfortunalety no, it returns all logged users, not only the user of the current session.
Comment from jkr
Date: 11/19/2003 11:14AM PST
Comment
>>it returns all logged users, not only the user of the current session
Yes, but that was the purpose.
Comment from granslant
Date: 11/21/2003 02:30AM PST
Comment
Actually, and if I remember well , here one solution to get only the current local session user (and not all logged users):
. get the desktop window
. get its process ID
. use OpenProcessToken and GetTokenInformation to retreive the SID of the desktop window's owner.
Comment from bharat_mane
Date: 01/06/2004 11:22PM PST
Comment
Hello Experts,
I have one doubt
By looking at the function I feel the data is coming from registry. I mean username and domin name are coming from registry.
I exactlly don't from which key but I think subkey of
HKEY_USERS/S-1-5-21-1244467668-1331586020-26564730-13072
What if I change these values from regisry manualkly then ,
what this function will return......
And if anybody knows from exactlly which kay the value of userid and domain name is comming then it would help me a lot.
Thanks
Bharat
Comment from bharat_mane
Date: 01/06/2004 11:23PM PST
Comment
Hello Experts,
I have one doubt
By looking at the function I feel the data is coming from registry. I mean username and domin name are coming from registry.
I exactlly don't from which key but I think subkey of
HKEY_USERS/S-1-5-21-1244467668-1331586020-26564730-13072
What if I change these values from regisry manually then ,
what this function will return......
And if anybody knows from exactly which key, value of userid and domain name is coming, then it would help me a lot.
Thanks
Bharat
Comment from scoubidou944
Date: 01/13/2004 06:54AM PST
Comment
Here is a shorter example but it returns SYSTEM for a serivce added to Windows Station Winsta0/default.
Having another idea ?
HDESK hDesk;
BOOL bResult;
HWINSTA hwinsta;
HANDLE hToken;
TOKEN_USER oUser[16];
DWORD u32Needed;
SID_NAME_USE sidType;
TCHAR userName[256], domainName[256];
DWORD userNameSize, domainNameSize;
// INIT
bResult = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken);
hwinsta = OpenWindowStation ("winsta0", FALSE, WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS | WINSTA_READATTRIBUTES | WINSTA_READSCREEN | WINSTA_ENUMERATE | WINSTA_ENUMDESKTOPS);
hDesk = OpenDesktop ("default", 0, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS);
memset (&oUser[0], 0, sizeof (oUser));
bResult = GetTokenInformation (hToken, TokenUser, &oUser[0], sizeof (oUser), &u32Needed);
userNameSize = sizeof (userName) - 1;
domainNameSize = sizeof (domainName) - 1;
bResult = LookupAccountSid (NULL, oUser[0].User.Sid, userName, &userNameSize, domainName, &domainNameSize, &sidType);
// HERE IS THE RESULT
// CLOSE
bResult = CloseDesktop (hDesk);
bResult = CloseWindowStation (hwinsta);
bResult = CloseHandle (hToken);
Comment from kirannapit
Date: 01/28/2004 02:34AM PST
Comment
hello
how to get user logged on to of a remote machine.
Comment from scoubidou944
Date: 01/28/2004 03:33AM PST
Comment
Looks like something not very white what you want to do...........
create a NULL connection to remote computer using NetBIOS "feature" to retrieve usefull informations.
Comment from deemehtani
Date: 03/02/2004 01:08PM PST
Comment
HI
If you put your VB program in the startup for all users instead of running it as a service, you would get the actual username instead of System
Comment from Magadass
Date: 03/24/2004 08:23AM PST
Comment
The reason scoubidou944's solution did not work is because you are retrieving the current process handle by using OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken); you are recieving a security token for the currently running instance. You will need to retrieve the process handle of the currently logged on user, which I am attempting to find out how to also. But if anyone know this would resolve the problem by chaning this one line to point to the current users process handle rather than GetCurrentProcess()
Comment from Magadass
Date: 03/25/2004 10:07AM PST
Comment
HANDLE hToken;
TOKEN_USER oUser[16];
DWORD u32Needed;
TCHAR sUserName[256], domainName[256];
DWORD userNameSize, domainNameSize;
SID_NAME_USE sidType;
ZeroMemory(oUser,sizeof(oUser));
OpenProcessToken(GetExplorerProcessHandle(), TOKEN_QUERY, &hToken);
GetTokenInformation(hToken,TokenUser,&oUser[0], sizeof(oUser), &u32Needed);
userNameSize = sizeof (sUserName) - 1;
domainNameSize = sizeof (domainName) - 1;
LookupAccountSid (NULL, oUser[0].User.Sid, sUserName, &userNameSize, domainName, &domainNameSize, &sidType);
HANDLE GetExplorerProcessHandle() //Needed to impersonate the logged in user...
{
HANDLE hSnapshot;
PROCESSENTRY32 pe32;
ZeroMemory(&pe32,sizeof(pe32));
HANDLE temp = NULL;
try
{
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
pe32.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hSnapshot,&pe32))
{
do
{
if(!strcmp(pe32.szExeFile,"explorer.exe"))
{
temp = OpenProcess (PROCESS_ALL_ACCESS,FALSE, pe32.th32ProcessID);
break;
}
}while(Process32Next(hSnapshot,&pe32));
}
}
catch(char *str)
{
HandleError(str);
}
return temp;
}
Comment from Magadass
Date: 03/25/2004 10:09AM PST
Comment
That works, I have it working in my application.
Comment from DevDan
Date: 04/08/2004 09:58AM PDT
Comment
I had the exact same problem. One of the componenets in my app runs on the PC and reports back to the server who is logged into the PC. It is a standard VB6 EXE and runs hidden. I upgraded this app to an NTService and now have the problem of only seeing "SYSTEM" as the logged in user. I've read your note, amongst others on the net, and decided a little creative thinking was necessary. To get around this problem I'm doing the following:
1.) When the user logs in, a standard EXE fires and grabs the login name via "GetUserName".
2.) Put the username in a file, or registry entry
3.) My NTService will read the file, or registry, and then subsequently kill the file or clear the reg
4.) The NTService will loop when loading until file exists or reg value > "".
Hope this round about trick helps. It's working fine for me.
Regards,
Comment from shivakarsh_sochrist
Date: 11/07/2004 09:01PM PST
Comment
Using API's like Getusername and stuff like that may not help. It returns SYSTEM when running as a service. The best thing is to share IPC and turn the NetBIOS on. So try doing this in the command prompt. nbtstat -a <ip address> . The address <03> returns the username. I've done this in my ISAPI App and runs well. When there's no user logged, it returns a NULL value.Generally IPC is shared by default in NT based systems. But if that is disabled, this idea may not work. Now our task is to run DOS commands and get the Output back in VB. Visit http://www.planetsourcecode.com/vb/scripts/ShowCode.asp?txtCodeId=43370&lngWId=1
Hope this works!
Comment from legionx
Date: 01/13/2005 06:07PM PST
Comment
You can also simply get the environment variable %USERNAME%, I have used it in this situation before.
e.g. in VBScript
Dim oShell
Dim UserName
Set oShell = Wscript.CreateObject("Wscript.Shell")
UserName = oShell.ExpandEnvironmentStrings("%USERNAME%")
WScript.Echo UserName
Comment from jkr
Date: 01/14/2005 07:08AM PST
Comment
>> You can also simply get the environment variable %USERNAME%
OK, so that'll be 'System'. Always.
Comment from DarthChucks
Date: 02/14/2005 10:27AM PST
Comment
How about using WTSGetActiveConsoleSessionId? Then use WTSQuerySessionInformation which returns a WTSInfoClass which in turn contains WTSDomainName and WTSUserName.
Check out
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/termserv/TermServ/wtsgetactiveconsolesessionid.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/termserv/TermServ/wtsquerysessioninformation.asp
This should work under fast user switching. Sorry, no code. I'm not a VB Programmer.
Rob
Comment from legionx
Date: 02/15/2005 08:53PM PST
Comment
>> OK, so that'll be 'System'. Always.
Not necessarily. I have tested in the situation where a standard user logs in and applications are delivered through Novell ZEN. The application install is set to run as unsecure system user but this does not alter the %USERNAME% variable.