summaryrefslogtreecommitdiff
path: root/LibTSforge/PhysicalStore/PhysicalStoreVista.cs
diff options
context:
space:
mode:
authorWitherOrNot2025-03-01 07:01:39 +0000
committerWitherOrNot2025-03-01 07:06:21 +0000
commit6d759899d85939c95f2b97c8e041d7b4865208f9 (patch)
tree08e174f929f4ddbbaa687207cf47784b29595f4b /LibTSforge/PhysicalStore/PhysicalStoreVista.cs
parent8aa1f9078d786a7b20d2b92bbeefdd77a93dd828 (diff)
downloadTSforge-6d759899d85939c95f2b97c8e041d7b4865208f9.zip
Add partial support (zcid, rtmr, non-functional kms4k) for vista
Co-authored-by: InvoxiPlayGames <[email protected]>
Diffstat (limited to 'LibTSforge/PhysicalStore/PhysicalStoreVista.cs')
-rw-r--r--LibTSforge/PhysicalStore/PhysicalStoreVista.cs356
1 files changed, 356 insertions, 0 deletions
diff --git a/LibTSforge/PhysicalStore/PhysicalStoreVista.cs b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs
new file mode 100644
index 0000000..809be77
--- /dev/null
+++ b/LibTSforge/PhysicalStore/PhysicalStoreVista.cs
@@ -0,0 +1,356 @@
+namespace LibTSforge.PhysicalStore
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using LibTSforge.Crypto;
+
+ public class VistaBlock
+ {
+ public BlockType Type;
+ public uint Flags;
+ public byte[] Value;
+ public string ValueAsStr
+ {
+ get
+ {
+ return Utils.DecodeString(Value);
+ }
+ set
+ {
+ Value = Utils.EncodeString(value);
+ }
+ }
+ public uint ValueAsInt
+ {
+ get
+ {
+ return BitConverter.ToUInt32(Value, 0);
+ }
+ set
+ {
+ Value = BitConverter.GetBytes(value);
+ }
+ }
+ public byte[] Data;
+ public string DataAsStr
+ {
+ get
+ {
+ return Utils.DecodeString(Data);
+ }
+ set
+ {
+ Data = Utils.EncodeString(value);
+ }
+ }
+ public uint DataAsInt
+ {
+ get
+ {
+ return BitConverter.ToUInt32(Data, 0);
+ }
+ set
+ {
+ Data = BitConverter.GetBytes(value);
+ }
+ }
+
+ internal void Encode(BinaryWriter writer)
+ {
+ writer.Write((uint)Type);
+ writer.Write(Flags);
+ writer.Write(Value.Length);
+ writer.Write(Data.Length);
+ writer.Write(Value);
+ writer.Write(Data);
+ }
+
+ internal static VistaBlock Decode(BinaryReader reader)
+ {
+ uint type = reader.ReadUInt32();
+ uint flags = reader.ReadUInt32();
+
+ int valueLen = reader.ReadInt32();
+ int dataLen = reader.ReadInt32();
+
+ byte[] value = reader.ReadBytes(valueLen);
+ byte[] data = reader.ReadBytes(dataLen);
+ return new VistaBlock
+ {
+ Type = (BlockType)type,
+ Flags = flags,
+ Value = value,
+ Data = data,
+ };
+ }
+ }
+
+ public sealed class PhysicalStoreVista : IPhysicalStore
+ {
+ private byte[] PreHeaderBytes = new byte[] { };
+ private readonly List<VistaBlock> Blocks = new List<VistaBlock>();
+ private readonly FileStream TSPrimary;
+ private readonly FileStream TSSecondary;
+ private readonly bool Production;
+
+ public byte[] Serialize()
+ {
+ BinaryWriter writer = new BinaryWriter(new MemoryStream());
+ writer.Write(PreHeaderBytes);
+
+ foreach (VistaBlock block in Blocks)
+ {
+ block.Encode(writer);
+ writer.Align(4);
+ }
+
+ return writer.GetBytes();
+ }
+
+ public void Deserialize(byte[] data)
+ {
+ int len = data.Length;
+
+ BinaryReader reader = new BinaryReader(new MemoryStream(data));
+ PreHeaderBytes = reader.ReadBytes(8);
+
+ while (reader.BaseStream.Position < len - 0x14)
+ {
+ Blocks.Add(VistaBlock.Decode(reader));
+ reader.Align(4);
+ }
+ }
+
+ public void AddBlock(PSBlock block)
+ {
+ Blocks.Add(new VistaBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+
+ public void AddBlocks(IEnumerable<PSBlock> blocks)
+ {
+ foreach (PSBlock block in blocks)
+ {
+ AddBlock(block);
+ }
+ }
+
+ public PSBlock GetBlock(string key, string value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr == value)
+ {
+ return new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ };
+ }
+ }
+
+ return null;
+ }
+
+ public PSBlock GetBlock(string key, uint value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == value)
+ {
+ return new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ };
+ }
+ }
+
+ return null;
+ }
+
+ public void SetBlock(string key, string value, byte[] data)
+ {
+ for (int i = 0; i < Blocks.Count; i++)
+ {
+ VistaBlock block = Blocks[i];
+
+ if (block.ValueAsStr == value)
+ {
+ block.Data = data;
+ Blocks[i] = block;
+ break;
+ }
+ }
+ }
+
+ public void SetBlock(string key, uint value, byte[] data)
+ {
+ for (int i = 0; i < Blocks.Count; i++)
+ {
+ VistaBlock block = Blocks[i];
+
+ if (block.ValueAsInt == value)
+ {
+ block.Data = data;
+ Blocks[i] = block;
+ break;
+ }
+ }
+ }
+
+ public void SetBlock(string key, string value, string data)
+ {
+ SetBlock(key, value, Utils.EncodeString(data));
+ }
+
+ public void SetBlock(string key, string value, uint data)
+ {
+ SetBlock(key, value, BitConverter.GetBytes(data));
+ }
+
+ public void SetBlock(string key, uint value, string data)
+ {
+ SetBlock(key, value, Utils.EncodeString(data));
+ }
+
+ public void SetBlock(string key, uint value, uint data)
+ {
+ SetBlock(key, value, BitConverter.GetBytes(data));
+ }
+
+ public void DeleteBlock(string key, string value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr == value)
+ {
+ Blocks.Remove(block);
+ return;
+ }
+ }
+ }
+
+ public void DeleteBlock(string key, uint value)
+ {
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == value)
+ {
+ Blocks.Remove(block);
+ return;
+ }
+ }
+ }
+
+ public PhysicalStoreVista(string primaryPath, bool production)
+ {
+ TSPrimary = File.Open(primaryPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
+ TSSecondary = File.Open(primaryPath.Replace("-0.", "-1."), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
+ Production = production;
+
+ Deserialize(PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), production, PSVersion.Vista));
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ }
+
+ public void Dispose()
+ {
+ if (TSPrimary.CanWrite && TSSecondary.CanWrite)
+ {
+ byte[] data = PhysStoreCrypto.EncryptPhysicalStore(Serialize(), Production, PSVersion.Vista);
+
+ TSPrimary.SetLength(data.LongLength);
+ TSSecondary.SetLength(data.LongLength);
+
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ TSSecondary.Seek(0, SeekOrigin.Begin);
+
+ TSPrimary.WriteAllBytes(data);
+ TSSecondary.WriteAllBytes(data);
+
+ TSPrimary.Close();
+ TSSecondary.Close();
+ }
+ }
+
+ public byte[] ReadRaw()
+ {
+ byte[] data = PhysStoreCrypto.DecryptPhysicalStore(TSPrimary.ReadAllBytes(), Production, PSVersion.Vista);
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ return data;
+ }
+
+ public void WriteRaw(byte[] data)
+ {
+ byte[] encrData = PhysStoreCrypto.EncryptPhysicalStore(data, Production, PSVersion.Vista);
+
+ TSPrimary.SetLength(encrData.LongLength);
+ TSSecondary.SetLength(encrData.LongLength);
+
+ TSPrimary.Seek(0, SeekOrigin.Begin);
+ TSSecondary.Seek(0, SeekOrigin.Begin);
+
+ TSPrimary.WriteAllBytes(encrData);
+ TSSecondary.WriteAllBytes(encrData);
+
+ TSPrimary.Close();
+ TSSecondary.Close();
+ }
+
+ public IEnumerable<PSBlock> FindBlocks(string valueSearch)
+ {
+ List<PSBlock> results = new List<PSBlock>();
+
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsStr.Contains(valueSearch))
+ {
+ results.Add(new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+ }
+
+ return results;
+ }
+
+ public IEnumerable<PSBlock> FindBlocks(uint valueSearch)
+ {
+ List<PSBlock> results = new List<PSBlock>();
+
+ foreach (VistaBlock block in Blocks)
+ {
+ if (block.ValueAsInt == valueSearch)
+ {
+ results.Add(new PSBlock
+ {
+ Type = block.Type,
+ Flags = block.Flags,
+ Key = new byte[0],
+ Value = block.Value,
+ Data = block.Data
+ });
+ }
+ }
+
+ return results;
+ }
+ }
+}