MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4/*5 * The registry wrapper provides a common interface to both the transacted6 * and non-transacted registry APIs. It is used exclusively by the registry provider7 * to perform registry operations. In most cases, the wrapper simply forwards the8 * call to the appropriate registry API.9 */10 11using System;12using System.Globalization;13using Microsoft.Win32;14using System.Security.AccessControl;15using System.Management.Automation.Provider;16using Microsoft.PowerShell.Commands.Internal;17 18namespace Microsoft.PowerShell.Commands19{20 21#nullable enable22 internal interface IRegistryWrapper23 {24 void SetValue(string? name, object value);25 26 void SetValue(string? name, object value, RegistryValueKind valueKind);27 28 string[] GetValueNames();29 30 void DeleteValue(string name);31 32 string[] GetSubKeyNames();33 34 IRegistryWrapper? CreateSubKey(string subkey);35 36 IRegistryWrapper? OpenSubKey(string name, bool writable);37 38 void DeleteSubKeyTree(string subkey);39 40 object? GetValue(string? name);41 42 object? GetValue(string? name, object? defaultValue, RegistryValueOptions options);43 44 RegistryValueKind GetValueKind(string? name);45 46 object RegistryKey { get; }47 48 void SetAccessControl(ObjectSecurity securityDescriptor);49 50 ObjectSecurity GetAccessControl(AccessControlSections includeSections);51 52 void Close();53 54 string Name { get; }55 56 int SubKeyCount { get; }57 }58#nullable restore59 60 internal static class RegistryWrapperUtils61 {62 public static object ConvertValueToUIntFromRegistryIfNeeded(string name, object value, RegistryValueKind kind)63 {64 try65 {66 // Workaround for CLR bug that doesn't support full range of DWORD or QWORD67 if (kind == RegistryValueKind.DWord)68 {69 value = (int)value;70 if ((int)value < 0)71 {72 value = BitConverter.ToUInt32(BitConverter.GetBytes((int)value), 0);73 }74 }75 else if (kind == RegistryValueKind.QWord)76 {77 value = (long)value;78 if ((long)value < 0)79 {80 value = BitConverter.ToUInt64(BitConverter.GetBytes((long)value), 0);81 }82 }83 }84 catch (System.IO.IOException)85 {86 // This is expected if the value does not exist.87 }88 89 return value;90 }91 92 public static object ConvertUIntToValueForRegistryIfNeeded(object value, RegistryValueKind kind)93 {94 // Workaround for CLR bug that doesn't support full range of DWORD or QWORD95 if (kind == RegistryValueKind.DWord)96 {97 UInt32 intValue = 0;98 99 // See if it's already a positive number100 try101 {102 intValue = Convert.ToUInt32(value, CultureInfo.InvariantCulture);103 value = BitConverter.ToInt32(BitConverter.GetBytes(intValue), 0);104 }105 catch (OverflowException)106 {107 // It must be a negative Int32, and therefore need no more conversion108 }109 }110 else if (kind == RegistryValueKind.QWord)111 {112 UInt64 intValue = 0;113 114 // See if it's already a positive number115 try116 {117 intValue = Convert.ToUInt64(value, CultureInfo.InvariantCulture);118 value = BitConverter.ToInt64(BitConverter.GetBytes(intValue), 0);119 }120 catch (OverflowException)121 {122 // It must be a negative Int64, and therefore need no more conversion123 }124 }125 126 return value;127 }128 }129 130 internal class RegistryWrapper : IRegistryWrapper131 {132 private readonly RegistryKey _regKey;133 134 internal RegistryWrapper(RegistryKey regKey)135 {136 _regKey = regKey;137 }138 139 #region IRegistryWrapper Members140 141 public void SetValue(string name, object value)142 {143 _regKey.SetValue(name, value);144 }145 146 public void SetValue(string name, object value, RegistryValueKind valueKind)147 {148 value = System.Management.Automation.PSObject.Base(value);149 value = RegistryWrapperUtils.ConvertUIntToValueForRegistryIfNeeded(value, valueKind);150 151 _regKey.SetValue(name, value, valueKind);152 }153 154 public string[] GetValueNames()155 {156 return _regKey.GetValueNames();157 }158 159 public void DeleteValue(string name)160 {161 _regKey.DeleteValue(name);162 }163 164 public string[] GetSubKeyNames()165 {166 return _regKey.GetSubKeyNames();167 }168 169 public IRegistryWrapper CreateSubKey(string subkey)170 {171 RegistryKey newKey = _regKey.CreateSubKey(subkey);172 if (newKey == null)173 return null;174 else175 return new RegistryWrapper(newKey);176 }177 178 public IRegistryWrapper OpenSubKey(string name, bool writable)179 {180 RegistryKey newKey = _regKey.OpenSubKey(name, writable);181 if (newKey == null)182 return null;183 else184 return new RegistryWrapper(newKey);185 }186 187 public void DeleteSubKeyTree(string subkey)188 {189 _regKey.DeleteSubKeyTree(subkey);190 }191 192 public object GetValue(string name)193 {194 object value = _regKey.GetValue(name);195 196 try197 {198 value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));199 }200 catch (System.IO.IOException)201 {202 // This is expected if the value does not exist.203 }204 205 return value;206 }207 208 public object GetValue(string name, object defaultValue, RegistryValueOptions options)209 {210 object value = _regKey.GetValue(name, defaultValue, options);211 212 try213 {214 value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));215 }216 catch (System.IO.IOException)217 {218 // This is expected if the value does not exist.219 }220 221 return value;222 }223 224 public RegistryValueKind GetValueKind(string name)225 {226 return _regKey.GetValueKind(name);227 }228 229 public void Close()230 {231 _regKey.Dispose();232 }233 234 public string Name235 {236 get { return _regKey.Name; }237 }238 239 public int SubKeyCount240 {241 get { return _regKey.SubKeyCount; }242 }243 244 public object RegistryKey245 {246 get { return _regKey; }247 }248 249 public void SetAccessControl(ObjectSecurity securityDescriptor)250 {251 _regKey.SetAccessControl((RegistrySecurity)securityDescriptor);252 }253 254 public ObjectSecurity GetAccessControl(AccessControlSections includeSections)255 {256 return _regKey.GetAccessControl(includeSections);257 }258 259 #endregion260 }261 262 internal class TransactedRegistryWrapper : IRegistryWrapper263 {264 private readonly TransactedRegistryKey _txRegKey;265 private readonly CmdletProvider _provider;266 267 internal TransactedRegistryWrapper(TransactedRegistryKey txRegKey, CmdletProvider provider)268 {269 _txRegKey = txRegKey;270 _provider = provider;271 }272 273 #region IRegistryWrapper Members274 275 public void SetValue(string name, object value)276 {277 using (_provider.CurrentPSTransaction)278 {279 _txRegKey.SetValue(name, value);280 }281 }282 283 public void SetValue(string name, object value, RegistryValueKind valueKind)284 {285 using (_provider.CurrentPSTransaction)286 {287 value = System.Management.Automation.PSObject.Base(value);288 value = RegistryWrapperUtils.ConvertUIntToValueForRegistryIfNeeded(value, valueKind);289 290 _txRegKey.SetValue(name, value, valueKind);291 }292 }293 294 public string[] GetValueNames()295 {296 using (_provider.CurrentPSTransaction)297 {298 return _txRegKey.GetValueNames();299 }300 }301 302 public void DeleteValue(string name)303 {304 using (_provider.CurrentPSTransaction)305 {306 _txRegKey.DeleteValue(name);307 }308 }309 310 public string[] GetSubKeyNames()311 {312 using (_provider.CurrentPSTransaction)313 {314 return _txRegKey.GetSubKeyNames();315 }316 }317 318 public IRegistryWrapper CreateSubKey(string subkey)319 {320 using (_provider.CurrentPSTransaction)321 {322 TransactedRegistryKey newKey = _txRegKey.CreateSubKey(subkey);323 if (newKey == null)324 return null;325 else326 return new TransactedRegistryWrapper(newKey, _provider);327 }328 }329 330 public IRegistryWrapper OpenSubKey(string name, bool writable)331 {332 using (_provider.CurrentPSTransaction)333 {334 TransactedRegistryKey newKey = _txRegKey.OpenSubKey(name, writable);335 if (newKey == null)336 return null;337 else338 return new TransactedRegistryWrapper(newKey, _provider);339 }340 }341 342 public void DeleteSubKeyTree(string subkey)343 {344 using (_provider.CurrentPSTransaction)345 {346 _txRegKey.DeleteSubKeyTree(subkey);347 }348 }349 350 public object GetValue(string name)351 {352 using (_provider.CurrentPSTransaction)353 {354 object value = _txRegKey.GetValue(name);355 356 try357 {358 value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));359 }360 catch (System.IO.IOException)361 {362 // This is expected if the value does not exist.363 }364 365 return value;366 }367 }368 369 public object GetValue(string name, object defaultValue, RegistryValueOptions options)370 {371 using (_provider.CurrentPSTransaction)372 {373 object value = _txRegKey.GetValue(name, defaultValue, options);374 375 try376 {377 value = RegistryWrapperUtils.ConvertValueToUIntFromRegistryIfNeeded(name, value, GetValueKind(name));378 }379 catch (System.IO.IOException)380 {381 // This is expected if the value does not exist.382 }383 384 return value;385 }386 }387 388 public RegistryValueKind GetValueKind(string name)389 {390 using (_provider.CurrentPSTransaction)391 {392 return _txRegKey.GetValueKind(name);393 }394 }395 396 public void Close()397 {398 using (_provider.CurrentPSTransaction)399 {400 _txRegKey.Close();401 }402 }403 404 public string Name405 {406 get407 {408 using (_provider.CurrentPSTransaction)409 {410 return _txRegKey.Name;411 }412 }413 }414 415 public int SubKeyCount416 {417 get418 {419 using (_provider.CurrentPSTransaction)420 {421 return _txRegKey.SubKeyCount;422 }423 }424 }425 426 public object RegistryKey427 {428 get { return _txRegKey; }429 }430 431 public void SetAccessControl(ObjectSecurity securityDescriptor)432 {433 using (_provider.CurrentPSTransaction)434 {435 _txRegKey.SetAccessControl((TransactedRegistrySecurity)securityDescriptor);436 }437 }438 439 public ObjectSecurity GetAccessControl(AccessControlSections includeSections)440 {441 using (_provider.CurrentPSTransaction)442 {443 return _txRegKey.GetAccessControl(includeSections);444 }445 }446 447 #endregion448 }449}450 