get current user and user profile path from window service

来源:互联网 发布:不要网络的单机麻将 编辑:程序博客网 时间:2024/05/20 13:14


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,

Dan
dmcgrail@coorsysinc.com


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.