xref: /reactos/sdk/tools/cabman/mszip.cxx (revision 19b18ce2)
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