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

748 lines
20 KiB
C#

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ArchestrAServices.Contract;
public static class VariantFactory
{
public static Variant MakeVariantValue(bool value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeBool),
Length = 1,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(sbyte value)
{
Variant result = new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeSByte),
Length = 1,
Payload = new byte[1]
};
result.Payload[0] = (byte)value;
return result;
}
public static Variant MakeVariantValue(byte value)
{
Variant result = new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeByte),
Length = 1,
Payload = new byte[1]
};
result.Payload[0] = value;
return result;
}
public static Variant MakeVariantValue(ushort value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeUInt16),
Length = 2,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(uint value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeUInt32),
Length = 4,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(ulong value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeUInt64),
Length = 8,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(short value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeInt16),
Length = 2,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(int value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeInt32),
Length = 4,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(long value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeInt64),
Length = 8,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValueAsDuration(long value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeDuration),
Length = 8,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValueAsDurationArray(long[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
result = MakeVariantValue(value);
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDurationArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDurationArray);
return result;
}
public static Variant MakeVariantValue(float value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeFloat),
Length = 4,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(double value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeDouble),
Length = 8,
Payload = BitConverter.GetBytes(value)
};
}
public static Variant MakeVariantValue(string value)
{
Variant result = default(Variant);
result.Type = EnumFactory.DataTypeToInt(DataType.TypeString);
result.Payload = Encoding.Unicode.GetBytes(value);
result.Length = result.Payload.Count();
return result;
}
public static Variant MakeVariantValue(DateTime value)
{
return new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeDateTime),
Length = 8,
Payload = BitConverter.GetBytes(value.ToFileTimeUtc())
};
}
public static Variant MakeVariantValue(Guid value)
{
Variant variant = new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeGuid)
};
return MakeVariantValue(value.ToString());
}
public static Variant MakeVariantValue(long value, bool bStatus)
{
Variant result = new Variant
{
Type = EnumFactory.DataTypeToInt(DataType.TypeLocalizedText)
};
MemoryStream memoryStream = null;
try
{
memoryStream = new MemoryStream();
using (StreamWriter streamWriter = new StreamWriter(memoryStream))
{
memoryStream = null;
streamWriter.Write(value);
streamWriter.Flush();
}
result.Payload = memoryStream.ToArray();
result.Length = result.Payload.Count();
return result;
}
finally
{
memoryStream?.Dispose();
}
}
public static Variant MakeVariantValue(CustomEnum customEnum)
{
Variant result = default(Variant);
short ordinal = customEnum.ordinal;
string ordinalValue = customEnum.OrdinalValue;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeEnum);
List<byte> list = new List<byte>();
list.AddRange(BitConverter.GetBytes(Convert.ToInt16(ordinal)));
list.AddRange(BitConverter.GetBytes(Convert.ToUInt32(ordinalValue.Length)));
list.AddRange(Encoding.Unicode.GetBytes(ordinalValue));
result.Length = 6 + ordinalValue.Length;
result.Payload = list.ToArray();
return result;
}
public static Variant MakeVariantValue(int[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 4];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt32Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt32Array);
return result;
}
public static Variant MakeVariantValue(uint[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 4];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt32Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt32Array);
return result;
}
public static Variant MakeVariantValue(long[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 8];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt64Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt64Array);
return result;
}
public static Variant MakeVariantValue(ulong[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 8];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt64Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt64Array);
return result;
}
public static Variant MakeVariantValue(float[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 4];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeFloatArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeFloatArray);
return result;
}
public static Variant MakeVariantValue(double[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 8];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDoubleArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDoubleArray);
return result;
}
public static Variant MakeVariantValue(short[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 2];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt16Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeInt16Array);
return result;
}
public static Variant MakeVariantValue(ushort[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 2];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt16Array);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeUInt16Array);
return result;
}
public static Variant MakeVariantValue(byte[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
result.Length = value.Length;
result.Payload = value;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeByteArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeByteArray);
return result;
}
public static Variant MakeVariantValue(sbyte[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeSByteArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeSByteArray);
return result;
}
public static Variant MakeVariantValue(bool[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeBoolArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeBoolArray);
return result;
}
public static Variant MakeVariantValue(DateTime[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
long[] array = new long[value.Length];
for (int i = 0; i < value.Length; i++)
{
array[i] = value[i].ToFileTimeUtc();
}
result = MakeVariantValue(array);
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDateTimeArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeDateTimeArray);
return result;
}
public static Variant MakeVariantValue(char[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
byte[] array = new byte[value.Length * 2];
Buffer.BlockCopy(value, 0, array, 0, array.Length);
result.Length = array.Length;
result.Payload = array;
result.Type = EnumFactory.DataTypeToInt(DataType.TypeCharArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeCharArray);
return result;
}
public static Variant MakeVariantValue(string[] value)
{
if (value == null || value.Length == 0)
{
return new Variant
{
Length = 0,
Payload = new byte[0],
Type = EnumFactory.DataTypeToInt(DataType.TypeStringArray)
};
}
byte[][] array = new byte[value.Length][];
int num = 0;
for (int i = 0; i < value.Length; i++)
{
if (value[i] == null)
{
array[i] = new byte[0];
}
else
{
array[i] = Encoding.Unicode.GetBytes(value[i]);
num += array[i].Length;
}
num += 4;
}
byte[] array2 = new byte[num];
int j = 0;
int num2 = 0;
for (; j < value.Length; j++)
{
byte[] bytes = BitConverter.GetBytes(array[j].Length);
Buffer.BlockCopy(bytes, 0, array2, num2, bytes.Length);
num2 += bytes.Length;
Buffer.BlockCopy(array[j], 0, array2, num2, array[j].Length);
num2 += array[j].Length;
}
return new Variant
{
Length = array2.Length,
Payload = array2,
Type = EnumFactory.DataTypeToInt(DataType.TypeStringArray)
};
}
public static Variant MakeVariantValue(Guid[] value)
{
Variant result = default(Variant);
if (value != null && value.Length != 0)
{
string[] array = new string[value.Length];
for (int i = 0; i < value.Length; i++)
{
array[i] = value[i].ToString();
}
result = MakeVariantValue(array);
result.Type = EnumFactory.DataTypeToInt(DataType.TypeGuidArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeGuidArray);
return result;
}
public static Variant MakeVariantValue(CustomEnum[] customEnum)
{
Variant result = default(Variant);
int num = 0;
List<byte> list = new List<byte>();
if (customEnum != null && customEnum.Length != 0)
{
for (int i = 0; i < customEnum.Length; i++)
{
short ordinal = customEnum[i].ordinal;
string ordinalValue = customEnum[i].OrdinalValue;
num += 6 + ordinalValue.Length;
list.AddRange(BitConverter.GetBytes(Convert.ToInt16(ordinal)));
list.AddRange(BitConverter.GetBytes(Convert.ToUInt32(ordinalValue.Length)));
list.AddRange(Encoding.Unicode.GetBytes(ordinalValue));
}
result.Length = num;
result.Payload = list.ToArray();
result.Type = EnumFactory.DataTypeToInt(DataType.TypeEnumArray);
return result;
}
result.Length = 0;
result.Payload = new byte[0];
result.Type = EnumFactory.DataTypeToInt(DataType.TypeEnum);
return result;
}
public static Variant MakeVariantArray(Array valueArray)
{
Variant result = default(Variant);
Type type = valueArray.GetType();
type.GetArrayRank();
int VariantElementSize = 0;
if (type.HasElementType)
{
CalculateTypeAndSize(type.GetElementType(), ref result.Type, ref VariantElementSize);
}
uint arrayRank = (uint)type.GetArrayRank();
byte[] array = new byte[4 + arrayRank * 4 + valueArray.Length * VariantElementSize];
int num = 0;
byte[] bytes = BitConverter.GetBytes(arrayRank);
bytes.CopyTo(array, num);
num += bytes.Count();
int[] array2 = new int[arrayRank];
for (int i = 0; i < array2.Count(); i++)
{
byte[] bytes2 = BitConverter.GetBytes((uint)valueArray.GetLength(i));
bytes2.CopyTo(array, num);
num += bytes2.Count();
array2[i] = 0;
}
PackArray(array, ref num, valueArray, array2, 0);
result.Payload = array;
result.Length = result.Payload.Count();
return result;
}
[GeneratedCode("Manually Avoid Code Metrics", "0.0.0.0")]
private static void CalculateTypeAndSize(Type valueArrayElementType, ref ushort VariantElementType, ref int VariantElementSize)
{
if (valueArrayElementType == typeof(bool))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeBoolArray);
VariantElementSize = 1;
}
else if (valueArrayElementType == typeof(sbyte))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeSByteArray);
VariantElementSize = 1;
}
else if (valueArrayElementType == typeof(byte))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeByteArray);
VariantElementSize = 1;
}
else if (valueArrayElementType == typeof(ushort))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeUInt16Array);
VariantElementSize = 2;
}
else if (valueArrayElementType == typeof(uint))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeUInt32Array);
VariantElementSize = 4;
}
else if (valueArrayElementType == typeof(ulong))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeUInt64Array);
VariantElementSize = 8;
}
else if (valueArrayElementType == typeof(short))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeInt16Array);
VariantElementSize = 2;
}
else if (valueArrayElementType == typeof(int))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeInt32Array);
VariantElementSize = 4;
}
else if (valueArrayElementType == typeof(long))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeInt64Array);
VariantElementSize = 8;
}
else if (valueArrayElementType == typeof(float))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeFloatArray);
VariantElementSize = 4;
}
else if (valueArrayElementType == typeof(double))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeDoubleArray);
VariantElementSize = 8;
}
else if (valueArrayElementType == typeof(string))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeStringArray);
VariantElementSize = 0;
}
else if (valueArrayElementType == typeof(DateTime))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeDateTimeArray);
VariantElementSize = 8;
}
else if (valueArrayElementType == typeof(Guid))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeGuidArray);
VariantElementSize = Guid.Empty.ToByteArray().Count();
}
else if (valueArrayElementType == typeof(byte[]))
{
VariantElementType = EnumFactory.DataTypeToInt(DataType.TypeByteStringArray);
VariantElementSize = 0;
}
}
private static void PackArray(byte[] Payload, ref int PayloadIndex, Array valueArray, int[] DimensionIndices, int Dimension)
{
if (Dimension == DimensionIndices.Count() - 1)
{
for (int i = 0; i < valueArray.GetLength(Dimension); i++)
{
DimensionIndices[Dimension] = i;
byte[] array = PackArrayElement(valueArray.GetValue(DimensionIndices));
array.CopyTo(Payload, PayloadIndex);
PayloadIndex += array.Count();
}
}
else
{
for (int j = 0; j < valueArray.GetLength(Dimension); j++)
{
DimensionIndices[Dimension] = j;
PackArray(Payload, ref PayloadIndex, valueArray, DimensionIndices, Dimension + 1);
}
}
}
[GeneratedCode("Manually Avoid Code Metrics", "0.0.0.0")]
private static byte[] PackArrayElement(object element)
{
if (element == null)
{
return new byte[0];
}
if (element.GetType() == typeof(bool))
{
return BitConverter.GetBytes((bool)element);
}
if (element.GetType() == typeof(sbyte))
{
return BitConverter.GetBytes((sbyte)element);
}
if (element.GetType() == typeof(byte))
{
return BitConverter.GetBytes((byte)element);
}
if (element.GetType() == typeof(ushort))
{
return BitConverter.GetBytes((ushort)element);
}
if (element.GetType() == typeof(uint))
{
return BitConverter.GetBytes((uint)element);
}
if (element.GetType() == typeof(ulong))
{
return BitConverter.GetBytes((ulong)element);
}
if (element.GetType() == typeof(short))
{
return BitConverter.GetBytes((int)element);
}
if (element.GetType() == typeof(int))
{
return BitConverter.GetBytes((int)element);
}
if (element.GetType() == typeof(long))
{
return BitConverter.GetBytes((int)element);
}
if (element.GetType() == typeof(float))
{
return BitConverter.GetBytes((float)element);
}
if (element.GetType() == typeof(double))
{
return BitConverter.GetBytes((double)element);
}
if (element.GetType() == typeof(string))
{
return Encoding.Unicode.GetBytes((string)element);
}
if (element.GetType() == typeof(DateTime))
{
return BitConverter.GetBytes(((DateTime)element).ToBinary());
}
if (element.GetType() == typeof(Guid))
{
return ((Guid)element).ToByteArray();
}
if (element.GetType() == typeof(byte[]))
{
return (byte[])element;
}
return new byte[0];
}
}