如何为从未登录过的新创建的Windows用户加载注册表配置单元?

问题描述 投票:0回答:1

我使用C#创建了一个新的Windows用户,我想限制通过使用C#设置注册表来运行的应用程序列表。但是用户个人资料及其注册表尚未初始化,因为用户从未登录过,因此不会加载注册表配置单元,因此我无法进行更改。

我尝试过Process.start()并设置LoadUserProfile = true。我可以看到该用户的文件夹是在C:\ Users \下创建的但是,如果获取用户的sid并检查HKEY_USERS \,则没有此类条目。我了解到,当用户登录时,Windows将加载注册表配置单元,并在注销时卸载。因此,我需要在没有用户登录的情况下加载注册表配置单元。

参考:

Editing registry value for newly created user

Load registry hive from C# fails

获取sid

NTAccount user = new NTAccount(username);
SecurityIdentifier s =  (SecurityIdentifier)user.Translate(typeof(SecurityIdentifier));
string sidString = s.ToString();

加载注册表

public class RegistryTest
{
    [StructLayout(LayoutKind.Sequential)]
    private struct LUID
    {
        public uint LowPart;
        public int HighPart;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct LUID_AND_ATTRIBUTES
    {
        public LUID pLuid;
        public UInt32 Attributes;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct TokPriv1Luid
    {
        public int Count;
        public LUID Luid;
        public UInt32 Attr;
    }

    private const Int32 ANYSIZE_ARRAY = 1;
    private const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
    private const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
    private const UInt32 TOKEN_QUERY = 0x0008;

    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", ExactSpelling = true, SetLastError = true)]
    static extern bool AdjustTokenPrivileges(
        IntPtr htok,
        bool disableAllPrivileges,
        ref TokPriv1Luid newState,
        int len,
        IntPtr prev,
        IntPtr relen);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern int RegLoadKey(UInt32 hKey, String lpSubKey, String lpFile);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern int RegUnLoadKey(UInt32 hKey, string lpSubKey);

    private IntPtr _myToken;
    private TokPriv1Luid _tokenPrivileges = new TokPriv1Luid();
    private TokPriv1Luid _tokenPrivileges2 = new TokPriv1Luid();

    private LUID _restoreLuid;
    private LUID _backupLuid;

    public RegistryTest(string sid)
    {
        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out _myToken))
            Console.WriteLine("OpenProcess Error");

        if (!LookupPrivilegeValue(null, SE_RESTORE_NAME, out _restoreLuid))
            Console.WriteLine("LookupPrivilegeValue Error");

        if (!LookupPrivilegeValue(null, SE_BACKUP_NAME, out _backupLuid))
            Console.WriteLine("LookupPrivilegeValue Error");

        _tokenPrivileges.Attr = SE_PRIVILEGE_ENABLED;
        _tokenPrivileges.Luid = _restoreLuid;
        _tokenPrivileges.Count = 1;

        _tokenPrivileges2.Attr = SE_PRIVILEGE_ENABLED;
        _tokenPrivileges2.Luid = _backupLuid;
        _tokenPrivileges2.Count = 1;

        if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges, 0, IntPtr.Zero, IntPtr.Zero))
            Console.WriteLine("AdjustTokenPrivileges Error: " + Marshal.GetLastWin32Error());

        if (!AdjustTokenPrivileges(_myToken, false, ref _tokenPrivileges2, 0, IntPtr.Zero, IntPtr.Zero))
            Console.WriteLine("AdjustTokenPrivileges Error: " + Marshal.GetLastWin32Error());

        // --> RegLoadKey fails with return value 32<--
        int retVal = RegLoadKey(HKEY_USERS, sid, @"C:\Users\Default\NTUSER.DAT");
        if (retVal != 0)
            Console.WriteLine("RegLoadKey Error:" + retVal);
    }
}

RegLoadKey API应该返回0,但我得到了32

c# windows
1个回答
0
投票

我已经找到了一种方法,我将默认注册表配置单元加载到C:\ Users \ Default中。在将其更改为C:\ Users \ [用户名] \ NTUSER.DAT之后,将加载注册表配置单元。

热门问题
推荐问题
最新问题