mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
450 lines
13 KiB
C#
450 lines
13 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
/*
|
|
* The registry wrapper provides a common interface to both the transacted
|
|
* and non-transacted registry APIs. It is used exclusively by the registry provider
|
|
* to perform registry operations. In most cases, the wrapper simply forwards the
|
|
* call to the appropriate registry API.
|
|
*/
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using Microsoft.Win32;
|
|
using System.Security.AccessControl;
|
|
using System.Management.Automation.Provider;
|
|
using Microsoft.PowerShell.Commands.Internal;
|
|
|
|
namespace Microsoft.PowerShell.Commands
|
|
{
|
|
|
|
#nullable enable
|
|
internal interface IRegistryWrapper
|
|
{
|
|
void SetValue(string? name, object value);
|
|
|
|
void SetValue(string? name, object value, RegistryValueKind valueKind);
|
|
|
|
string[] GetValueNames();
|
|
|
|
void DeleteValue(string name);
|
|
|
|
string[] GetSubKeyNames();
|
|
|
|
IRegistryWrapper? CreateSubKey(string subkey);
|
|
|
|
IRegistryWrapper? OpenSubKey(string name, bool writable);
|
|
|
|
void DeleteSubKeyTree(string subkey);
|
|
|
|
object? GetValue(string? name);
|
|
|
|
object? GetValue(string? name, object? defaultValue, RegistryValueOptions options);
|
|
|
|
RegistryValueKind GetValueKind(string? name);
|
|
|
|
object RegistryKey { get; }
|
|
|
|
void SetAccessControl(ObjectSecurity securityDescriptor);
|
|
|
|
ObjectSecurity GetAccessControl(AccessControlSections includeSections);
|
|
|
|
void Close();
|
|
|
|
string Name { get; }
|
|
|
|
int SubKeyCount { get; }
|
|
}
|
|
#nullable restore
|
|
|
|
internal static class RegistryWrapperUtils
|
|
{
|
|
public static object ConvertValueToUIntFromRegistryIfNeeded(string name, object value, RegistryValueKind kind)
|
|
{
|
|
try
|
|
{
|
|
// Workaround for CLR bug that doesn't support full range of DWORD or QWORD
|
|
if (kind == RegistryValueKind.DWord)
|
|
{
|
|
value = (int)value;
|
|
if ((int)value < 0)
|
|
{
|
|
value = BitConverter.ToUInt32(BitConverter.GetBytes((int)value), 0);
|
|
}
|
|
}
|
|
else if (kind == RegistryValueKind.QWord)
|
|
{
|
|
value = (long)value;
|
|
if ((long)value < 0)
|
|
{
|
|
value = BitConverter.ToUInt64(BitConverter.GetBytes((long)value), 0);
|
|
}
|
|
}
|
|
}
|
|
catch (System.IO.IOException)
|
|
{
|
|
// This is expected if the value does not exist.
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
public static object ConvertUIntToValueForRegistryIfNeeded(object value, RegistryValueKind kind)
|
|
{
|
|
// Workaround for CLR bug that doesn't support full range of DWORD or QWORD
|
|
if (kind == RegistryValueKind.DWord)
|
|
{
|
|
UInt32 intValue = 0;
|
|
|
|
// See if it's already a positive number
|
|
try
|
|
{
|
|
intValue = Convert.ToUInt32(value, CultureInfo.InvariantCulture);
|
|
value = BitConverter.ToInt32(BitConverter.GetBytes(intValue), 0);
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
// It must be a negative Int32, and therefore need no more conversion
|
|
}
|
|
}
|
|
else if (kind == RegistryValueKind.QWord)
|
|
{
|
|
UInt64 intValue = 0;
|
|
|
|
// See if it's already a positive number
|
|
try
|
|
{
|
|
intValue = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
|
|
value = BitConverter.ToInt64(BitConverter.GetBytes(intValue), 0);
|
|
}
|
|
catch (OverflowException)
|
|
{
|
|
// It must be a negative Int64, and therefore need no more conversion
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
internal class RegistryWrapper : IRegistryWrapper
|
|
{
|
|
private readonly RegistryKey _regKey;
|
|
|
|
internal RegistryWrapper(RegistryKey regKey)
|
|
{
|
|
_regKey = regKey;
|
|
}
|
|
|
|
#region IRegistryWrapper Members
|
|
|
|
public void SetValue(string name, object value)
|
|
{
|
|
_regKey.SetValue(name, value);
|
|
}
|
|
|
|
public void SetValue(string name, object value, RegistryValueKind valueKind)
|
|
{
|
|
value = System.Management.Automation.PSObject.Base(value);
|
|
value = RegistryWrapperUtils.ConvertUIntToValueForRegistryIfNeeded(value, valueKind);
|
|
|
|
_regKey.SetValue(name, value, valueKind);
|
|
}
|
|
|
|
public string[] GetValueNames()
|
|
{
|
|
return _regKey.GetValueNames();
|
|
}
|
|
|
|
public void DeleteValue(string name)
|
|
{
|
|
_regKey.DeleteValue(name);
|
|
}
|
|
|
|
public string[] GetSubKeyNames()
|
|
{
|
|
return _regKey.GetSubKeyNames();
|
|
}
|
|
|
|
public IRegistryWrapper CreateSubKey(string subkey)
|
|
{
|
|
RegistryKey newKey = _regKey.CreateSubKey(subkey);
|
|
if (newKey == null)
|
|
return null;
|
|
else
|
|
return new RegistryWrapper(newKey);
|
|
}
|
|
|
|
public IRegistryWrapper OpenSubKey(string name, bool writable)
|
|
{
|
|
RegistryKey newKey = _regKey.OpenSubKey(name, writable);
|
|
if (newKey == null)
|
|
return null;
|
|
else
|
|
return new RegistryWrapper(newKey);
|
|
}
|
|
|
|
public void DeleteSubKeyTree(string subkey)
|
|
{
|
|
_regKey.DeleteSubKeyTree(subkey);
|
|
}
|
|
|
|
public object GetValue(string name)
|
|
{
|
|
object value = _regKey.GetValue(name);
|
|
|
|
try
|
|
{
|
|
value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));
|
|
}
|
|
catch (System.IO.IOException)
|
|
{
|
|
// This is expected if the value does not exist.
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
public object GetValue(string name, object defaultValue, RegistryValueOptions options)
|
|
{
|
|
object value = _regKey.GetValue(name, defaultValue, options);
|
|
|
|
try
|
|
{
|
|
value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));
|
|
}
|
|
catch (System.IO.IOException)
|
|
{
|
|
// This is expected if the value does not exist.
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
public RegistryValueKind GetValueKind(string name)
|
|
{
|
|
return _regKey.GetValueKind(name);
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
_regKey.Dispose();
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return _regKey.Name; }
|
|
}
|
|
|
|
public int SubKeyCount
|
|
{
|
|
get { return _regKey.SubKeyCount; }
|
|
}
|
|
|
|
public object RegistryKey
|
|
{
|
|
get { return _regKey; }
|
|
}
|
|
|
|
public void SetAccessControl(ObjectSecurity securityDescriptor)
|
|
{
|
|
_regKey.SetAccessControl((RegistrySecurity)securityDescriptor);
|
|
}
|
|
|
|
public ObjectSecurity GetAccessControl(AccessControlSections includeSections)
|
|
{
|
|
return _regKey.GetAccessControl(includeSections);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
internal class TransactedRegistryWrapper : IRegistryWrapper
|
|
{
|
|
private readonly TransactedRegistryKey _txRegKey;
|
|
private readonly CmdletProvider _provider;
|
|
|
|
internal TransactedRegistryWrapper(TransactedRegistryKey txRegKey, CmdletProvider provider)
|
|
{
|
|
_txRegKey = txRegKey;
|
|
_provider = provider;
|
|
}
|
|
|
|
#region IRegistryWrapper Members
|
|
|
|
public void SetValue(string name, object value)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
_txRegKey.SetValue(name, value);
|
|
}
|
|
}
|
|
|
|
public void SetValue(string name, object value, RegistryValueKind valueKind)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
value = System.Management.Automation.PSObject.Base(value);
|
|
value = RegistryWrapperUtils.ConvertUIntToValueForRegistryIfNeeded(value, valueKind);
|
|
|
|
_txRegKey.SetValue(name, value, valueKind);
|
|
}
|
|
}
|
|
|
|
public string[] GetValueNames()
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.GetValueNames();
|
|
}
|
|
}
|
|
|
|
public void DeleteValue(string name)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
_txRegKey.DeleteValue(name);
|
|
}
|
|
}
|
|
|
|
public string[] GetSubKeyNames()
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.GetSubKeyNames();
|
|
}
|
|
}
|
|
|
|
public IRegistryWrapper CreateSubKey(string subkey)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
TransactedRegistryKey newKey = _txRegKey.CreateSubKey(subkey);
|
|
if (newKey == null)
|
|
return null;
|
|
else
|
|
return new TransactedRegistryWrapper(newKey, _provider);
|
|
}
|
|
}
|
|
|
|
public IRegistryWrapper OpenSubKey(string name, bool writable)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
TransactedRegistryKey newKey = _txRegKey.OpenSubKey(name, writable);
|
|
if (newKey == null)
|
|
return null;
|
|
else
|
|
return new TransactedRegistryWrapper(newKey, _provider);
|
|
}
|
|
}
|
|
|
|
public void DeleteSubKeyTree(string subkey)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
_txRegKey.DeleteSubKeyTree(subkey);
|
|
}
|
|
}
|
|
|
|
public object GetValue(string name)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
object value = _txRegKey.GetValue(name);
|
|
|
|
try
|
|
{
|
|
value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));
|
|
}
|
|
catch (System.IO.IOException)
|
|
{
|
|
// This is expected if the value does not exist.
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public object GetValue(string name, object defaultValue, RegistryValueOptions options)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
object value = _txRegKey.GetValue(name, defaultValue, options);
|
|
|
|
try
|
|
{
|
|
value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));
|
|
}
|
|
catch (System.IO.IOException)
|
|
{
|
|
// This is expected if the value does not exist.
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public RegistryValueKind GetValueKind(string name)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.GetValueKind(name);
|
|
}
|
|
}
|
|
|
|
public void Close()
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
_txRegKey.Close();
|
|
}
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.Name;
|
|
}
|
|
}
|
|
}
|
|
|
|
public int SubKeyCount
|
|
{
|
|
get
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.SubKeyCount;
|
|
}
|
|
}
|
|
}
|
|
|
|
public object RegistryKey
|
|
{
|
|
get { return _txRegKey; }
|
|
}
|
|
|
|
public void SetAccessControl(ObjectSecurity securityDescriptor)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
_txRegKey.SetAccessControl((TransactedRegistrySecurity)securityDescriptor);
|
|
}
|
|
}
|
|
|
|
public ObjectSecurity GetAccessControl(AccessControlSections includeSections)
|
|
{
|
|
using (_provider.CurrentPSTransaction)
|
|
{
|
|
return _txRegKey.GetAccessControl(includeSections);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|