/* libmspack -- a library for working with Microsoft compression formats. * (C) 2003-2019 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 * * 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. */ /** \mainpage * * \section intro Introduction * * libmspack is a library which provides compressors and decompressors, * archivers and dearchivers for Microsoft compression formats. * * \section formats Formats supported * * The following file formats are supported: * - SZDD files, which use LZSS compression * - KWAJ files, which use LZSS, LZSS+Huffman or deflate compression * - .HLP (MS Help) files, which use LZSS compression * - .CAB (MS Cabinet) files, which use deflate, LZX or Quantum compression * - .CHM (HTML Help) files, which use LZX compression * - .LIT (MS EBook) files, which use LZX compression and DES encryption * - .LZX (Exchange Offline Addressbook) files, which use LZX compression * * To determine the capabilities of the library, and the binary * compatibility version of any particular compressor or decompressor, use * the mspack_version() function. The UNIX library interface version is * defined as the highest-versioned library component. * * \section starting Getting started * * The macro MSPACK_SYS_SELFTEST() should be used to ensure the library can * be used. In particular, it checks if the caller is using 32-bit file I/O * when the library is compiled for 64-bit file I/O and vice versa. * * If compiled normally, the library includes basic file I/O and memory * management functionality using the standard C library. This can be * customised and replaced entirely by creating a SystemImpl structure. * * A compressor or decompressor for the required format must be * instantiated before it can be used. Each construction function takes * one parameter, which is either a pointer to a custom SystemImpl * structure, or null to use the default. The instantiation returned, if * not null, contains function pointers (methods) to work with the given * file format. * * For compression: * - CreateCABCompressor() creates a mscab_compressor * - CreateCHMCompressor() creates a mschm_compressor * - CreateLITCompressor() creates a mslit_compressor * - CreateHLPCompressor() creates a mshlp_compressor * - CreateSZDDCompressor() creates a msszdd_compressor * - CreateKWAJCompressor() creates a mskwaj_compressor * - CreateOABCompressor() creates a msoab_compressor * * For decompression: * - mspack_create_cab_decompressor() creates a mscab_decompressor * - mspack_create_chm_decompressor() creates a mschm_decompressor * - mspack_create_lit_decompressor() creates a mslit_decompressor * - mspack_create_hlp_decompressor() creates a mshlp_decompressor * - mspack_create_szdd_decompressor() creates a msszdd_decompressor * - mspack_create_kwaj_decompressor() creates a mskwaj_decompressor * - mspack_create_oab_decompressor() creates a msoab_decompressor * * Once finished working with a format, each kind of * compressor/decompressor has its own specific destructor: * - mspack_destroy_cab_compressor() * - mspack_destroy_cab_decompressor() * - mspack_destroy_chm_compressor() * - mspack_destroy_chm_decompressor() * - mspack_destroy_lit_compressor() * - mspack_destroy_lit_decompressor() * - mspack_destroy_hlp_compressor() * - mspack_destroy_hlp_decompressor() * - mspack_destroy_szdd_compressor() * - mspack_destroy_szdd_decompressor() * - mspack_destroy_kwaj_compressor() * - mspack_destroy_kwaj_decompressor() * - mspack_destroy_oab_compressor() * - mspack_destroy_oab_decompressor() * * Destroying a compressor or decompressor does not destroy any objects, * structures or handles that have been created using that compressor or * decompressor. Ensure that everything created or opened is destroyed or * closed before compressor/decompressor is itself destroyed. * * \section threading Multi-threading * * libmspack methods are reentrant and multithreading-safe when each * thread has its own compressor or decompressor. * You should not call multiple methods simultaneously on a single * compressor or decompressor instance. * * If this may happen, you can either use one compressor or * decompressor per thread, or you can use your preferred lock, * semaphore or mutex library to ensure no more than one method on a * compressor/decompressor is called simultaneously. libmspack will * not do this locking for you. * * Example of incorrect behaviour: * - thread 1 calls mspack_create_cab_decompressor() * - thread 1 calls open() * - thread 1 calls extract() for one file * - thread 2 simultaneously calls extract() for another file * * Correct behaviour: * - thread 1 calls mspack_create_cab_decompressor() * - thread 2 calls mspack_create_cab_decompressor() * - thread 1 calls its own open() / extract() * - thread 2 simultaneously calls its own open() / extract() * * Also correct behaviour: * - thread 1 calls mspack_create_cab_decompressor() * - thread 1 locks a mutex for with the decompressor before * calling any methods on it, and unlocks the mutex after each * method returns. * - thread 1 can share the results of open() with thread 2, and both * can call extract(), provided they both guard against simultaneous * use of extract(), and any other methods, with the mutex */ using LibMSPackSharp.Compression; namespace LibMSPackSharp { public static class Library { #region CAB /// /// Creates a new CAB compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static CAB.Compressor CreateCABCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new CAB decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static CAB.Decompressor CreateCABDecompressor(SystemImpl sys) { if (sys == null) sys = SystemImpl.DefaultSystem; if (!SystemImpl.ValidSystem(sys)) return null; return new CAB.DecompressorImpl() { Open = CAB.Implementation.Open, Close = CAB.Implementation.Close, Search = CAB.Implementation.Search, Extract = CAB.Implementation.Extract, Prepend = CAB.Implementation.Prepend, Append = CAB.Implementation.Append, SetParam = CAB.Implementation.Param, LastError = CAB.Implementation.LastError, System = sys, State = null, Error = Error.MSPACK_ERR_OK, SearchBufferSize = 32768, FixMSZip = false, BufferSize = 4096, Salvage = false, }; } /// /// Destroys an existing CAB compressor. /// /// the to destroy public static void DestroyCABCompressor(CAB.Compressor c) { // TODO } /// /// Destroys an existing CAB decompressor. /// /// the to destroy public static void DestroyCABDecompressor(CAB.Decompressor d) { CAB.DecompressorImpl self = d as CAB.DecompressorImpl; if (self != null) { SystemImpl sys = self.System; if (self.State != null) { if (self.State.InputFileHandle != null) sys.Close(self.State.InputFileHandle); CAB.Implementation.FreeDecompressionState(self); sys.Free(self.State); } sys.Free(self); } } #endregion #region CHM /// /// Creates a new CHM compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static CHM.Compressor CreateCHMCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new CHM decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static CHM.Decompressor CreateCHMDecompressor(SystemImpl sys) { if (sys == null) sys = SystemImpl.DefaultSystem; if (!SystemImpl.ValidSystem(sys)) return null; return new CHM.DecompressorImpl() { 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, }; } /// /// Destroys an existing CHM compressor. /// /// the to destroy public static void DestroyCHMCompressor(CHM.Compressor c) { // TODO } /// /// Destroys an existing CHM decompressor. /// /// the to destroy public static void DestroyCHMDecompressor(CHM.Decompressor d) { CHM.DecompressorImpl self = d as CHM.DecompressorImpl; if (self != null) { SystemImpl sys = self.System; if (self.State != null) { if (self.State.InputFileHandle != null) sys.Close(self.State.InputFileHandle); if (self.State.State != null) LZX.Free(self.State.State); sys.Free(self.State); } sys.Free(self); } } #endregion #region LIT /// /// Creates a new LIT compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static LIT.Compressor CreateLITCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new LIT decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static LIT.Decompressor CreateLITDecompressor(SystemImpl sys) { // TODO return null; } /// /// Destroys an existing LIT compressor. /// /// the to destroy public static void DestroyLITCompressor(LIT.Compressor c) { // TODO } /// /// Destroys an existing LIT decompressor. /// /// the to destroy public static void DestroyLITDecompressor(LIT.Decompressor d) { // TODO } #endregion #region HLP /// /// Creates a new HLP compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static HLP.Compressor CreateHLPCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new HLP decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static HLP.Decompressor CreateHLPDecompressor(SystemImpl sys) { // TODO return null; } /// /// Destroys an existing HLP compressor. /// /// the to destroy public static void DestroyHLPCompressor(HLP.Compressor c) { // TODO } /// /// Destroys an existing HLP decompressor. /// /// the to destroy public static void DestroyHLPDecompressor(HLP.Decompressor d) { // TODO } #endregion #region SZDD /// /// Creates a new SZDD compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static SZDD.Compressor CreateSZDDCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new SZDD decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static SZDD.Decompressor CreateSZDDDecompressor(SystemImpl sys) { if (sys == null) sys = SystemImpl.DefaultSystem; if (!SystemImpl.ValidSystem(sys)) return null; return new SZDD.DecompressorImpl() { Open = SZDD.Implementation.Open, Close = SZDD.Implementation.Close, Extract = SZDD.Implementation.Extract, Decompress = SZDD.Implementation.Decompress, LastError = SZDD.Implementation.LastError, System = sys, Error = Error.MSPACK_ERR_OK, }; } /// /// Destroys an existing SZDD compressor. /// /// the to destroy public static void DestroySZDDCompressor(SZDD.Compressor c) { // TODO } /// /// Destroys an existing SZDD decompressor. /// /// the to destroy public static void DestroySZDDDecompressor(SZDD.Decompressor d) { SZDD.DecompressorImpl self = d as SZDD.DecompressorImpl; if (self != null) { SystemImpl sys = self.System; sys.Free(self); } } #endregion #region KWAJ /// /// Creates a new KWAJ compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static KWAJ.Compressor CreateKWAJCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new KWAJ decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static KWAJ.Decompressor CreateKWAJDecompressor(SystemImpl sys) { if (sys == null) sys = SystemImpl.DefaultSystem; if (!SystemImpl.ValidSystem(sys)) return null; return new KWAJ.DecompressorImpl() { Open = KWAJ.Implementation.Open, Close = KWAJ.Implementation.Close, Extract = KWAJ.Implementation.Extract, Decompress = KWAJ.Implementation.Decompress, LastError = KWAJ.Implementation.LastError, System = sys, Error = Error.MSPACK_ERR_OK, }; } /// /// Destroys an existing KWAJ compressor. /// /// the to destroy public static void DestroyKWAJCompressor(KWAJ.Compressor c) { // TODO } /// /// Destroys an existing KWAJ decompressor. /// /// the to destroy public static void DestroyKWAJDecompressor(KWAJ.Decompressor d) { KWAJ.DecompressorImpl self = d as KWAJ.DecompressorImpl; if (self != null) { SystemImpl sys = self.System; sys.Free(self); } } #endregion #region OAB /// /// Creates a new OAB compressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static OAB.Compressor CreateOABCompressor(SystemImpl sys) { // TODO return null; } /// /// Creates a new OAB decompressor. /// /// a custom SystemImpl structure, or null to use the default /// a or null public static OAB.Decompressor CreateOABDecompressor(SystemImpl sys) { if (sys == null) sys = SystemImpl.DefaultSystem; if (!SystemImpl.ValidSystem(sys)) return null; return new OAB.DecompressorImpl() { Decompress = OAB.Implementation.Decompress, DecompressIncremental = OAB.Implementation.DecompressIncremental, SetParam = OAB.Implementation.Param, System = sys, BufferSize = 4096, }; } /// /// Destroys an existing OAB compressor. /// /// the to destroy public static void DestroyOABCompressor(OAB.Compressor c) { // TODO } /// /// Destroys an existing OAB decompressor. /// /// the to destroy public static void DestroyOABDecompressor(OAB.Decompressor d) { OAB.DecompressorImpl self = d as OAB.DecompressorImpl; if (self != null) { SystemImpl sys = self.System; sys.Free(self); } } #endregion } }