CHM objectification

This commit is contained in:
Matt Nadareski
2022-05-22 23:46:29 -07:00
parent 044c398fa7
commit b29198b3d4
15 changed files with 2009 additions and 1761 deletions

View File

@@ -0,0 +1,85 @@
/* libmspack -- a library for working with Microsoft compression formats.
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
namespace LibMSPackSharp.CHM
{
/// <summary>
/// A structure which represents a CHM helpfile.
///
/// All fields are READ ONLY.
/// </summary>
public class CHM
{
#region Internal
/// <summary>
/// CHM header information
/// </summary>
internal _CHMHeader Header { get; set; }
/// <summary>
/// Header section table information
/// </summary>
internal _HeaderSectionTable HeaderSectionTable { get; set; }
/// <summary>
/// Header section 0 information
/// </summary>
internal _HeaderSection0 HeaderSection0 { get; set; }
/// <summary>
/// Header section 1 information
/// </summary>
internal _HeaderSection1 HeaderSection1 { get; set; }
#endregion
/// <summary>
/// The filename of the CHM helpfile. This is given by the library user
/// and may be in any format.
/// </summary>
public string Filename { get; set; }
/// <summary>
/// A list of all non-system files in the CHM helpfile.
/// </summary>
public DecompressFile Files { get; set; }
/// <summary>
/// A list of all system files in the CHM helpfile.
///
/// System files are files which begin with "::". They are meta-files
/// generated by the CHM creation process.
/// </summary>
public DecompressFile SysFiles { get; set; }
/// <summary>
/// The section 0 (uncompressed) data in this CHM helpfile.
/// </summary>
public UncompressedSection Sec0 { get; set; }
/// <summary>
/// The section 1 (MSCompressed) data in this CHM helpfile.
/// </summary>
public MSCompressedSection Sec1 { get; set; }
/// <summary>
/// A cache of loaded chunks, filled in by mschm_decoder::fast_find().
/// Available only in CHM decoder version 2 and above.
/// </summary>
public byte[][] ChunkCache { get; set; }
}
}

View File

@@ -27,6 +27,20 @@ namespace LibMSPackSharp.CHM
/// <see cref="Library.DestroyCHMCompressor(Compressor)"/>
public class Compressor
{
#region Fields
public SystemImpl System { get; set; }
public string TempFile { get; set; }
public bool UseTempFile { get; set; }
public Error Error { get; set; }
#endregion
#region Public Functionality
/// <summary>
/// Generates a CHM help file.
///
@@ -43,10 +57,6 @@ namespace LibMSPackSharp.CHM
/// use one. See use_temporary_file() for the behaviour of generate() in
/// these two different modes.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the mschm_compressor
/// instance being called
/// </param>
/// <param name="fileList">
/// an array of mschmc_file structures, terminated
/// with an entry whose mschmc_file::section field is
@@ -64,7 +74,7 @@ namespace LibMSPackSharp.CHM
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
/// <see cref="UseTemporaryFile"/>
/// <see cref="SetParam"/>
public Func<Compressor, CompressFile[], string, Error> Generate;
public Func<CompressFile[], string, Error> Generate;
/// <summary>
/// Specifies whether a temporary file is used during CHM generation.
@@ -108,10 +118,6 @@ namespace LibMSPackSharp.CHM
/// update, the appropriate sections are seek() ed to and re-written, then
/// the output file is closed.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the mschm_compressor
/// instance being called
/// </param>
/// <param name="useTempFile">
/// non-zero if the temporary file should be used,
/// zero if the temporary file should not be used.
@@ -124,15 +130,11 @@ namespace LibMSPackSharp.CHM
/// </param>
/// <returns>an error code, or MSPACK_ERR_OK if successful</returns>
/// <see cref="Generate"/>
public Func<Compressor, bool, string, Error> UseTemporaryFile;
public Func<bool, string, Error> UseTemporaryFile;
/// <summary>
/// Sets a CHM compression engine parameter.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the mschm_compressor
/// instance being called
/// </param>
/// <param name="param">the parameter to set</param>
/// <param name="value">the value to set the parameter to</param>
/// <returns>
@@ -140,18 +142,8 @@ namespace LibMSPackSharp.CHM
/// is a problem with either parameter or value.
/// </returns>
/// <see cref="Generate"/>
public Func<Compressor, Parameters, int, Error> SetParam;
public Func<Parameters, int, Error> SetParam;
/// <summary>
/// Returns the error code set by the most recently called method.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the mschm_compressor
/// instance being called
/// </param>
/// <returns>the most recent error code</returns>
/// <see cref="SetParam"/>
/// <see cref="Generate"/>
public Func<Compressor, Error> LastError;
#endregion
}
}

View File

@@ -1,22 +0,0 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
namespace LibMSPackSharp.CHM
{
public class CompressorImpl : Compressor
{
public SystemImpl System { get; set; }
public string TempFile { get; set; }
public bool UseTempFile { get; set; }
public Error Error { get; set; }
}
}

View File

@@ -0,0 +1,53 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
namespace LibMSPackSharp.CHM
{
public class Constants
{
// _PMGHeader
internal const int pmgl_Signature = 0x0000;
internal const int pmgl_QuickRefSize = 0x0004;
internal const int pmgl_PMGIEntries = 0x0008; // Unknown1 in PMGL
internal const int pmgl_PrevChunk = 0x000C; // Not in PMGI
internal const int pmgl_NextChunk = 0x0010; // Not in PMGI
internal const int pmgl_PMGLEntries = 0x0014; // Not in PMGI
internal const int pmgl_headerSIZEOF = 0x0014;
internal const int pmgi_headerSIZEOF = 0x000C;
// _LZXControlData
internal const int lzxcd_Length = 0x0000;
internal const int lzxcd_Signature = 0x0004;
internal const int lzxcd_Version = 0x0008;
internal const int lzxcd_ResetInterval = 0x000C;
internal const int lzxcd_WindowSize = 0x0010;
internal const int lzxcd_CacheSize = 0x0014;
internal const int lzxcd_Unknown1 = 0x0018;
internal const int lzxcd_SIZEOF = 0x001C;
// _LZXResetTable
internal const int lzxrt_Unknown1 = 0x0000;
internal const int lzxrt_NumEntries = 0x0004;
internal const int lzxrt_EntrySize = 0x0008;
internal const int lzxrt_TableOffset = 0x000C;
internal const int lzxrt_UncompLen = 0x0010;
internal const int lzxrt_CompLen = 0x0018;
internal const int lzxrt_FrameLen = 0x0020;
internal const int lzxrt_Entries = 0x0028;
internal const int lzxrt_headerSIZEOF = 0x0028;
// Filenames of the system files used for decompression.
// - Content and ControlData are essential.
// - ResetTable is preferred, but SpanInfo can be used if not available
internal const string ContentName = "::DataSpace/Storage/MSCompressed/Content";
internal const string ControlName = "::DataSpace/Storage/MSCompressed/ControlData";
internal const string SpanInfoName = "::DataSpace/Storage/MSCompressed/SpanInfo";
internal const string ResetTableName = "::DataSpace/Storage/MSCompressed/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable";
}
}

View File

@@ -17,7 +17,7 @@ namespace LibMSPackSharp.CHM
/// <summary>
/// CHM file being decompressed
/// </summary>
public Header Header { get; set; }
public CHM Header { get; set; }
/// <summary>
/// Uncompressed offset within folder

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
namespace LibMSPackSharp.CHM
{
public class DecompressorImpl : Decompressor
{
public SystemImpl System { get; set; }
public DecompressState State { get; set; }
public Error Error { get; set; }
}
}

View File

@@ -1,135 +0,0 @@
/* libmspack -- a library for working with Microsoft compression formats.
* (C) 2003-2019 Stuart Caie <kyzer@cabextract.org.uk>
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
namespace LibMSPackSharp.CHM
{
/// <summary>
/// A structure which represents a CHM helpfile.
///
/// All fields are READ ONLY.
/// </summary>
public class Header
{
/// <summary>
/// The version of the CHM file format used in this file.
/// </summary>
public uint Version { get; set; }
/// <summary>
/// The "timestamp" of the CHM helpfile.
///
/// It is the lower 32 bits of a 64-bit value representing the number of
/// centiseconds since 1601-01-01 00:00:00 UTC, plus 42. It is not useful
/// as a timestamp, but it is useful as a semi-unique ID.
/// </summary>
public uint Timestamp { get; set; }
/// <summary>
/// The default Language and Country ID (LCID) of the user who ran the
/// HTMLHelp Compiler. This is not the language of the CHM file itself.
/// </summary>
public uint Language { get; set; }
/// <summary>
/// The filename of the CHM helpfile. This is given by the library user
/// and may be in any format.
/// </summary>
public string Filename { get; set; }
/// <summary>
/// The length of the CHM helpfile, in bytes.
/// </summary>
public long Length { get; set; }
/// <summary>
/// A list of all non-system files in the CHM helpfile.
/// </summary>
public DecompressFile Files { get; set; }
/// <summary>
/// A list of all system files in the CHM helpfile.
///
/// System files are files which begin with "::". They are meta-files
/// generated by the CHM creation process.
/// </summary>
public DecompressFile SysFiles { get; set; }
/// <summary>
/// The section 0 (uncompressed) data in this CHM helpfile.
/// </summary>
public UncompressedSection Sec0 { get; set; }
/// <summary>
/// The section 1 (MSCompressed) data in this CHM helpfile.
/// </summary>
public MSCompressedSection Sec1 { get; set; }
/// <summary>
/// The file offset of the first PMGL/PMGI directory chunk.
/// </summary>
public long DirOffset { get; set; }
/// <summary>
/// The number of PMGL/PMGI directory chunks in this CHM helpfile.
/// </summary>
public uint NumChunks { get; set; }
/// <summary>
/// The size of each PMGL/PMGI chunk, in bytes.
/// </summary>
public uint ChunkSize { get; set; }
/// <summary>
/// The "density" of the quick-reference section in PMGL/PMGI chunks.
/// </summary>
public uint Density { get; set; }
/// <summary>
/// The depth of the index tree.
///
/// - if 1, there are no PMGI chunks, only PMGL chunks.
/// - if 2, there is 1 PMGI chunk. All chunk indices point to PMGL chunks.
/// - if 3, the root PMGI chunk points to secondary PMGI chunks, which in turn point to PMGL chunks.
/// - and so on...
/// </summary>
public uint Depth { get; set; }
/// <summary>
/// The number of the root PMGI chunk.
///
/// If there is no index in the CHM helpfile, this will be 0xFFFFFFFF.
/// </summary>
public uint IndexRoot { get; set; }
/// <summary>
/// The number of the first PMGL chunk. Usually zero.
/// Available only in CHM decoder version 2 and above.
/// </summary>
public uint FirstPMGL { get; set; }
/// <summary>
/// The number of the last PMGL chunk. Usually num_chunks-1.
/// Available only in CHM decoder version 2 and above.
/// </summary>
public uint LastPMGL { get; set; }
/// <summary>
/// A cache of loaded chunks, filled in by mschm_decoder::fast_find().
/// Available only in CHM decoder version 2 and above.
/// </summary>
public byte[][] ChunkCache { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,7 @@ namespace LibMSPackSharp.CHM
/// <summary>
/// A pointer to the CHM helpfile that contains this section.
/// </summary>
public Header Header { get; set; }
public CHM Header { get; set; }
/// <summary>
/// The section ID. Either 0 for the uncompressed section

View File

@@ -0,0 +1,118 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
namespace LibMSPackSharp.CHM
{
internal class _CHMHeader
{
#region Fields
/// <summary>
/// "ITSF"
/// </summary>
/// <remarks>0x0000</remarks>
public uint Signature { get; private set; }
/// <summary>
/// The version of the CHM file format used in this file.
/// </summary>
/// <remarks>0x0004</remarks>
public uint Version { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0008</remarks>
public uint HeaderLen { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x000C</remarks>
public uint Unknown1 { get; private set; }
/// <summary>
/// The "timestamp" of the CHM helpfile.
/// </summary>
/// <remarks>
/// 0x0010
///
/// It is the lower 32 bits of a 64-bit value representing the number of
/// centiseconds since 1601-01-01 00:00:00 UTC, plus 42. It is not useful
/// as a timestamp, but it is useful as a semi-unique ID.
/// </remarks>
public uint Timestamp { get; private set; }
/// <summary>
/// The default Language and Country ID (LCID) of the user who ran the
/// HTMLHelp Compiler. This is not the language of the CHM file itself.
/// </summary>
/// <remarks>0x0014</remarks>
public uint LanguageID { get; private set; }
/// <summary>
/// Header GUID 1
/// </summary>
/// <remarks>0x0018</remarks>
public Guid GUID1 { get; private set; }
/// <summary>
/// Header GUID 2
/// </summary>
/// <remarks>0x0028</remarks>
public Guid GUID2 { get; private set; }
/// <summary>
/// Total size of the CHM header in bytes
/// </summary>
public const int Size = 0x0038;
#endregion
/// <summary>
/// Private constructor
/// </summary>
private _CHMHeader() { }
/// <summary>
/// Create a _CHMHeader from a byte array, if possible
/// </summary>
public static Error Create(byte[] buffer, out _CHMHeader header)
{
header = null;
if (buffer == null || buffer.Length < Size)
return Error.MSPACK_ERR_READ;
header = new _CHMHeader();
header.Signature = BitConverter.ToUInt32(buffer, 0x0000);
if (header.Signature != 0x46535449)
return Error.MSPACK_ERR_SIGNATURE;
// Expect version less than or equal to 3, but don't validate
header.Version = BitConverter.ToUInt32(buffer, 0x0004);
header.HeaderLen = BitConverter.ToUInt32(buffer, 0x0008);
header.Unknown1 = BitConverter.ToUInt32(buffer, 0x000C);
header.Timestamp = BitConverter.ToUInt32(buffer, 0x0010);
header.LanguageID = BitConverter.ToUInt32(buffer, 0x0014);
header.GUID1 = new Guid(new ReadOnlySpan<byte>(buffer, 0x0018, 0x10).ToArray());
if (header.GUID1 != Guid.Parse("7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC"))
return Error.MSPACK_ERR_SIGNATURE;
header.GUID2 = new Guid(new ReadOnlySpan<byte>(buffer, 0x0028, 0x10).ToArray());
if (header.GUID2 != Guid.Parse("7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC"))
return Error.MSPACK_ERR_SIGNATURE;
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -0,0 +1,85 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
namespace LibMSPackSharp.CHM
{
internal class _HeaderSection0
{
#region Fields
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0000</remarks>
public uint Unknown1 { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0004</remarks>
public uint Unknown2 { get; private set; }
/// <summary>
/// The length of the CHM helpfile, in bytes.
/// </summary>
/// <remarks>0x0008</remarks>
public long FileLength { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0010</remarks>
public uint Unknown3 { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0014</remarks>
public uint Unknown4 { get; private set; }
/// <summary>
/// Total size of the header section 0 in bytes
/// </summary>
public const int Size = 0x0018;
#endregion
/// <summary>
/// Private constructor
/// </summary>
private _HeaderSection0() { }
/// <summary>
/// Create a _HeaderSection0 from a byte array, if possible
/// </summary>
public static Error Create(byte[] buffer, out _HeaderSection0 headerSection)
{
headerSection = null;
if (buffer == null || buffer.Length < Size)
return Error.MSPACK_ERR_READ;
headerSection = new _HeaderSection0();
headerSection.Unknown1 = BitConverter.ToUInt32(buffer, 0x0000);
headerSection.Unknown2 = BitConverter.ToUInt32(buffer, 0x0004);
headerSection.FileLength = BitConverter.ToInt64(buffer, 0x0008);
// TODO: Is this supposed to be == 0?
if (headerSection.FileLength != 0)
return Error.MSPACK_ERR_DATAFORMAT;
headerSection.Unknown3 = BitConverter.ToUInt32(buffer, 0x0010);
headerSection.Unknown4 = BitConverter.ToUInt32(buffer, 0x0014);
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -0,0 +1,184 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
namespace LibMSPackSharp.CHM
{
internal class _HeaderSection1
{
#region Fields
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0000</remarks>
public uint Signature { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0004</remarks>
public uint Version { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0008</remarks>
public uint HeaderLen { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x000C</remarks>
public uint Unknown1 { get; private set; }
/// <summary>
/// The size of each PMGL/PMGI chunk, in bytes.
/// </summary>
/// <remarks>0x0010</remarks>
public uint ChunkSize { get; private set; }
/// <summary>
/// The "density" of the quick-reference section in PMGL/PMGI chunks.
/// </summary>
/// <remarks>0x0014</remarks>
public uint Density { get; private set; }
/// <summary>
/// The depth of the index tree.
/// </summary>
/// <remarks>
/// 0x0018
///
/// - if 1, there are no PMGI chunks, only PMGL chunks.
/// - if 2, there is 1 PMGI chunk. All chunk indices point to PMGL chunks.
/// - if 3, the root PMGI chunk points to secondary PMGI chunks, which in turn point to PMGL chunks.
/// - and so on...
/// </remarks>
public uint Depth { get; private set; }
/// <summary>
/// The number of the root PMGI chunk.
/// </summary>
/// <remarks>
/// 0x001C
///
/// If there is no index in the CHM helpfile, this will be 0xFFFFFFFF.
/// </remarks>
public uint IndexRoot { get; private set; }
/// <summary>
/// The number of the first PMGL chunk. Usually zero.
/// Available only in CHM decoder version 2 and above.
/// </summary>
/// <remarks>0x0020</remarks>
public uint FirstPMGL { get; private set; }
/// <summary>
/// The number of the last PMGL chunk. Usually num_chunks-1.
/// Available only in CHM decoder version 2 and above.
/// </summary>
/// <remarks>0x0024</remarks>
public uint LastPMGL { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0028</remarks>
public uint Unknown2 { get; private set; }
/// <summary>
/// The number of PMGL/PMGI directory chunks in this CHM helpfile.
/// </summary>
/// <remarks>0x002C</remarks>
public uint NumChunks { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0030</remarks>
public uint LanguageID { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0034</remarks>
public Guid GUID { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0044</remarks>
public uint Unknown3 { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0048</remarks>
public uint Unknown4 { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x004C</remarks>
public uint Unknown5 { get; private set; }
/// <summary>
/// UNKNOWN
/// </summary>
/// <remarks>0x0050</remarks>
public uint Unknown6 { get; private set; }
/// <summary>
/// Total size of the header section 1 in bytes
/// </summary>
public const int Size = 0x0054;
#endregion
/// <summary>
/// Private constructor
/// </summary>
private _HeaderSection1() { }
/// <summary>
/// Create a _HeaderSection1 from a byte array, if possible
/// </summary>
public static Error Create(byte[] buffer, out _HeaderSection1 headerSection)
{
headerSection = null;
if (buffer == null || buffer.Length < Size)
return Error.MSPACK_ERR_READ;
headerSection = new _HeaderSection1();
headerSection.Signature = BitConverter.ToUInt32(buffer, 0x0000);
headerSection.Version = BitConverter.ToUInt32(buffer, 0x0004);
headerSection.HeaderLen = BitConverter.ToUInt32(buffer, 0x0008);
headerSection.Unknown1 = BitConverter.ToUInt32(buffer, 0x000C);
headerSection.ChunkSize = BitConverter.ToUInt32(buffer, 0x0010);
headerSection.Density = BitConverter.ToUInt32(buffer, 0x0014);
headerSection.Depth = BitConverter.ToUInt32(buffer, 0x0018);
headerSection.IndexRoot = BitConverter.ToUInt32(buffer, 0x001C);
headerSection.FirstPMGL = BitConverter.ToUInt32(buffer, 0x0020);
headerSection.LastPMGL = BitConverter.ToUInt32(buffer, 0x0024);
headerSection.Unknown2 = BitConverter.ToUInt32(buffer, 0x0028);
headerSection.NumChunks = BitConverter.ToUInt32(buffer, 0x002C);
headerSection.LanguageID = BitConverter.ToUInt32(buffer, 0x0030);
headerSection.GUID = new Guid(new ReadOnlySpan<byte>(buffer, 0x0034, 0x10).ToArray());
headerSection.Unknown3 = BitConverter.ToUInt32(buffer, 0x0044);
headerSection.Unknown4 = BitConverter.ToUInt32(buffer, 0x0048);
headerSection.Unknown5 = BitConverter.ToUInt32(buffer, 0x004C);
headerSection.Unknown6 = BitConverter.ToUInt32(buffer, 0x0050);
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -0,0 +1,104 @@
/* This file is part of libmspack.
* (C) 2003-2004 Stuart Caie.
*
* libmspack is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL) version 2.1
*
* For further details, see the file COPYING.LIB distributed with libmspack
*/
using System;
namespace LibMSPackSharp.CHM
{
internal class _HeaderSectionTable
{
#region Regular Table
/// <summary>
/// Header section 0 offset
/// </summary>
/// <remarks>0x0000</remarks>
public long OffsetHS0 { get; private set; }
/// <summary>
/// Header section 0 length
/// </summary>
/// <remarks>0x0008</remarks>
public long LengthHS0 { get; private set; }
/// <summary>
/// Header section 1 offset
/// The file offset of the first PMGL/PMGI directory chunk.
/// </summary>
/// <remarks>
/// 0x0010
///
/// This is internally settable because it has to be corrected in some cases
/// </remarks>
public long OffsetHS1 { get; internal set; }
/// <summary>
/// Header section 1 length
/// </summary>
/// <remarks>0x0018</remarks>
public long LengthHS1 { get; private set; }
/// <summary>
/// Total size of the version 1 and 2 header section table in bytes
/// </summary>
public const int Size = 0x0020;
#endregion
#region Version 3 Table
/// <summary>
/// Header section 0 offset correct
/// </summary>
/// <remarks>0x0020</remarks>
public long OffsetCS0 { get; private set; }
/// <summary>
/// Total size of the version 3 header section table in bytes
/// </summary>
public const int V3Size = 0x0028;
#endregion
/// <summary>
/// Private constructor
/// </summary>
private _HeaderSectionTable() { }
/// <summary>
/// Create a _HeaderSectionTable from a byte array, if possible
/// </summary>
public static Error Create(byte[] buffer, out _HeaderSectionTable headerSectionTable)
{
headerSectionTable = null;
if (buffer == null || buffer.Length < Size)
return Error.MSPACK_ERR_READ;
headerSectionTable = new _HeaderSectionTable();
headerSectionTable.OffsetHS0 = BitConverter.ToInt64(buffer, 0x0000);
headerSectionTable.LengthHS0 = BitConverter.ToInt64(buffer, 0x0008);
headerSectionTable.OffsetHS1 = BitConverter.ToInt64(buffer, 0x0010);
headerSectionTable.LengthHS1 = BitConverter.ToInt64(buffer, 0x0018);
if (buffer.Length >= V3Size)
{
headerSectionTable.OffsetCS0 = BitConverter.ToInt64(buffer, 0x0020);
}
// OffsetCS0 does not exist in version 1 or 2 CHM files.
// The offset will be corrected later, once HS1 is read.
// TODO: Are these supposed to be == 0?
if (headerSectionTable.OffsetHS0 != 0 || headerSectionTable.OffsetHS1 != 0 || headerSectionTable.OffsetCS0 != 0)
return Error.MSPACK_ERR_DATAFORMAT;
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -225,14 +225,8 @@ namespace LibMSPackSharp
if (!SystemImpl.ValidSystem(sys))
return null;
return new CHM.DecompressorImpl()
return new CHM.Decompressor()
{
Open = CHM.Implementation.Open,
Close = CHM.Implementation.Close,
Extract = CHM.Implementation.Extract,
LastError = CHM.Implementation.LastError,
FastOpen = CHM.Implementation.FastOpen,
FastFind = CHM.Implementation.FastFind,
System = sys,
Error = Error.MSPACK_ERR_OK,
State = null,
@@ -242,8 +236,8 @@ namespace LibMSPackSharp
/// <summary>
/// Destroys an existing CHM compressor.
/// </summary>
/// <param name="c">the <see cref="CHM.Compressor"/> to destroy</param>
public static void DestroyCHMCompressor(CHM.Compressor c)
/// <param name="self">the <see cref="CHM.Compressor"/> to destroy</param>
public static void DestroyCHMCompressor(CHM.Compressor self)
{
// TODO
}
@@ -251,10 +245,9 @@ namespace LibMSPackSharp
/// <summary>
/// Destroys an existing CHM decompressor.
/// </summary>
/// <param name="d">the <see cref="CHM.Decompressor"/> to destroy</param>
public static void DestroyCHMDecompressor(CHM.Decompressor d)
/// <param name="self">the <see cref="CHM.Decompressor"/> to destroy</param>
public static void DestroyCHMDecompressor(CHM.Decompressor self)
{
CHM.DecompressorImpl self = d as CHM.DecompressorImpl;
if (self != null)
{
SystemImpl sys = self.System;