Files
Joseph Doherty fe2a6db786
rust / build / test / clippy / fmt (push) Has been cancelled
Initial project state: .NET reference, design, Rust port (M0+M1), evidence
Layout:
- src/                    .NET 10 x64 reference: MxNativeCodec, MxNativeClient,
                          MxAsbClient, probes, tests, harnesses. Executable spec.
- design/                 Architectural plan for the Rust port (M0–M6), error
                          model, protocol invariants, risks (R1–R16), adversarial
                          review log (review.md).
- rust/                   Rust workspace. M0 skeleton + M1 codec parity.
                          mxaccess-codec: 215 unit tests + 2 cross-implementation
                          parity tests (byte-identical against .NET reference).
                          Other crates are M0 stubs awaiting M2+.
- captures/               Frida + netsh + pcap evidence per CLAUDE.md
                          ("captures are evidence, not throwaway logs").
- analysis/               Decompiled C# (frida/proxy/decompiled-*),
                          Ghidra exports for native DLLs (`exports/` only —
                          working state at `projects/` and AVEVA's input
                          binaries at `input/` are gitignored).
- docs/                   Reverse-engineering reference docs.
- tools/                  Setup-LiveProbeEnv.ps1 (Infisical credential fetcher),
                          Compute-Crc.ps1 (.NET parity helper).
- .github/workflows/      Rust CI: fmt + build + test + clippy on Windows.
- LICENSE                 MIT (Joseph Doherty, 2026).

Verified:
- cargo test --workspace → 217 passed (215 unit + 2 .NET parity), 0 failed
- cargo clippy --workspace -- -D warnings → clean
- cargo fmt --all -- --check → clean
- cargo publish --dry-run -p mxaccess-codec → packages cleanly

Excluded from history (see .gitignore):
- **/bin, **/obj, **/target — build artifacts
- analysis/ghidra/projects/ — Ghidra working state (regenerable)
- analysis/ghidra/input/ — AVEVA proprietary DLLs (vendor IP)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:21:00 -04:00

955 lines
29 KiB
C#

#define TRACE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security;
using System.Security.AccessControl;
using System.Text;
using System.Xml.Linq;
using Microsoft.Win32;
namespace ArchestrAServices.Common;
public class RegistryHandler
{
private static string asbInstallPath = string.Empty;
private static string asbCoreServicesInstallPath = string.Empty;
private static string managementServerAddress = string.Empty;
public static string ASBSolutionsSubkey = string.Empty;
public static string ASBRegistration = "NodeRegistration";
public static string LDSPort = "808";
public static string PGDSEndPoint = "PrimaryGlobalDiscovery";
public static string SGDSEndPoint = "SecondaryGlobalDiscovery";
public static string PUDSEndPoint = "PrimaryUniversalDiscovery";
public static string SUDSEndPoint = "SecondaryUniversalDiscovery";
public static string LDSEndPoint = "EndPointLocalDiscovery";
private static string Wow64OptionalLayer
{
get
{
if (!Environment.Is64BitProcess)
{
return string.Empty;
}
return "Wow6432Node\\";
}
}
public static string RegistryPath => "SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices\\";
public static string Registry32Path => "SOFTWARE\\ArchestrA\\ArchestrAServices\\";
public static string ASBSolutionPath => RegistryPath + ASBSolutionsSubkey;
public static string ASBNodeRegistraion => $"{RegistryPath}{ASBRegistration}";
public static string ASBInstallPath
{
get
{
if (string.IsNullOrEmpty(asbInstallPath))
{
try
{
asbInstallPath = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "ASBInstallPath", string.Empty).ToString();
}
catch (NullReferenceException)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "ParentKey for ASBInstallPath key was not found in registry");
}
}
return asbInstallPath;
}
}
public static string AsbCoreServicesInstallPath
{
get
{
if (!string.IsNullOrEmpty(asbCoreServicesInstallPath))
{
return asbCoreServicesInstallPath;
}
try
{
string text = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "FwkInstallPath", string.Empty).ToString();
if (!string.IsNullOrEmpty(text))
{
asbCoreServicesInstallPath = Path.Combine(text, "CoreServices");
}
}
catch (NullReferenceException)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "ParentKey for FwkInstallPath key was not found in registry");
}
return asbCoreServicesInstallPath;
}
}
public static SecureCommunicationModes SecureCommunicationMode
{
get
{
try
{
string text = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "SecureCommunicationMode", 0).ToString();
if (!string.IsNullOrEmpty(text))
{
int.TryParse(text, out var result);
return (SecureCommunicationModes)result;
}
}
catch
{
}
return SecureCommunicationModes.Never;
}
set
{
try
{
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "SecureCommunicationMode", (int)value, RegistryValueKind.DWord);
}
catch
{
}
}
}
public static bool AsbManagedCertificates
{
get
{
try
{
return Convert.ToBoolean(Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "ASBManagedCertificates", 1));
}
catch
{
}
return true;
}
set
{
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "ASBManagedCertificates", value, RegistryValueKind.DWord);
}
}
public static int DefaultSslPort
{
get
{
try
{
return Convert.ToInt32(Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\WebApplications\\Default", "SslPort", 443));
}
catch
{
}
return 443;
}
set
{
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\WebApplications\\Default", "SslPort", value, RegistryValueKind.DWord);
}
}
public static string ManagementServerAddress
{
get
{
try
{
if (string.IsNullOrEmpty(managementServerAddress))
{
managementServerAddress = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\" + Wow64OptionalLayer + "ArchestrA\\ArchestrAServices", "MSAddress", string.Empty).ToString();
}
return managementServerAddress;
}
catch
{
}
return string.Empty;
}
}
public static Uri MakeLDSProbeEndpointAddress(string NodeName)
{
return new Uri("net.tcp://" + NodeName + "/LDS/Probe");
}
public static Uri MakeLDSEndpointAddress(string NodeName)
{
return new Uri("net.tcp://" + NodeName + "/LDS");
}
public static string DeleteFromRegistry(string solutionName)
{
string SRNodeName;
string srNode = GetSrNode(solutionName, out SRNodeName);
if (!string.IsNullOrEmpty(srNode))
{
return srNode;
}
if (SRNodeName.ToUpperInvariant() == Environment.MachineName.ToUpperInvariant())
{
return "Cannot delete the SR node solution.";
}
string subkey = RegistryPath;
if (!string.IsNullOrEmpty(solutionName))
{
subkey = ASBSolutionPath + solutionName;
}
try
{
Registry.LocalMachine.DeleteSubKeyTree(subkey);
return "Success";
}
catch (ArgumentNullException ex)
{
return "Node Does not exist to delete: " + ex.Message;
}
catch (SecurityException ex2)
{
return "Security Error: " + ex2.Message;
}
catch (ArgumentException ex3)
{
return "Node Does not exist to delete: " + ex3.Message;
}
catch (ObjectDisposedException ex4)
{
return ex4.Message;
}
catch (UnauthorizedAccessException ex5)
{
return "UnauthorizedAccessException: " + ex5.Message;
}
}
public static string CreateASBConfigInfoStructureInRegistry(ASBConfigurationInformation securityConfiguration, string srNode, bool isRegister)
{
try
{
if (securityConfiguration != null)
{
CreateSolutionKey(securityConfiguration);
CreateNodeRegistrationyKey(securityConfiguration, isRegister);
return "Success";
}
return "Cannot write security configuration to registry: Please provide SecurityConfiguration";
}
catch (UnauthorizedAccessException ex)
{
return "Cannot write security configuration to registry: " + ex.Message;
}
catch (SecurityException ex2)
{
return "Cannot write security configuration to registry: " + ex2.Message;
}
catch (IOException ex3)
{
return "Cannot write security configuration to registry: " + ex3.Message;
}
catch (ObjectDisposedException ex4)
{
return "Cannot write security configuration to registry: " + ex4.Message;
}
}
public static string ReadASBConfigInfoStructureFromRegistry(string solutionName, out ASBConfigurationInformation securityConfiguration)
{
string empty = string.Empty;
string text = solutionName;
string DefaultSolutionName;
string defaultSolutionName = GetDefaultSolutionName(out DefaultSolutionName);
if (string.IsNullOrEmpty(solutionName))
{
if (string.IsNullOrEmpty(defaultSolutionName))
{
securityConfiguration = null;
return "Read of default ASBSolution requested, but no default on local machine";
}
text = DefaultSolutionName;
}
RegistryKey registryKey = null;
using (RegistryKey registryKey2 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
{
registryKey = registryKey2.OpenSubKey(Registry32Path + "\\" + text);
registryKey2.Close();
if (registryKey == null)
{
securityConfiguration = null;
return "ASBSolution " + text + " does not exist local machine";
}
}
using (registryKey)
{
securityConfiguration = FillConfigurationFromRegistry(registryKey, text, DefaultSolutionName);
registryKey.Close();
return empty;
}
}
private static ASBConfigurationInformation FillConfigurationFromRegistry(RegistryKey asbSolutionKey, string solutionNameToRead, string defaultSolutionName)
{
if (asbSolutionKey == null)
{
return null;
}
ASBConfigurationInformation aSBConfigurationInformation = new ASBConfigurationInformation
{
SolutionName = solutionNameToRead
};
try
{
aSBConfigurationInformation.Generator = asbSolutionKey.GetValue("Generator", string.Empty).ToString();
aSBConfigurationInformation.Prime = asbSolutionKey.GetValue("Prime", string.Empty).ToString();
aSBConfigurationInformation.HashAlgorithm = asbSolutionKey.GetValue("HashAlgorthim", string.Empty).ToString();
aSBConfigurationInformation.InitializationVector = asbSolutionKey.GetValue("initailizationVector", string.Empty).ToString();
aSBConfigurationInformation.SaltValue = asbSolutionKey.GetValue("saltValue", string.Empty).ToString();
string s = asbSolutionKey.GetValue("passowordIterations", "0").ToString();
aSBConfigurationInformation.PasswordDerivationIterations = int.Parse(s);
string s2 = asbSolutionKey.GetValue("keySize", "0").ToString();
aSBConfigurationInformation.KeySize = int.Parse(s2);
try
{
DPUtility dPUtility = new DPUtility(DPUtility.Store.USE_MACHINE_STORE);
byte[] bytes = Encoding.Unicode.GetBytes("wonderware");
byte[] cipherText = (byte[])asbSolutionKey.GetValue("sharedsecret", RegistryValueKind.Binary);
byte[] bytes2 = dPUtility.Decrypt(cipherText, bytes);
aSBConfigurationInformation.EncryptedSharedSecret = Encoding.Unicode.GetString(bytes2);
}
catch (Exception ex)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "Reading and decrypting shared secret failed with exception {0}", ex.Message);
}
aSBConfigurationInformation.EncryptedCertificate = asbSolutionKey.GetValue("Certificate", RegistryValueKind.String).ToString();
aSBConfigurationInformation.IsDefault = ((string.Compare(solutionNameToRead, defaultSolutionName, ignoreCase: true) == 0) ? "true" : "false");
if (string.IsNullOrEmpty(GetSrNode(solutionNameToRead, out var SRNodeName)))
{
aSBConfigurationInformation.SRNodeName = SRNodeName;
}
}
catch (Exception ex2)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "Failed to read a solution element for ASB Solution {0} with exception {1}", solutionNameToRead, ex2.Message);
}
return aSBConfigurationInformation;
}
private static void CreateNodeRegistrationyKey(ASBConfigurationInformation securityConfiguration, bool isRegister)
{
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(ASBSolutionPath + securityConfiguration.SolutionName + "\\NodeRegistration", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
Uri uri = MakeLDSEndpointAddress(securityConfiguration.SRNodeName);
if (registryKey != null)
{
SetSecurityParameter(uri.AbsoluteUri, registryKey, LDSEndPoint);
SetSecurityParameter(securityConfiguration.PrimaryGlobalDiscovery, registryKey, PGDSEndPoint);
SetSecurityParameter(securityConfiguration.SecondaryGlobalDiscovery, registryKey, SGDSEndPoint);
SetSecurityParameter(securityConfiguration.PrimaryUniversalDiscovery, registryKey, PUDSEndPoint);
SetSecurityParameter(securityConfiguration.SecondaryUniversalDiscovery, registryKey, SUDSEndPoint);
SetSecurityParameter(securityConfiguration.SRNodeName, registryKey, "ServiceRepositoryNode");
registryKey.Close();
registryKey.Dispose();
}
if (isRegister && string.Compare(securityConfiguration.IsDefault, "true", StringComparison.OrdinalIgnoreCase) == 0)
{
RegistryKey registryKey2 = Registry.LocalMachine.CreateSubKey(RegistryPath + "NodeRegistration", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
Uri uri2 = MakeLDSEndpointAddress(Environment.MachineName);
if (registryKey2 != null)
{
SetSecurityParameter(uri2.AbsoluteUri, registryKey2, LDSEndPoint);
SetSecurityParameter(securityConfiguration.PrimaryGlobalDiscovery, registryKey2, PGDSEndPoint);
SetSecurityParameter(securityConfiguration.SecondaryGlobalDiscovery, registryKey2, SGDSEndPoint);
SetSecurityParameter(securityConfiguration.PrimaryUniversalDiscovery, registryKey2, PUDSEndPoint);
SetSecurityParameter(securityConfiguration.SecondaryUniversalDiscovery, registryKey2, SUDSEndPoint);
SetSecurityParameter(securityConfiguration.SRNodeName, registryKey2, "ServiceRepositoryNode");
CreateRootKey(securityConfiguration);
registryKey2.Close();
registryKey2.Dispose();
}
}
}
private static void CreateRootKey(ASBConfigurationInformation securityConfiguration)
{
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(RegistryPath, RegistryKeyPermissionCheck.ReadWriteSubTree);
registryKey?.SetValue("DefaultASBSolution", securityConfiguration.SolutionName);
}
private static void CreateSolutionKey(ASBConfigurationInformation securityConfiguration)
{
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(ASBSolutionPath + securityConfiguration.SolutionName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
if (registryKey != null)
{
SetSecurityParameter(securityConfiguration.EncryptedCertificate, registryKey, "Certificate");
SetSecurityParameter(securityConfiguration.Generator, registryKey, "Generator");
SetSecurityParameter(securityConfiguration.HashAlgorithm, registryKey, "HashAlgorthim");
SetSecurityParameter(securityConfiguration.InitializationVector, registryKey, "initailizationVector");
SetSecurityParameter(securityConfiguration.SaltValue, registryKey, "saltValue");
SetSecurityParameter(securityConfiguration.Prime, registryKey, "Prime");
try
{
DPUtility dPUtility = new DPUtility(DPUtility.Store.USE_MACHINE_STORE);
byte[] bytes = Encoding.Unicode.GetBytes(securityConfiguration.EncryptedSharedSecret);
byte[] bytes2 = Encoding.Unicode.GetBytes("wonderware");
byte[] value = dPUtility.Encrypt(bytes, bytes2);
registryKey.SetValue("sharedsecret", value, RegistryValueKind.Binary);
}
catch (Exception ex)
{
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Failed to write passphrase to registry: {0}", ex.Message);
}
registryKey.SetValue("passowordIterations", securityConfiguration.PasswordDerivationIterations);
registryKey.SetValue("keySize", securityConfiguration.KeySize);
registryKey.Close();
registryKey.Dispose();
}
}
private static void SetSecurityParameter(string securityConfiguration, RegistryKey solutionKey, string name)
{
if (!string.IsNullOrEmpty(securityConfiguration))
{
solutionKey.SetValue(name, securityConfiguration);
}
else
{
solutionKey.SetValue(name, string.Empty);
}
}
public static string CreateUniversalSolutionStructureInRegistry(ASBConfigurationInformation securityConfiguration)
{
string result = string.Empty;
try
{
if (securityConfiguration != null)
{
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(ASBSolutionPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue);
if (registryKey == null)
{
result = "Cannot open parent registry key for creating the Universal Solution.";
}
else
{
using (RegistryKey registryKey2 = registryKey.OpenSubKey(securityConfiguration.SolutionName))
{
if (registryKey2 == null)
{
CreateSolutionKey(securityConfiguration);
}
}
registryKey.SetValue("UniversalSolution", securityConfiguration.SolutionName, RegistryValueKind.String);
}
}
else
{
result = "Please provide details for configuring the Universal Solution.";
}
}
catch (UnauthorizedAccessException ex)
{
result = ex.Message;
}
catch (SecurityException ex2)
{
result = ex2.Message;
}
catch (IOException ex3)
{
result = ex3.Message;
}
catch (ObjectDisposedException ex4)
{
result = ex4.Message;
}
return result;
}
public static string GetSrNode(out string SRNodeName)
{
SRNodeName = string.Empty;
RegistryKey registryKey = null;
string result = string.Empty;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(RegistryPath + "NodeRegistration");
object obj = null;
if (registryKey != null && (obj = registryKey.GetValue("ServiceRepositoryNode")) != null)
{
SRNodeName = obj.ToString();
if (string.IsNullOrEmpty(SRNodeName))
{
result = "Default SR Node name is empty";
}
}
else
{
result = "Unable to open registry key " + RegistryPath + "NodeRegistration\\ServiceRepositoryNode";
}
}
catch (UnauthorizedAccessException ex)
{
result = ex.Message;
}
catch (SecurityException ex2)
{
result = ex2.Message;
}
catch (IOException ex3)
{
result = ex3.Message;
}
catch (ObjectDisposedException ex4)
{
result = ex4.Message;
}
finally
{
registryKey?.Close();
}
return result;
}
public static bool GetSRInstalled()
{
bool result = false;
try
{
result = GetBinaryRegistryValue(RegistryPath, "SRInstalled");
}
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is SecurityException || ex is IOException || ex is ObjectDisposedException)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "GetSRInstalled: Unable to read SR installation status from registry, assuming false: {0}", ex.Message);
}
return result;
}
public static bool GetManagementServerInstalled()
{
bool result = false;
try
{
result = GetBinaryRegistryValue(RegistryPath, "MSInstalled");
}
catch (Exception ex) when (ex is UnauthorizedAccessException || ex is SecurityException || ex is IOException || ex is ObjectDisposedException)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "GetManagementServerInstalled: Unable to read Management Server installation status from registry, assuming false: {0}", ex.Message);
}
return result;
}
public static string GetSrNode(string SolutionName, out string SRNodeName)
{
SRNodeName = string.Empty;
RegistryKey registryKey = null;
string result = string.Empty;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(ASBSolutionPath + SolutionName + "\\NodeRegistration", writable: true);
object obj = null;
if (registryKey != null && (obj = registryKey.GetValue("ServiceRepositoryNode")) != null)
{
SRNodeName = obj.ToString();
if (string.IsNullOrEmpty(SRNodeName))
{
result = "Default SR Node name is empty";
}
}
else
{
result = "Unable to open registry key " + ASBSolutionPath + SolutionName + "\\NodeRegistration\\ServiceRepositoryNode";
}
}
catch (UnauthorizedAccessException ex)
{
result = ex.Message;
}
catch (SecurityException ex2)
{
result = ex2.Message;
}
catch (IOException ex3)
{
result = ex3.Message;
}
catch (ObjectDisposedException ex4)
{
result = ex4.Message;
}
finally
{
registryKey?.Close();
}
return result;
}
public static string GetDefaultSolutionName(out string DefaultSolutionName)
{
DefaultSolutionName = string.Empty;
RegistryKey registryKey = null;
string result = string.Empty;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(RegistryPath, writable: false);
object obj = null;
if (registryKey != null && (obj = registryKey.GetValue("DefaultASBSolution")) != null)
{
DefaultSolutionName = obj.ToString();
result = string.Empty;
}
else
{
result = "Unable to open registry key " + RegistryPath + "\\DefaultASBSolution";
}
}
catch (UnauthorizedAccessException ex)
{
result = ex.Message;
}
catch (SecurityException ex2)
{
result = ex2.Message;
}
catch (IOException ex3)
{
result = ex3.Message;
}
catch (ObjectDisposedException ex4)
{
result = ex4.Message;
}
finally
{
registryKey?.Close();
}
return result;
}
public static string GetSolutionPassphrase(string asbSolution, out string passphrase)
{
passphrase = string.Empty;
string result = string.Empty;
if (string.IsNullOrEmpty(asbSolution))
{
result = GetDefaultSolutionName(out asbSolution);
}
if (string.IsNullOrEmpty(asbSolution))
{
passphrase = string.Empty;
return result;
}
RegistryKey registryKey = null;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(ASBSolutionPath + asbSolution, writable: false);
object obj = null;
if (registryKey != null && (obj = registryKey.GetValue("sharedsecret")) != null)
{
try
{
byte[] bytes = new DPUtility(DPUtility.Store.USE_MACHINE_STORE).Decrypt(optionalEntropy: Encoding.Unicode.GetBytes("wonderware"), cipherText: (byte[])obj);
passphrase = Encoding.Unicode.GetString(bytes);
result = string.Empty;
}
catch (Exception)
{
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Failed to read passphrase from registry.");
}
}
else
{
result = string.Format("Unable to find the passphrase for the solution: '{0}'. Confirm that local galaxy and remote galaxy (whose solution name is '{0}') have been paired", asbSolution);
SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Unable to open registry key {0}{1}\\sharedsecret", ASBSolutionPath, asbSolution);
}
}
catch (UnauthorizedAccessException ex2)
{
result = ex2.Message;
}
catch (SecurityException ex3)
{
result = ex3.Message;
}
catch (IOException ex4)
{
result = ex4.Message;
}
catch (ObjectDisposedException ex5)
{
result = ex5.Message;
}
finally
{
registryKey?.Close();
}
return result;
}
public static List<string> EnumerateSolutionsAtThisNode()
{
_ = string.Empty;
List<string> list = new List<string>();
RegistryKey registryKey = null;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(ASBSolutionPath, writable: true);
if (registryKey != null)
{
string[] subKeyNames = registryKey.GetSubKeyNames();
foreach (string text in subKeyNames)
{
if (string.Compare(text, ASBRegistration, ignoreCase: true) != 0)
{
list.Add(text);
}
}
}
else
{
_ = "Unable to open registry key " + ASBSolutionPath;
}
}
catch (UnauthorizedAccessException ex)
{
_ = ex.Message;
}
catch (SecurityException ex2)
{
_ = ex2.Message;
}
catch (IOException ex3)
{
_ = ex3.Message;
}
catch (ObjectDisposedException ex4)
{
_ = ex4.Message;
}
finally
{
registryKey?.Close();
}
return list;
}
public static List<KeyValuePair<string, string>> ReadDiscoveryInfoFromRegistry(string asbSolutionName)
{
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
using (RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(ASBSolutionPath + asbSolutionName + "\\" + ASBRegistration, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None))
{
if (registryKey != null)
{
list.Add(new KeyValuePair<string, string>(LDSEndPoint, registryKey.GetValue(LDSEndPoint, string.Empty).ToString()));
list.Add(new KeyValuePair<string, string>(PGDSEndPoint, registryKey.GetValue(PGDSEndPoint, string.Empty).ToString()));
list.Add(new KeyValuePair<string, string>(SGDSEndPoint, registryKey.GetValue(SGDSEndPoint, string.Empty).ToString()));
list.Add(new KeyValuePair<string, string>(PUDSEndPoint, registryKey.GetValue(PUDSEndPoint, string.Empty).ToString()));
list.Add(new KeyValuePair<string, string>(SUDSEndPoint, registryKey.GetValue(SUDSEndPoint, string.Empty).ToString()));
list.Add(new KeyValuePair<string, string>("ServiceRepositoryNode", registryKey.GetValue("ServiceRepositoryNode", string.Empty).ToString()));
registryKey.Close();
}
}
return list;
}
public static bool SetDiscoveryInfoInRegistry(string solutionName, List<KeyValuePair<string, string>> extraInfo, string srNode = null)
{
if (extraInfo == null)
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "SetDiscoveryInfoInRegistry: Unable to proceed with no info to set, not setting Discovery information");
return false;
}
if (!string.IsNullOrEmpty(srNode))
{
extraInfo.Add(new KeyValuePair<string, string>("ServiceRepositoryNode", srNode));
}
string text = solutionName;
if (!string.IsNullOrEmpty(GetDefaultSolutionName(out var DefaultSolutionName)))
{
DefaultSolutionName = string.Empty;
}
if (string.IsNullOrEmpty(text))
{
text = DefaultSolutionName;
}
if (string.IsNullOrEmpty(text))
{
SvcTrace.DiagControl.TraceEvent(TraceEventType.Warning, 0, "SetDiscoveryInfoInRegistry: Default solution specified, but does not exist, not setting Discovery information");
return false;
}
using (RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(ASBSolutionPath + solutionName + "\\NodeRegistration", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None))
{
if (registryKey != null)
{
foreach (KeyValuePair<string, string> item in extraInfo)
{
if (string.Compare(item.Key, LDSEndPoint) == 0 || string.Compare(item.Key, PGDSEndPoint) == 0 || string.Compare(item.Key, SGDSEndPoint) == 0 || string.Compare(item.Key, PUDSEndPoint) == 0 || string.Compare(item.Key, SUDSEndPoint) == 0 || string.Compare(item.Key, "ServiceRepositoryNode") == 0)
{
SetSecurityParameter(item.Value, registryKey, item.Key);
break;
}
}
registryKey.Close();
}
}
if (string.Compare(text, DefaultSolutionName, ignoreCase: true) == 0)
{
using RegistryKey registryKey2 = Registry.LocalMachine.CreateSubKey(RegistryPath + "NodeRegistration", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
if (registryKey2 != null)
{
foreach (KeyValuePair<string, string> item2 in extraInfo)
{
if (string.Compare(item2.Key, LDSEndPoint) == 0 || string.Compare(item2.Key, PGDSEndPoint) == 0 || string.Compare(item2.Key, SGDSEndPoint) == 0 || string.Compare(item2.Key, PUDSEndPoint) == 0 || string.Compare(item2.Key, SUDSEndPoint) == 0 || string.Compare(item2.Key, "ServiceRepositoryNode") == 0)
{
SetSecurityParameter(item2.Value, registryKey2, item2.Key);
break;
}
}
registryKey2.Close();
}
}
return true;
}
public static void UpdateDiscoveryInfos(List<KeyValuePair<string, string>> discoveryInfos)
{
UpdateDiscoverySingleRegKey(string.Empty, discoveryInfos);
if (string.IsNullOrEmpty(GetDefaultSolutionName(out var DefaultSolutionName)))
{
UpdateDiscoverySingleRegKey(DefaultSolutionName, discoveryInfos);
}
}
private static void UpdateDiscoverySingleRegKey(string solutionName, List<KeyValuePair<string, string>> discoveryInfos)
{
if (solutionName == null)
{
solutionName = string.Empty;
}
if (!string.IsNullOrEmpty(solutionName))
{
solutionName += "\\";
}
RegistryKey registryKey = Registry.LocalMachine.CreateSubKey(ASBSolutionPath + solutionName + "NodeRegistration", RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryOptions.None);
if (registryKey == null)
{
return;
}
foreach (KeyValuePair<string, string> discoveryInfo in discoveryInfos)
{
switch (discoveryInfo.Key)
{
case "PrimaryGlobalDiscovery":
WriteRegistryValue(registryKey, PGDSEndPoint, discoveryInfo.Value);
break;
case "SecondaryGlobalDiscovery":
WriteRegistryValue(registryKey, SGDSEndPoint, discoveryInfo.Value);
break;
case "PrimaryUniversalDiscovery":
WriteRegistryValue(registryKey, PUDSEndPoint, discoveryInfo.Value);
break;
case "SecondaryUniversalDiscovery":
WriteRegistryValue(registryKey, SUDSEndPoint, discoveryInfo.Value);
break;
}
}
}
private static void WriteRegistryValue(RegistryKey solutionKey, string key, string value)
{
if (solutionKey != null)
{
if (!string.IsNullOrEmpty(value))
{
solutionKey.SetValue(key, value);
}
else
{
solutionKey.SetValue(key, string.Empty);
}
}
}
public static string GenerateXMLExtraInfo(List<KeyValuePair<string, string>> Parameters)
{
XElement xElement = new XElement("extrainfo");
if (Parameters != null)
{
foreach (KeyValuePair<string, string> Parameter in Parameters)
{
XElement xElement2 = new XElement("parameter");
xElement2.Add(new XAttribute("name", Parameter.Key));
xElement2.Add(new XAttribute("value", Parameter.Value));
xElement.Add(xElement2);
}
}
return xElement.ToString();
}
public static Dictionary<string, string> ParseXMLExtraInfo(string XMLExtraInfo)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(XMLExtraInfo))
{
XElement xElement = null;
using StringReader stringReader = new StringReader(XMLExtraInfo);
if (stringReader != null)
{
xElement = XElement.Load(stringReader);
}
if (xElement != null)
{
foreach (XElement item in xElement.Elements("parameter"))
{
XAttribute xAttribute = item.Attribute("name");
XAttribute xAttribute2 = item.Attribute("value");
if (xAttribute != null && xAttribute2 != null)
{
dictionary.Add(xAttribute.Value, xAttribute2.Value);
}
}
}
else
{
SvcTrace.DiagException.TraceEvent(TraceEventType.Warning, 0, $"ParseXMLExtraInfo failed to parse XMLExtraInfo {XMLExtraInfo}");
}
}
return dictionary;
}
private static bool GetBinaryRegistryValue(string keyPath, string keyName)
{
bool result = false;
RegistryKey registryKey = null;
try
{
registryKey = Registry.LocalMachine.OpenSubKey(keyPath);
if (registryKey != null)
{
result = Convert.ToBoolean(registryKey.GetValue(keyName));
}
registryKey?.Close();
}
catch (Exception)
{
registryKey?.Close();
throw;
}
return result;
}
}