[CABMAN]
[reactos.git] / reactos / sdk / tools / cabman / mszip.cxx
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 AllocateMemory(items * size);
25 }
26
27 void MSZipFree (voidpf opaque, voidpf address)
28 {
29 DPRINT(DEBUG_MEMORY, ("\n"));
30 FreeMemory(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 */