/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS cabinet manager * FILE: tools/cabman/mszip.cpp * PURPOSE: CAB codec for MSZIP compressed data * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * NOTES: The ZLIB does the real work. Get the full version * from http://www.cdrom.com/pub/infozip/zlib/ * REVISIONS: * CSH 21/03-2001 Created * CSH 15/08-2003 Made it portable */ #include #include "mszip.h" /* Memory functions */ voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size) { DPRINT(DEBUG_MEMORY, ("items = (%d) size = (%d)\n", items, size)); return AllocateMemory(items * size); } void MSZipFree (voidpf opaque, voidpf address) { DPRINT(DEBUG_MEMORY, ("\n")); FreeMemory(address); } /* CMSZipCodec */ CMSZipCodec::CMSZipCodec() /* * FUNCTION: Default constructor */ { ZStream.zalloc = MSZipAlloc; ZStream.zfree = MSZipFree; ZStream.opaque = (voidpf)0; } CMSZipCodec::~CMSZipCodec() /* * FUNCTION: Default destructor */ { } unsigned long CMSZipCodec::Compress(void* OutputBuffer, void* InputBuffer, unsigned long InputLength, unsigned long* OutputLength) /* * FUNCTION: Compresses data in a buffer * ARGUMENTS: * OutputBuffer = Pointer to buffer to place compressed data * InputBuffer = Pointer to buffer with data to be compressed * InputLength = Length of input buffer * OutputLength = Address of buffer to place size of compressed data */ { unsigned short* Magic; DPRINT(MAX_TRACE, ("InputLength (%d).\n", InputLength)); Magic = (unsigned short*)OutputBuffer; *Magic = MSZIP_MAGIC; ZStream.next_in = (unsigned char*)InputBuffer; ZStream.avail_in = InputLength; ZStream.next_out = (unsigned char*)((unsigned long)OutputBuffer + 2); ZStream.avail_out = CAB_BLOCKSIZE + 12; /* WindowBits is passed < 0 to tell that there is no zlib header */ Status = deflateInit2(&ZStream, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, /* memLevel */ Z_DEFAULT_STRATEGY); if (Status != Z_OK) { DPRINT(MIN_TRACE, ("deflateInit() returned (%d).\n", Status)); return CS_NOMEMORY; } Status = deflate(&ZStream, Z_FINISH); if ((Status != Z_OK) && (Status != Z_STREAM_END)) { DPRINT(MIN_TRACE, ("deflate() returned (%d) (%s).\n", Status, ZStream.msg)); if (Status == Z_MEM_ERROR) return CS_NOMEMORY; return CS_BADSTREAM; } *OutputLength = ZStream.total_out + 2; Status = deflateEnd(&ZStream); if (Status != Z_OK) { DPRINT(MIN_TRACE, ("deflateEnd() returned (%d).\n", Status)); return CS_BADSTREAM; } return CS_SUCCESS; } unsigned long CMSZipCodec::Uncompress(void* OutputBuffer, void* InputBuffer, unsigned long InputLength, unsigned long* OutputLength) /* * FUNCTION: Uncompresses data in a buffer * ARGUMENTS: * OutputBuffer = Pointer to buffer to place uncompressed data * InputBuffer = Pointer to buffer with data to be uncompressed * InputLength = Length of input buffer * OutputLength = Address of buffer to place size of uncompressed data */ { unsigned short Magic; DPRINT(MAX_TRACE, ("InputLength (%d).\n", InputLength)); Magic = *((unsigned short*)InputBuffer); if (Magic != MSZIP_MAGIC) { DPRINT(MID_TRACE, ("Bad MSZIP block header magic (0x%X)\n", Magic)); return CS_BADSTREAM; } ZStream.next_in = (unsigned char*)((unsigned long)InputBuffer + 2); ZStream.avail_in = InputLength - 2; ZStream.next_out = (unsigned char*)OutputBuffer; ZStream.avail_out = CAB_BLOCKSIZE + 12; /* WindowBits is passed < 0 to tell that there is no zlib header. * Note that in this case inflate *requires* an extra "dummy" byte * after the compressed stream in order to complete decompression and * return Z_STREAM_END. */ Status = inflateInit2(&ZStream, -MAX_WBITS); if (Status != Z_OK) { DPRINT(MIN_TRACE, ("inflateInit2() returned (%d).\n", Status)); return CS_BADSTREAM; } while ((ZStream.total_out < CAB_BLOCKSIZE + 12) && (ZStream.total_in < InputLength - 2)) { Status = inflate(&ZStream, Z_NO_FLUSH); if (Status == Z_STREAM_END) break; if (Status != Z_OK) { DPRINT(MIN_TRACE, ("inflate() returned (%d) (%s).\n", Status, ZStream.msg)); if (Status == Z_MEM_ERROR) return CS_NOMEMORY; return CS_BADSTREAM; } } *OutputLength = ZStream.total_out; Status = inflateEnd(&ZStream); if (Status != Z_OK) { DPRINT(MIN_TRACE, ("inflateEnd() returned (%d).\n", Status)); return CS_BADSTREAM; } return CS_SUCCESS; } /* EOF */