Get registry keys of Windows users that are not currently logged in

I have an application that should read all Windows users' registry keys (folders).

I though this is simple. We have HKEY_USERS, and I know how to translate the SIDs to user names. This is not a problem. The problem is that HKEY_USERS only contains the keys (folders) of users that are currently logged in, and any other users are just missing. (But as soon as I log in with a user, its folder appears in HKEY_USERS).

So my question is how I can access the keys of users that are not currently logged in?

My app is in C#, but that's not really relevant.
LVL 1
kerznerAsked:
Who is Participating?
 
kris_perConnect With a Mentor Commented:

In the step 'Enter a SubKey name' I mentioned above, it doesnt need to be an existing key name. It can be anything like 'loadedKey' which you can use to read the values from.

Below is c# code (converted from vb code in the above link). I provide the converted code as is and I haven't tried it run. But I hope this gives you the complete idea on what you need to do.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
    public partial class Form9 : Form
    {
        private struct LUID
        {
            public long LowPart;
            public long HighPart;
        }

        private struct LUID_AND_ATTRIBUTES
        {
            public LUID pLuid;
            public long Attributes;
        }

        private class TOKEN_PRIVILEGES
        {
            public long PrivilegeCount;
            public LUID_AND_ATTRIBUTES[] Privileges = new LUID_AND_ATTRIBUTES[2];
        }

        private const  int TOKEN_ADJUST_PRIVLEGES = 0x20;
        private const  int TOKEN_QUERY = 0x8;
        private const  int SE_PRIVILEGE_ENABLED = 0x2;
        private const  uint HKEY_USERS = 0x80000003;
        private const  string SE_RESTORE_NAME = "SeRestorePrivilege";
        private const  string SE_BACKUP_NAME = "SeBackupPrivilege";

        [DllImport("kernel32.dll")]
        static extern IntPtr GetCurrentProcess();
        
        [DllImport("advapi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, 
            UInt32 DesiredAccess, out IntPtr TokenHandle);

        [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool LookupPrivilegeValue(string lpSystemName, string lpName,
            out LUID lpLuid);
        
        [DllImport("advapi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, 
            [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges, 
            ref TOKEN_PRIVILEGES NewState, 
            UInt32 Zero,
            IntPtr Null1, 
            IntPtr Null2);
        
        [DllImport("advapi32.dll", SetLastError=true)]
        static extern long RegLoadKey(UInt32 hKey, String lpSubKey, String lpFile);

        [DllImport("advapi32.dll", SetLastError=true)]
        static extern long RegUnLoadKey(
            UInt32 hKey,
            string lpSubKey);
                
        private string strKeyName;
        private IntPtr MyToken;
        private TOKEN_PRIVILEGES TP = new TOKEN_PRIVILEGES();
        private LUID RestoreLuid;
        private LUID BackupLuid;

        public Form9()
        {
            InitializeComponent();
        }

        private void Form9_Load(object sender, EventArgs e)
        {
            strKeyName = "keyLoaded";
            // Path to file on Windows NT: C:\WinNT\Profiles\<Profile Name>\NtUser.Dat
            // Path to file on Windows 2000: C:\Documents and Settings\<Profile Name>\NtUser.Dat
    
            textBox1.Text = "<Path to File>";
            button2.Enabled = false;

            bool bRetval = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVLEGES | TOKEN_QUERY, 
                        out MyToken);
            if (!bRetval) MessageBox.Show("OpenProcess Error");
            
            bRetval = LookupPrivilegeValue(null, SE_RESTORE_NAME, out RestoreLuid);
            if (!bRetval) MessageBox.Show("LookupPrivilegeValue Error");
    
            bRetval = LookupPrivilegeValue(null, SE_BACKUP_NAME, out BackupLuid);
            if (!bRetval) MessageBox.Show("LookupPrivilegeValue Error");
            
            TP.PrivilegeCount = 2;
            TP.Privileges[0].pLuid = RestoreLuid;
            TP.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
            TP.Privileges[1].pLuid = BackupLuid;
            TP.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;

            bRetval = AdjustTokenPrivileges(MyToken, false, ref TP, 0, IntPtr.Zero, IntPtr.Zero);
            if (!bRetval) MessageBox.Show("AdjustTokenPrivileges Error");
        }

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            long Retval = RegLoadKey(HKEY_USERS, strKeyName, textBox1.Text);
            if(Retval != 0) MessageBox.Show("RegLoadKey Error");
            button2.Enabled = true;
        }

        private void buttonUnload_Click(object sender, EventArgs e)
        {
            long Retval = RegUnLoadKey(HKEY_USERS, strKeyName);
            if (Retval != 0) MessageBox.Show("RegUnLoadKey Error");
        }

        private void Form9_FormClosing(object sender, FormClosingEventArgs e)
        {
            bool bRetval = AdjustTokenPrivileges(MyToken, true, ref TP, 0, IntPtr.Zero, IntPtr.Zero);
            if (!bRetval) MessageBox.Show("AdjustTokenPrivileges Error");
        }
    }
}

Open in new window

0
 
kris_perCommented:

Can you try logging in as admin and see if you get the details of other users.
0
 
kerznerAuthor Commented:
This is what I do, and the answer is no. I am running Win 7, but the same happened on my old Win XP when we originally discovered the problem.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
ipajonesCommented:
If you make the changes to HKEY_USERS\.DEFAULT then these will be inherited when the users logs in.
0
 
kris_perCommented:
To view the profile of other users in Registry:

Start RegEdit (Click Start, click Run, type regedit, click OK)
Click on the HKEY_USERS node.
Select 'Load Hive' under File menu.
Select the NTUSER.DAT file of the other user2 (typically from the folder C:\Documents and Settings\<user name>)
Enter a SubKey name to load (for example AppEvents, Console, etc which you can see under HKEY_USERS\<user sid>\)

Now that subkey will be loaded under HKEY_USERS node and the data under this Subkey can be read from any other programs (like your c# program).

What you need to do is to do this 'Load Hive' functionality programmatically in your program.

A sample on How to programmatically load another user's NTUSER.DAT in registry is available here (in vb code) => http://support.microsoft.com/kb/297060

Hope this helps.


0
 
kerznerAuthor Commented:
Thanks! That code works great in VB. For whatever reason it did not want to run properly under .NET (AdjustTokenPrivileges was always failing), but I guess I will keep it in a VB app and run it from my own app. So problem solved!
0
 
kris_perCommented:

Great. Glad I could help a bit.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.