[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 282
  • Last Modified:

Any way to get home directories of all user's on a windows system

Hi All,

Is there any way to get home directories of all user accounts on Windows machine.

by default they are under: C:\Documents and Settings\<account name>.

Any help will be greatly appreciated.

I am looking for something that can be written in C++ or C code

Regards,
0
nkanand
Asked:
nkanand
1 Solution
 
jkrCommented:
Use 'NetUserEnum()' and 'NetUserGetInfo()', e.g.

http://win32.mvps.org/network/nue_nqdi.cpp ("NetUserEnum")
http://win32.mvps.org/network/nugi.cpp ("NetUserGetInfo")

You'll need the 1st API to enumerate all users, then the 2nd one to obtain the home directory, which will be returned in USER_INFO_3::usri3_home_dir:

// compile with:
//            "cl -DUNICODE nugi.cpp" for a Unicode app
//            "cl nugi.cpp" for an MBCS app

// make sure that either both _UNICODE and UNICODE are defined, or none of them is
#if defined( _UNICODE ) && ! defined( UNICODE )
#define UNICODE 1
#endif
#if defined( UNICODE ) && ! defined( _UNICODE )
#define _UNICODE 1
#endif

#include <windows.h>
#include <lm.h>
#include <stdio.h>
#include <time.h>
#include <tchar.h>
#pragma hdrstop
#pragma comment( lib, "netapi32.lib" )



// in Unicode apps, _tprintf() maps to wprintf(), and "%s" refers to
// a Unicode string, while "%S" wants an ANSI string. In MBCS apps,
// "%s" expects an ANSI string, while "%S" wants a Unicode string. We
// could do some creative trickery with macros, but I am lazy, so I'll
// rely on "%hs" and "%ls" instead. Independent of whether printf() or
// wprintf() is ultimately invokes, "%hs" always expects an ANSI string,
// and "%ls" always expects a Unicode string.
// Since Net*() APIs on NT deal in Unicode only, the strings from the
// USER_INFO_3 struct get shown with "%ls" (but note that strings from
// elsewhere are in the ambient character size and use plain "%s").



#define lenof(a) (sizeof(a)/sizeof((a)[0]))



typedef struct {
      DWORD bits;
      const TCHAR *name;
} flag_t;



const TCHAR *getText( DWORD num, flag_t *defs )
{
      static TCHAR s[60];

      for ( ; defs->name != 0; ++ defs )
      {
            if ( defs->bits == num )
                  return defs->name;
      }

      _stprintf( s, _T( "%lu [0x%lx] (unknown)" ), num, num );
      return &s[0];
}



const TCHAR *buildFlags( DWORD bits, flag_t *defs )
{
      static TCHAR s[4096];
      TCHAR *p = &s[0];

      p += _stprintf( p, _T( "0x%lx" ), bits );

      for ( ; defs->name != 0; ++ defs )
      {
            if ( ( defs->bits & bits ) == defs->bits )
            {
                  if ( p != &s[0] )
                  {
                        _tcscpy( p, _T( ", " ) );
                        p += _tcslen( p );
                  }
                  _tcscpy( p, defs->name );
                  p += _tcslen( p );
            }
      }

      return &s[0];
}



int nugi( TCHAR *machine, TCHAR *user )
{
      DWORD rc;
      USER_INFO_3 *buf = 0;
      TCHAR temp[40];
      wchar_t unicodeMachine[UNCLEN + 4], unicodeUser[UNLEN + 2];
      static flag_t privilegeTexts[] =
      {
            { USER_PRIV_GUEST, _T( "USER_PRIV_GUEST" ) },
            { USER_PRIV_USER, _T( "USER_PRIV_USER" ) },
            { USER_PRIV_ADMIN, _T( "USER_PRIV_ADMIN" ) },
            { 0, 0 }
      };
      static flag_t authFlags[] =
      {
            { AF_OP_PRINT, _T( "AF_OP_PRINT" ) },
            { AF_OP_COMM, _T( "AF_OP_COMM" ) },
            { AF_OP_SERVER, _T( "AF_OP_SERVER" ) },
            { AF_OP_ACCOUNTS, _T( "AF_OP_ACCOUNTS" ) },
            { 0, 0 }
      };
      static flag_t acctFlags[] =
      {
            { UF_SCRIPT, _T( "UF_SCRIPT" ) },
            { UF_ACCOUNTDISABLE, _T( "UF_ACCOUNTDISABLE" ) },
            { UF_HOMEDIR_REQUIRED, _T( "UF_HOMEDIR_REQUIRED" ) },
            { UF_PASSWD_NOTREQD, _T( "UF_PASSWD_NOTREQD" ) },
            { UF_PASSWD_CANT_CHANGE, _T( "UF_PASSWD_CANT_CHANGE" ) },
            { UF_LOCKOUT, _T( "UF_LOCKOUT" ) },
            { UF_DONT_EXPIRE_PASSWD, _T( "UF_DONT_EXPIRE_PASSWD" ) },
#ifdef UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED
            { UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED, _T( "UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED" ) },
#endif
#ifdef UF_NOT_DELEGATED
            { UF_NOT_DELEGATED, _T( "UF_NOT_DELEGATED" ) },
#endif
#ifdef UF_SMARTCARD_REQUIRED
            { UF_SMARTCARD_REQUIRED, _T( "UF_SMARTCARD_REQUIRED" ) },
#endif
            { UF_NORMAL_ACCOUNT, _T( "UF_NORMAL_ACCOUNT" ) },
            { UF_TEMP_DUPLICATE_ACCOUNT, _T( "UF_TEMP_DUPLICATE_ACCOUNT" ) },
            { UF_WORKSTATION_TRUST_ACCOUNT, _T( "UF_WORKSTATION_TRUST_ACCOUNT" ) },
            { UF_SERVER_TRUST_ACCOUNT, _T( "UF_SERVER_TRUST_ACCOUNT" ) },
            { UF_INTERDOMAIN_TRUST_ACCOUNT, _T( "UF_INTERDOMAIN_TRUST_ACCOUNT" ) },
            { 0, 0 }
      };

#ifdef UNICODE
      _tcsncpy( unicodeMachine, machine, lenof( unicodeMachine ) );
      _tcsncpy( unicodeUser, user, lenof( unicodeUser ) );
#else
      mbstowcs( unicodeMachine, machine, lenof( unicodeMachine ) );
      mbstowcs( unicodeUser, user, lenof( unicodeUser ) );
#endif
      unicodeMachine[lenof( unicodeMachine ) - 1] = _T( '\0' );
      unicodeUser[lenof( unicodeUser ) - 1] = _T( '\0' );

      _tprintf( _T( "User %s on %s: " ), user, machine );

      rc = NetUserGetInfo( unicodeMachine, unicodeUser, 3, (byte **) &buf );
      if ( rc != 0 )
      {
            _tprintf( _T( "error %lu.\n" ), rc );
            return rc;
      }

      _tprintf( _T( "found.\n" ) );

      _tprintf( _T( "  Name:          %ls\n" ), buf->usri3_name );
      _tprintf( _T( "  Password:      %ls\n" ), buf->usri3_password );
      _tprintf( _T( "  Password age:  %lu days, %02lu:%02lu:%02lu\n" ), buf->usri3_password_age / 86400UL,
            buf->usri3_password_age % 86400UL / 3600UL, buf->usri3_password_age % 3600UL / 60UL,
            buf->usri3_password_age % 60UL );
      _tprintf( _T( "  Privilege:     %s\n" ), getText( buf->usri3_priv, privilegeTexts ) );
      _tprintf( _T( "  Home dir:      %ls\n" ), buf->usri3_home_dir );
      _tprintf( _T( "  Comment:       %ls\n" ), buf->usri3_comment );
      _tprintf( _T( "  Flags:         %s\n" ), buildFlags( buf->usri3_flags, acctFlags ) );
      _tprintf( _T( "  Script path:   %ls\n" ), buf->usri3_script_path );
      _tprintf( _T( "  Auth flags:    %s\n" ), buildFlags( buf->usri3_auth_flags, authFlags ) );
      _tprintf( _T( "  Full name:     %ls\n" ), buf->usri3_full_name );
      _tprintf( _T( "  User comment:  %ls\n" ), buf->usri3_usr_comment );
      _tprintf( _T( "  RAS params:    (not displayed)\n" ) );
      _tprintf( _T( "  Workstations:  %ls\n" ), buf->usri3_workstations );
      _tprintf( _T( "  Last logon:    %s" ), buf->usri3_last_logon == 0? _T( "never\n" ): _tctime( (long *) &buf->usri3_last_logon ) );
      _tprintf( _T( "  Last logoff:   %s" ), buf->usri3_last_logoff == 0? _T( "unknown\n" ): _tctime( (long *) &buf->usri3_last_logoff ) );
      _tprintf( _T( "  Expires:       %s" ), buf->usri3_acct_expires == TIMEQ_FOREVER? _T( "never\n" ): _tctime( (long *) &buf->usri3_acct_expires ) );
      _tprintf( _T( "  Max storage:   %s\n" ), buf->usri3_max_storage == USER_MAXSTORAGE_UNLIMITED? _T( "unlimited" ): _ultot( buf->usri3_max_storage, temp, 10 ) );
      _tprintf( _T( "  Logon hours:   (not displayed)\n" ) );
      _tprintf( _T( "  Bad PW count:  %s\n" ), buf->usri3_bad_pw_count == (DWORD) -1L? _T( "unlimited" ): _ultot( buf->usri3_bad_pw_count, temp, 10 ) );
      _tprintf( _T( "  # of logons:   %s\n" ), buf->usri3_num_logons == (DWORD) -1L? _T( "unknown" ): _ultot( buf->usri3_num_logons, temp, 10 ) );
      _tprintf( _T( "  Logon server:  %ls\n" ), buf->usri3_logon_server );
      _tprintf( _T( "  Country code:  %lu\n" ), buf->usri3_country_code );
      _tprintf( _T( "  Code page:     %lu\n" ), buf->usri3_code_page );
      _tprintf( _T( "  User RID:      %lu\n" ), buf->usri3_user_id );
      _tprintf( _T( "  Pgroup RID:    %lu\n" ), buf->usri3_primary_group_id );
      _tprintf( _T( "  Profile path:  %ls\n" ), buf->usri3_profile );
      _tprintf( _T( "  Home drive:    %ls\n" ), buf->usri3_home_dir_drive );
      _tprintf( _T( "  PW expired:    %s\n" ), buf->usri3_password_expired? _T( "yes" ): _T( "no" ) );
      _tprintf( _T( "\n" ) );

      return 0;
}



#ifdef UNICODE
int wmain( int argc, TCHAR *argv[] )
#else
int main( int argc, TCHAR *argv[] )
#endif
{
      TCHAR *machine = 0;
      int i;

      if ( argc < 2 )
      {
            _tprintf( _T( "usage: nugi [\\\\machine] user [user ...] [[\\\\machine] user [user ...] ...]\n" ) );
            return 1;
      }

      for ( i = 1; i < argc; ++ i )
      {
            if ( argv[i][0] == _T( '\\' ) && argv[i][1] == _T( '\\' ) )
            {
                  machine = argv[i];
                  continue;
            }

            nugi( machine, argv[i] );
      }

      return 0;
}
0
 
novitiateCommented:
0
 
B1-66ERCommented:
You can try to use values in registry key
"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DocFolderPaths", here the example of program code, which will display full path to home directories of every user, registered in system :


 HKEY RegKey;
 CHAR     achKey[MAX_PATH];
 char tmp[MAX_PATH] ;

 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DocFolderPaths",0,KEY_ALL_ACCESS,&RegKey); // opening key
 int err = 0;
 int i = 0;
 DWORD Size;
 int counter = 0;
 Size = MAX_PATH;

while (err==ERROR_SUCCESS || err == ERROR_MORE_DATA) // start to read sub-keys from opened key
{
err = RegEnumValue(RegKey,i,achKey,&Size,NULL,NULL,NULL,NULL); // extract 'i' sub-key
i++;

if (err != ERROR_NO_MORE_ITEMS)
{
 Size = MAX_PATH;
 RegQueryValueEx(RegKey, achKey, NULL, NULL, tmp, &Size) ; // take its value
 tmp[strlen(tmp) - 13] = '\0'; // cut off '\My Documents' substring in extracted value
 MessageBox(0,tmp, "rs[i]",MB_OK) ; // and show full path
 counter++;
}
}

RegCloseKey(RegKey);
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
jkrCommented:
I'd say that this Q is answered.
0
 
waysideCommented:
No comment has been added to this question in more than 21 days, so it is now classified as abandoned..
I will leave the following recommendation for this question in the Cleanup topic area:

Split between jkr, B1-66ER

Any objections should be posted here in the next 4 days. After that time, the question will be closed.

wayside
EE Cleanup Volunteer
0
 
jkrCommented:
Tend to object. You can have users without any "DocFolderPaths" (i.e. all that don't have a profile), thus I consider B1-66ER' suggestion error prone here. It's not the 'official' way anyway.
0
 
waysideCommented:
I think that depends on what the OP meant by "all user accounts on Windows machine." I believe in a local enviroment, all accounts created on that machine will have an entry in DocFolderPaths.
0
 
jkrCommented:
>>all accounts created on that machine will have an entry in DocFolderPaths

No, only those whose users logged on locally at least once. That is e.g. not the case for all users with roaming profiles, who never log on at the server's console, yet have do have a valid (domain) account.
0
 
waysideCommented:
I stand corrected.

Change recommendation to:

Accept: jkr
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now