Use Img2Ffu reader code

This commit is contained in:
Gustave Monce
2024-09-07 23:12:17 +02:00
parent 227bc44a75
commit 487b20c2f5
51 changed files with 1180 additions and 2058 deletions
+21 -69
View File
@@ -4,10 +4,6 @@ VisualStudioVersion = 17.7.33927.210
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ffu2Vhdx", "Ffu2Vhdx\Ffu2Vhdx.csproj", "{6BB88918-A58C-4510-A99F-AA22C7D5BD55}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageCommon", "ImageCommon\ImageCommon.csproj", "{8CA492CB-6F12-4862-991C-B28468172730}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageStorageServiceManaged", "ImageStorageServiceManaged\ImageStorageServiceManaged.csproj", "{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscUtils.Core", "DiscUtils\DiscUtils.Core\DiscUtils.Core.csproj", "{A76FBCBD-08EB-413D-8DD7-8264D4E50304}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscUtils.Streams", "DiscUtils\DiscUtils.Streams\DiscUtils.Streams.csproj", "{37E19DC2-07BE-4E1E-8878-7A7BA28F5D45}"
@@ -16,9 +12,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscUtils.Vhdx", "DiscUtils
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DiscUtils", "DiscUtils", "{A431EF08-BBEF-4228-A12D-88149C3844F6}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WindowsPhone", "WindowsPhone", "{6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FfuStream", "FfuStream\FfuStream.csproj", "{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Img2Ffu", "Img2Ffu\Img2Ffu.csproj", "{97E58534-9D04-4E73-9243-50AA143A1DA6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -54,46 +48,6 @@ Global
{6BB88918-A58C-4510-A99F-AA22C7D5BD55}.Release|x64.Build.0 = Release|x64
{6BB88918-A58C-4510-A99F-AA22C7D5BD55}.Release|x86.ActiveCfg = Release|x86
{6BB88918-A58C-4510-A99F-AA22C7D5BD55}.Release|x86.Build.0 = Release|x86
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|ARM32.ActiveCfg = Debug|ARM32
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|ARM32.Build.0 = Debug|ARM32
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|ARM64.Build.0 = Debug|ARM64
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|x64.ActiveCfg = Debug|x64
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|x64.Build.0 = Debug|x64
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|x86.ActiveCfg = Debug|x86
{8CA492CB-6F12-4862-991C-B28468172730}.Debug|x86.Build.0 = Debug|x86
{8CA492CB-6F12-4862-991C-B28468172730}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CA492CB-6F12-4862-991C-B28468172730}.Release|Any CPU.Build.0 = Release|Any CPU
{8CA492CB-6F12-4862-991C-B28468172730}.Release|ARM32.ActiveCfg = Release|ARM32
{8CA492CB-6F12-4862-991C-B28468172730}.Release|ARM32.Build.0 = Release|ARM32
{8CA492CB-6F12-4862-991C-B28468172730}.Release|ARM64.ActiveCfg = Release|ARM64
{8CA492CB-6F12-4862-991C-B28468172730}.Release|ARM64.Build.0 = Release|ARM64
{8CA492CB-6F12-4862-991C-B28468172730}.Release|x64.ActiveCfg = Release|x64
{8CA492CB-6F12-4862-991C-B28468172730}.Release|x64.Build.0 = Release|x64
{8CA492CB-6F12-4862-991C-B28468172730}.Release|x86.ActiveCfg = Release|x86
{8CA492CB-6F12-4862-991C-B28468172730}.Release|x86.Build.0 = Release|x86
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|ARM32.ActiveCfg = Debug|ARM32
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|ARM32.Build.0 = Debug|ARM32
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|ARM64.ActiveCfg = Debug|ARM64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|ARM64.Build.0 = Debug|ARM64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|x64.ActiveCfg = Debug|x64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|x64.Build.0 = Debug|x64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|x86.ActiveCfg = Debug|x86
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Debug|x86.Build.0 = Debug|x86
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|Any CPU.Build.0 = Release|Any CPU
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|ARM32.ActiveCfg = Release|ARM32
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|ARM32.Build.0 = Release|ARM32
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|ARM64.ActiveCfg = Release|ARM64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|ARM64.Build.0 = Release|ARM64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x64.ActiveCfg = Release|x64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x64.Build.0 = Release|x64
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x86.ActiveCfg = Release|x86
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16}.Release|x86.Build.0 = Release|x86
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A76FBCBD-08EB-413D-8DD7-8264D4E50304}.Debug|ARM32.ActiveCfg = Debug|ARM32
@@ -154,33 +108,31 @@ Global
{77D1F20E-4CD6-4810-9C5C-EF6CA3A9BC53}.Release|x64.Build.0 = Release|x64
{77D1F20E-4CD6-4810-9C5C-EF6CA3A9BC53}.Release|x86.ActiveCfg = Release|x86
{77D1F20E-4CD6-4810-9C5C-EF6CA3A9BC53}.Release|x86.Build.0 = Release|x86
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|ARM32.ActiveCfg = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|ARM32.Build.0 = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|ARM64.Build.0 = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|x64.ActiveCfg = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|x64.Build.0 = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|x86.ActiveCfg = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Debug|x86.Build.0 = Debug|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|Any CPU.Build.0 = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|ARM32.ActiveCfg = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|ARM32.Build.0 = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|ARM64.ActiveCfg = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|ARM64.Build.0 = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|x64.ActiveCfg = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|x64.Build.0 = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|x86.ActiveCfg = Release|Any CPU
{64DDFC5B-0C2F-4426-9DEE-1164292C0F25}.Release|x86.Build.0 = Release|Any CPU
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|ARM32.ActiveCfg = Debug|ARM32
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|ARM32.Build.0 = Debug|ARM32
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|ARM64.ActiveCfg = Debug|ARM64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|ARM64.Build.0 = Debug|ARM64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|x64.ActiveCfg = Debug|x64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|x64.Build.0 = Debug|x64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|x86.ActiveCfg = Debug|x86
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Debug|x86.Build.0 = Debug|x86
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|Any CPU.Build.0 = Release|Any CPU
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|ARM32.ActiveCfg = Release|ARM32
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|ARM32.Build.0 = Release|ARM32
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|ARM64.ActiveCfg = Release|ARM64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|ARM64.Build.0 = Release|ARM64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|x64.ActiveCfg = Release|x64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|x64.Build.0 = Release|x64
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|x86.ActiveCfg = Release|x86
{97E58534-9D04-4E73-9243-50AA143A1DA6}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{8CA492CB-6F12-4862-991C-B28468172730} = {6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}
{5C2B4F9B-479D-4301-AEB9-33B83B6F5B16} = {6B6B2266-D083-4F82-9A0A-4A2D8D8F3F16}
{A76FBCBD-08EB-413D-8DD7-8264D4E50304} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
{37E19DC2-07BE-4E1E-8878-7A7BA28F5D45} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
{77D1F20E-4CD6-4810-9C5C-EF6CA3A9BC53} = {A431EF08-BBEF-4228-A12D-88149C3844F6}
+2 -2
View File
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Platforms>x64;AnyCPU;ARM32;ARM64;x86</Platforms>
@@ -10,7 +10,7 @@
<ItemGroup>
<ProjectReference Include="..\DiscUtils\DiscUtils.Vhdx\DiscUtils.Vhdx.csproj" />
<ProjectReference Include="..\FfuStream\FfuStream.csproj" />
<ProjectReference Include="..\Img2Ffu\Img2Ffu.csproj" />
</ItemGroup>
</Project>
+7 -11
View File
@@ -1,7 +1,8 @@
using DiscUtils;
using DiscUtils.Streams;
using DiscUtils.Vhdx;
using FfuStream;
using Img2Ffu.Reader;
using Img2Ffu.Reader.Data;
namespace Ffu2Vhdx
{
@@ -102,12 +103,9 @@ namespace Ffu2Vhdx
{
DiscUtils.Setup.SetupHelper.RegisterAssembly(typeof(Disk).Assembly);
using FileStream ffuStream = File.OpenRead(ffuPath);
FfuFile ffuFile = new(ffuStream);
for (int i = 0; i < ffuFile.StoreCount; i++)
for (int i = 0; i < FullFlashUpdateReaderStream.GetStoreCount(ffuPath); i++)
{
using FfuStoreStream store = ffuFile.OpenStore(i);
using FullFlashUpdateReaderStream store = new(ffuPath, (ulong)i);
string friendlyDevicePath = FormatDevicePath(store.DevicePath);
string vhdfile = Path.Combine(outputDirectory, $"Store{i}_{ReplaceInvalidChars(store.DevicePath)}.vhdx");
@@ -117,18 +115,16 @@ namespace Ffu2Vhdx
Console.WriteLine($"Device Path: {friendlyDevicePath}");
Console.WriteLine($"Destination: {vhdfile}");
long SectorSize = ffuFile.GetSectorSize(i);
using Stream fs = new FileStream(vhdfile, FileMode.CreateNew, FileAccess.ReadWrite);
using VirtualDisk outDisk = Disk.InitializeDynamic(fs, Ownership.None, store.Length, logicalSectorSize: (int)SectorSize);
using VirtualDisk outDisk = Disk.InitializeDynamic(fs, Ownership.None, store.Length, logicalSectorSize: store.SectorSize);
StreamPump pump = new()
{
InputStream = store,
OutputStream = outDisk.Content,
SparseCopy = true,
SparseChunkSize = (int)SectorSize,
BufferSize = (int)SectorSize * 1024
SparseChunkSize = store.SectorSize,
BufferSize = store.SectorSize * 1024
};
long totalBytes = store.Length;
-73
View File
@@ -1,73 +0,0 @@
using Microsoft.WindowsPhone.Imaging;
namespace FfuStream
{
public class FfuFile
{
private readonly FullFlashUpdateImage ffuImage;
private readonly PayloadReader payloadReader;
public FfuFile(Stream stream)
{
ffuImage = new(stream);
Stream imageStream = ffuImage.GetImageStream();
payloadReader = new(imageStream);
if (payloadReader.Payloads.Count() != ffuImage.StoreCount)
{
throw new ImageStorageException("Store counts in metadata and store header do not match.");
}
}
public int StoreCount => ffuImage.StoreCount;
public void WriteStoreToStream(int StoreIndex, Stream outputStream)
{
if (StoreIndex >= StoreCount || StoreIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
}
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
StorePayload storePayload = payloadReader.Payloads[StoreIndex];
payloadReader.WriteToStream(outputStream, storePayload, fullFlashUpdateStore.MinSectorCount, fullFlashUpdateStore.SectorSize);
}
public FfuStoreStream OpenStore(int StoreIndex)
{
if (StoreIndex >= StoreCount || StoreIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
}
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
StorePayload storePayload = payloadReader.Payloads[StoreIndex];
return new FfuStoreStream(payloadReader, fullFlashUpdateStore, storePayload);
}
public uint GetMinSectorCount(int StoreIndex)
{
if (StoreIndex >= StoreCount || StoreIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
}
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
return fullFlashUpdateStore.MinSectorCount;
}
public uint GetSectorSize(int StoreIndex)
{
if (StoreIndex >= StoreCount || StoreIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(StoreIndex));
}
FullFlashUpdateStore fullFlashUpdateStore = ffuImage.Stores[StoreIndex];
return fullFlashUpdateStore.SectorSize;
}
}
}
-114
View File
@@ -1,114 +0,0 @@
using Microsoft.WindowsPhone.Imaging;
namespace FfuStream
{
public partial class FfuStoreStream : Stream
{
private readonly PayloadReader payloadReader;
private readonly FullFlashUpdateStore fullFlashUpdateStore;
private readonly StorePayload storePayload;
private long position = 0;
public FfuStoreStream(PayloadReader payloadReader, FullFlashUpdateStore fullFlashUpdateStore, StorePayload storePayload)
{
this.payloadReader = payloadReader;
this.fullFlashUpdateStore = fullFlashUpdateStore;
this.storePayload = storePayload;
}
public string DevicePath => fullFlashUpdateStore.DevicePath;
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => ((long)fullFlashUpdateStore.MinSectorCount * fullFlashUpdateStore.SectorSize);
public override long Position
{
get => position;
set => position = value;
}
public override void Flush()
{
// Nothing to do!
}
public override int Read(byte[] buffer, int offset, int count)
{
if (position + count > Length)
{
count = (int)Length - (int)position;
}
payloadReader.WriteToStream(storePayload, fullFlashUpdateStore.MinSectorCount, fullFlashUpdateStore.SectorSize, position, buffer, offset, count);
position += count;
return count;
}
public override long Seek(long offset, SeekOrigin origin)
{
if (offset > Length)
{
throw new ArgumentOutOfRangeException(nameof(offset));
}
switch (origin)
{
case SeekOrigin.Begin:
{
if (offset < 0)
{
throw new IOException();
}
position = offset;
break;
}
case SeekOrigin.Current:
{
int tempPosition = (int)position + (int)offset;
if (tempPosition < 0)
{
throw new IOException();
}
position = tempPosition;
break;
}
case SeekOrigin.End:
{
int tempPosition = (int)Length + (int)offset;
if (tempPosition < 0)
{
throw new IOException();
}
position = tempPosition;
break;
}
default:
{
throw new ArgumentException(nameof(origin));
}
}
return position;
}
public override void SetLength(long value)
{
// Nothing to do!
}
public override void Write(byte[] buffer, int offset, int count)
{
// Nothing to do!
}
}
}
-14
View File
@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ImageCommon\ImageCommon.csproj" />
<ProjectReference Include="..\ImageStorageServiceManaged\ImageStorageServiceManaged.csproj" />
</ItemGroup>
</Project>
-19
View File
@@ -1,19 +0,0 @@
namespace Microsoft.WindowsPhone.Imaging
{
public enum CodeSite
{
Unknown = -1,
Security,
ImageCommon,
Imaging,
Packages,
FeatureManifests,
StorageService,
CommitImage,
UpdateAPI,
DeviceLayoutValidation,
CompDBCommon,
WcosImagePrep,
LCUPub
}
}
-13
View File
@@ -1,13 +0,0 @@
namespace Microsoft.WindowsPhone.Imaging
{
public enum ErrorCategory
{
Unknown = -1,
BadCommandLineParams,
IncorrectUserInput,
MissingArtifact,
BadContent,
UnexpectedState,
XmlSerialization
}
}
-24
View File
@@ -1,24 +0,0 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.WindowsPhone.Imaging
{
public static class FullFlashUpdateHeaders
{
public static byte[] GetSecurityHeaderSignature()
{
return Encoding.ASCII.GetBytes("SignedImage ");
}
public static byte[] GetImageHeaderSignature()
{
return Encoding.ASCII.GetBytes("ImageFlash ");
}
public static uint SecurityHeaderSize => (uint)(Marshal.SizeOf(default(SecurityHeader)) + GetSecurityHeaderSignature().Length);
public static uint ImageHeaderSize => (uint)(FullFlashUpdateImage.ImageHeaderSize + GetImageHeaderSignature().Length);
public static uint ImageHeaderExSize => (uint)(FullFlashUpdateImage.ImageHeaderExSize + GetImageHeaderSignature().Length);
}
}
-149
View File
@@ -1,149 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.WindowsPhone.Imaging
{
public class FullFlashUpdateImage
{
private readonly Stream imageStream;
public FullFlashUpdateImage(Stream imageStream)
{
this.imageStream = imageStream;
_ffuStoragePools = new List<FullFlashUpdateStoragePool>();
_ffuStores = new List<FullFlashUpdateStore>();
using BinaryReader binaryReader = new(imageStream, Encoding.UTF8, true);
uint num = binaryReader.ReadUInt32();
byte[] signature = binaryReader.ReadBytes(12);
if (num != FullFlashUpdateHeaders.SecurityHeaderSize || !SecurityHeader.ValidateSignature(signature))
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, "Unable to load image because the security header is invalid.");
}
_securityHeader.ByteCount = num;
_securityHeader.ChunkSize = binaryReader.ReadUInt32();
_securityHeader.HashAlgorithmID = binaryReader.ReadUInt32();
_securityHeader.CatalogSize = binaryReader.ReadUInt32();
_securityHeader.HashTableSize = binaryReader.ReadUInt32();
CatalogData = binaryReader.ReadBytes((int)_securityHeader.CatalogSize);
HashTableData = binaryReader.ReadBytes((int)_securityHeader.HashTableSize);
_ = binaryReader.ReadBytes((int)SecurityPadding);
num = binaryReader.ReadUInt32();
signature = binaryReader.ReadBytes(12);
if ((num != FullFlashUpdateHeaders.ImageHeaderSize && num != FullFlashUpdateHeaders.ImageHeaderExSize) || !ImageHeader.ValidateSignature(signature))
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, "Unable to load image because the image header is invalid.");
}
_imageHeader.ByteCount = num;
_imageHeader.ManifestLength = binaryReader.ReadUInt32();
_imageHeader.ChunkSize = binaryReader.ReadUInt32();
_imageHeader.NumberOfDeviceTargetingIds = num == FullFlashUpdateHeaders.ImageHeaderSize ? 0U : binaryReader.ReadUInt32();
Manifest = new FullFlashUpdateManifest(this, binaryReader.ReadBytes((int)_imageHeader.ManifestLength));
Manifest.Validate("2.0");
if (_imageHeader.ChunkSize > 0U)
{
_ = binaryReader.ReadBytes((int)CalculateAlignment((uint)imageStream.Position, _imageHeader.ChunkSize * 1024U));
}
_payloadOffset = imageStream.Position;
}
public Stream GetImageStream()
{
imageStream.Position = _payloadOffset;
return imageStream;
}
internal void AddStoragePool(ManifestCategory A_1)
{
if (A_1 == null)
{
throw new ArgumentNullException("category");
}
_ffuStoragePools.Add(new FullFlashUpdateStoragePool(this, A_1));
}
internal void AddStore(ManifestCategory A_1)
{
if (A_1 == null)
{
throw new ArgumentNullException("category");
}
_ffuStores.Add(new FullFlashUpdateStore(this, null, A_1));
}
public static int ImageHeaderSize => Marshal.SizeOf(new ImageHeader());
public static int ImageHeaderExSize => Marshal.SizeOf(new ImageHeaderEx());
public byte[] CatalogData
{
get; set;
}
public byte[] HashTableData
{
get; set;
}
public List<FullFlashUpdateStoragePool> StoragePools => new(_ffuStoragePools);
public List<FullFlashUpdateStore> Stores => new(_ffuStores);
public int StoreCount => Stores.Count;
public FullFlashUpdateManifest Manifest
{
get; private set;
}
internal uint SecurityPadding
{
get
{
uint num = 1024U;
if (_imageHeader.ChunkSize != 0U)
{
num *= _imageHeader.ChunkSize;
}
else
{
if (_securityHeader.ChunkSize == 0U)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, "Neither the of the headers have been initialized with a chunk size.");
}
num *= _securityHeader.ChunkSize;
}
return CalculateAlignment(FullFlashUpdateHeaders.SecurityHeaderSize + (uint)(CatalogData != null ? CatalogData.Length : 0) + (uint)(HashTableData != null ? HashTableData.Length : 0), num);
}
}
private uint CalculateAlignment(uint A_1, uint A_2)
{
uint result = 0U;
uint num = A_1 % A_2;
if (num > 0U)
{
result = A_2 - num;
}
return result;
}
public static readonly uint PartitionTypeMbr = 0U;
public static readonly uint PartitionTypeGpt = 1U;
private readonly List<FullFlashUpdateStoragePool> _ffuStoragePools;
private readonly List<FullFlashUpdateStore> _ffuStores;
private readonly long _payloadOffset;
private readonly ImageHeaderEx _imageHeader = new();
private SecurityHeader _securityHeader;
}
}
-156
View File
@@ -1,156 +0,0 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Microsoft.WindowsPhone.Imaging
{
public class FullFlashUpdateManifest
{
internal FullFlashUpdateManifest(FullFlashUpdateImage A_1)
{
_ffuImage = A_1;
}
internal FullFlashUpdateManifest(FullFlashUpdateImage A_1, byte[] A_2) : this(A_1)
{
using MemoryStream memoryStream = new(A_2);
using StreamReader streamReader = new(memoryStream, Encoding.ASCII);
Regex regex = new("^\\s*\\[(?<category>[^\\]]+)\\]\\s*$");
Regex regex2 = new("^\\s*(?<key>[^=\\s]+)\\s*=\\s*(?<value>.*)(\\s*$)");
Match match = null;
ManifestCategory manifestCategory = null;
while (!streamReader.EndOfStream)
{
string text = streamReader.ReadLine();
if (regex.IsMatch(text))
{
match = null;
string value = regex.Match(text).Groups["category"].Value;
ProcessCategory(manifestCategory);
if (string.Compare(value, "StoragePool", StringComparison.Ordinal) == 0)
{
manifestCategory = new ManifestCategory("StoragePool", "StoragePool");
}
else
{
manifestCategory = string.Compare(value, "StoragePoolStore", StringComparison.Ordinal) == 0
? new ManifestCategory("StoragePoolStore", "StoragePoolStore")
: string.Compare(value, "StoragePoolPartition", StringComparison.Ordinal) == 0
? new ManifestCategory("StoragePoolPartition", "StoragePoolPartition")
: string.Compare(value, "Store", StringComparison.Ordinal) == 0
? new ManifestCategory("Store", "Store")
: string.Compare(value, "Partition", StringComparison.Ordinal) == 0
? new ManifestCategory("Partition", "Partition")
: AddCategory(value, value);
}
}
else if (manifestCategory != null && regex2.IsMatch(text))
{
match = null;
Match match2 = regex2.Match(text);
manifestCategory[match2.Groups["key"].Value] = match2.Groups["value"].Value;
if (match2.Groups["key"].ToString() == "Description")
{
match = match2;
}
}
else if (match != null)
{
ManifestCategory manifestCategory2 = manifestCategory;
string value2 = match.Groups["key"].Value;
manifestCategory2[value2] = manifestCategory2[value2] + "\r\n" + text;
}
}
ProcessCategory(manifestCategory);
}
internal ManifestCategory AddCategory(string A_1, string A_2)
{
if (this[A_1] != null)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "Cannot add duplicate categories to a manifest.");
}
ManifestCategory manifestCategory = new(A_1, A_2);
_ = _categories.Add(manifestCategory);
return manifestCategory;
}
internal ManifestCategory this[string A_1]
{
get
{
foreach (object obj in _categories)
{
ManifestCategory manifestCategory = (ManifestCategory)obj;
if (string.Compare(manifestCategory.Name, A_1, StringComparison.Ordinal) == 0)
{
return manifestCategory;
}
}
return null;
}
}
internal void Validate(string A_1)
{
if (this["FullFlash"] == null)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, "Missing 'FullFlash' or 'Image' category in the manifest");
}
string text = this["FullFlash"]["Version"];
if (text == null)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, "Missing 'Version' name/value pair in the 'FullFlash' category.");
}
if (!text.Equals(A_1, StringComparison.OrdinalIgnoreCase))
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.BadContent, string.Concat(new string[]
{
"'Version' value (",
text,
") does not match current version of ",
A_1,
"."
}));
}
}
private void ProcessCategory(ManifestCategory A_1)
{
if (A_1 != null)
{
if (string.CompareOrdinal(A_1.Name, "StoragePool") == 0)
{
_ffuImage.AddStoragePool(A_1);
return;
}
if (string.CompareOrdinal(A_1.Name, "StoragePoolStore") == 0)
{
_ffuImage.StoragePools.Last().AddStore(A_1);
return;
}
if (string.CompareOrdinal(A_1.Name, "StoragePoolPartition") == 0)
{
_ffuImage.StoragePools.Last().Stores.Last().AddPartition(A_1);
return;
}
if (string.CompareOrdinal(A_1.Name, "Store") == 0)
{
_ffuImage.AddStore(A_1);
return;
}
if (string.CompareOrdinal(A_1.Name, "Partition") == 0)
{
_ffuImage.Stores.Last().AddPartition(A_1);
}
}
}
private readonly ArrayList _categories = new(20);
private readonly FullFlashUpdateImage _ffuImage;
}
}
-137
View File
@@ -1,137 +0,0 @@
namespace Microsoft.WindowsPhone.Imaging
{
public class FullFlashUpdatePartition
{
public FullFlashUpdatePartition()
{
}
public FullFlashUpdatePartition(FullFlashUpdateStore A_1, InputPartition A_2) : this()
{
Store = A_1;
SectorsInUse = 0U;
TotalSectors = A_2.TotalSectors;
PartitionType = A_2.Type;
PartitionId = A_2.Id;
Name = A_2.Name;
UseAllSpace = A_2.UseAllSpace;
FileSystem = A_2.FileSystem;
Bootable = A_2.Bootable;
ReadOnly = A_2.ReadOnly;
Hidden = A_2.Hidden;
AttachDriveLetter = A_2.AttachDriveLetter;
ServicePartition = A_2.ServicePartition;
PrimaryPartition = A_2.PrimaryPartition;
RequiredToFlash = A_2.RequiredToFlash;
ByteAlignment = A_2.ByteAlignment;
ClusterSize = A_2.ClusterSize;
OffsetInSectors = A_2.OffsetInSectors;
PrepareFveMetadata = A_2.PrepareFveMetadata;
}
public override string ToString()
{
return Name;
}
private FullFlashUpdateStore Store
{
get; set;
}
public string Name
{
get; set;
}
public uint TotalSectors
{
get; set;
}
public string PartitionType
{
get; set;
}
public string PartitionId
{
get; set;
}
public bool Bootable
{
get; set;
}
public bool ReadOnly
{
get; set;
}
public bool Hidden
{
get; set;
}
public bool AttachDriveLetter
{
get; set;
}
public bool ServicePartition
{
get; set;
}
public string PrimaryPartition
{
get; set;
}
public string FileSystem
{
get; set;
}
public uint ByteAlignment
{
get; set;
}
public uint ClusterSize
{
get; set;
}
public uint SectorsInUse
{
get; set;
}
public bool UseAllSpace
{
get; set;
}
public bool RequiredToFlash
{
get; set;
}
public uint SectorAlignment
{
get; set;
}
public ulong OffsetInSectors
{
get; set;
}
public bool PrepareFveMetadata
{
get; set;
}
}
}
-42
View File
@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
namespace Microsoft.WindowsPhone.Imaging
{
public class FullFlashUpdateStoragePool
{
private FullFlashUpdateStoragePool()
{
_ffuStores = new List<FullFlashUpdateStore>();
}
public FullFlashUpdateStoragePool(FullFlashUpdateImage A_1, ManifestCategory A_2) : this()
{
Image = A_1;
Name = A_2.GetString("Name");
}
public FullFlashUpdateImage Image
{
get; private set;
}
private string Name
{
get; set;
}
public List<FullFlashUpdateStore> Stores => new(_ffuStores);
internal void AddStore(ManifestCategory A_1)
{
if (A_1 == null)
{
throw new ArgumentNullException("category");
}
_ffuStores.Add(new FullFlashUpdateStore(Image, this, A_1));
}
private readonly List<FullFlashUpdateStore> _ffuStores;
}
}
-238
View File
@@ -1,238 +0,0 @@
using System;
using System.Collections.Generic;
namespace Microsoft.WindowsPhone.Imaging
{
public class FullFlashUpdateStore : IDisposable
{
public FullFlashUpdateStore()
{
_ffuPartitions = new List<FullFlashUpdatePartition>();
}
public FullFlashUpdateStore(FullFlashUpdateImage A_1, FullFlashUpdateStoragePool A_2, ManifestCategory A_3) : this()
{
Initialize(A_1, A_2, A_3.GetString("StoreId"), A_3.GetString("StoreType"), A_3.GetBool("IsSpace"), A_3.GetBool("IsMainOSStore", true), A_3.GetString("Provisioning"), A_3.GetString("DevicePath"), A_3.GetBool("OnlyAllocateDefinedGptEntries"), A_3.GetUInt32("MinSectorCount"), A_3.GetUInt32("SectorSize"));
}
private void Initialize(FullFlashUpdateImage A_1, FullFlashUpdateStoragePool A_2, string A_3, string A_4, bool A_5, bool A_6, string A_7, string A_8, bool A_9, uint A_10, uint A_11)
{
Image = A_1;
StoragePool = A_2;
Id = A_3;
Type = A_4;
IsSpace = A_5;
IsMainOSStore = A_6;
Provisioning = A_7;
DevicePath = A_8;
OnlyAllocateDefinedGptEntries = A_9;
MinSectorCount = A_10;
SectorSize = A_11;
}
~FullFlashUpdateStore()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool A_1)
{
if (_alreadyDisposed)
{
return;
}
if (A_1)
{
Partitions = null;
}
_alreadyDisposed = true;
}
private FullFlashUpdateImage Image
{
get; set;
}
private FullFlashUpdateStoragePool StoragePool
{
get; set;
}
private string Id
{
get; set;
}
private string Type
{
get; set;
}
public bool IsMainOSStore
{
get; private set;
}
private string Provisioning
{
get; set;
}
public string DevicePath
{
get; private set;
}
private bool OnlyAllocateDefinedGptEntries
{
get; set;
}
public uint MinSectorCount
{
get; set;
}
public uint SectorSize
{
get; set;
}
public List<FullFlashUpdatePartition> Partitions
{
get => new(_ffuPartitions);
private set => _ffuPartitions = value;
}
public FullFlashUpdatePartition this[string A_1]
{
get
{
foreach (FullFlashUpdatePartition fullFlashUpdatePartition in Partitions)
{
if (string.CompareOrdinal(fullFlashUpdatePartition.Name, A_1) == 0)
{
return fullFlashUpdatePartition;
}
}
return null;
}
}
public bool IsSpace
{
get; private set;
}
internal void AddPartition(FullFlashUpdatePartition A_1)
{
if (this[A_1.Name] != null)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "Two partitions in a store have the same name (" + A_1.Name + ").");
}
if (!IsSpace && IsMainOSStore)
{
if (MinSectorCount != 0U && A_1.TotalSectors > MinSectorCount)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "The partition " + A_1.Name + " is too large for the store.");
}
if (A_1.UseAllSpace)
{
using (List<FullFlashUpdatePartition>.Enumerator enumerator = Partitions.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (enumerator.Current.UseAllSpace)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "Two partitions in the same store have the UseAllSpace flag set.");
}
}
goto IL_FA;
}
}
if (A_1.SectorsInUse > A_1.TotalSectors)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, string.Format("The partition data is invalid. There are more used sectors ({0}) than total sectors ({1}) for partition:{2}", A_1.SectorsInUse, A_1.TotalSectors, A_1.Name));
}
IL_FA:
if (MinSectorCount != 0U)
{
if (A_1.UseAllSpace)
{
_sectorsUsed += 1U;
}
else
{
_sectorsUsed += A_1.TotalSectors;
}
if (_sectorsUsed > MinSectorCount)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, string.Format("Partition ({0}) on the Store does not fit. SectorsUsed = {1} > MinSectorCount = {2}", A_1.Name, _sectorsUsed, MinSectorCount));
}
}
}
_ffuPartitions.Add(A_1);
}
internal void AddPartition(ManifestCategory A_1)
{
uint sectorsInUse = 0U;
uint num = 0U;
bool flag = false;
if (A_1 == null)
{
throw new ArgumentNullException("category");
}
if (IsMainOSStore)
{
sectorsInUse = A_1.GetUInt32("UsedSectors");
num = A_1.GetUInt32("TotalSectors");
flag = A_1.GetBool("UseAllSpace");
if (!flag && num == 0U)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "The partition category for partition " + A_1.GetString("Name") + " must contain either a 'TotalSectors' or 'UseAllSpace' key/value pair.");
}
if (flag && num > 0U)
{
throw new ImageCommonException(CodeSite.StorageService, ErrorCategory.IncorrectUserInput, "The partition category for partition " + A_1.GetString("Name") + " cannot contain both a 'TotalSectors' and a 'UseAllSpace' key/value pair.");
}
}
AddPartition(new FullFlashUpdatePartition(this, new InputPartition
{
Name = A_1.GetString("Name"),
Type = A_1.GetString("Type"),
Id = A_1.GetString("Id"),
ReadOnly = A_1.GetBool("ReadOnly"),
AttachDriveLetter = A_1.GetBool("AttachDriveLetter"),
ServicePartition = A_1.GetBool("ServicePartition"),
Hidden = A_1.GetBool("Hidden"),
Bootable = A_1.GetBool("Bootable"),
TotalSectors = num,
UseAllSpace = flag,
FileSystem = A_1.GetString("FileSystem"),
PrimaryPartition = A_1.GetString("Primary"),
RequiredToFlash = A_1.GetBool("RequiredToFlash"),
ByteAlignment = A_1.GetUInt32("ByteAlignment"),
ClusterSize = A_1.GetUInt32("ClusterSize"),
OffsetInSectors = A_1.GetUInt64("OffsetInSectors"),
PrepareFveMetadata = A_1.GetBool("PrepareFveMetadata")
})
{
SectorsInUse = sectorsInUse,
SectorAlignment = A_1.GetUInt32("SectorAlignment")
});
}
private List<FullFlashUpdatePartition> _ffuPartitions;
private uint _sectorsUsed;
private bool _alreadyDisposed;
}
}
-11
View File
@@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<OutputType>Library</OutputType>
<Company>Microsoft Corporation</Company>
<Copyright>Copyright %28c%29 Microsoft Corporation. All rights reserved.</Copyright>
<Product>Microsoft %28R%29 Windows %28R%29 Operating System</Product>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
<Platforms>x64;AnyCPU;ARM32;ARM64;x86</Platforms>
</PropertyGroup>
</Project>
-36
View File
@@ -1,36 +0,0 @@
using System;
using System.Text;
namespace Microsoft.WindowsPhone.Imaging
{
[Serializable]
public class ImageCommonException : Exception
{
public CodeSite CodeSite
{
get; set;
} = CodeSite.Unknown;
public ErrorCategory ErrorCategory
{
get; set;
} = ErrorCategory.Unknown;
public ImageCommonException(CodeSite A_1, ErrorCategory A_2, string A_3) : base(A_3)
{
CodeSite = A_1;
ErrorCategory = A_2;
}
public override string ToString()
{
StringBuilder stringBuilder = new();
_ = stringBuilder.AppendLine(Message);
if (InnerException != null)
{
_ = stringBuilder.Append(InnerException.ToString());
}
return stringBuilder.ToString();
}
}
}
-24
View File
@@ -1,24 +0,0 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Microsoft.WindowsPhone.Imaging
{
[StructLayout(LayoutKind.Sequential)]
public class ImageHeader
{
public static bool ValidateSignature(byte[] A_0)
{
return A_0.SequenceEqual(FullFlashUpdateHeaders.GetImageHeaderSignature());
}
[MarshalAs(UnmanagedType.U4)]
public uint ByteCount;
[MarshalAs(UnmanagedType.U4)]
public uint ManifestLength;
[MarshalAs(UnmanagedType.U4)]
public uint ChunkSize;
}
}
-11
View File
@@ -1,11 +0,0 @@
using System.Runtime.InteropServices;
namespace Microsoft.WindowsPhone.Imaging
{
[StructLayout(LayoutKind.Sequential)]
public class ImageHeaderEx : ImageHeader
{
[MarshalAs(UnmanagedType.U4)]
public uint NumberOfDeviceTargetingIds;
}
}
-98
View File
@@ -1,98 +0,0 @@
using System.Xml.Serialization;
namespace Microsoft.WindowsPhone.Imaging
{
public class InputPartition
{
public string Name
{
get; set;
}
public string Type
{
get; set;
}
public string Id
{
get; set;
}
public bool ReadOnly
{
get; set;
}
public bool AttachDriveLetter
{
get; set;
}
public bool Hidden
{
get; set;
}
public bool ServicePartition
{
get; set;
}
public bool Bootable
{
get; set;
}
public uint TotalSectors
{
get; set;
}
public bool UseAllSpace
{
get; set;
}
public string FileSystem
{
get; set;
}
public string PrimaryPartition
{
get => string.IsNullOrEmpty(_primaryPartition) ? Name : _primaryPartition;
set => _primaryPartition = value;
}
public bool RequiredToFlash
{
get; set;
}
[XmlIgnore]
public uint ByteAlignment
{
get; set;
}
[XmlIgnore]
public uint ClusterSize
{
get; set;
}
[XmlIgnore]
public ulong OffsetInSectors
{
get; set;
}
public bool PrepareFveMetadata
{
get; set;
}
private string _primaryPartition;
}
}
-90
View File
@@ -1,90 +0,0 @@
using System.Collections;
using System.Globalization;
namespace Microsoft.WindowsPhone.Imaging
{
public class ManifestCategory
{
public string this[string A_1]
{
get => (string)_keyValues[A_1];
set
{
if (_keyValues.ContainsKey(A_1))
{
_keyValues[A_1] = value;
return;
}
if (A_1.Length > _maxKeySize)
{
_maxKeySize = A_1.Length;
}
_keyValues.Add(A_1, value);
}
}
public string Category
{
get; set;
}
public string Name
{
get; private set;
}
public ManifestCategory(string A_1)
{
Name = A_1;
}
public ManifestCategory(string A_1, string A_2) : this(A_1)
{
Category = A_2;
}
internal bool GetBool(string A_1)
{
return GetBool(A_1, false);
}
internal bool GetBool(string A_1, bool A_2)
{
return _keyValues.ContainsKey(A_1) ? bool.Parse(this[A_1]) : A_2;
}
internal uint GetUInt32(string A_1)
{
return GetUInt32(A_1, 0U);
}
internal uint GetUInt32(string A_1, uint A_2)
{
return _keyValues.ContainsKey(A_1) ? uint.Parse(this[A_1], CultureInfo.InvariantCulture) : A_2;
}
internal ulong GetUInt64(string A_1)
{
return GetUInt64(A_1, 0UL);
}
internal ulong GetUInt64(string A_1, ulong A_2)
{
return _keyValues.ContainsKey(A_1) ? ulong.Parse(this[A_1], CultureInfo.InvariantCulture) : A_2;
}
internal string GetString(string A_1)
{
return GetString(A_1, null);
}
internal string GetString(string A_1, string A_2)
{
return _keyValues.ContainsKey(A_1) ? this[A_1] : A_2;
}
private int _maxKeySize;
private readonly Hashtable _keyValues = new();
}
}

Some files were not shown because too many files have changed in this diff Show More