MSI was really CFB all along

This commit is contained in:
Matt Nadareski
2023-01-10 10:51:36 -08:00
parent 661808826a
commit 5ea89eefe8
7 changed files with 119 additions and 103 deletions

View File

@@ -25,6 +25,11 @@
/// </summary>
BZip2,
/// <summary>
/// Compound File Binary
/// </summary>
CFB,
/// <summary>
/// CTR Importable Archive
/// </summary>
@@ -80,11 +85,6 @@
/// </summary>
MPQ,
/// <summary>
/// Microsoft installation package
/// </summary>
MSI,
/// <summary>
/// Nintendo 3DS cart image
/// </summary>

View File

@@ -9,9 +9,9 @@ using static BurnOutSharp.Utilities.Dictionary;
namespace BurnOutSharp.FileType
{
/// <summary>
/// Microsoft installation package
/// Compound File Binary
/// </summary>
public class MSI : IScannable
public class CFB : IScannable
{
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)

View File

@@ -427,6 +427,14 @@ namespace BurnOutSharp
AppendToDictionary(protections, subProtections);
}
// CFB
if (fileName != null && scannable is CFB)
{
var subProtections = scannable.Scan(this, fileName);
PrependToKeys(subProtections, fileName);
AppendToDictionary(protections, subProtections);
}
// GCF
if (scannable is GCF)
{
@@ -475,14 +483,6 @@ namespace BurnOutSharp
AppendToDictionary(protections, subProtections);
}
// MSI
if (fileName != null && scannable is MSI)
{
var subProtections = scannable.Scan(this, fileName);
PrependToKeys(subProtections, fileName);
AppendToDictionary(protections, subProtections);
}
// MoPaQ archive
if (fileName != null && scannable is MPQ)
{

View File

@@ -43,6 +43,13 @@ namespace BurnOutSharp.Tools
#endregion
#region CFB
if (magic.StartsWith(new byte?[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
return SupportedFileType.CFB;
#endregion
#region CIA
// No magic checks for CIA
@@ -150,13 +157,6 @@ namespace BurnOutSharp.Tools
#endregion
#region MSI
if (magic.StartsWith(new byte?[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
return SupportedFileType.MSI;
#endregion
#region N3DS
// No magic checks for N3DS
@@ -365,6 +365,30 @@ namespace BurnOutSharp.Tools
#endregion
#region CFB
// Installer package
if (extension.Equals("msi", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.CFB;
// Merge module
else if (extension.Equals("msm", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.CFB;
// Patch Package
else if (extension.Equals("msp", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.CFB;
// Transform
else if (extension.Equals("mst", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.CFB;
// Patch Creation Properties
else if (extension.Equals("pcp", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.CFB;
#endregion
#region CIA
if (extension.Equals("cia", StringComparison.OrdinalIgnoreCase))
@@ -433,13 +457,6 @@ namespace BurnOutSharp.Tools
#endregion
#region MSI
if (extension.Equals("msi", StringComparison.OrdinalIgnoreCase))
return SupportedFileType.MSI;
#endregion
#region N3DS
// 3DS cart image
@@ -717,6 +734,7 @@ namespace BurnOutSharp.Tools
case SupportedFileType.BFPK: return new FileType.BFPK();
case SupportedFileType.BSP: return new FileType.BSP();
case SupportedFileType.BZip2: return new FileType.BZip2();
case SupportedFileType.CFB: return new FileType.CFB();
//case SupportedFileType.CIA: return new FileType.CIA();
case SupportedFileType.Executable: return new FileType.Executable();
case SupportedFileType.GCF: return new FileType.GCF();
@@ -728,7 +746,6 @@ namespace BurnOutSharp.Tools
case SupportedFileType.MicrosoftCAB: return new FileType.MicrosoftCAB();
case SupportedFileType.MicrosoftLZ: return new FileType.MicrosoftLZ();
case SupportedFileType.MPQ: return new FileType.MPQ();
case SupportedFileType.MSI: return new FileType.MSI();
//case SupportedFileType.N3DS: return new FileType.N3DS();
//case SupportedFileType.NCF: return new FileType.NCF();
//case SupportedFileType.Nitro: return new FileType.Nitro();

View File

@@ -156,7 +156,7 @@ Below is a list of container formats that are supported in some way:
| 7-zip archive | No | Yes | Yes | Via `SharpCompress` |
| BFPK custom archive format | Yes | Yes | Yes | |
| bzip2 archive | No | Yes | Yes | Via `SharpCompress` |
| Compound File Binary (CFB) | Yes | Yes* | No | Basis of MSI, only CFB common pieces printable |
| Compound File Binary (CFB) | Yes* | Yes | Yes | Via `OpenMcdf`, only CFB common pieces printable |
| gzip archive | No | Yes | Yes | Via `SharpCompress` |
| Half-Life Game Cache File (GCF) | Yes | Yes | Yes | |
| Half-Life Level (BSP) | Yes | Yes | Yes | |
@@ -171,7 +171,6 @@ Below is a list of container formats that are supported in some way:
| Microsoft cabinet file | Yes | Yes | Yes | |
| Microsoft LZ-compressed files | No | Yes | Yes | |
| MoPaQ game data archive (MPQ) | No | Yes | Yes | Via `StormLibSharp` |
| Microsoft installation package (MSI) | No | Yes | Yes | Via `OpenMcdf` |
| MS-DOS Executable | Yes | Yes | No | Incomplete |
| New Exectuable | Yes | Yes | No | Incomplete |
| Nintendo 3DS cart image | Yes | Yes | No | |

View File

@@ -189,6 +189,58 @@ namespace Test
}
}
// CFB
else if (ft == SupportedFileType.CFB)
{
// Build the installer information
Console.WriteLine("Extracting CFB contents");
Console.WriteLine();
// If the CFB file itself fails
try
{
using (CompoundFile cf = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default))
{
cf.RootStorage.VisitEntries((e) =>
{
if (!e.IsStream)
return;
var str = cf.RootStorage.GetStream(e.Name);
if (str == null)
return;
byte[] strData = str.GetData();
if (strData == null)
return;
string decoded = BurnOutSharp.FileType.CFB.DecodeStreamName(e.Name).TrimEnd('\0');
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
// UTF-8 encoding of 0x4840.
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
decoded = decoded.Substring(3);
foreach (char c in Path.GetInvalidFileNameChars())
{
decoded = decoded.Replace(c, '_');
}
string filename = Path.Combine(outputDirectory, decoded);
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(strData, 0, strData.Length);
}
}, recursive: true);
}
}
catch (Exception ex)
{
Console.WriteLine($"Something went wrong extracting CFB: {ex}");
Console.WriteLine();
}
}
// GCF
else if (ft == SupportedFileType.GCF)
{
@@ -458,58 +510,6 @@ namespace Test
}
#endif
// MSI
else if (ft == SupportedFileType.MSI)
{
// Build the installer information
Console.WriteLine("Extracting MSI contents");
Console.WriteLine();
// If the MSI file itself fails
try
{
using (CompoundFile msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default))
{
msi.RootStorage.VisitEntries((e) =>
{
if (!e.IsStream)
return;
var str = msi.RootStorage.GetStream(e.Name);
if (str == null)
return;
byte[] strData = str.GetData();
if (strData == null)
return;
string decoded = BurnOutSharp.FileType.MSI.DecodeStreamName(e.Name).TrimEnd('\0');
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
// UTF-8 encoding of 0x4840.
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
decoded = decoded.Substring(3);
foreach (char c in Path.GetInvalidFileNameChars())
{
decoded = decoded.Replace(c, '_');
}
string filename = Path.Combine(outputDirectory, decoded);
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(strData, 0, strData.Length);
}
}, recursive: true);
}
}
catch (Exception ex)
{
Console.WriteLine($"Something went wrong extracting MSI: {ex}");
Console.WriteLine();
}
}
// PAK
else if (ft == SupportedFileType.PAK)
{

View File

@@ -174,6 +174,25 @@ namespace Test
bsp.Print();
}
// CFB
else if (ft == SupportedFileType.CFB)
{
// Build the CFB information
Console.WriteLine("Creating Compact File Binary deserializer");
Console.WriteLine();
var cfb = CFB.Create(stream);
if (cfb == null)
{
Console.WriteLine("Something went wrong parsing Compact File Binary");
Console.WriteLine();
return;
}
// Print the CFB to screen
cfb.Print();
}
// CIA
else if (ft == SupportedFileType.CIA)
{
@@ -257,25 +276,6 @@ namespace Test
cabinet.Print();
}
// MSI -- TODO: Technically CFB
else if (ft == SupportedFileType.MSI)
{
// Build the CFB information
Console.WriteLine("Creating Compact File Binary deserializer");
Console.WriteLine();
var cfb = CFB.Create(stream);
if (cfb == null)
{
Console.WriteLine("Something went wrong parsing Compact File Binary");
Console.WriteLine();
return;
}
// Print the CFB to screen
cfb.Print();
}
// N3DS
else if (ft == SupportedFileType.N3DS)
{