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