1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS cabinet manager 4 * FILE: tools/cabman/mszip.cxx 5 * PURPOSE: CAB codec for MSZIP compressed data 6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * Colin Finck <mail@colinfinck.de> 8 * NOTES: The ZLIB does the real work. Get the full version 9 * from http://www.cdrom.com/pub/infozip/zlib/ 10 * REVISIONS: 11 * CSH 21/03-2001 Created 12 * CSH 15/08-2003 Made it portable 13 * CF 04/05-2007 Made it compatible with 64-bit operating systems 14 */ 15 #include <stdio.h> 16 #include "mszip.h" 17 18 19 /* Memory functions */ 20 21 voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size) 22 { 23 DPRINT(DEBUG_MEMORY, ("items = (%d) size = (%d)\n", items, size)); 24 return malloc(items * size); 25 } 26 27 void MSZipFree (voidpf opaque, voidpf address) 28 { 29 DPRINT(DEBUG_MEMORY, ("\n")); 30 free(address); 31 } 32 33 34 /* CMSZipCodec */ 35 36 CMSZipCodec::CMSZipCodec() 37 /* 38 * FUNCTION: Default constructor 39 */ 40 { 41 ZStream.zalloc = MSZipAlloc; 42 ZStream.zfree = MSZipFree; 43 ZStream.opaque = (voidpf)0; 44 } 45 46 47 CMSZipCodec::~CMSZipCodec() 48 /* 49 * FUNCTION: Default destructor 50 */ 51 { 52 } 53 54 55 ULONG CMSZipCodec::Compress(void* OutputBuffer, 56 void* InputBuffer, 57 ULONG InputLength, 58 PULONG OutputLength) 59 /* 60 * FUNCTION: Compresses data in a buffer 61 * ARGUMENTS: 62 * OutputBuffer = Pointer to buffer to place compressed data 63 * InputBuffer = Pointer to buffer with data to be compressed 64 * InputLength = Length of input buffer 65 * OutputLength = Address of buffer to place size of compressed data 66 */ 67 { 68 PUSHORT Magic; 69 70 DPRINT(MAX_TRACE, ("InputLength (%u).\n", (UINT)InputLength)); 71 72 Magic = (PUSHORT)OutputBuffer; 73 *Magic = MSZIP_MAGIC; 74 75 ZStream.next_in = (unsigned char*)InputBuffer; 76 ZStream.avail_in = InputLength; 77 ZStream.next_out = ((unsigned char *)OutputBuffer + 2); 78 ZStream.avail_out = CAB_BLOCKSIZE + 12; 79 80 /* WindowBits is passed < 0 to tell that there is no zlib header */ 81 Status = deflateInit2(&ZStream, 82 Z_DEFAULT_COMPRESSION, 83 Z_DEFLATED, 84 -MAX_WBITS, 85 8, /* memLevel */ 86 Z_DEFAULT_STRATEGY); 87 if (Status != Z_OK) 88 { 89 DPRINT(MIN_TRACE, ("deflateInit() returned (%d).\n", Status)); 90 return CS_NOMEMORY; 91 } 92 93 Status = deflate(&ZStream, Z_FINISH); 94 if ((Status != Z_OK) && (Status != Z_STREAM_END)) 95 { 96 DPRINT(MIN_TRACE, ("deflate() returned (%d) (%s).\n", Status, ZStream.msg)); 97 if (Status == Z_MEM_ERROR) 98 return CS_NOMEMORY; 99 return CS_BADSTREAM; 100 } 101 102 *OutputLength = ZStream.total_out + 2; 103 104 Status = deflateEnd(&ZStream); 105 if (Status != Z_OK) 106 { 107 DPRINT(MIN_TRACE, ("deflateEnd() returned (%d).\n", Status)); 108 return CS_BADSTREAM; 109 } 110 111 return CS_SUCCESS; 112 } 113 114 115 ULONG CMSZipCodec::Uncompress(void* OutputBuffer, 116 void* InputBuffer, 117 ULONG InputLength, 118 PULONG OutputLength) 119 /* 120 * FUNCTION: Uncompresses data in a buffer 121 * ARGUMENTS: 122 * OutputBuffer = Pointer to buffer to place uncompressed data 123 * InputBuffer = Pointer to buffer with data to be uncompressed 124 * InputLength = Length of input buffer 125 * OutputLength = Address of buffer to place size of uncompressed data 126 */ 127 { 128 USHORT Magic; 129 130 DPRINT(MAX_TRACE, ("InputLength (%u).\n", (UINT)InputLength)); 131 132 Magic = *((PUSHORT)InputBuffer); 133 134 if (Magic != MSZIP_MAGIC) 135 { 136 DPRINT(MID_TRACE, ("Bad MSZIP block header magic (0x%X)\n", Magic)); 137 return CS_BADSTREAM; 138 } 139 140 ZStream.next_in = ((unsigned char*)InputBuffer + 2); 141 ZStream.avail_in = InputLength - 2; 142 ZStream.next_out = (unsigned char*)OutputBuffer; 143 ZStream.avail_out = CAB_BLOCKSIZE + 12; 144 145 /* WindowBits is passed < 0 to tell that there is no zlib header. 146 * Note that in this case inflate *requires* an extra "dummy" byte 147 * after the compressed stream in order to complete decompression and 148 * return Z_STREAM_END. 149 */ 150 Status = inflateInit2(&ZStream, -MAX_WBITS); 151 if (Status != Z_OK) 152 { 153 DPRINT(MIN_TRACE, ("inflateInit2() returned (%d).\n", Status)); 154 return CS_BADSTREAM; 155 } 156 157 while ((ZStream.total_out < CAB_BLOCKSIZE + 12) && 158 (ZStream.total_in < InputLength - 2)) 159 { 160 Status = inflate(&ZStream, Z_NO_FLUSH); 161 if (Status == Z_STREAM_END) break; 162 if (Status != Z_OK) 163 { 164 DPRINT(MIN_TRACE, ("inflate() returned (%d) (%s).\n", Status, ZStream.msg)); 165 if (Status == Z_MEM_ERROR) 166 return CS_NOMEMORY; 167 return CS_BADSTREAM; 168 } 169 } 170 171 *OutputLength = ZStream.total_out; 172 173 Status = inflateEnd(&ZStream); 174 if (Status != Z_OK) 175 { 176 DPRINT(MIN_TRACE, ("inflateEnd() returned (%d).\n", Status)); 177 return CS_BADSTREAM; 178 } 179 return CS_SUCCESS; 180 } 181 182 /* EOF */ 183