2

私は最近、ユーザー アカウントを偽装し、CURRENT_USER レジストリ キーへのハンドルを取得し (PInvoke "LoadUserProfile" を使用して ProfileInfo.hProfile オブジェクトを取得)、RegistryKey.FromHandle を使用してレジストリ キーを作成するアプリケーションを作成しました。

参照コード:

using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(hToken))
{
    using (SafeRegistryHandle safeHandle = new SafeRegistryHandle(hProfile, true))
    {
        using (RegistryKey impersonatedUserHkcu = RegistryKey.FromHandle(safeHandle, RegistryView.Default))
        {
            // Do something with registry
        }
    }
}

このコードはうまく機能します (Windows 7 で実行) が、.NET 4.0 以降でのみサポートされているオブジェクト/メソッド (SafeRegistryHandle、RegistryKey.FromHandle()、RegistryView enum) を使用していました。

ここで、このアプリケーションを .NET 3.5 と互換性を持たせる必要があります。これは、Windows XP を搭載したマシンで使用し、.NET Framework 4.0 をインストールする可能性がないためです。

同じ結果を得るために .NET 3.5 で使用できる同等のオブジェクトはありますか? (つまり、偽装ユーザーのレジストリ キーを変更します)。それとも、.NET 4 オブジェクトのみの何らかのソース コードが存在しますか?

4

2 に答える 2

5

数日間の調査と MSDN コミュニティからの同じ質問への支援の後、私は自分のニーズを達成するために従う方法を見つけました。

最初の提案は、Win Api 関数を使用することでしたRegOpenKeyEx(情報とサンプルについては、 P/Invoke Web サイトを参照してください)。しかし、このMSDNの記事によると、私はそれを発見しました

サービスまたはアプリケーションが別のユーザーになりすます場合は、HKEY_CURRENT_USER でこの関数を使用しないでください。代わりに、RegOpenCurrentUser 関数を呼び出します。

最後に、RegOpenCurrentUser機能です。(残念ながら、P/Invoke Web サイトにはまだこの機能の痕跡はありませんが、MSDN でいくつかの情報を見つけることができます)

これは私が現在それを定義する方法です:

[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenCurrentUser(int samDesired, out IntPtr phkResult);    

public enum RegistrySecurity
{
    KEY_ALL_ACCESS = 0xF003F,
    KEY_CREATE_LINK = 0x0020,
    KEY_CREATE_SUB_KEY = 0x0004,
    KEY_ENUMERATE_SUB_KEYS = 0x0008,
    KEY_EXECUTE = 0x20019,
    KEY_NOTIFY = 0x0010,
    KEY_QUERY_VALUE = 0x0001,
    KEY_READ = 0x20019,
    KEY_SET_VALUE = 0x0002,
KEY_WOW64_32KEY = 0x0200,
    KEY_WOW64_64KEY = 0x0100,
    KEY_WRITE = 0x20006,
}

public IntPtr GetImpersonateUserRegistryHandle(RegistrySecurity _access)
{
    IntPtr safeHandle = new IntPtr();
    int result = RegOpenCurrentUser((int)_access, out safeHandle);

    return safeHandle;
}

/// <summary>
/// Get a registry key from a pointer.
/// </summary>
/// <param name="hKey">Pointer to the registry key</param>
/// <param name="writable">Whether or not the key is writable.</param>
/// <param name="ownsHandle">Whether or not we own the handle.</param>
/// <returns>Registry key pointed to by the given pointer.</returns>
public RegistryKey _pointerToRegistryKey(IntPtr hKey, bool writable, bool ownsHandle)
{
    //Get the BindingFlags for private contructors
    System.Reflection.BindingFlags privateConstructors = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic;

    //Get the Type for the SafeRegistryHandle
    Type safeRegistryHandleType =
            typeof(Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid).Assembly.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");

    //Get the array of types matching the args of the ctor we want
    Type[] safeRegistryHandleCtorTypes = new Type[] { typeof(IntPtr), typeof(bool) };

    //Get the constructorinfo for our object
    System.Reflection.ConstructorInfo safeRegistryHandleCtorInfo = safeRegistryHandleType.GetConstructor(
            privateConstructors, null, safeRegistryHandleCtorTypes, null);

    //Invoke the constructor, getting us a SafeRegistryHandle
    Object safeHandle = safeRegistryHandleCtorInfo.Invoke(new Object[] { hKey, ownsHandle });

    //Get the type of a RegistryKey
    Type registryKeyType = typeof(RegistryKey);

    //Get the array of types matching the args of the ctor we want
    Type[] registryKeyConstructorTypes = new Type[] { safeRegistryHandleType, typeof(bool) };

    //Get the constructorinfo for our object
    System.Reflection.ConstructorInfo registryKeyCtorInfo = registryKeyType.GetConstructor(
            privateConstructors, null, registryKeyConstructorTypes, null);

    //Invoke the constructor, getting us a RegistryKey
    RegistryKey resultKey = (RegistryKey)registryKeyCtorInfo.Invoke(new Object[] { safeHandle, writable });

    //return the resulting key
    return resultKey;
}

これを使用してレジストリを取得する方法は次のとおりです。

IntPtr localRegistryHandle = GetImpersonateUserRegistryHandle(TestRegistryAccess.RegistrySecurity.KEY_ALL_ACCESS);

using(RegistryKey localRegistry = _pointerToRegistryKey(localRegistryHandle, true, true))
{
    // do something with local registry
}
于 2013-05-29T08:18:47.040 に答える