More CAB-specific cleanup

This commit is contained in:
Matt Nadareski
2022-05-19 22:19:06 -07:00
parent b6b5dc4efa
commit ddb2be278a
26 changed files with 1633 additions and 2245 deletions

View File

@@ -66,4 +66,8 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="External\cabextract\" />
</ItemGroup>
</Project>

View File

@@ -69,9 +69,9 @@ namespace LibMSPackSharp.CAB
/// If this cabinet is part of a merged cabinet set, the #files and #folders
/// fields are common to all cabinets in the set, and will be identical.
/// </summary>
/// <see cref="Decompressor.Open"/>
/// <see cref="Decompressor.Close"/>
/// <see cref="Decompressor.Search"/>
/// <see cref="Decompressor.Open(string)"/>
/// <see cref="Decompressor.Close(Cabinet)"/>
/// <see cref="Decompressor.Search(string)"/>
public class Cabinet
{
#region Internal

View File

@@ -21,6 +21,6 @@ namespace LibMSPackSharp.CAB
/// </summary>
public class Compressor
{
public int Dummy { get; set; }
public SystemImpl System { get; set; }
}
}

View File

@@ -1,19 +0,0 @@
/* This file is part of libmspack.
* (C) 2003-2018 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.CAB
{
/// <summary>
/// TODO
/// </summary>
public class CompressorImpl : Compressor
{
public SystemImpl System { get; set; }
}
}

View File

@@ -0,0 +1,91 @@
/* This file is part of libmspack.
* (C) 2003-2018 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
*/
/* Cabinet (.CAB) files are a form of file archive. Each cabinet contains
* "folders", which are compressed spans of data. Each cabinet has
* "files", whose metadata is in the cabinet header, but whose actual data
* is stored compressed in one of the "folders". Cabinets can span more
* than one physical file on disk, in which case they are a "cabinet set",
* and usually the last folder of each cabinet extends into the next
* cabinet.
*
* For a complete description of the format, see the MSDN site:
* http://msdn.microsoft.com/en-us/library/bb267310.aspx
*/
/* Notes on compliance with cabinet specification:
*
* One of the main changes between cabextract 0.6 and libmspack's cab
* decompressor is the move from block-oriented decompression to
* stream-oriented decompression.
*
* cabextract would read one data block from disk, decompress it with the
* appropriate method, then write the decompressed data. The CAB
* specification is specifically designed to work like this, as it ensures
* compression matches do not span the maximum decompressed block size
* limit of 32kb.
*
* However, the compression algorithms used are stream oriented, with
* specific hacks added to them to enforce the "individual 32kb blocks"
* rule in CABs. In other file formats, they do not have this limitation.
*
* In order to make more generalised decompressors, libmspack's CAB
* decompressor has moved from being block-oriented to more stream
* oriented. This also makes decompression slightly faster.
*
* However, this leads to incompliance with the CAB specification. The
* CAB controller can no longer ensure each block of input given to the
* decompressors is matched with their output. The "decompressed size" of
* each individual block is thrown away.
*
* Each CAB block is supposed to be seen as individually compressed. This
* means each consecutive data block can have completely different
* "uncompressed" sizes, ranging from 1 to 32768 bytes. However, in
* reality, all data blocks in a folder decompress to exactly 32768 bytes,
* excepting the final block.
*
* Given this situation, the decompression algorithms are designed to
* realign their input bitstreams on 32768 output-byte boundaries, and
* various other special cases have been made. libmspack will not
* correctly decompress LZX or Quantum compressed folders where the blocks
* do not follow this "32768 bytes until last block" pattern. It could be
* implemented if needed, but hopefully this is not necessary -- it has
* not been seen in over 3Gb of CAB archives.
*/
namespace LibMSPackSharp.CAB
{
public static class Constants
{
// CAB data blocks are <= 32768 bytes in uncompressed form.Uncompressed
// blocks have zero growth. MSZIP guarantees that it won't grow above
// uncompressed size by more than 12 bytes.LZX guarantees it won't grow
// more than 6144 bytes.Quantum has no documentation, but the largest
// block seen in the wild is 337 bytes above uncompressed size.
public const int CAB_BLOCKMAX = 32768;
public const int CAB_INPUTMAX = CAB_BLOCKMAX + 6144;
// input buffer needs to be CAB_INPUTMAX + 1 byte to allow for max-sized block
// plus 1 trailer byte added by cabd_sys_read_block() for Quantum alignment.
//
// When MSCABD_PARAM_SALVAGE is set, block size is not checked so can be
// up to 65535 bytes, so max input buffer size needed is 65535 + 1
public const int CAB_INPUTMAX_SALVAGE = 65535;
public const int CAB_INPUTBUF = CAB_INPUTMAX_SALVAGE + 1;
// There are no more than 65535 data blocks per folder, so a folder cannot
// be more than 32768*65535 bytes in length.As files cannot span more than
// one folder, this is also their max offset, length and offset+length limit.
public const int CAB_FOLDERMAX = 65535;
public const int CAB_LENGTHMAX = CAB_BLOCKMAX * CAB_FOLDERMAX;
}
}

View File

@@ -66,12 +66,12 @@ namespace LibMSPackSharp.CAB
/// <summary>
/// Input file handle
/// </summary>
public object InputFileHandle { get; set; }
public DefaultFileImpl InputFileHandle { get; set; }
/// <summary>
/// Output file handle
/// </summary>
public object OutputFileHandle { get; set; }
public DefaultFileImpl OutputFileHandle { get; set; }
/// <summary>
/// Input data consumed
@@ -86,6 +86,6 @@ namespace LibMSPackSharp.CAB
/// <summary>
/// One input block of data
/// </summary>
public byte[] Input { get; set; } = new byte[Implementation.CAB_INPUTBUF];
public byte[] Input { get; set; } = new byte[Constants.CAB_INPUTBUF];
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +0,0 @@
/* This file is part of libmspack.
* (C) 2003-2018 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.CAB
{
public class DecompressorImpl : Decompressor
{
public DecompressState State { get; set; }
public SystemImpl System { get; set; }
public int BufferSize { get; set; }
public int SearchBufferSize { get; set; }
public bool FixMSZip { get; set; }
public bool Salvage { get; set; }
public Error Error { get; set; }
public Error ReadError { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -41,11 +41,11 @@ namespace LibMSPackSharp.CHM
/// <summary>
/// Input file handle
/// </summary>
public object InputFileHandle { get; set; }
public DefaultFileImpl InputFileHandle { get; set; }
/// <summary>
/// Output file handle
/// </summary>
public object OutputFileHandle { get; set; }
public DefaultFileImpl OutputFileHandle { get; set; }
}
}

View File

@@ -152,8 +152,8 @@ namespace LibMSPackSharp.CHM
SystemImpl sys = self.System;
object fh;
if ((fh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_READ)) != null)
DefaultFileImpl fh;
if ((fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ)) != null)
{
chm = new Header();
chm.Filename = filename;
@@ -209,12 +209,11 @@ namespace LibMSPackSharp.CHM
for (fi = chm.Files; fi != null; fi = nfi)
{
nfi = fi.Next;
sys.Free(fi);
}
for (fi = chm.SysFiles; fi != null; fi = nfi)
{
nfi = fi.Next;
sys.Free(fi);
}
// If this CHM was being decompressed, free decompression state
@@ -223,25 +222,8 @@ namespace LibMSPackSharp.CHM
if (self.State.InputFileHandle != null)
sys.Close(self.State.InputFileHandle);
if (self.State.State != null)
LZX.Free(self.State.State);
sys.Free(self.State);
self.State = null;
}
// If this CHM had a chunk cache, free it and contents
if (chm.ChunkCache != null)
{
for (i = 0; i < chm.NumChunks; i++)
{
sys.Free(chm.ChunkCache[i]);
}
sys.Free(chm.ChunkCache);
}
sys.Free(chm);
}
#endregion
@@ -267,10 +249,10 @@ namespace LibMSPackSharp.CHM
/// non-zero, all file entries will also be read. fills out a pre-existing
/// mschmd_header structure, allocates memory for files as necessary
/// </summary>
public static Error ReadHeaders(SystemImpl sys, object fh, Header chm, bool entire)
public static Error ReadHeaders(SystemImpl sys, DefaultFileImpl fh, Header chm, bool entire)
{
uint section, nameLen, x, errors, numChunks;
byte[] buf = new byte[0x54], chunk = null;
byte[] buf = new byte[0x54];
int name, p, end;
DecompressFile fi, link = null;
long offset, length;
@@ -431,8 +413,7 @@ namespace LibMSPackSharp.CHM
numChunks = chm.LastPMGL - x + 1;
if ((chunk = sys.Alloc(sys, (int)chm.ChunkSize)) == null)
return Error.MSPACK_ERR_NOMEMORY;
byte[] chunk = new byte[chm.ChunkSize];
// Read and process all chunks from FirstPMGL to LastPMGL
errors = 0;
@@ -440,10 +421,7 @@ namespace LibMSPackSharp.CHM
{
// Read next chunk
if (sys.Read(fh, chunk, 0, (int)chm.ChunkSize) != (int)chm.ChunkSize)
{
sys.Free(chunk);
return Error.MSPACK_ERR_READ;
}
// Process only directory (PMGL) chunks
if (BitConverter.ToUInt32(chunk, pmgl_Signature) != 0x4C474D50)
@@ -573,7 +551,6 @@ namespace LibMSPackSharp.CHM
}
}
sys.Free(chunk);
return (errors > 0) ? Error.MSPACK_ERR_DATAFORMAT : Error.MSPACK_ERR_OK;
}
@@ -592,7 +569,7 @@ namespace LibMSPackSharp.CHM
{
DecompressorImpl self = d as DecompressorImpl;
SystemImpl sys;
object fh;
DefaultFileImpl fh;
// p and end are initialised to prevent MSVC warning about "potentially"
// uninitialised usage. This is provably untrue, but MS won't fix:
@@ -610,7 +587,7 @@ namespace LibMSPackSharp.CHM
// Clear the results structure
f_ptr = new DecompressFile();
if ((fh = sys.Open(sys, chm.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
if ((fh = sys.Open(chm.Filename, OpenMode.MSPACK_SYS_OPEN_READ)) == null)
return Error.MSPACK_ERR_OPEN;
// Go through PMGI chunk hierarchy to reach PMGL chunk
@@ -722,10 +699,9 @@ namespace LibMSPackSharp.CHM
/// Reads the given chunk into memory, storing it in a chunk cache
/// so it doesn't need to be read from disk more than once
/// </summary>
public static byte[] ReadChunk(DecompressorImpl self, Header chm, object fh, uint chunkNum)
public static byte[] ReadChunk(DecompressorImpl self, Header chm, DefaultFileImpl fh, uint chunkNum)
{
SystemImpl sys = self.System;
byte[] buf;
// Check arguments - most are already checked by chmd_fast_find
if (chunkNum >= chm.NumChunks)
@@ -740,24 +716,18 @@ namespace LibMSPackSharp.CHM
return chm.ChunkCache[chunkNum];
// Need to read chunk - allocate memory for it
if ((buf = sys.Alloc(sys, (int)chm.ChunkSize)) == null)
{
self.Error = Error.MSPACK_ERR_NOMEMORY;
return null;
}
byte[] buf = new byte[chm.ChunkSize];
// Seek to block and read it
if (!sys.Seek(fh, (chm.DirOffset + (chunkNum * chm.ChunkSize)), SeekMode.MSPACK_SYS_SEEK_START))
{
self.Error = Error.MSPACK_ERR_SEEK;
sys.Free(buf);
return null;
}
if (sys.Read(fh, buf, 0, (int)chm.ChunkSize) != (int)chm.ChunkSize)
{
self.Error = Error.MSPACK_ERR_READ;
sys.Free(buf);
return null;
}
@@ -765,7 +735,6 @@ namespace LibMSPackSharp.CHM
if (!((buf[0] == 0x50) && (buf[1] == 0x4D) && (buf[2] == 0x47) && ((buf[3] == 0x4C) || (buf[3] == 0x49))))
{
self.Error = Error.MSPACK_ERR_SEEK;
sys.Free(buf);
return null;
}
@@ -1025,20 +994,17 @@ namespace LibMSPackSharp.CHM
if (self.State.InputFileHandle != null)
sys.Close(self.State.InputFileHandle);
if (self.State.State != null)
LZX.Free(self.State.State);
self.State.Header = chm;
self.State.Offset = 0;
self.State.State = null;
self.State.InputFileHandle = sys.Open(sys, chm.Filename, OpenMode.MSPACK_SYS_OPEN_READ);
self.State.InputFileHandle = sys.Open(chm.Filename, OpenMode.MSPACK_SYS_OPEN_READ);
if (self.State.InputFileHandle == null)
return self.Error = Error.MSPACK_ERR_OPEN;
}
// Open file for output
object fh;
if ((fh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
DefaultFileImpl fh;
if ((fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
return self.Error = Error.MSPACK_ERR_OPEN;
// If file is empty, simply creating it is enough
@@ -1093,10 +1059,7 @@ namespace LibMSPackSharp.CHM
if (self.State.State == null || (file.Offset < self.State.Offset))
{
if (self.State.State != null)
{
LZX.Free(self.State.State);
self.State.State = null;
}
if (InitDecompressor(self, file) != Error.MSPACK_ERR_OK)
break;
@@ -1128,12 +1091,7 @@ namespace LibMSPackSharp.CHM
// If an LZX error occured, the LZX decompressor is now useless
if (self.Error != Error.MSPACK_ERR_OK)
{
if (self.State.State != null)
LZX.Free(self.State.State);
self.State.State = null;
}
break;
}
@@ -1220,7 +1178,6 @@ namespace LibMSPackSharp.CHM
// Check LZXC signature
if (BitConverter.ToUInt32(data, lzxcd_Signature) != 0x43585A4C)
{
sys.Free(data);
return self.Error = Error.MSPACK_ERR_SIGNATURE;
}
@@ -1237,13 +1194,9 @@ namespace LibMSPackSharp.CHM
break;
default:
Console.WriteLine("bad controldata version");
sys.Free(data);
return self.Error = Error.MSPACK_ERR_DATAFORMAT;
}
// Free ControlData
sys.Free(data);
// Find window_bits from window_size
switch (window_size)
{
@@ -1304,7 +1257,7 @@ namespace LibMSPackSharp.CHM
length -= self.State.Offset;
// Initialise LZX stream
self.State.State = LZX.Init(self.State.Sys, self.State.InputFileHandle, self, window_bits, reset_interval / LZX.LZX_FRAME_SIZE, 4096, length, false);
self.State.State = LZX.Init(self.State.Sys, self.State.InputFileHandle, self.State.OutputFileHandle, window_bits, reset_interval / LZX.LZX_FRAME_SIZE, 4096, length, false);
if (self.State.State == null)
self.Error = Error.MSPACK_ERR_NOMEMORY;
@@ -1359,16 +1312,12 @@ namespace LibMSPackSharp.CHM
if (BitConverter.ToUInt32(data, lzxrt_FrameLen) != LZX.LZX_FRAME_SIZE)
{
Console.WriteLine(("bad reset table frame length"));
sys.Free(data);
return false;
}
// Get the uncompressed length of the LZX stream
if ((length_ptr = BitConverter.ToInt64(data, lzxrt_UncompLen)) == 0)
{
sys.Free(data);
return false;
}
uint entrysize = BitConverter.ToUInt32(data, lzxrt_EntrySize);
uint pos = BitConverter.ToUInt32(data, lzxrt_TableOffset) + (entry * entrysize);
@@ -1397,9 +1346,6 @@ namespace LibMSPackSharp.CHM
err = Error.MSPACK_ERR_ARGS;
}
// Free the reset table
sys.Free(data);
// Return success
return (err == Error.MSPACK_ERR_OK);
}
@@ -1442,10 +1388,6 @@ namespace LibMSPackSharp.CHM
// Get the uncompressed length of the LZX stream
length_ptr = BitConverter.ToInt64(data, 0);
sys.Free(data);
if (err != Error.MSPACK_ERR_OK)
return Error.MSPACK_ERR_DATAFORMAT;
if (length_ptr <= 0)
{
Console.WriteLine("output length is invalid");
@@ -1514,14 +1456,12 @@ namespace LibMSPackSharp.CHM
if (sys.Seek(self.State.InputFileHandle, file.Section.Header.Sec0.Offset + file.Offset, SeekMode.MSPACK_SYS_SEEK_START))
{
self.Error = Error.MSPACK_ERR_SEEK;
sys.Free(data);
return null;
}
if (sys.Read(self.State.InputFileHandle, data, 0, len) != len)
{
self.Error = Error.MSPACK_ERR_READ;
sys.Free(data);
return null;
}

View File

@@ -79,59 +79,50 @@ namespace LibMSPackSharp.Compression
uint pos = LZSS_WINDOW_SIZE - (uint)((mode == LZSSMode.LZSS_MODE_QBASIC) ? 18 : 16);
uint invert = (uint)((mode == LZSSMode.LZSS_MODE_MSHELP) ? ~0 : 0);
int iPtr = 0, iEnd = 0;
int i_ptr = 0, i_end = 0;
// Loop forever; exit condition is in ENSURE_BYTES macro
for (; ; )
{
//ENSURE_BYTES
if (iPtr >= iEnd)
if (i_ptr >= i_end)
{
read = system.Read(input, window, inbuf, inputBufferSize);
if (read <= 0)
{
system.Free(window);
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
}
iPtr = 0;
iEnd = read;
i_ptr = 0;
i_end = read;
}
c = window[iPtr++] ^ invert;
c = window[i_ptr++] ^ invert;
for (i = 0x01; (i & 0xFF) != 0; i <<= 1)
{
if (c != 0 & i != 0)
{
// Literal
//ENSURE_BYTES
if (iPtr >= iEnd)
if (i_ptr >= i_end)
{
read = system.Read(input, window, inbuf, inputBufferSize);
if (read <= 0)
{
system.Free(window);
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
}
iPtr = 0;
iEnd = read;
i_ptr = 0;
i_end = read;
}
window[pos] = window[iPtr++];
window[pos] = window[i_ptr++];
//ENSURE_BYTES
if (iPtr >= iEnd)
if (i_ptr >= i_end)
{
read = system.Read(input, window, inbuf, inputBufferSize);
if (read <= 0)
{
system.Free(window);
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
}
iPtr = 0;
iEnd = read;
i_ptr = 0;
i_end = read;
}
pos++; pos &= LZSS_WINDOW_SIZE - 1;
@@ -140,47 +131,38 @@ namespace LibMSPackSharp.Compression
{
// Match
//ENSURE_BYTES
if (iPtr >= iEnd)
if (i_ptr >= i_end)
{
read = system.Read(input, window, inbuf, inputBufferSize);
if (read <= 0)
{
system.Free(window);
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
}
iPtr = 0;
iEnd = read;
i_ptr = 0;
i_end = read;
}
mpos = window[iPtr++];
mpos = window[i_ptr++];
//ENSURE_BYTES
if (iPtr >= iEnd)
if (i_ptr >= i_end)
{
read = system.Read(input, window, inbuf, inputBufferSize);
if (read <= 0)
{
system.Free(window);
return (read < 0) ? Error.MSPACK_ERR_READ : Error.MSPACK_ERR_OK;
}
iPtr = 0;
iEnd = read;
i_ptr = 0;
i_end = read;
}
mpos |= (uint)(window[iPtr] & 0xF0) << 4;
len = (uint)(window[iPtr++] & 0x0F) + 3;
mpos |= (uint)(window[i_ptr] & 0xF0) << 4;
len = (uint)(window[i_ptr++] & 0x0F) + 3;
while (len-- != 0)
{
window[pos] = window[mpos];
//WRITE_BYTE;
if (system.Write(output, window, (int)pos, 1) != 1)
{
system.Free(window);
return Error.MSPACK_ERR_WRITE;
}
pos++;
pos &= LZSS_WINDOW_SIZE - 1;

View File

@@ -267,7 +267,7 @@ namespace LibMSPackSharp.Compression
/// a pointer to an initialised LZXDStream structure, or null if
/// there was not enough memory or parameters to the function were wrong.
/// </returns>
public static LZXDStream Init(SystemImpl system, object input, object output, int windowBits, int resetInterval, int inputBufferSize, long outputLength, bool isDelta)
public static LZXDStream Init(SystemImpl system, DefaultFileImpl input, DefaultFileImpl output, int windowBits, int resetInterval, int inputBufferSize, long outputLength, bool isDelta)
{
uint windowSize = (uint)(1 << windowBits);
@@ -984,7 +984,7 @@ namespace LibMSPackSharp.Compression
if (i > this_run)
i = this_run;
lzx.Sys.Copy(lzx.InputBuffer, i_ptr, window, rundest, i);
Array.Copy(lzx.InputBuffer, i_ptr, window, rundest, i);
rundest += i;
i_ptr += i;
this_run -= i;
@@ -1044,7 +1044,7 @@ namespace LibMSPackSharp.Compression
int abs_off, rel_off;
lzx.OutputPointer = data;
lzx.Sys.Copy(lzx.Window, (int)lzx.FramePosition, lzx.e8_buf, data, (int)frame_size);
Array.Copy(lzx.Window, (int)lzx.FramePosition, lzx.e8_buf, data, (int)frame_size);
while (data < dataend)
{
@@ -1112,23 +1112,6 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
/// <summary>
/// Frees all state associated with an LZX data stream. This will call
/// system.free() using the system pointer given in lzxd_init().
/// </summary>
/// <param name="lzx">LZX decompression state to free.</param>
public static void Free(object s)
{
LZXDStream lzx = s as LZXDStream;
if (lzx != null)
{
SystemImpl sys = lzx.Sys;
sys.Free(lzx.InputBuffer);
sys.Free(lzx.Window);
sys.Free(lzx);
}
}
private static Error ReadLens(LZXDStream lzx, byte[] lens, uint first, uint last)
{
// Bit buffer and huffman symbol decode variables

View File

@@ -93,7 +93,7 @@ namespace LibMSPackSharp.Compression
/// and 'holes' left will be filled with zero bytes. This allows at least
/// a partial recovery of erroneous data.
/// </summary>
public static MSZIPDStream Init(SystemImpl system, object input, object output, int input_buffer_size, bool repair_mode)
public static MSZIPDStream Init(SystemImpl system, DefaultFileImpl input, DefaultFileImpl output, int input_buffer_size, bool repair_mode)
{
if (system == null)
return null;
@@ -329,22 +329,6 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
/// <summary>
/// Frees all stream associated with an MS-ZIP data stream
///
/// - calls system.free() using the system pointer given in mszipd_init()
/// </summary>
public static void Free(object s)
{
MSZIPDStream zip = s as MSZIPDStream;
if (zip != null)
{
SystemImpl sys = zip.Sys;
sys.Free(zip.InputBuffer);
sys.Free(zip);
}
}
private static InflateErrorCode ReadLens(MSZIPDStream zip)
{
// For the bit buffer and huffman decoding
@@ -467,14 +451,14 @@ namespace LibMSPackSharp.Compression
// Copy LITERAL code lengths and clear any remaining
i = lit_codes;
zip.Sys.Copy(lens, 0, zip.LITERAL_len, 0, i);
Array.Copy(lens, 0, zip.LITERAL_len, 0, i);
while (i < MSZIP_LITERAL_MAXSYMBOLS)
{
zip.LITERAL_len[i++] = 0;
}
i = dist_codes;
zip.Sys.Copy(lens, lit_codes, zip.DISTANCE_len, 0, i);
Array.Copy(lens, lit_codes, zip.DISTANCE_len, 0, i);
while (i < MSZIP_DISTANCE_MAXSYMBOLS)
{
zip.DISTANCE_len[i++] = 0;
@@ -561,7 +545,7 @@ namespace LibMSPackSharp.Compression
if (this_run > (MSZIP_FRAME_SIZE - zip.WindowPosition))
this_run = (int)(MSZIP_FRAME_SIZE - zip.WindowPosition);
zip.Sys.Copy(zip.InputBuffer, i_ptr, zip.Window, (int)zip.WindowPosition, this_run);
Array.Copy(zip.InputBuffer, i_ptr, zip.Window, (int)zip.WindowPosition, this_run);
zip.WindowPosition += (uint)this_run;
i_ptr += this_run;
length -= this_run;

View File

@@ -0,0 +1,56 @@
/* This file is part of libmspack.
* (C) 2003-2018 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.Compression
{
public class None
{
public static NoneState Init(SystemImpl sys, DefaultFileImpl input, DefaultFileImpl output, int bufsize)
{
NoneState state = new NoneState();
byte[] buf = new byte[bufsize];
if (state != null && buf != null)
{
state.Sys = sys;
state.Input = input;
state.Output = output;
state.Buffer = buf;
state.BufferSize = bufsize;
}
else
{
state = null;
}
return state;
}
public static Error Decompress(object s, long bytes)
{
NoneState state = (NoneState)s;
if (state == null)
return Error.MSPACK_ERR_ARGS;
int run;
while (bytes > 0)
{
run = (bytes > state.BufferSize) ? state.BufferSize : (int)bytes;
if (state.Sys.Read(state.Input, state.Buffer, 0, run) != run)
return Error.MSPACK_ERR_READ;
if (state.Sys.Write(state.Output, state.Buffer, 0, run) != run)
return Error.MSPACK_ERR_WRITE;
bytes -= run;
}
return Error.MSPACK_ERR_OK;
}
}
}

View File

@@ -7,7 +7,7 @@
* For further details, see the file COPYING.LIB distributed with libmspack
*/
namespace LibMSPackSharp.CAB
namespace LibMSPackSharp.Compression
{
/// <summary>
/// The "not compressed" method decompressor

View File

@@ -91,7 +91,7 @@ namespace LibMSPackSharp.Compression
/// - window_bits is the size of the Quantum window, from 1Kb(10) to 2Mb(21).
/// - input_buffer_size is the number of bytes to use to store bitstream data.
/// </summary>
public static QTMDStream Init(SystemImpl system, object input, object output, int window_bits, int input_buffer_size)
public static QTMDStream Init(SystemImpl system, DefaultFileImpl input, DefaultFileImpl output, int window_bits, int input_buffer_size)
{
uint window_size = (uint)(1 << window_bits);
@@ -474,22 +474,6 @@ namespace LibMSPackSharp.Compression
return Error.MSPACK_ERR_OK;
}
/// <summary>
/// Frees all state associated with a Quantum data stream
/// - calls system.free() using the system pointer given in qtmd_init()
/// </summary>
public static void Free(object s)
{
QTMDStream qtm = s as QTMDStream;
if (qtm != null)
{
SystemImpl sys = qtm.Sys;
sys.Free(qtm.Window);
sys.Free(qtm.InputBuffer);
sys.Free(qtm);
}
}
/// <summary>
/// Arithmetic decoder:
///

View File

@@ -11,6 +11,6 @@ namespace LibMSPackSharp.KWAJ
{
public class HeaderImpl : Header
{
public object FileHandle { get; set; }
public DefaultFileImpl FileHandle { get; set; }
}
}

View File

@@ -76,7 +76,7 @@ namespace LibMSPackSharp.KWAJ
SystemImpl sys = self.System;
object fh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_READ);
DefaultFileImpl fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
HeaderImpl hdr = new HeaderImpl();
if (fh != null && hdr != null)
{
@@ -96,7 +96,6 @@ namespace LibMSPackSharp.KWAJ
if (fh != null)
sys.Close(fh);
sys.Free(hdr);
hdr = null;
}
@@ -121,9 +120,6 @@ namespace LibMSPackSharp.KWAJ
// Close the file handle associated
self.System.Close(hdr_p.FileHandle);
// Free the memory associated
self.System.Free(hdr);
self.Error = Error.MSPACK_ERR_OK;
}
@@ -134,7 +130,7 @@ namespace LibMSPackSharp.KWAJ
/// <summary>
/// Reads the headers of a KWAJ format file
/// </summary>
public static Error ReadHeaders(SystemImpl sys, object fh, Header hdr)
public static Error ReadHeaders(SystemImpl sys, DefaultFileImpl fh, Header hdr)
{
int i;
@@ -287,7 +283,7 @@ namespace LibMSPackSharp.KWAJ
return self.Error = Error.MSPACK_ERR_ARGS;
SystemImpl sys = self.System;
object fh = (hdr as HeaderImpl)?.FileHandle;
DefaultFileImpl fh = (hdr as HeaderImpl)?.FileHandle;
if (fh == null)
return Error.MSPACK_ERR_ARGS;
@@ -296,8 +292,8 @@ namespace LibMSPackSharp.KWAJ
return self.Error = Error.MSPACK_ERR_SEEK;
// Open file for output
object outfh;
if ((outfh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
DefaultFileImpl outfh;
if ((outfh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
return self.Error = Error.MSPACK_ERR_OPEN;
self.Error = Error.MSPACK_ERR_OK;
@@ -329,8 +325,6 @@ namespace LibMSPackSharp.KWAJ
if (read < 0)
self.Error = Error.MSPACK_ERR_READ;
sys.Free(buf);
}
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_SZDD)
{
@@ -340,13 +334,11 @@ namespace LibMSPackSharp.KWAJ
{
InternalStream lzh = LZHInit(sys, fh, outfh);
self.Error = (lzh != null) ? LZHDecompress(lzh) : Error.MSPACK_ERR_NOMEMORY;
LZHFree(lzh);
}
else if (hdr.CompressionType == CompressionType.MSKWAJ_COMP_MSZIP)
{
MSZIPDStream zip = MSZIP.Init(sys, fh, outfh, KWAJ_INPUT_SIZE, false);
self.Error = (zip != null) ? MSZIP.DecompressKWAJ(zip) : Error.MSPACK_ERR_NOMEMORY;
MSZIP.Free(zip);
}
else
{
@@ -588,15 +580,6 @@ namespace LibMSPackSharp.KWAJ
return Error.MSPACK_ERR_OK;
}
private static void LZHFree(InternalStream lzh)
{
if (lzh == null || lzh.Sys == null)
return;
SystemImpl sys = lzh.Sys;
sys.Free(lzh);
}
public static Error LZHReadLens(InternalStream lzh, uint type, uint numsyms, byte[] lens)
{
uint bit_buffer = 0, bits_left = 0;

View File

@@ -129,8 +129,6 @@
* use of extract(), and any other methods, with the mutex
*/
using LibMSPackSharp.Compression;
namespace LibMSPackSharp
{
public static class Library
@@ -160,16 +158,8 @@ namespace LibMSPackSharp
if (!SystemImpl.ValidSystem(sys))
return null;
return new CAB.DecompressorImpl()
return new CAB.Decompressor()
{
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,
@@ -184,8 +174,8 @@ namespace LibMSPackSharp
/// <summary>
/// Destroys an existing CAB compressor.
/// </summary>
/// <param name="c">the <see cref="CAB.Compressor"/> to destroy</param>
public static void DestroyCABCompressor(CAB.Compressor c)
/// <param name="self">the <see cref="CAB.Compressor"/> to destroy</param>
public static void DestroyCABCompressor(CAB.Compressor self)
{
// TODO
}
@@ -193,10 +183,9 @@ namespace LibMSPackSharp
/// <summary>
/// Destroys an existing CAB decompressor.
/// </summary>
/// <param name="d">the <see cref="CAB.Decompressor"/> to destroy</param>
public static void DestroyCABDecompressor(CAB.Decompressor d)
/// <param name="self">the <see cref="CAB.Decompressor"/> to destroy</param>
public static void DestroyCABDecompressor(CAB.Decompressor self)
{
CAB.DecompressorImpl self = d as CAB.DecompressorImpl;
if (self != null)
{
SystemImpl sys = self.System;
@@ -205,11 +194,8 @@ namespace LibMSPackSharp
if (self.State.InputFileHandle != null)
sys.Close(self.State.InputFileHandle);
CAB.Implementation.FreeDecompressionState(self);
sys.Free(self.State);
self.FreeDecompressionState();
}
sys.Free(self);
}
}
@@ -277,13 +263,7 @@ namespace LibMSPackSharp
{
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);
}
}
@@ -427,15 +407,7 @@ namespace LibMSPackSharp
/// Destroys an existing SZDD decompressor.
/// </summary>
/// <param name="d">the <see cref="SZDD.Decompressor"/> to destroy</param>
public static void DestroySZDDDecompressor(SZDD.Decompressor d)
{
SZDD.DecompressorImpl self = d as SZDD.DecompressorImpl;
if (self != null)
{
SystemImpl sys = self.System;
sys.Free(self);
}
}
public static void DestroySZDDDecompressor(SZDD.Decompressor d) { }
#endregion
@@ -489,15 +461,7 @@ namespace LibMSPackSharp
/// Destroys an existing KWAJ decompressor.
/// </summary>
/// <param name="d">the <see cref="KWAJ.Decompressor"/> to destroy</param>
public static void DestroyKWAJDecompressor(KWAJ.Decompressor d)
{
KWAJ.DecompressorImpl self = d as KWAJ.DecompressorImpl;
if (self != null)
{
SystemImpl sys = self.System;
sys.Free(self);
}
}
public static void DestroyKWAJDecompressor(KWAJ.Decompressor d) { }
#endregion
@@ -549,15 +513,7 @@ namespace LibMSPackSharp
/// Destroys an existing OAB decompressor.
/// </summary>
/// <param name="d">the <see cref="OAB.Decompressor"/> to destroy</param>
public static void DestroyOABDecompressor(OAB.Decompressor d)
{
OAB.DecompressorImpl self = d as OAB.DecompressorImpl;
if (self != null)
{
SystemImpl sys = self.System;
sys.Free(self);
}
}
public static void DestroyOABDecompressor(OAB.Decompressor d) { }
#endregion
}

View File

@@ -118,12 +118,10 @@ namespace LibMSPackSharp.OAB
SystemImpl sys = self.System;
object infh = sys.Open(sys, input, OpenMode.MSPACK_SYS_OPEN_READ);
DefaultFileImpl infh = sys.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
if (infh == null)
{
ret = Error.MSPACK_ERR_OPEN;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -133,8 +131,6 @@ namespace LibMSPackSharp.OAB
if (sys.Read(infh, hdrbuf, 0, oabhead_SIZEOF) != oabhead_SIZEOF)
{
ret = Error.MSPACK_ERR_READ;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -145,8 +141,6 @@ namespace LibMSPackSharp.OAB
BitConverter.ToUInt32(hdrbuf, oabhead_VersionLo) != 1)
{
ret = Error.MSPACK_ERR_SIGNATURE;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -156,12 +150,10 @@ namespace LibMSPackSharp.OAB
uint block_max = BitConverter.ToUInt32(hdrbuf, oabhead_BlockMax);
uint target_size = BitConverter.ToUInt32(hdrbuf, oabhead_TargetSize);
object outfh = sys.Open(sys, output, OpenMode.MSPACK_SYS_OPEN_WRITE);
DefaultFileImpl outfh = sys.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
if (outfh == null)
{
ret = Error.MSPACK_ERR_OPEN;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
@@ -189,14 +181,11 @@ namespace LibMSPackSharp.OAB
if (sys.Read(infh, buf, 0, oabblk_SIZEOF) != oabblk_SIZEOF)
{
ret = Error.MSPACK_ERR_READ;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
@@ -208,14 +197,11 @@ namespace LibMSPackSharp.OAB
if (blk_dsize > block_max || blk_dsize > target_size || blk_flags > 1)
{
ret = Error.MSPACK_ERR_DATAFORMAT;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
@@ -225,28 +211,22 @@ namespace LibMSPackSharp.OAB
if (blk_dsize != blk_csize)
{
ret = Error.MSPACK_ERR_DATAFORMAT;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
ret = CopyFileHandle(sys, infh, outfh, (int)blk_dsize, buf, self.BufferSize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
}
@@ -272,53 +252,42 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
ret = LZX.Decompress(lzx, blk_dsize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
LZX.Free(lzx);
lzx = null;
// Consume any trailing padding bytes before the next block
ret = CopyFileHandle(sys, infh, null, in_ofh.Available, buf, self.BufferSize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
if (out_ofh.CRC != blk_crc)
{
ret = Error.MSPACK_ERR_CHECKSUM;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
}
@@ -326,14 +295,11 @@ namespace LibMSPackSharp.OAB
target_size -= blk_dsize;
}
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
@@ -355,12 +321,10 @@ namespace LibMSPackSharp.OAB
SystemImpl sys = self.System;
object infh = sys.Open(sys, input, OpenMode.MSPACK_SYS_OPEN_READ);
DefaultFileImpl infh = sys.Open(input, OpenMode.MSPACK_SYS_OPEN_READ);
if (infh == null)
{
ret = Error.MSPACK_ERR_OPEN;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -370,8 +334,6 @@ namespace LibMSPackSharp.OAB
if (sys.Read(infh, hdrbuf, 0, patchhead_SIZEOF) != patchhead_SIZEOF)
{
ret = Error.MSPACK_ERR_READ;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -382,8 +344,6 @@ namespace LibMSPackSharp.OAB
BitConverter.ToUInt32(hdrbuf, patchhead_VersionLo) != 2)
{
ret = Error.MSPACK_ERR_SIGNATURE;
if (lzx != null)
LZX.Free(lzx);
if (infh != null)
sys.Close(infh);
@@ -397,12 +357,10 @@ namespace LibMSPackSharp.OAB
if (block_max < patchblk_SIZEOF)
block_max = patchblk_SIZEOF;
object basefh = sys.Open(sys, basePath, OpenMode.MSPACK_SYS_OPEN_READ);
DefaultFileImpl basefh = sys.Open(basePath, OpenMode.MSPACK_SYS_OPEN_READ);
if (basefh == null)
{
ret = Error.MSPACK_ERR_OPEN;
if (lzx != null)
LZX.Free(lzx);
if (basefh != null)
sys.Close(basefh);
if (infh != null)
@@ -411,12 +369,10 @@ namespace LibMSPackSharp.OAB
return ret;
}
object outfh = sys.Open(sys, output, OpenMode.MSPACK_SYS_OPEN_WRITE);
DefaultFileImpl outfh = sys.Open(output, OpenMode.MSPACK_SYS_OPEN_WRITE);
if (outfh == null)
{
ret = Error.MSPACK_ERR_OPEN;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -446,8 +402,6 @@ namespace LibMSPackSharp.OAB
if (sys.Read(infh, buf, 0, patchblk_SIZEOF) != patchblk_SIZEOF)
{
ret = Error.MSPACK_ERR_READ;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -455,7 +409,6 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
@@ -467,8 +420,6 @@ namespace LibMSPackSharp.OAB
if (blk_dsize > block_max || blk_dsize > target_size || blk_ssize > block_max)
{
ret = Error.MSPACK_ERR_DATAFORMAT;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -476,7 +427,6 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
@@ -501,15 +451,12 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
ret = LZX.SetReferenceData(lzx, sys, basefh, blk_ssize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -517,15 +464,12 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
ret = LZX.Decompress(lzx, blk_dsize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -533,19 +477,15 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
LZX.Free(lzx);
lzx = null;
// Consume any trailing padding bytes before the next block
ret = CopyFileHandle(sys, infh, null, in_ofh.Available, buf, self.BufferSize);
if (ret != Error.MSPACK_ERR_OK)
{
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -553,15 +493,12 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
if (out_ofh.CRC != blk_crc)
{
ret = Error.MSPACK_ERR_CHECKSUM;
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -569,15 +506,12 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}
target_size -= blk_dsize;
}
if (lzx != null)
LZX.Free(lzx);
if (outfh != null)
sys.Close(outfh);
if (basefh != null)
@@ -585,7 +519,6 @@ namespace LibMSPackSharp.OAB
if (infh != null)
sys.Close(infh);
sys.Free(buf);
return ret;
}

View File

@@ -16,7 +16,7 @@
namespace LibMSPackSharp.OAB
{
public class InternalFile
public class InternalFile : DefaultFileImpl
{
public SystemImpl OrigSys { get; set; }

View File

@@ -11,6 +11,6 @@ namespace LibMSPackSharp.SZDD
{
public class HeaderImpl : Header
{
public object FileHandle { get; set; }
public DefaultFileImpl FileHandle { get; set; }
}
}

View File

@@ -33,7 +33,7 @@ namespace LibMSPackSharp.SZDD
SystemImpl sys = self.System;
object fh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_READ);
DefaultFileImpl fh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_READ);
HeaderImpl hdr = new HeaderImpl();
if (fh != null && hdr != null)
{
@@ -53,7 +53,6 @@ namespace LibMSPackSharp.SZDD
if (fh != null)
sys.Close(fh);
sys.Free(hdr);
hdr = null;
}
@@ -78,9 +77,6 @@ namespace LibMSPackSharp.SZDD
// Close the file handle associated
self.System.Close(hdr_p.FileHandle);
// Free the memory associated
self.System.Free(hdr);
self.Error = Error.MSPACK_ERR_OK;
}
@@ -158,7 +154,7 @@ namespace LibMSPackSharp.SZDD
SystemImpl sys = self.System;
object fh = (hdr as HeaderImpl)?.FileHandle;
DefaultFileImpl fh = (hdr as HeaderImpl)?.FileHandle;
if (fh == null)
return Error.MSPACK_ERR_ARGS;
@@ -168,8 +164,8 @@ namespace LibMSPackSharp.SZDD
return self.Error = Error.MSPACK_ERR_SEEK;
// Open file for output
object outfh;
if ((outfh = sys.Open(sys, filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
DefaultFileImpl outfh;
if ((outfh = sys.Open(filename, OpenMode.MSPACK_SYS_OPEN_WRITE)) == null)
return self.Error = Error.MSPACK_ERR_OPEN;
// Decompress the data

View File

@@ -43,13 +43,6 @@ namespace LibMSPackSharp
/// <summary>
/// Opens a file for reading, writing, appending or updating.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the SystemImpl
/// structure whose Open() method is being called. If
/// this pointer is required by Close(), Read(), Write(),
/// Seek() or Tell(), it should be stored in the result
/// structure at this time.
/// </param>
/// <param name="filename">
/// the file to be opened. It is passed directly from the
/// library caller without being modified, so it is up to
@@ -57,21 +50,55 @@ namespace LibMSPackSharp
/// </param>
/// <param name="mode">One of the <see cref="OpenMode"/> values</param>
/// <returns>
/// a pointer to a mspack_file structure. This structure officially
/// A pointer to a DefaultFileImpl structure. This structure officially
/// contains no members, its true contents are up to the
/// SystemImpl implementor. It should contain whatever is needed
/// for other SystemImpl methods to operate. Returning the null
/// pointer indicates an error condition.
/// </returns>
public Func<SystemImpl, string, OpenMode, object> Open;
public DefaultFileImpl Open(string filename, OpenMode mode)
{
try
{
DefaultFileImpl fileHandle = new DefaultFileImpl();
switch (mode)
{
case OpenMode.MSPACK_SYS_OPEN_READ:
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_WRITE:
fileHandle.FileHandle = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_UPDATE:
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_APPEND:
fileHandle.FileHandle = File.Open(filename, FileMode.Append, FileAccess.ReadWrite, FileShare.ReadWrite);
break;
default:
return null;
}
return fileHandle;
}
catch (Exception ex)
{
Message(null, $"Could not open {filename}: {ex}");
return null;
}
}
/// <summary>
/// Closes a previously opened file. If any memory was allocated for this
/// particular file handle, it should be freed at this time.
/// </summary>
/// <param name="file">the file to close</param>
/// <see cref="Open"/>
public Action<object> Close;
/// <see cref="Open(string, OpenMode)"/>
public void Close(DefaultFileImpl file) => file?.FileHandle?.Close();
/// <summary>
/// Reads a given number of bytes from an open file.
@@ -86,7 +113,7 @@ namespace LibMSPackSharp
/// reads and assumes short reads are due to EOF, so you should
/// avoid returning short reads because of transient errors.
/// </returns>
/// <see cref="Open"/>
/// <see cref="Open(string, OpenMode)"/>
/// <see cref="Write"/>
public Func<object, byte[], int, int, int> Read;
@@ -103,7 +130,7 @@ namespace LibMSPackSharp
/// bytes were written than requested are considered by the library
/// to be an error.
/// </returns>
/// <see cref="Open"/>
/// <see cref="Open(string, OpenMode)"/>
/// <see cref="Read"/>
public Func<object, byte[], int, int, int> Write;
@@ -124,18 +151,40 @@ namespace LibMSPackSharp
/// <param name="offset">an offset to seek, measured in bytes</param>
/// <param name="mode">One of the <see cref="SeekMode"/> values</param>
/// <returns>zero for success, non-zero for an error</returns>
/// <see cref="Open"/>
/// <see cref="Tell"/>
public Func<object, long, SeekMode, bool> Seek;
/// <see cref="Open(string, OpenMode)"/>
/// <see cref="Tell(DefaultFileImpl)"/>
public bool Seek(DefaultFileImpl self, long offset, SeekMode mode)
{
if (self == null)
return false;
switch (mode)
{
case SeekMode.MSPACK_SYS_SEEK_START:
try { self.FileHandle.Seek(offset, SeekOrigin.Begin); return true; }
catch { return false; }
case SeekMode.MSPACK_SYS_SEEK_CUR:
try { self.FileHandle.Seek(offset, SeekOrigin.Current); return true; }
catch { return false; }
case SeekMode.MSPACK_SYS_SEEK_END:
try { self.FileHandle.Seek(offset, SeekOrigin.End); return true; }
catch { return false; }
default:
return false;
}
}
/// <summary>
/// Returns the current file position (in bytes) of the given file.
/// </summary>
/// <param name="file">the file whose file position is wanted</param>
/// <returns>the current file position of the file</returns>
/// <see cref="Open"/>
/// <see cref="Seek"/>
public Func<object, long> Tell;
/// <see cref="Open(string, OpenMode)"/>
/// <see cref="Seek(DefaultFileImpl, long, SeekMode)"/>
public long Tell(DefaultFileImpl self) => (self != null ? self.FileHandle.Position : 0);
/// <summary>
/// Used to send messages from the library to the user.
@@ -150,80 +199,32 @@ namespace LibMSPackSharp
/// a specific file.
/// </param>
/// <param name="format">a printf() style format string. It does NOT include a trailing newline.</param>
/// <see cref="Open"/>
public Action<object, string> Message;
/// <see cref="Open(string, OpenMode)"/>
public void Message(DefaultFileImpl file, string format)
{
if (file != null)
Console.Error.Write($"{file.Name}: ");
/// <summary>
/// Allocates memory.
/// </summary>
/// <param name="self">
/// a self-referential pointer to the SystemImpl
/// structure whose Alloc() method is being called.
/// </param>
/// <param name="bytes">the number of bytes to allocate</param>
/// <returns>
/// a pointer to the requested number of bytes, or null if
/// not enough memory is available
/// </returns>
/// <see cref="Free"/>
public Func<SystemImpl, int, byte[]> Alloc;
/// <summary>
/// Frees memory.
/// </summary>
/// <param name="ptr">the memory to be freed. null is accepted and ignored.</param>
/// <see cref="Alloc"/>
public Action<object> Free;
/// <summary>
/// Copies from one region of memory to another.
///
/// The regions of memory are guaranteed not to overlap, are usually less
/// than 256 bytes, and may not be aligned. Please note that the source
/// parameter comes before the destination parameter, unlike the standard
/// C function memcpy().
/// </summary>
/// <param name="src">the region of memory to copy from</param>
/// <param name="dest">the region of memory to copy to</param>
/// <param name="bytes">the size of the memory region, in bytes</param>
public Action<byte[], int, byte[], int, int> Copy;
/// <summary>
/// A null pointer to mark the end of SystemImpl. It must equal null.
///
/// Should the SystemImpl structure extend in the future, this null
/// will be seen, rather than have an invalid method pointer called.
/// </summary>
public readonly object NullPtr = null;
Console.Error.Write($"{format}\n");
}
#region Helpers
/// <summary>
/// Returns the length of a file opened for reading
/// </summary>
public static Error GetFileLength(SystemImpl system, object file, out long length)
public Error GetFileLength(DefaultFileImpl file, out long length)
{
length = 0;
long current;
if (system == null || file == null)
return Error.MSPACK_ERR_OPEN;
// Get current offset
current = system.Tell(file);
// Seek to end of file
if (!system.Seek(file, 0, SeekMode.MSPACK_SYS_SEEK_END))
try
{
length = file?.FileHandle?.Length ?? 0;
return Error.MSPACK_ERR_OK;
}
catch
{
length = 0;
return Error.MSPACK_ERR_SEEK;
// Get offset of end of file
length = system.Tell(file);
// Seek back to original offset
if (!system.Seek(file, current, SeekMode.MSPACK_SYS_SEEK_START))
return Error.MSPACK_ERR_SEEK;
return Error.MSPACK_ERR_OK;
}
}
/// <summary>
@@ -231,10 +232,7 @@ namespace LibMSPackSharp
/// </summary>
public static bool ValidSystem(SystemImpl sys)
{
return (sys != null) && (sys.Open != null) && (sys.Close != null) &&
(sys.Read != null) && (sys.Write != null) && (sys.Seek != null) &&
(sys.Tell != null) && (sys.Message != null) && (sys.Alloc != null) &&
(sys.Free != null) && (sys.Copy != null) && (sys.NullPtr == null);
return (sys != null) && (sys.Read != null) && (sys.Write != null);
}
#endregion
@@ -243,53 +241,10 @@ namespace LibMSPackSharp
public static SystemImpl DefaultSystem => new SystemImpl()
{
Open = DefaultOpen,
Close = DefaultClose,
Read = DefaultRead,
Write = DefaultWrite,
Seek = DefaultSeek,
Tell = DefaultTell,
Message = DefaultMessage,
Alloc = DefaultAlloc,
Free = DefaultFree,
Copy = DefaultCopy,
};
private static object DefaultOpen(SystemImpl self, string filename, OpenMode mode)
{
DefaultFileImpl fileHandle = new DefaultFileImpl();
switch (mode)
{
case OpenMode.MSPACK_SYS_OPEN_READ:
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_WRITE:
fileHandle.FileHandle = File.Open(filename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_UPDATE:
fileHandle.FileHandle = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
break;
case OpenMode.MSPACK_SYS_OPEN_APPEND:
fileHandle.FileHandle = File.Open(filename, FileMode.Append, FileAccess.ReadWrite, FileShare.ReadWrite);
break;
default:
return null;
}
return fileHandle;
}
private static void DefaultClose(object file)
{
DefaultFileImpl self = file as DefaultFileImpl;
if (self != null)
self.FileHandle.Close();
}
private static int DefaultRead(object file, byte[] buffer, int pointer, int bytes)
{
DefaultFileImpl self = file as DefaultFileImpl;
@@ -314,62 +269,6 @@ namespace LibMSPackSharp
return -1;
}
private static bool DefaultSeek(object file, long offset, SeekMode mode)
{
DefaultFileImpl self = file as DefaultFileImpl;
if (self != null)
{
switch (mode)
{
case SeekMode.MSPACK_SYS_SEEK_START:
try { self.FileHandle.Seek(offset, SeekOrigin.Begin); return true; }
catch { return false; }
case SeekMode.MSPACK_SYS_SEEK_CUR:
try { self.FileHandle.Seek(offset, SeekOrigin.Current); return true; }
catch { return false; }
case SeekMode.MSPACK_SYS_SEEK_END:
try { self.FileHandle.Seek(offset, SeekOrigin.End); return true; }
catch { return false; }
default:
return false;
}
}
return false;
}
private static long DefaultTell(object file)
{
DefaultFileImpl self = file as DefaultFileImpl;
return (self != null ? (int)self.FileHandle.Position : 0);
}
private static void DefaultMessage(object file, string format)
{
if (file != null)
Console.Error.Write($"{(file as DefaultFileImpl)?.Name}: ");
Console.Error.Write($"{format}\n");
}
private static byte[] DefaultAlloc(SystemImpl self, int bytes)
{
return new byte[bytes];
}
private static void DefaultFree(object buffer)
{
buffer = null;
}
private static void DefaultCopy(byte[] src, int srcPtr, byte[] dest, int destPtr, int bytes)
{
Array.Copy(src, srcPtr, dest, destPtr, bytes);
}
#endregion
}
}

View File

@@ -3,7 +3,7 @@ using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Interfaces;
using BurnOutSharp.Tools;
using WixToolset.Dtf.Compression.Cab;
using LibMSPackSharp;
namespace BurnOutSharp.FileType
{
@@ -41,20 +41,32 @@ namespace BurnOutSharp.FileType
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
CabInfo cabfile = new CabInfo(file);
foreach (var sub in cabfile.GetFiles())
var decompressor = Library.CreateCABDecompressor(null);
//decompressor.SetParam(LibMSPackSharp.CAB.Parameters.MSCABD_PARAM_FIXMSZIP, 1);
//decompressor.SetParam(LibMSPackSharp.CAB.Parameters.MSCABD_PARAM_SALVAGE, 1);
var cabFile = decompressor.Open(file);
var sub = cabFile.Files;
while (sub != null)
{
// If an individual entry fails
try
{
// The trim here is for some very odd and stubborn files
string tempFile = Path.Combine(tempPath, sub.Name.TrimEnd('.'));
sub.CopyTo(tempFile);
string tempFile = Path.Combine(tempPath, sub.Filename.TrimEnd('\0', ' ', '.'));
Error error = decompressor.Extract(sub, tempFile);
if (error != Error.MSPACK_ERR_OK)
{
if (scanner.IncludeDebug) Console.WriteLine($"Error occurred during extraction of '{sub.Filename}': {error}");
}
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
sub = sub.Next;
}
// Collect and format all found protections