diff --git a/BurnOutSharp/Enums.cs b/BurnOutSharp/Enums.cs
index 74db8859..c861df19 100644
--- a/BurnOutSharp/Enums.cs
+++ b/BurnOutSharp/Enums.cs
@@ -25,6 +25,11 @@
///
BZip2,
+ ///
+ /// Compound File Binary
+ ///
+ CFB,
+
///
/// CTR Importable Archive
///
@@ -80,11 +85,6 @@
///
MPQ,
- ///
- /// Microsoft installation package
- ///
- MSI,
-
///
/// Nintendo 3DS cart image
///
diff --git a/BurnOutSharp/FileType/MSI.cs b/BurnOutSharp/FileType/CFB.cs
similarity index 98%
rename from BurnOutSharp/FileType/MSI.cs
rename to BurnOutSharp/FileType/CFB.cs
index b448c1be..a6b77b04 100644
--- a/BurnOutSharp/FileType/MSI.cs
+++ b/BurnOutSharp/FileType/CFB.cs
@@ -9,9 +9,9 @@ using static BurnOutSharp.Utilities.Dictionary;
namespace BurnOutSharp.FileType
{
///
- /// Microsoft installation package
+ /// Compound File Binary
///
- public class MSI : IScannable
+ public class CFB : IScannable
{
///
public ConcurrentDictionary> Scan(Scanner scanner, string file)
diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs
index d399224a..cadff05c 100644
--- a/BurnOutSharp/Scanner.cs
+++ b/BurnOutSharp/Scanner.cs
@@ -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)
{
diff --git a/BurnOutSharp/Tools/Utilities.cs b/BurnOutSharp/Tools/Utilities.cs
index 3ba036d1..f90a0aae 100644
--- a/BurnOutSharp/Tools/Utilities.cs
+++ b/BurnOutSharp/Tools/Utilities.cs
@@ -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();
diff --git a/README.md b/README.md
index dbe775f4..56c04e99 100644
--- a/README.md
+++ b/README.md
@@ -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 | |
diff --git a/Test/Extractor.cs b/Test/Extractor.cs
index aa304718..f5dc3c51 100644
--- a/Test/Extractor.cs
+++ b/Test/Extractor.cs
@@ -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)
{
diff --git a/Test/Printer.cs b/Test/Printer.cs
index bbf58165..4ffc4184 100644
--- a/Test/Printer.cs
+++ b/Test/Printer.cs
@@ -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)
{